Why RPATH_CHECK in CMake deletes executable? - cmake

The following CMake's action will delete executable if RPATH is not the same.
file(RPATH_CHECK
FILE "${CMAKE_CURRENT_SOURCE_DIR}/moc"
RPATH "\$ORIGIN/../lib")
If RPATH will not be $ORIGIN/../lib then - ops, and no more executable.
Is it correct behavior of CMake, or it is a bug?
What RPATH_CHECK should do?
I caught this problem in Qt 6.2.1 on Linux. Qt builds successfully, but cmake --install . fails because CMake deletes executable in reason of RPATH_CHECK file's action with mismatched RPATH (declared and actual). Actual RPATH is :::::::::::::: at point of execution RPATH_CHECK.
I'm on Kubuntu 20.04. I installed sources of Qt with official Online Installer. To configure Qt I used:
./configure -nomake tests -nomake examples -skip qttest -skip qtwebengine -skip qtwebview -skip qtpositioning -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtnfc -skip qtcharts -skip qt3d -skip qtwayland -skip qtcoap -skip qtdatavis3d -skip qtlottie -skip qtmqtt -skip qtnetworkauth -skip qtopcua -skip qtquick3d -skip qtquicktimeline -skip qtremoteobjects -skip qtvirtualkeyboard -skip qtwebchannel -skip qtwebsockets -release -shared -skip qt5compat -skip qtdoc -skip qtscxml -skip qttranslations -skip qttools
Then
cmake --build . --parallel
CMake version 3.16.3

Why RPATH_CHECK in CMake deletes executable?
Because that's what it does. (?)
Is it correct behavior of CMake, or it is a bug?
Correct.
What RPATH_CHECK should do?
Check if the file has desired RPATH, and if it doesn't, the file should be removed.
If you have any other concerns about RPATH features in CMake, I posted the source code in the last answer - all is there. Search for RPATH_CHECK in CMake source tree, and you'll find the find the function - from function names you can "guess" meaning and the algorithm used.

Related

How to copy linked and mingw libs to output dir of executable?

