Передача параметров компилятора cmake

Я знаю, как передать параметры компилятора с помощью команды cmake

set(CMAKE_CXX_FLAGS "-Wall -Wno-dev -Wl,-rpath=/home/abcd/libs/")

Также есть ли способ передать параметры из командной строки, которые переопределят параметры CMakeList.txt, что-то вроде -

cmake -Wl,-rpath=/home/abcd/newlibs/ path/to/CMakeLists.txt

или же

cmake -D CMAKE_CXX_FLAGS="-Wno-dev -Wl,-rpath=/home/abcd/libs/" path/to/CMakeLists.txt

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

6 ответов

Да, вы можете добавить параметры компилятора и компоновщика. Но есть две вещи, которые вы должны различать в CMake: первый вызов для генерации среды сборки и все последовательные вызовы для повторной генерации этой среды сборки после изменений в вашем CMakeList.txt файлы или зависимости.

Вот некоторые из возможностей (исключая более сложные варианты набора инструментов):

Добавить флаги компилятора

  1. Исходный контент из кэша CMAKE_CXX_FLAGS переменная представляет собой комбинацию CMAKE_CXX_FLAGS_INIT устанавливается самим CMake во время обнаружения ОС / цепочки инструментов и всего, что установлено в CXXFLAGS переменная окружения. Таким образом, вы можете сначала позвонить:

    cmake -E env CXXFLAGS="-Wall" cmake ..
    
  2. Позже CMake будет ожидать, что пользователь изменяет CMAKE_CXX_FLAGS кэшированная переменная напрямую для добавления вещей, например, с помощью редактора, такого как ccmake совершить с CMake.

  3. Вы можете легко представить свой собственный тип сборки, например ALL_WARNINGS, Отдельные части типа сборки добавляются:

     cmake -DCMAKE_CXX_FLAGS_ALL_WARNINGS:STRING="-Wall" -DCMAKE_BUILD_TYPE=ALL_WARNINGS ..
    

Добавить флаги компоновщика

Параметры компоновщика более или менее эквивалентны параметрам компилятора. Просто имена переменных CMake зависят от типа цели (EXE, SHARED или же MODULE).

  1. CMAKE_EXE_LINKER_FLAGS_INIT, CMAKE_SHARED_LINKER_FLAGS_INIT или же CMAKE_MODULE_LINKER_FLAGS_INIT в сочетании с переменной среды LDFLAGS в CMAKE_EXE_LINKER_FLAGS, CMAKE_SHARED_LINKER_FLAGS а также CMAKE_MODULE_LINKER_FLAGS,

    Так что вы можете, например, позвонить:

    cmake -E env LDFLAGS="-rpath=/home/abcd/libs/" cmake ..
    
  2. Смотри выше.

  3. Части, относящиеся к типу сборки, прилагаются:

    cmake -DCMAKE_SHARED_LINKER_FLAGS_MY_RPATH:STRING="-rpath=/home/abcd/libs/" -DCMAKE_BUILD_TYPE=MY_RPATH ..
    

альтернативы

Просто имейте в виду, что CMake предоставляет специальную переменную для установки флагов компилятора / компоновщика независимо от платформы. Так что вам не нужно знать конкретную опцию компилятора / компоновщика.

Вот некоторые примеры:

  • CMAKE_CXX_STANDARD
  • CMAKE_POSITION_INDEPENDENT_CODE
  • CMAKE_BUILD_RPATH
  • CMAKE_INSTALL_RPATH_USE_LINK_PATH

К сожалению, для уровня предупреждения компилятора пока нет

Рекомендации

Мой ответ призван доказать одно:

Параметры командной строки, такие как CMAKE_C_FLAGS а также CMAKE_CXX_FLAGS только добавлять и никогда не перезаписывать.

Вот оно.

Подготовить файлы в папке hello_world

Привет

#include <stdio.h>


int main(int argc, char* argv[]) {
    printf("Hello World!\n");
#ifdef DEFINED_IN_CMAKELISTS
    printf("You are here because you defined DEFINED_IN_CMAKELISTS in CMakeLists and it is not overwritten.\n");
#else
    printf("You are here because CLI CMAKE_C_FLAGS overwrote DEFINED_IN_CMAKELISTS, or you have NOT defined DEFINED_IN_CMAKELISTS.\n");
#endif 
#ifdef DEFINED_IN_CLI
    printf("You are here because you defined DEFINED_IN_CLI when running cmake -DCMAKE_C_FLAGS.\n");
#else
    printf("You are here because you have NOT defined DEFINED_IN_CLI when running cmake -DCMAKE_C_FLAGS.\n");
#endif // #ifdef DEFINED_IN_CLI
    return 0;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1 FATAL_ERROR)
