[CMake] using "INSTALL(CODE ..." for multiple configurations.

Michael Hertling mhertling at online.de
Mon May 30 12:08:25 EDT 2011


On 05/30/2011 12:54 PM, Campbell Barton wrote:
> On Mon, May 30, 2011 at 1:55 AM, Michael Hertling <mhertling at online.de> wrote:
>> On 05/30/2011 02:58 AM, Campbell Barton wrote:
>>> Checking if this is possible since its quite verbose to have the same
>>> command 4 times, one for each configuration.
>>>
>>> For blender3d on windows we need to extract python into the install
>>> dir since we bundle it.
>>>
>>> This command looks like this:
>>> --- snip
>>>
>>> install(
>>>       CODE
>>>       "
>>>       execute_process(COMMAND \"${CMAKE_COMMAND}\" -E chdir
>>> \"${TARGETDIR_VER}/python/lib\"
>>>               \"${CMAKE_COMMAND}\" -E tar xzfv \"${LIBDIR}/release/python32.tar.gz\")
>>>       "
>>>       CONFIGURATIONS Release
>>> )
>>>
>>> --- snip
>>>
>>> The annoyance is that the same command needs to be called 3 times,
>>> Release/RelWithDebInfo/MinSizeRel
>>> Is there some way to list multiple 'CONFIGURATIONS' ?
>>
>> CMake's documentation states about INSTALL()'s CONFIGURATIONS
>> argument: "The CONFIGURATIONS argument specifies a *list* of
>> build configurations for which the install rule applies
>> (Debug, Release, etc.)."
>>
>>> Ideally in this case Id like to have any 'Debug' extract
>>> python32_d.tar.gz and any other configuration extract python32.tar.gz,
>>> but a ways to have multiple configurations do one command would at
>>> least be less verbose.
>>
>> Are you sure that the CONFIGURATIONS clause is available for the
>> INSTALL(CODE ...) command? It's not specified, and on *nix, the
>> following CMakeLists.txt issues the message upon "make install"
>> regardless of the CMAKE_BUILD_TYPE variable's value whereas the
>> INSTALL(FILES ...) command is sensitive as expected:
>>
>> CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
>> PROJECT(INSTCONF NONE)
>> SET(CMAKE_VERBOSE_MAKEFILE ON)
>> INSTALL(CODE "MESSAGE(\"Installing\")" CONFIGURATIONS Release)
>> INSTALL(FILES ${CMAKE_SOURCE_DIR}/CMakeLists.txt
>>        DESTINATION ${CMAKE_BINARY_DIR}/cmake
>>        CONFIGURATIONS Release)
>>
>> Does it work differently on Windows?
>>
>> Regards,
>>
>> Michael
> 
> Looked into this further, First, multiple configurations can be passed
> separated by either spaces or ;.
> 
> So this works as expected:
> ---
> 	install(
> 		FILES ${LIBDIR}/python/lib/python32.dll
> 		DESTINATION ${TARGETDIR}
> 		CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel
> 	)
> ---
> 
> You're right, the install(CODE ... doesn't support configurations, in
> fact our install target on windows was extracting python 4 times!
> 
> Instead I added a check in the CODE
> ---
> 	install(
> 		CODE
> 		"
> 		if(\"\${CMAKE_INSTALL_CONFIG_NAME}\" STREQUAL \"Debug\")
> 			execute_process(COMMAND \"${CMAKE_COMMAND}\" -E chdir
> \"${TARGETDIR_VER}/python/lib\"
> 				\"${CMAKE_COMMAND}\" -E tar xzfv \"${LIBDIR}/release/python32_d.tar.gz\")
> 		else()
> 			execute_process(COMMAND \"${CMAKE_COMMAND}\" -E chdir
> \"${TARGETDIR_VER}/python/lib\"
> 				\"${CMAKE_COMMAND}\" -E tar xzfv \"${LIBDIR}/release/python32.tar.gz\")
> 		endif()
> 		"
> 	)
> ---
> 
> Since CONFIGURATIONS is listed as an option I assumed it would work
> with all install uses of install.
> It would be good if the cmake docs mentioned which commands support
> CONFIGURATIONS (FILES/DIRECTORY only?), I re-read and couldn't find
> anything relating to this.
> 
> - Campbell

At the top of the INSTALL() command's documentation, it reads:

"There are multiple signatures for this command. Some of them define
installation properties for files and targets. Properties common to
multiple signatures are covered here but they are valid only for
signatures that specify them."

Subsequently, those properties are explained, followed by the command's
signatures. Perhaps, the term "properties" is somewhat misleading here.

Due to the limitations of INSTALL(CODE|SCRIPT ...), I'd recommend
against doing non-trivial things with these signatures during the
installation. In general, I'd prefer to perform actions like your
Python extraction at build time with custom targets/commands and
install the results via INSTALL(FILES ...), e.g.:

# CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(BUNDLE NONE)
SET(CMAKE_VERBOSE_MAKEFILE ON)
ADD_CUSTOM_TARGET(bundle ALL
    ${CMAKE_COMMAND} -DCONFIGURATION="$<CONFIGURATION>"
                     -P ${CMAKE_SOURCE_DIR}/bundle.cmake)
SET(NON_DEBUG_CONFIGS "${CMAKE_CONFIGURATION_TYPES}")
LIST(REMOVE_ITEM NON_DEBUG_CONFIGS Debug)
INSTALL(FILES ${CMAKE_BINARY_DIR}/bundle.tar
    DESTINATION ${CMAKE_BINARY_DIR}/tmp
    CONFIGURATIONS ${NON_DEBUG_CONFIGS})
INSTALL(FILES ${CMAKE_BINARY_DIR}/bundle_d.tar
    DESTINATION ${CMAKE_BINARY_DIR}/tmp
    CONFIGURATIONS Debug)

# bundle.cmake:
SET(BUNDLE "bundle")
IF(CONFIGURATION STREQUAL Debug)
    SET(BUNDLE "${BUNDLE}_d")
ENDIF()
EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E tar cf ${BUNDLE}.tar
    CMakeCache.txt)

This exemplary project simply packages its CMakeCache.txt in bundle.tar
or in bundle_d.tar, respectively, when the current configuration equals
"Debug". Apparently, the "generator expressions" of custom commands are
also available for custom targets - an undocumented feature which makes
it particularly easy to refer to the current configuration by the "$<>"
notion within the custom target. Perhaps, you could test and report if
this actually works since I've not tested it on Windows.

Regards,

Michael


More information about the CMake mailing list