Reputation: 1826
The docs for CMake 3.2.2 state, that it is possible to use generator expressions for the install(<FILES|PROGRAMS> ...)
signature. I was trying to use generator expressions in other signatures of install()
, but apparently it is not working. I would like to do something like this:
install(TARGETS foo EXPORT fooConfig
RUNTIME DESTINATION "Bin/$<CONFIG>"
LIBRARY DESTINATION "Lib/$<CONFIG>"
ARCHIVE DESTINATION "Lib/$<CONFIG>"
I also tried calling install()
multiple times like this:
install(TARGETS foo EXPORT fooConfig
RUNTIME DESTINATION "Bin/Debug" CONFIGURATIONS Debug
LIBRARY DESTINATION "Lib/Debug" CONFIGURATIONS Debug
ARCHIVE DESTINATION "Lib/Debug" CONFIGURATIONS Debug
install(TARGETS foo EXPORT fooConfig
RUNTIME DESTINATION "Bin/Release" CONFIGURATIONS Release
LIBRARY DESTINATION "Lib/Release" CONFIGURATIONS Release
ARCHIVE DESTINATION "Lib/Release" CONFIGURATIONS Release
install(TARGETS foo EXPORT fooConfig
RUNTIME DESTINATION "Bin/MinSizeRel" CONFIGURATIONS MinSizeRel
LIBRARY DESTINATION "Lib/MinSizeRel" CONFIGURATIONS MinSizeRel
ARCHIVE DESTINATION "Lib/MinSizeRel" CONFIGURATIONS MinSizeRel
install(TARGETS foo EXPORT fooConfig
RUNTIME DESTINATION "Bin/RelWithDebInfo" CONFIGURATIONS RelWithDebInfo
LIBRARY DESTINATION "Lib/RelWithDebInfo" CONFIGURATIONS RelWithDebInfo
ARCHIVE DESTINATION "Lib/RelWithDebInfo" CONFIGURATIONS RelWithDebInfo
This causes CMake to emit an error along the lines of Target 'foo' exported more than once in 'fooConfig'.
I cannot use CMAKE_BUILD_TYPE
here either without updating the CMake cache and re-running the build. Rather than that, I want to use the Visual Studio batch-build feature, which builds multiple configurations for me.
There was a little hack that I tried too. I noticed that CMake's generated INSTALL
project is simply invoking a CMake script ${CMAKE_BINARY_DIR}/cmake_install.cmake
with the argument -DBUILD_TYPE=$(Configuration)
. So I tried the following:
install(TARGETS foo EXPORT fooConfig
RUNTIME DESTINATION "Bin/\${BUILD_TYPE}"
LIBRARY DESTINATION "Lib/\${BUILD_TYPE}"
ARCHIVE DESTINATION "Lib/\${BUILD_TYPE}"
This actually worked well for the installation. However, the installed export script, i.e. the output of install(EXPORT fooConfig DESTINATION .)
now also tries to use ${BUILD_TYPE}
, which is not set at the time the user includes that script...
If anyone knows another way to accomplish my goals, please let me know.
Upvotes: 10
Views: 6590
Reputation: 65931
Unluckily the install
command only supports generator expressions for the list of files to be installed, but not for the destination directory.
I would recommend on sticking with your little hack, but use CMAKE_INSTALL_CONFIG_NAME
instead of CMAKE_BUILD_TYPE
, i.e.:
install(TARGETS foo EXPORT fooConfig
RUNTIME DESTINATION "Bin/\${CMAKE_INSTALL_CONFIG_NAME}"
LIBRARY DESTINATION "Lib/\${CMAKE_INSTALL_CONFIG_NAME}"
ARCHIVE DESTINATION "Lib/\${CMAKE_INSTALL_CONFIG_NAME}"
CMAKE_INSTALL_CONFIG_NAME
is set to the actual build configuration used for installing in the generated cmake_install.cmake
script.
The generated export scripts (e.g., fooConfig-debug.cmake
) can be automatically fixed by adding a patch script to the installation process. Generate a file patch_export_files.cmake
with the following contents in the source directory:
file(GLOB_RECURSE _configFiles "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/fooConfig-*.cmake")
foreach(_configFile ${_configFiles})
file (READ "${_configFile}" _contents)
string (REGEX MATCH "configuration \"[A-Za-z]+\"" _configName "${_contents}")
if (_configName MATCHES "\"([A-Za-z]+)\"")
message(STATUS "Patching: ${_configFile}")
string (REPLACE "\${CMAKE_INSTALL_CONFIG_NAME}" "${CMAKE_MATCH_1}" _patchedContents "${_contents}")
file (WRITE "${_configFile}" "${_patchedContents}")
endif()
endforeach()
The patch script need to be run at installation time by adding an install(SCRIPT ...
call after the install(EXPORT ...
:
install(EXPORT fooConfig DESTINATION .)
...
install(SCRIPT patch_export_files.cmake)
The patch script first parses the configuration that the generated export script is valid for from its header comment and then replaces each use of ${CMAKE_INSTALL_CONFIG_NAME}
with the configuration name.
Upvotes: 10
Reputation: 1960
I am working on a project which requires builds with different configurations. The way I have achieved this is using "ExternalProject".
I have created a sample repository to show you the idea: https://github.com/mpaluru/cmake_multiple_build_configs_example
(Linux is the environment I use mostly and don't have access to Visual Studio.) If you pass on the -G flag in the top level CMakeLists.txt, you should be able to generate your VS files. I have tested this on Linux and "make -j" works fine. Both the Debug and Release configurations build in parallel.
Summary: You create a new superbuild project which calls your project using ExternalProject_Add with different CMAKE_BUILD_TYPE.
And based on the build type, you pass different definitions, or do install differently.
Upvotes: 2