project(Hello)

set(HELLO_SRCS Hello.c)

add_executable(Hello ${HELLO_SRCS})

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDEFINED_IN_CMAKELISTS")

Создание файлов CMake

$ mkdir _build && cd _build && cmake ..
-- The C compiler identification is AppleClang 11.0.3.11030032
-- The CXX compiler identification is AppleClang 11.0.3.11030032
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/me/Desktop/_dev/playground/cmake/hello_world/_build

Сделать и запустить

$ make
Scanning dependencies of target Hello
[ 50%] Building C object CMakeFiles/Hello.dir/Hello.c.o
[100%] Linking C executable Hello
[100%] Built target Hello
$ ./Hello
Hello World!
You are here because you defined DEFINED_IN_CMAKELISTS in CMakeLists and it is not overwritten.
You are here because you have NOT defined DEFINED_IN_CLI when running cmake -DCMAKE_C_FLAGS.

Определите новые параметры компилятора из командной строки

$ cmake -DCMAKE_C_FLAGS="-DDEFINED_IN_CLI" ..
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/me/Desktop/_dev/playground/cmake/hello_world/_build

Сделать и запустить

$ make
[ 50%] Building C object CMakeFiles/Hello.dir/Hello.c.o
[100%] Linking C executable Hello
[100%] Built target Hello
$ ./Hello 
Hello World!
You are here because you defined DEFINED_IN_CMAKELISTS in CMakeLists and it is not overwritten.
You are here because you defined DEFINED_IN_CLI when running cmake -DCMAKE_C_FLAGS.

Вывод

Из приведенного выше теста вы можете видеть, что даже без буквального добавления, используя что-то вроде -DCMAKE_C_FLAGS="${CMAKE_C_FLAGS} -DDEFINED_IN_CLI", CMake добавляет определения препроцессора CLI к другим определениям в CMakeLists.txt.

cmake -D CMAKE_CXX_FLAGS="-Wno-dev -Wl,-rpath=/home/abcd/libs/" path/to/CMakeLists.txt

это должно сработать, проблема в том, что если вы найдёте пакет, который также изменяет CMAKE_CXX_FLAGS, то он будет работать не только частично.

Возможно, это сработает -

cmake -DCMAKE_CXX_FLAGS="$(CMAKE_CXX_FLAGS) -DYOUR_CUSTOM_DEFINE=1" <rest of original cmake cmdline>

как упомянул выше Томаз. -м

Большинство ответов здесь действительны, но я также наткнулся на то, как пройтиCMAKE_CXX_FLAGS и добавьте каталог include с пробелом в нем (Windows).

Очевидно, если вы запустите этот аргумент из командной строки - вам нужно быть особенно осторожным с цитатой (см. Также здесь)

cmake ... -DCMAKE_CXX_FLAGS="-fms-compatibility-version=19.00 --target=i686--windows -X -I """C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um""" "

Итак, если путь включения содержит пробелы, и это нужно указать в кавычках, но вам также нужно указать CMAKE_CXX_FLAGS, который заканчивается начальной цитатой с одинарной кавычки ("), и всякий раз, когда вам нужна цитата, вы помещаете вместо нее три символа кавычки. (""")

В целом это немного странно. Потребовалось время, чтобы понять это.

Я просто использую оператор $ENV() для получения переменной окружения, например, в CMakeLists.txt:

      add_compile_options($ENV{MY_CXXFLAG})

Единственная проблема заключается в том, что $ENV() читается только на этапе конфигурации, поэтому cmake не видит настройки среды на текущем этапе сборки. Но повторная настройка запускается измененными файлами cmake, поэтому я просто использую touchдля имитации изменения. Вот пример командной строки:

      touch CMakeLists.txt && MY_CXXFLAG="-D DEBUG" cmake --build build --config Debug

или какие другие варианты вы используете. В этом простом примере все еще есть некоторые причуды со строкой флага переменной среды, например, более одной опции. Но не должно быть большой проблемы с обработкой строк в CMakeLists.txt, чтобы украсить это.

Другие вопросы по тегам