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
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.
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.
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.
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)
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