如何在CMake文件中添加链接器或编译标志?

sol*_*lti 196 c++ cmake

我正在使用arm-linux-androideabi-g++编译器.当我尝试编译一个简单的"你好,世界!" 程序编译好.当我通过在该代码中添加一个简单的异常处理来测试它时它也可以工作(添加之后-fexceptions..我猜它默认是禁用的).

这适用于Android设备,我只想使用CMake,而不是ndk-build.

例如 - first.cpp

#include <iostream>

using namespace std;

int main()
{
   try
   {
   }
   catch (...)
   {
   }
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

./arm-linux-androideadi-g++ -o first-test first.cpp -fexceptions

它没有问题......

问题 ...我试图用CMake文件编译文件.

我想添加-fexceptions标志.我试过了

set (CMAKE_EXE_LINKER_FLAGS -fexceptions ) or set (CMAKE_EXE_LINKER_FLAGS "fexceptions" )
Run Code Online (Sandbox Code Playgroud)

set ( CMAKE_C_FLAGS "fexceptions")
Run Code Online (Sandbox Code Playgroud)

它仍然显示错误.

Off*_*rmo 227

假设您要添加这些标志(最好将它们声明为常量):

SET(GCC_COVERAGE_COMPILE_FLAGS "-fprofile-arcs -ftest-coverage")
SET(GCC_COVERAGE_LINK_FLAGS    "-lgcov")
Run Code Online (Sandbox Code Playgroud)

有几种方法可以添加它们:

  1. 最简单的(不干净,但简单方便,只适用于编译标志,C&C++一次):

    add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
    
    Run Code Online (Sandbox Code Playgroud)
  2. 附加到相应的CMake变量:

    SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")
    SET(CMAKE_EXE_LINKER_FLAGS  "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用目标属性,参见 doc CMake编译标志目标属性,需要知道目标名称.

    get_target_property(TEMP ${THE_TARGET} COMPILE_FLAGS)
    if(TEMP STREQUAL "TEMP-NOTFOUND")
      SET(TEMP "") # Set to empty string
    else()
      SET(TEMP "${TEMP} ") # A space to cleanly separate from existing content
    endif()
    # Append our values
    SET(TEMP "${TEMP}${GCC_COVERAGE_COMPILE_FLAGS}" )
    set_target_properties(${THE_TARGET} PROPERTIES COMPILE_FLAGS ${TEMP} )
    
    Run Code Online (Sandbox Code Playgroud)

现在我使用方法2.

  • @leinaD_natipaC:[官方文档](http://www.cmake.org/cmake/help/v3.0/command/add_definitions.html)说:_这个命令可以用来添加任何标志,但它的目的是为了添加预处理器定义_.我想这就是原因. (13认同)
  • 为什么add_definitions()不干净? (4认同)
  • 虽然这是公认的答案,但它确实显示了非常旧的 CMAKE 风格,请参阅 @vitaut 的答案,了解如何根据编译时参数构建任何新的 CMAKE 代码 (4认同)
  • `string(APPEND CMAKE_EXE_LINKER_FLAGS "new_value")` 比 `set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} new_value")` 更短、更清晰 (2认同)
  • 过时的建议 (2认同)

vit*_*aut 146

在较新版本的CMake中,您可以分别使用target_compile_options和设置单个目标的编译器和链接器标志target_link_libraries(是的,后者也设置链接器选项):

target_compile_options(first-test PRIVATE -fexceptions)
Run Code Online (Sandbox Code Playgroud)

这种方法的优点是你可以控制选项传播到依赖于这个PUBLIC和/的其他目标PRIVATE.

从CMake 3.13开始,您还可以使用target_link_options添加链接器选项,使意图更清晰.

  • 哦,`target_link_libraries`我错过了doc的那一部分:"指定在链接给定目标时使用的库**或标志**." 谢谢. (9认同)
  • 最近添加的内容:CMake 3.13引入了[`target_link_options`](https://cmake.org/cmake/help/latest/command/target_link_options.html#command:target_link_options)作为指定链接器标记的更简洁方法。您将来应该避免将“ target_link_libraries”用于链接器标志,而应改用“ target_link_options”。 (3认同)
  • 我试图使用它:`target_compile_options(main_static PRIVATE --static)`但它似乎不起作用,任何想法为什么? (2认同)
  • `-static`可能是一个链接器,而不是编译器选项.尝试将其传递给`target_link_libraries`. (2认同)
  • 还有 [add_compile_options](https://cmake.org/cmake/help/v3.0/command/add_compile_options.html) - 见 /sf/ask/2765103701/ -options-and-setcmake-cxx-flags 和最近的 [add_link_options](https://cmake.org/cmake/help/v3.13/command/add_link_options.html) (2认同)
  • @BruceAdams 但是请永远不要在现代基于目标的 CMake 中使用它们。 (2认同)

sak*_*kra 40

尝试设置变量CMAKE_CXX_FLAGS而不是CMAKE_C_FLAGS:

set (CMAKE_CXX_FLAGS "-fexceptions")
Run Code Online (Sandbox Code Playgroud)

该变量CMAKE_C_FLAGS仅影响C编译器,但您正在编译C++代码.

添加标志CMAKE_EXE_LINKER_FLAGS是多余的.

  • -DCMAKE_CXX_FLAGS =" - fexceptions"=和"之间不应该有空格 (8认同)
  • 我解决了这个问题,但不是一个好的方法,它是一个糟糕的解决方法..我在命令行中创建了-DCMAKE_CXX_FLAGS =" - fexceptions".由于某种原因,cmake没有从.cmake文件中读取标志.:(谢谢你sakra你的答案.. (3认同)

Joh*_*ane 5

指定特定于工具链的选项的首选方法是使用 CMake 的工具链工具。这确保了以下各项之间的清晰划分:

  • 关于如何将源文件组织成目标的说明——用CMakeLists.txt文件表示,完全与工具链无关;和
  • 应如何配置某些工具链的详细信息——分成 CMake 脚本文件,可由项目的未来用户扩展,可扩展。

理想情况下,您的CMakeLists.txt文件中不应该有编译器/链接器标志——即使在if/endif块中。并且您的程序应该使用默认工具链(例如 GNU/Linux 上的 GCC 或 Windows 上的 MSVC)为本地平台构建,没有任何额外的标志。

添加工具链的步骤:

  1. 使用全局工具链设置创建一个文件,例如arm-linux-androideadi-gcc.cmake

    set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
    set(CMAKE_CXX_FLAGS_INIT "-fexceptions")
    
    Run Code Online (Sandbox Code Playgroud)

    (您可以在此处找到一个示例 Linux 交叉编译工具链文件。)

  2. 当您想使用此工具链生成构建系统时,请CMAKE_TOOLCHAIN_FILE在命令行中指定参数:

    set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
    set(CMAKE_CXX_FLAGS_INIT "-fexceptions")
    
    Run Code Online (Sandbox Code Playgroud)

    (注意:您不能使用相对路径。)

  3. 正常构建:

    mkdir android-arm-build && cd android-arm-build
    cmake -DCMAKE_TOOLCHAIN_FILE=$(pwd)/../arm-linux-androideadi-gcc.cmake ..
    
    Run Code Online (Sandbox Code Playgroud)

工具链文件使交叉编译更容易,但它们还有其他用途:

  • 一般来说,在 CMake 中,变量 CMAKE_&lt;LANG&gt;_FLAGS[_&lt;CONFIG&gt;]` 是由构建应用程序/库的客户端设置的。它们永远不应该以编程方式设置。附加,很少。 (2认同)