Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake: how to get target location for install rule

Tags:

cmake

I have a CMakeLists.txt that does this:

get_target_property(myloc mytarget LOCATION)

It used to work fine, but CMake 3.0 deprecated using LOCATION (see https://cmake.org/cmake/help/v3.0/policy/CMP0026.html). So I tried using a generator expression:

set(myloc $<TARGET_FILE:mytarget>)

This seemed like it would work, except that generator expressions are not evaluated everywhere, they only seem to work when setting properties of other targets, and are resolved during the "generation" step, not the earlier "configuration" step. The problem is, I need to know the target location in an install() rule, something like this (the real use is not strip but that doesn't matter):

install(CODE "execute_process(COMMAND strip ${myloc})")

This worked fine when using LOCATION but now that's deprecated and I can't figure out the right way to do this. The root of the problem seems to be that install() is invoked during the "configuration" step, when the target path is not known.

How can I bridge this gap, and discover the target output path as I used to do, before calling install()?

like image 212
John Zwinck Avatar asked Jun 06 '19 01:06

John Zwinck


People also ask

How do I specify the install directory in CMake?

The installation directory is usually left at its default, which is /usr/local . Installing software here ensures that it is automatically available to users. It is possible to specify a different installation directory by adding -DCMAKE_INSTALL_PREFIX=/path/to/install/dir to the CMake command line.

What does install command do in CMake?

CMake provides the install command to specify how a project is to be installed. This command is invoked by a project in the CMakeLists file and tells CMake how to generate installation scripts. The scripts are executed at install time to perform the actual installation of files.

What is an install target?

Installation Target refers to the target of an installation operation. Targets are defined, among other parameters, in terms of the following definitions: Sample 1. Installation Target refers to the target of an installation operation.

What is Cmake_install CMake file?

cmake contains the commands generated by install command from your CMakeLists. txt . You can execute it by cmake -P cmake_install. cmake and it performs the installation of your project even on windows.


2 Answers

Ideally, it would be done via generator expressions:

install(CODE "execute_process(COMMAND strip $<TARGET_FILE:mytarget>)")

Unfortunately, support for generator expressions in CODE and SCRIPT modes of install command has been added only in CMake 3.14 (see documentation of install command in that version).

Before CMake 3.14 you may work only with single-configuration generators (e.g. with Makefile but not with Visual Studio).

In such conditions, you may either disable CMP0026 warning, as suggested in the Th.Thielemann's answer and read LOCATION property.

Or you may use install(SCRIPT) flow of the command, where the script is prepared with file(GENERATE) command which is like configure_file but works with generator expressions:

file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/mytarget_strip.cmake
     CONTENT "execute_process(COMMAND strip $<TARGET_FILE:mytarget>)")

install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/mytarget_strip.cmake)

Note, that the approach with file(GENERATE) still doesn't work with multi-configuration generators: CMake requires filename for OUTPUT clause to be unique between the configurations. One may "fix" that with

file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/mytarget_strip.cmake_$<CONFIG>
     CONTENT "execute_process(COMMAND strip $<TARGET_FILE:mytarget>)")

install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/mytarget_strip.cmake_${CMAKE_BUILD_TYPE})

but this still won't work: in multi-configuration generators CMAKE_BUILD_TYPE is evaluated to empty string.

(Replacing ${CMAKE_BUILD_TYPE} with $<CONFIG> in install(SCRIPT) command would work only in CMake 3.14 and after, but in these versions the whole file(GENERATE) is not needed and one may just use the very first snippet.)

like image 157
Tsyvarev Avatar answered Nov 02 '22 17:11

Tsyvarev


You can try to use/re-enable the < v3.0 behaviour.

cmake_policy(SET CMP0026 OLD)

See cmake-policies

like image 38
Th. Thielemann Avatar answered Nov 02 '22 17:11

Th. Thielemann