Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to modify environment variables passed to custom CMake target?

Perhaps I am missing something obvious, but I can't seem to figure out how to explicitly set environment variables that can be seen by processes launched through add_custom_target().

I tried the following:

set(ENV{PATH} "C:/Some/Path;$ENV{PATH}") add_custom_target(newtarget somecommand) 

Unfortunately, the %PATH% environment variable appears unchanged to somecommand. (I have set up a Gist that reproduces the problem here.)

What am I doing wrong?

like image 733
Nathan Osman Avatar asked Jan 27 '16 05:01

Nathan Osman


2 Answers

A portable way of setting environment variables for a custom target is to use CMake's command-line tool mode command env:

env [--unset=NAME]... [NAME=VALUE]... COMMAND [ARG]... 

Run command in a modified environment.

E.g.:

add_custom_target(newtarget ${CMAKE_COMMAND} -E env NAME=VALUE somecommand) 

Also see Command Line Tool Mode.

like image 137
sakra Avatar answered Sep 20 '22 07:09

sakra


You set environment variable at configuration step, but command specified for add_custom_target is executed at build step. See also CMake FAQ: How can I get or set environment variables?

[...]
environment variables SET in the CMakeLists.txt only take effect for cmake itself (configure-time), so you cannot use this method to set an environment variable that a custom command might need (build-time). Barring environment variable support by various CMake commands (e.g. add_custom_command(), currently not supported yet), an acceptable workaround may be to invoke shell scripts instead which wrap the commands to be executed.

Currently add_custom_target (and others commands, which define actions for build step, e.g. add_custom_command) doesn't support simple setting environment variables. As adviced in this bugreport, for set variable's value without spaces on Linux you may prepend command with "VAR=VAL" clauses. For general cases you may prepare wrapper script, which setups environment and run actual command:

On Windows:

wrapper.bat:

@ECHO OFF set PATH=C:\\Some\\Path;%PATH% %* 

CMakeLists.txt:

add_custom_target(...     COMMAND cmd /c ${CMAKE_CURRENT_SOURCE_DIR}/wrapper.bat <real_command> args... ) 

On Linux:

wrapper.sh:

export "PATH=/Some/Path:$PATH" eval "$*" 

CMakeLists.txt:

add_custom_target(...     COMMAND /bin/sh ${CMAKE_CURRENT_SOURCE_DIR}/wrapper.sh <real_command> args... ) 

If value of variable depends on configuration, you may configure wrapper script with configure_file.

UPDATE:

As noted by @sakra, env tool mode of cmake executable can be used as a wrapper script:

add_custom_target(...     COMMAND ${CMAKE_COMMAND} -E env "PATH=C:/Some/Path;$ENV{PATH}" <real_command> args... ) 

This way is available since CMake 3.2.

like image 27
Tsyvarev Avatar answered Sep 19 '22 07:09

Tsyvarev