Я пытаюсь создать настраиваемую команду, которая запускается с некоторыми переменными среды, такими как LDFLAGS, значение которых необходимо указать, если оно содержит пробелы:

LDFLAGS="-Lmydir -Lmyotherdir"

Я не могу найти способ включить этот аргумент в настраиваемую команду CMake из-за правил экранирования CMake. Вот что я пробовал до сих пор:

COMMAND LDFLAGS="-Ldir -Ldir2" echo blah VERBATIM)

Дает "LDFLAGS=\"-Ldir -Ldir2\"" echo blah

COMMAND LDFLAGS=\"-Ldir -Ldir2\" echo blah VERBATIM)

Дает LDFLAGS=\"-Ldir -Ldir2\" echo blah

Кажется, я либо цитирую всю строку, либо экранированные кавычки не разрешаются при использовании как части команды.

Я был бы признателен либо за использование буквальных двойных кавычек, либо за лучший способ установки переменных среды для команды. Обратите внимание, что я все еще использую CMake 2.8, поэтому у меня нет новой команды "env", доступной в версии 3.2.

Обратите внимание, что это не дубликат Когда помещать переменные в кавычки? поскольку ни один из этих методов цитирования не работает в данном конкретном случае.

14
Devin Lane 7 Сен 2016 в 14:21

4 ответа

Лучший ответ

Очевидный выбор - часто рекомендуемый при выходе за границы COMMAND, особенно со старыми версиями CMake - это использовать внешний скрипт.

Я просто хотел добавить несколько простых COMMAND вариантов, которые действительно работают и не нуждаются в оболочке, но, я должен признать, все еще частично зависят от платформы.

  • Один из примеров - поместить в переменную только указанную в кавычках часть:

    set(vars_as_string "-Ldir -Ldir2")
    add_custom_target(
        QuotedEnvVar
        COMMAND env LD_FLAGS=${vars_as_string} | grep LD_FLAGS
    )
    

    Что на самом деле избегает пробела, а не кавычек.

  • Другой пример - добавить его с экранированными кавычками в качестве правила запуска:

    add_custom_target(
        LauncherEnvVar
        COMMAND env | grep LD_FLAGS
    )
    set_target_properties(
        LauncherEnvVar 
        PROPERTIES RULE_LAUNCH_CUSTOM "env LD_FLAGS=\"-Ldir -Ldir2\""
    )
    

Изменить : добавлены примеры для нескольких аргументов в кавычках без необходимости экранирования кавычек.

  • Другой пример - «скрыть некоторую сложность» в функции и - если вы хотите добавить это ко всем своим пользовательским вызовам команд - использовать каталог global / RULE_LAUNCH_CUSTOM:

    function(set_env)
        get_property(_env GLOBAL PROPERTY RULE_LAUNCH_CUSTOM)
        if (NOT _env)
            set_property(GLOBAL PROPERTY RULE_LAUNCH_CUSTOM "env")
        endif()
        foreach(_arg IN LISTS ARGN)
            set_property(GLOBAL APPEND_STRING PROPERTY RULE_LAUNCH_CUSTOM " ${_arg}")
        endforeach()
    endfunction(set_env)
    
    set_env(LDFLAGS="-Ldir1 -Ldir2" CFLAGS="-Idira -Idirb")
    
    add_custom_target(
        MultipleEnvVar
        COMMAND env | grep -E 'LDFLAGS|CFLAGS'
    )
    

Альтернатива (для CMake> = 3.0)

  • Я думаю, то, что мы действительно ищем здесь (помимо cmake -E env ...), называется Аргумент скобки и разрешает любой символ без необходимости добавления обратной косой черты:

    set_property(
        GLOBAL PROPERTY 
            RULE_LAUNCH_CUSTOM [=[env LDFLAGS="-Ldir1 -Ldir2" CFLAGS="-Idira -Idirb"]=]
    )
    add_custom_target(
        MultipleEnvVarNew
        COMMAND env | grep -E 'LDFLAGS|CFLAGS'
    )
    

Ссылки

6
Community 23 Май 2017 в 12:30

Некоторые ребята предлагают использовать $ {CMAKE_COMMAND} и передавать ваш исполняемый файл в качестве аргумента, например:

COMMAND ${CMAKE_COMMAND} -E env "$(WindowsSdkDir)/bin/x64/makecert.exe" ...

Это сработало для меня.

0
Artyom Chirkov 19 Июн 2020 в 11:23

Вам понадобится три обратной косой черты. Мне это понадобилось недавно, чтобы получить определение препроцессора из PkgConfig и применить его к моим флагам C ++:

pkg_get_variable(SHADERDIR movit shaderdir)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSHADERDIR=\\\"${SHADERDIR}\\\"")
1
ulatekh 22 Май 2020 в 04:43

Хорошо, я удалил свой исходный ответ, так как вариант, предложенный @Florian, лучше. Для нескольких аргументов в кавычках требуется одна дополнительная настройка. Рассмотрим список переменных среды как таковых:

set(my_env_vars LDFLAGS="-Ldir1 -Ldir2" CFLAGS="-Idira -Idirb")

Чтобы получить желаемое расширение, преобразуйте его в строку, а затем замените ; пробелом.

set(my_env_string "${my_env_vars}") #produces LDFLAGS="...";CFLAGS="..."
string(REPLACE ";" " " my_env_string "${my_env_string}")

Затем вы можете перейти к блестящему ответу @Florian и добавить настраиваемое правило запуска. Если вам нужны точки с запятой в вашей строке, вам нужно сначала преобразовать их во что-то другое.

Затем вы можете перейти к блестящему ответу @Florian и добавить настраиваемое правило запуска. Если вам нужны точки с запятой в вашей строке, вам нужно сначала преобразовать их во что-то другое.…

set_target_properties(mytarget PROPERTIES RULE_LAUNCH_CUSTOM "${my_env_string}")

Конечно, это зависит от вашей оболочки.

Если подумать, мой исходный ответ приведен ниже, так как у меня также есть случай, когда у меня нет доступа к целевому имени.

set(my_env LDFLAGS=\"-Ldir -Ldir2" CFLAGS=\"-Idira -Idirb\")
add_custom_command(COMMAND sh -c "${my_env} grep LDFLAGS" VERBATIM)

Этот метод по-прежнему требует замены точек с запятой при преобразовании списка в строку.

0
Devin Lane 9 Сен 2016 в 05:04