传递编译器选项cmake

时间:2017-05-31 12:02:01

标签: 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

我的主要问题是我想知道如何附加标志以及如何从命令行覆盖现有的编译器标志。

5 个答案:

答案 0 :(得分:21)

是的,您可以附加编译器和链接器选项。但是你需要在CMake中区分两件事:第一次调用生成构建环境,以及在更改CMakeList.txt文件或依赖项后重新生成构建环境的所有连续调用。

以下是一些可能性(不包括更复杂的toolchain变体):

附加编译器标志

  1. 缓存的CMAKE_CXX_FLAGS变量的初始内容是在OS /工具链检测期间由CMake自身设置的CMAKE_CXX_FLAGS_INITCXXFLAGS环境变量中设置的内容的组合。所以你最初可以打电话:

    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 ..
    
  4. 附加链接标志

    链接器选项或多或少等同于编译器选项。只是CMake的变量名称取决于目标类型(EXESHAREDMODULE)。

    1. CMAKE_EXE_LINKER_FLAGS_INITCMAKE_SHARED_LINKER_FLAGS_INITCMAKE_MODULE_LINKER_FLAGS_INIT确实与环境变量LDFLAGS合并为CMAKE_EXE_LINKER_FLAGSCMAKE_SHARED_LINKER_FLAGS和{{ 3}}

      所以你可以打电话:

      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 ..
      
    4. 替代

      请注意,CMake确实提供了特殊的变量来以独立于平台的方式设置编译器/链接器标志。因此,您不需要知道特定的编译器/链接器选项。

      以下是一些例子:

      不幸的是,编译器的警告级别(CMAKE_INSTALL_RPATH_USE_LINK_PATH

      没有

      参考

答案 1 :(得分:3)

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

这应该可行,问题是如果你find_package()一些包也改变了CMAKE_CXX_FLAGS,那么它不仅会部分工作。

答案 2 :(得分:2)

我的答案旨在证明一件事:

CMAKE_C_FLAGSCMAKE_CXX_FLAGS之类的命令行选项始终附加,并且永远不会覆盖。

来了。

准备文件夹hello_world下的文件

hello.c

#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中。

答案 3 :(得分:1)

也许这行得通-

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

就像上面提到的Tomaz一样。 -m

答案 4 :(得分:0)

这里的大多数答案都是有效的,但是我也偶然发现如何通过 CMAKE_CXX_FLAGS并添加包含目录的目录(在Windows中)。

显然,如果您从命令行运行该参数-您需要格外小心加引号(另请参见here

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""" "

因此,如果include路径包含空格,则需要将其引号,但您还需要引号CMAKE_CXX_FLAGS,最后以单引号(")引号开始,无论何时,需要引用-您放置三个引号字符来代替。 ("""

总体来说有点奇怪。花了一段时间才能弄清楚。