Передача параметров компилятора 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
файлы или зависимости.
Вот некоторые из возможностей (исключая более сложные варианты набора инструментов):
Добавить флаги компилятора
Исходный контент из кэша
CMAKE_CXX_FLAGS
переменная представляет собой комбинациюCMAKE_CXX_FLAGS_INIT
устанавливается самим CMake во время обнаружения ОС / цепочки инструментов и всего, что установлено вCXXFLAGS
переменная окружения. Таким образом, вы можете сначала позвонить:cmake -E env CXXFLAGS="-Wall" cmake ..
Позже CMake будет ожидать, что пользователь изменяет
CMAKE_CXX_FLAGS
кэшированная переменная напрямую для добавления вещей, например, с помощью редактора, такого какccmake
совершить с CMake.Вы можете легко представить свой собственный тип сборки, например
ALL_WARNINGS
, Отдельные части типа сборки добавляются:cmake -DCMAKE_CXX_FLAGS_ALL_WARNINGS:STRING="-Wall" -DCMAKE_BUILD_TYPE=ALL_WARNINGS ..
Добавить флаги компоновщика
Параметры компоновщика более или менее эквивалентны параметрам компилятора. Просто имена переменных CMake зависят от типа цели (EXE
, SHARED
или же MODULE
).
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 ..
Смотри выше.
Части, относящиеся к типу сборки, прилагаются:
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, чтобы украсить это.