Steve Lorimer
Steve Lorimer

Reputation: 28719

How can I use CMake to configure an environment variable to be used during the build?

I am using distcc to speed up building my C++ project.

I configure cmake to use distcc using the CMAKE_CXX_COMPILER_LAUNCHER variable:

set(CMAKE_CXX_COMPILER_LAUNCHER "distcc")

At times, some of the hosts in the distcc pool are not available, and thus, at build time, I want to use lsdistcc to find which hosts are currently available.

Below are my attempts to generate an environment variable, DISTCC_HOSTS, available at build time, of which distcc hosts are currently online.

I would like to do this in my cmake scripts, so that colleagues who use IDE's to generate and run the Makefiles when building vs those who use a command line all benefit from getting an up-to-date list of build hosts.

This is what I have so far:

I have a cmake script, distcc_hosts.cmake which finds the set of distcc hosts currently available, using lsdistcc, and sets an environment variable with the result:

distcc_hosts.cmake:

execute_process(
    COMMAND
        sh -c "lsdistcc $LSDISTCC_HOSTS | sed \"s/.*/&\\/8,lzo /g\" | tr -d '\n'"
    OUTPUT_VARIABLE
        DISTCC_HOSTS
    )

set(ENV{DISTCC_HOSTS} ${DISTCC_HOSTS})

I have configured this to run at build time using add_custom_target:

add_custom_target(distcc_hosts
    ALL
    COMMAND
        {CMAKE_COMMAND} -P ${CMAKE_SCRIPTS_DIR}/distcc_hosts.cmake
)

and I've created a dependency link so that it is run before everything else:

add_dependencies(my_core_target distcc_hosts)

This all works fine, in that it creates a phony target, distcc_hosts which runs my scripts etc:

generated Makfile:

CMakeFiles/distcc_hosts:
    /usr/bin/cmake -P /src/cmake/distcc_hosts.cmake

The problem that I'm having is that obviously the above command to run cmake executes in a subshell, and the exported environment variable ${DISTCC_HOSTS} exists only in that subshell.

So when the rest of the build commands run, ${DISTCC_HOSTS} is not set.

Ideally I would be able to eval a script, so that the parent environment is modified, or I could execute a command such as export DISTCC_HOSTS := $(shell lsdistcc ...).

Is there a way to run a command at build time, and set an environment variable made available to the rest of the build?

Upvotes: 1

Views: 1562

Answers (1)

starball
starball

Reputation: 52429

You can't do this with set($ENV{FOO} BAR). As per the docs:

This command affects only the current CMake process, not the process from which CMake was called, nor the system environment at large, nor the environment of subsequent build or test processes.

But you can use the environment field of a build preset. Here's a brief excerpt from the docs (please see the docs for full info):

An optional map of environment variables. The key is the variable name (which may not be an empty string), and the value is either null or a string representing the value of the variable.

To use a build preset, use the --preset flag in your cmake --build command invocation.

Upvotes: 1

Related Questions