Как изменить переменные среды, переданные в пользовательскую цель CMake?

Возможно, я упускаю что-то очевидное, но я не могу понять, как явно установить переменные среды, которые могут видеть процессы, запускаемые через add_custom_target(),

Я попробовал следующее:

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

К сожалению, %PATH% переменная среды кажется неизменной somecommand, (Я создал Gist, который воспроизводит проблему здесь.)

Что я делаю неправильно?

4 ответа

Решение

Портативный способ установки переменных среды для пользовательской цели - использовать команду режима командной строки CMake. env:

env [--unset=NAME]... [NAME=VALUE]... COMMAND [ARG]...
Run command in a modified environment.

Например:

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

Также см. Режим инструмента командной строки.

Вы устанавливаете переменную среды на шаге настройки, но команда указана для add_custom_target выполняется на этапе сборки. См. Также CMake FAQ: Как я могу получить или установить переменные окружения?

[...]
переменные среды SET в CMakeLists.txt действуют только для самого cmake (времяконфигурирования), поэтому вы не можете использовать этот метод для установки переменной окружения, которая может потребоваться пользовательской команде (времясборки). Запрет поддержки переменных окружения различными командами CMake (например, add_custom_command()(в настоящее время еще не поддерживается), приемлемый обходной путь может заключаться в том, чтобы вместо этого вызывать сценарии оболочки, которые обертывают команды для выполнения.

В настоящее время add_custom_target (и другие команды, которые определяют действия для этапа сборки, например add_custom_command) не поддерживает простую настройку переменных среды. Как указано в этом сообщении об ошибке, для установки значения переменной без пробелов в Linux вы можете добавить команду с предложениями "VAR=VAL". Для общих случаев вы можете подготовить скрипт- обертку, который настраивает среду и запускает реальную команду:

В 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...
)

В 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...
)

Если значение переменной зависит от конфигурации, вы можете настроить скрипт оболочки с помощью configure_file,

ОБНОВЛЕНИЕ:

Как отмечает @sakra, env инструментальный режим cmake Исполняемый файл может быть использован в качестве сценария оболочки:

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

Этот способ доступен с CMake 3.2.

Поздний ответ на этот вопрос, но, возможно, это кому-то поможет. Мы используем оператор && для этого в наших файлах cmake в Windows.

set(MY_COMMAND set "PATH=C:\\some\\path\;%PATH%"&&
        somecommand)

add_custom_target(TARGET newtarget COMMAND ${MY_COMMAND})

Обратите внимание, что перед && нельзя ставить пробел (по причинам, которые я не совсем понимаю). Кроме того, здесь очень сложно иметь дело с пробелами, поэтому я не знаю, правильно ли я понимаю, если в c:\some\path есть пробелы. Это работает, если в исходном пути есть пробелы.

Команда работает для меня

      add_custom_target(
    run
    DEPENDS ${PROJECT_NAME}
    COMMAND ASAN_OPTIONS=alloc_dealloc_mismatch=0 ./${PROJECT_NAME}
)
Другие вопросы по тегам