I'm new in CMake.
Could someone please describe to me what I should write in my CMakeLists.txt to copy dependencies to the output directory of the executable file?
So, I have a CMake project:
# top-level CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
project(CoolLib VERSION 0.0.1)
set(CMAKE_CXX_STANDARD 23)
add_subdirectory(mylib)
add_subdirectory(mytestconsole)
install(TARGETS mnconsole mnlib
RUNTIME DESTINATION bin COMPONENT Runtime
LIBRARY DESTINATION lib COMPONENT Runtime
ARCHIVE DESTINATION lib/myproject COMPONENT Development)
# mylib/CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
project(mylib VERSION 0.0.1)
add_library(mylib SHARED mylib.cpp mylib.h)
target_include_directories(mylib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
# mytestconsole/CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
project(mytestconsole VERSION 0.0.1)
add_executable(mytestconsole main.cpp)
target_link_libraries(mytestconsole LINK_PUBLIC mylib)
target_include_directories(mytestconsole PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/mylib)
As you can see, I've added an install() command, but this isn't exactly what I want.
As far as I understand, the install() command will copy my program to the Program Files directory in Windows.
GOAL:
I want to copy the mingw libraries (e.g. libgcc_s_seh-1, libstdc++-6, libwinpthread-1, etc.) and mylib to the output directory of the mytestconsole.exe file.
PS: I saw this answer, but GetPrerequesites is deprecated. And I didn't understand how to use it.
I tried to do this:
add_custom_command(
TARGET mnconsole POST_BUILD
COMMAND LIST_PREREQUISITES($<TARGET_FILE:mnconsole>)
VERBATIM)
But got an error:
D:\Programs\JetBrains\CLion\bin\cmake\win\bin\cmake.exe --build D:\Projects\MethaneNumber\_builds\debug --target mnconsole -j 9
[1/1] Linking CXX executable mnconsole\mnconsole.exe
FAILED: mnconsole/mnconsole.exe
cmd.exe /C "cd . && D:\Programs\mingw64\12.2.0\x64\posix-seh\bin\c++.exe -g mnconsole/CMakeFiles/mnconsole.dir/main.cpp.obj -o mnconsole\mnconsole.exe -Wl,--out-implib,mnconsole\libmnconsole.dll.a -Wl,--major-image-version,0,--minor-image-version,0 mnlib/libmnlib.a -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cmd.exe /C "cd /D D:\Projects\MethaneNumber\_builds\debug\mnconsole && LIST_PREREQUISITES ( D:/Projects/MethaneNumber/_builds/debug/mnconsole/mnconsole.exe )""
"LIST_PREREQUISITES" is ­not recognized as an internal command.
ninja: build stopped: subcommand failed.
PS2: It should work like windeployqt.exe with Qt, but I'm not using Qt in this project right now.

CMake generator expression evaluated to "" instead of nothing

I'm using generator expressions in a custom command to compile hlsl shaders:
add_custom_command(TARGET Shaders
COMMAND vendor/shader-compiling/fxc.exe /nologo /Emain /Tvs_5_0 $<$<CONFIG:Debug>:/Od> /Zi /Fo ${TARGET_SHADER_PATH}/hlsl/${FILE_WE}_vs.cso /Fd ${CMAKE_BINARY_DIR}/${FILE_WE}_vs.pdb ${TARGET_SHADER_PATH}/hlsl/${FILE_WE}_vs.hlsl
COMMAND vendor/shader-compiling/fxc.exe /nologo /Emain /Tps_5_0 $<$<CONFIG:Debug>:/Od> /Zi /Fo ${TARGET_SHADER_PATH}/hlsl/${FILE_WE}_fs.cso /Fd ${CMAKE_BINARY_DIR}/${FILE_WE}_fs.pdb ${TARGET_SHADER_PATH}/hlsl/${FILE_WE}_fs.hlsl
MAIN_DEPENDENCY ${FILE}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Compiling HLSL shader ${TARGET_SHADER_PATH}/hlsl/${FILE_WE}.hlsl"
VERBATIM)
and in debug mode everything works fine.
However, in release mode, my expected result is the /Od flag does not get included in the command at all. However, what ended up happening is $<$<CONFIG:Debug>:/Od> gets evaluated to two double quotes and the command doesn't work.
Any ideas on why this is happening?
Just in case anybody finds this useful, I solved the problem by adding COMMAND_EXPAND_LISTS to my add_custom_command command. Not sure why that works but it does get rid of the empty pair of quotes in the middle of the command therefore the command works.

Unknown CMake command "CMAKE_DEPENDENT_OPTION"

I faced with an issue that my installed on Ubuntu cmake
cmake --version
cmake version 3.17.2
doesn't recognize CMAKE_DEPENDENT_OPTION command.
So, my CMakeLists.txt with dependent option example from cmake.org/v3.16:
cmake_minimum_required(VERSION 3.4.1)
project(myexe)
CMAKE_DEPENDENT_OPTION(USE_FOO "Use Foo" ON
"USE_BAR;NOT USE_ZOT" OFF)
file(GLOB SRC_FILES "src/*.cpp")
add_executable(${PROJECT_NAME} ${SRC_FILES})
The following error is displayed when running cmake:
CMake Error at CMakeLists.txt:5 (CMAKE_DEPENDENT_OPTION):
Unknown CMake command "CMAKE_DEPENDENT_OPTION".
Why does it happen because the spec says it is supported? Thanks for any help!
You need to add
include(CMakeDependentOption)
before accessing this function.

Linking error -- openSSL to libcurl

I'm doing C++ using libcURL. I got the task to test functions in Travis CI. So I used .travis.yml to get libcurl-dev and libssl-dev to connect to the project. I installed them and checked cURL configuration:
SSL support: enabled (OpenSSL)
But as I was trying to make main test file i got list of errors (example)
`Linking CXX executable ../bin/TechProject_example
/usr/local/lib/libcurl.a(libcurl_la-openssl.o): In function ossl_recv:
openssl.c:(.text+0xf3): undefined reference to ERR_clear_error
openssl.c:(.text+0x11c): undefined reference to SSL_read
openssl.c:(.text+0x163): undefined reference to SSL_get_error`
and so on...
The only thing I was able to check is that libcurl is working properly. I placed
--without-ssl flag and got protocol error.
Also I used
`- sudo ln -fs /usr/lib/libcurl.so.4 /usr/local/lib/`
to avoid cmake error. (I'm not very good at UNIX command, so this can be a problem)
So how should properly connect openSSL to C++ project that has <curl/curl.h> ?
EDIT:
Here is CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project (TechProject)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(HEADERS ${PROJECT_SOURCE_DIR}/include/testclass.h)
set(HEADERS ${PROJECT_SOURCE_DIR}/include/catch.hpp)
set(SOURCES ${PROJECT_SOURCE_DIR}/sources/testclass.cpp)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
include_directories(${PROJECT_SOURCE_DIR}/include)
add_library (${PROJECT_NAME} STATIC ${SOURCES})
add_subdirectory(example)
add_subdirectory(tests)
find_library(FOO_LIB libcurl.a)
target_link_libraries(TechProject "${FOO_LIB}")
And CMakeLists.txt in tests subdir:
cmake_minimum_required(VERSION 2.8)
set(TESTS_FOR_PROJECT TechProject)
project(${TESTS_FOR_PROJECT}_tests)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
option(BUILD_SHARED_LIBS "Build shared instead of static library" OFF)
file(GLOB ${PROJECT_NAME}_sources "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp")
find_package(${TESTS_FOR_PROJECT})
include_directories(${${TESTS_FOR_PROJECT}_INCLUDE_DIRS}})
include_directories(${CPM_INCLUDE_DIRS})
add_executable(${PROJECT_NAME} ${${PROJECT_NAME}_sources} ${${PROJECT_NAME}_headers})
target_link_libraries(${PROJECT_NAME} ${TESTS_FOR_PROJECT})
add_custom_command(TARGET ${PROJECT_NAME} PRE_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_SOURCE_DIR}/fixtures $<TARGET_FILE_DIR:${PROJECT_NAME}>)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${PROJECT_NAME} -s -r compact WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

Error with variables when invoking CMake from CMake

I need to invoke cmake from within cmake so that I can have binaries built before project files are generated. I have the following CmakeLists.txt:
cmake_minimum_required(VERSION 3.2)
project(StarEngine)
set(CMAKE_CXX_FLAGS "-std=c++11")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
#copy the other cmake file into where we'd like to invoke cmake
configure_file(deps-CMakeLists.txt deps/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} . WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps)
#eventually binaries will be built, for now this doesn't accomplish anything
execute_process(COMMAND ${CMAKE_COMMAND} --build . WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps)
And its friend, deps-CmakeLists.txt, a test script:
set(GENERATED_DIR "test")
MESSAGE( STATUS ${GENERATED_DIR} )
In the following file structure:
Project
build
Code
CmakeLists.txt
deps-CmakeLists.txt
No matter what I put in for the variable value, it is blank when displayed in MESSAGE. I imagine this is weird behavior resulting from invoking cmake from cmake. I had a bunch of other strange errors to, but I suspect if I can figure out this one that will help crack them all.
Thanks to #Florian, the problem was with variable replacement and I needed to add the COPYONLY option to configure_file