Because the 'Abc_Win.dll' is shared ('dll') and needs to be copied to the target-EXE I added a custom target - like this. I'm working with MS-VisualStudio 2005-2011 and using cmake 2.8.8.
add_custom_target( "Abc_Win.dll" )
add_custom_command( TARGET "Abc_Win.dll" POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"MyDllSource/${CMAKE_CFG_INTDIR}/Abc_Win.dll"
"MyExeDest/${MWEB_CMAKE_CFG_INTDIR}/Abc_Win.dll" )
set_property(Abc_Win.dll" PROPERTY FOLDER ${MWEB_FOLDER_ADDON}/${MWEB_FOLDER_RTE})
All above working like I expect and the 'Abc_Win.dll' get on the right place when I build.
Now I add an the following install command - expecting 'Abc_Win.dll' in "Bin"-Directory beside my EXE.
install(FILES "MyDllSource/${CMAKE_CFG_INTDIR}/Abc_Win.dll" DESTINATION "Bin")
When I build now the CMakePredefinedTargets->INSTALL (doesn't matter which MS-StudioVersion I use) I get always a build error in the cmake generated file 'cmake_install.cmake':
file INSTALL cannot find
"MyDllSource/$(Configuration)/Abc_Win.dll"
I understand that cmake does not uses build-rules from MS-VS - like it does it for add_custom_command. It also seems to be that this cmake-file has no glue from the Content $(CONFIGRATION) which is set actual to 'Debug'.
Has anybody an idea how to solve this Problem? Help would be very appreciated. Thanks.
There's an undocumented variable you can use here: CMAKE_INSTALL_CONFIG_NAME.
Unless you happen to have defined this yourself in your CMakeLists.txt, it will be undefined when CMake runs.
However, when you use install commands in your CMakeLists.txt, CMake generates a file called "cmake_install.cmake" in the root of your build tree (same place as CMakeCache.txt). This is executed at install time, and it sets CMAKE_INSTALL_CONFIG_NAME to your current configuration in Visual Studio.
There's another slight twist; to avoid CMake expanding ${CMAKE_INSTALL_CONFIG_NAME} in the install command (it would expand to an empty string), you need to escape it with a \.
So, you just need to change your install command to:
install(FILES "MyDllSource/\${CMAKE_INSTALL_CONFIG_NAME}/Abc_Win.dll"
DESTINATION "Bin")
Related
In my CMakeLists.txt, I define a custom target and command:
add_custom_command(
OUTPUT
${CMAKE_CURRENT_SOURCE_DIR}/input.csv
${CMAKE_CURRENT_SOURCE_DIR}/output1.csv
${CMAKE_CURRENT_SOURCE_DIR}/output2.csv
COMMAND python3
${CMAKE_CURRENT_SOURCE_DIR}/tests/genVectors.py)
add_custom_target(TEST_VECTORS
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/input.csv
${CMAKE_CURRENT_SOURCE_DIR}/output1.csv
${CMAKE_CURRENT_SOURCE_DIR}/output2.csv)
add_executable(VectorTest tests/VectorTest.cpp)
add_dependencies(VectorTest TEST_VECTORS)
It always generates new CSV files even though the files exist. I only need to generate the vectors (with genVectors.py python file) if they do not exist. Is that something wrong with my configuration?
The OUTPUT option of add_custom_command does not guarantee that the generated files are placed here; it just tells CMake that the generated files are expected to be placed there. It is likely that your python script is generating files at a relative path, so they are just being placed somewhere in your CMake binary directory (your build folder). So while your files may be generated correctly, your custom target doesn't see them because it is looking in CMAKE_CURRENT_SOURCE_DIR. Thus, the custom target will always trigger the custom command to re-run.
CMake runs add_custom_command from the CMAKE_CURRENT_BINARY_DIR by default, but you can change it to run from CMAKE_CURRENT_SOURCE_DIR by adding the WORKING_DIRECTORY option. This way, the generated files will be placed at the expected location, and achieve your desired behavior. Try something like this:
add_custom_command(
OUTPUT
${CMAKE_CURRENT_SOURCE_DIR}/input.csv
${CMAKE_CURRENT_SOURCE_DIR}/output1.csv
${CMAKE_CURRENT_SOURCE_DIR}/output2.csv
COMMAND python3
${CMAKE_CURRENT_SOURCE_DIR}/tests/genVectors.py
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
add_custom_target(TEST_VECTORS
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/input.csv
${CMAKE_CURRENT_SOURCE_DIR}/output1.csv
${CMAKE_CURRENT_SOURCE_DIR}/output2.csv)
add_executable(VectorTest tests/VectorTest.cpp)
add_dependencies(VectorTest TEST_VECTORS)
You can try to generate your file at time of configuration(i.e. while calling cmake). By this way it will created only once.
You can remove add_custom_command and use execute_process to create your files.
Part of my source code is generated by a tool which is also built under our main project with a add_subdirectory. We execute this tool with a execute_process command. Clearly, if the tool is not built before we reach the execute_process statement it will fail.
I use a GLOB (file(GLOB...)) to find the source files generated. I do this because it is not possible to know beforehand how many files are generated, neither their names.
How do I force cmake to wait for the subproject to be compiled before the execute process? I would need something like a DEPENDS property for the execute_process but this option is not available.
# This subproject will source generator the tool
add_subdirectory(generator)
# I need something like: wait_for(generator)
execute_process(COMMAND generator ${CMAKE_SOURCE_DIR}/src)
file(GLOB GeneratedSources ${CMAKE_SOURCE_DIR}/src/*.cpp)
add_executable(mainprject.exe ${ProcessorSourceFiles}
Command execute_process executes its COMMAND immediately, at configuration stage. So it cannot be arranged after the executable is created with add_executable command: that executable will be built only at build stage.
You need to build subproject at configuration stage too. E.g. with
execute_process(COMMAND ${CMAKE_COMMAND}
-S ${CMAKE_SOURCE_DIR}/generator
-B ${CMAKE_BINARY_DIR}/generator
-G ${CMAKE_GENERATOR}
)
execute_process(COMMAND ${CMAKE_COMMAND}
--build ${CMAKE_BINARY_DIR}/generator
)
The first command invokes cmake for configure the 'generator' project, located under ${CMAKE_SOURCE_DIR}/generator directory. With -G option we use for subproject the same CMake generator, as one used for the main project.
The second command builds that project, so it produces generator executable.
After generator executable is created, you may use it for your project:
execute_process(COMMAND ${CMAKE_BINARY_DIR}/generator/<...>/generator ${CMAKE_SOURCE_DIR}/src)
Here you need to pass absolute path to the generator executable as the first parameter to COMMAND: CMake no longer have generator executable target, so it won't substitute its path automatically.
You will need to model this with target dependencies. The tool "generator" should be a cmake target. In that case use add_custom_target instead of execute_process somthing like this:
add_custom_target(generate_sources ALL COMMAND generator ${CMAKE_SOURCE_DIR}/src))
Then add a target dependency to "generator" using add_dependencies:
add_dependencies(generate_sources generator)
This will make sure your target "generate_sources", which runs the tool will only run during build after the target "generator" has been compiled.
The following is false, see the comments for more info:
Use add_dependencies to add a dependency from "mainproject.exe" to "generate_sources". Now this I have never tested, so take with a grain of salt: With CMake more recent than version 3.12, according to the entry on file, you should then be able to change your file command to:
file(GLOB GeneratedSources CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/src/*.cpp)
Which I interpret as this will re-glob the files during build if the directory changes.
in my CMake project, I use an external project called ep_glslang which is quite straightforward:
ExternalProject_Add(ep_glslang
DEPENDS ep_vulkan_headers
URL https://github.com/KhronosGroup/glslang/archive/7.11.3113.tar.gz
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${_PREFIX}
-DVULKAN_HEADERS_INSTALL_DIR=${_PREFIX}
)
Yet, before the configure step I need to run a Python located at the root of the source directory of glslang.
I created a custom step for my external project:
ExternalProject_Add_Step(ep_glslang update_glslang_sources
DEPENDEES update
DEPENDERS configure
COMMAND ${PYTHON_EXECUTABLE} update_glslang_sources.py
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${_PREFIX}
)
It seems to be an idiomatic way of doing that. Yet the step fails for it does not find the python script.
How would I get the source directory of the external project in order to make things like this:
...
COMMAND ${PYTHON_EXECUTABLE} ${EP_SRC_DIR}/update_glslang_sources.py
...
I don't find anything, even in the generator expressions, that would help me.
Thank you :)
The solution by Tsyvarev:
For refer to source directory in ExternalProject_Add use <SOURCE_DIR> expression: COMMAND ${PYTHON_EXECUTABLE} <SOURCE_DIR>/update_glslang_sources.py.
So, there are numerous ways to copy files (and directories) at CMake runtime (file(COPY ...), configure_file(...) and add_custom_command() all work*), but I haven't yet found out how to make a file or directory copied from the source to build directory appear in an archive generated by CPack. I though that this SO answer would fix it, as it actually links the copying to a target which will then have an install linked to it:
install(TARGET mytarget DESTINATION bin)
whereas I did recognise that the file() and configure_file() commands don't have an obvious way to be added to a target. But, this didn't work. So, given a simple CMakeLists.txt, such as the one below, how do I make all of the files (including the exmaple directory) appear in the archive?!
cmake_minimum_required(VERSION 2.6 FATAL_ERROR)
enable_language(FORTRAN)
add_executable(mytarget ${PROJECT_SOURCE_DIR}/myprog.for)
install(TARGETS mytarget DESTINATION bin)
add_custom_command(TARGET mytarget PREBUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${PROJECT_SOURCE_DIR}/examplefiles ${PROJECT_BINARY_DIR}/examplefiles)
set(CPACK_GENERATOR "TGZ")
include(CPack)
* I haven't yet found out which one of these 3 methods is actually (most?) correct - so any advice on this too will be hugely appreciated
As explained in the documentation of the CPack module, the binary installers created by CPack contain everything installed via CMake's INSTALL command. Thus the executable mytarget in your example will be included in the CPack archive, because you use the install command to copy it to the bin folder.
To also have CPack include the example folder in the generated archive, you can use the DIRECTORY variant of the install command in the following way:
install(DIRECTORY "${PROJECT_SOURCE_DIR}/examplefiles/" DESTINATION "example")
The file(COPY ...) and configure_file(...) do not have an effect on what is installed by CPack. Both command are usually used to copy files from the source tree to the binary tree upon configuring the CMake project.
Using add_custom_command with ${CMAKE_COMMAND} -E copy_directory ... will postpone the actual copying of files to the build time of the project. It will however not trigger the inclusion of the copied files in the CPack archive, either.
I'm trying to include an external library in a build environment that uses CMake. I'm not trying to install it on the local system (in fact I'd rather not do that, I don't want /usr/local clogged up with all kinds of libraries); I'd just like to have the resulting libxml2.a available for linking with my executable. I can build it fine with the following in CMakeLists.txt:
set (LIBXML_PATH ${MY_SOURCE_DIR}/libxml2-2.9.1)
add_custom_target (build_libxml ALL
COMMENT "Building libxml"
COMMAND ./configure --prefix=/tmp
COMMAND make
WORKING_DIRECTORY ${LIBXML_PATH}
)
But I'm still having trouble with the following:
1) Is this the right approach in the first place, for the general purpose of getting libraries built with configure and make into a CMake environment?
2) How do I get the resulting library (i.e. libxml2.a) under my build output directory?
3) How can I link to that library for my executable builds?
I tried a fiddly solution with
ADD_LIBRARY( xml2 STATIC libxml2.a )
but it seems like there must be a better way than hauling a whole library's contents into… a library.
Thanks.
You need to make it clearer to CMake what is going on here. All it can see now is that you have some custom command that it will run every time. Instead of using add_custom_target with COMMAND, I've found it better to use add_custom_command.
Something like this:
set (LIBXML_PATH ${MY_SOURCE_DIR}/libxml2-2.9.1)
add_custom_command(
OUTPUT libxml2.a
COMMENT "Building libxml"
COMMAND ./configure --prefix=/tmp
COMMAND make
WORKING_DIRECTORY ${LIBXML_PATH}
)
target_link_libraries(your-program libxml2.a)
By doing it this way, CMake can understand that your custom command's essential product is libxml2.a, and when CMake sees something depending on that, it will run the command (if the library doesn't exist already).