传递编译器选项cmake

inf*_*ged 29 cmake

我知道如何使用cmake命令传递编译器选项

set(CMAKE_CXX_FLAGS "-Wall -Wno-dev -Wl,-rpath=/home/abcd/libs/")
Run Code Online (Sandbox Code Playgroud)

是否还有任何方法可以从命令行传递选项,这将覆盖CMakeList.txt选项,类似于 -

cmake -Wl,-rpath=/home/abcd/newlibs/ path/to/CMakeLists.txt
Run Code Online (Sandbox Code Playgroud)

要么

cmake -D CMAKE_CXX_FLAGS="-Wno-dev -Wl,-rpath=/home/abcd/libs/" path/to/CMakeLists.txt
Run Code Online (Sandbox Code Playgroud)

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

Flo*_*ian 29

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

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

附加编译器标志

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

    cmake -E env CXXFLAGS="-Wall" cmake ..
    
    Run Code Online (Sandbox Code Playgroud)
  2. 之后CMake会期望用户CMAKE_CXX_FLAGS直接修改缓存变量以附加内容,例如使用像ccmakeCMake 一样的编辑器.

  3. 您可以轻松地介绍自己的构建类型ALL_WARNINGS.构建类型特定部分附加:

     cmake -DCMAKE_CXX_FLAGS_ALL_WARNINGS:STRING="-Wall" -DCMAKE_BUILD_TYPE=ALL_WARNINGS ..
    
    Run Code Online (Sandbox Code Playgroud)

附加链接器标志

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

  1. CMAKE_EXE_LINKER_FLAGS_INIT,CMAKE_SHARED_LINKER_FLAGS_INITCMAKE_MODULE_LINKER_FLAGS_INIT不与环境现状变量结合LDFLAGSCMAKE_EXE_LINKER_FLAGS,CMAKE_SHARED_LINKER_FLAGSCMAKE_MODULE_LINKER_FLAGS.

    所以你可以打电话:

    cmake -E env LDFLAGS="-rpath=/home/abcd/libs/" cmake ..
    
    Run Code Online (Sandbox Code Playgroud)
  2. 往上看.

  3. 附加构建类型特定部分:

    cmake -DCMAKE_SHARED_LINKER_FLAGS_MY_RPATH:STRING="-rpath=/home/abcd/libs/" -DCMAKE_BUILD_TYPE=MY_RPATH ..
    
    Run Code Online (Sandbox Code Playgroud)

备择方案

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

这里有些例子:

遗憾的是编译器的警告级别没有(尚未)

参考


kak*_*kyo 17

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

命令行选项像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;
}

Run Code Online (Sandbox Code Playgroud)

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")
Run Code Online (Sandbox Code Playgroud)

生成 CMake 文件

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")
Run Code Online (Sandbox Code Playgroud)

制作并运行

$ 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
Run Code Online (Sandbox Code Playgroud)
$ 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
Run Code Online (Sandbox Code Playgroud)

从命令行定义新的编译器选项

$ ./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.
Run Code Online (Sandbox Code Playgroud)

制作并运行

$ 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
Run Code Online (Sandbox Code Playgroud)
$ make
[ 50%] Building C object CMakeFiles/Hello.dir/Hello.c.o
[100%] Linking C executable Hello
[100%] Built target Hello
Run Code Online (Sandbox Code Playgroud)

结论

从上面的测试中,您可以看到即使没有使用类似的硬附加

-DCMAKE_C_FLAGS="${CMAKE_C_FLAGS} -DDEFINED_IN_CLI"
Run Code Online (Sandbox Code Playgroud)

,CMake 仍然将 CLI 选项附加到CMakeLists.txt.

  • 您的结论令人困惑:您说“即使没有硬附加...”,但在您使用的 CMakeLists.txt 中,它_字面上有行_ `set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDEFINED_IN_CMAKELISTS")`。我已经验证,如果您将此行更改为 `set(CMAKE_C_FLAGS "-DDEFINED_IN_CMAKELISTS")`,则 `cmake -DCMAKE_C_FLAGS="-DDEFINED_IN_CLI" ..` 不再按预期工作。因此,您的结论应该是:“如果项目的 CMakeLists.txt 文件是以这种特定方式设置的,那么 `-DCMAKE_C_FLAGS=` 就可以解决问题;但如果项目的 CMakeLists.txt 不同,这可能不起作用。” (3认同)
  • 超级答案。这个应该被评为#1。 (2认同)

Tom*_*ava 5

cmake -D CMAKE_CXX_FLAGS="-Wno-dev -Wl,-rpath=/home/abcd/libs/" path/to/CMakeLists.txt
Run Code Online (Sandbox Code Playgroud)

这应该可以工作,问题是,如果您find_package()还更改了的某些软件包CMAKE_CXX_FLAGS,那么它不仅会部分工作。

  • 好吧,我也猜想也是如此。但是,如何将一个选项附加到现有选项上。在这里“ =”不会起作用。 (3认同)

小智 5

也许这会起作用 -

cmake -DCMAKE_CXX_FLAGS="$(CMAKE_CXX_FLAGS) -DYOUR_CUSTOM_DEFINE=1" <rest of original cmake cmdline>
Run Code Online (Sandbox Code Playgroud)

就像上面提到的托马兹。-m