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


220

我正在使用arm-linux-androideabi-g++编译器。当我尝试编译一个简单的“ Hello,World!”时 程序可以编译良好。当我通过在该代码中添加简单的异常处理来对其进行测试时,它也可以工作(添加-fexceptions.. 后,我认为默认情况下它是禁用的)。

这是针对Android设备的,我只想使用CMake,而不是ndk-build

例如 - first.cpp

#include <iostream>

using namespace std;

int main()
{
   try
   {
   }
   catch (...)
   {
   }
   return 0;
}

./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" )

set ( CMAKE_C_FLAGS "fexceptions")

它仍然显示错误。


现在我遇到了同样的问题,并且正在尝试不同的方法。稍等一下,我发布答案。对于编译标志,有一种不干净但很简单的方法:add_definitions(“-truc”)
Offirmo 2012年

有关此问题的最新讨论(尤其是在使用CMake 3.x或更高版本的情况下):在CMake中设置通用编译标志的现代方法是什么?
ComicSansMS 2015年

如果你想瞄准配置链接标志rpath的然后看看具体的CMake rpath的命令gitlab.kitware.com/cmake/community/wikis/doc/cmake/...
加布里埃尔Devillers

Answers:


243

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

SET(GCC_COVERAGE_COMPILE_FLAGS "-fprofile-arcs -ftest-coverage")
SET(GCC_COVERAGE_LINK_FLAGS    "-lgcov")

有几种添加方式:

  1. 最简单的方法(不是干净的方法,但简单又方便,并且仅适用于一次编译标志,C和C ++):

    add_definitions(${GCC_COVERAGE_COMPILE_FLAGS})
  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}")
  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} )

现在我使用方法2。


4
为什么add_definitions()不干净?
leinaD_natipaC 2014年

14
@leinaD_natipaC:官方文档说:该命令可用于添加任何标志,但旨在添加预处理器定义。我认为这就是原因。
Benoit Blanchon 2014年

虽然这是一个确实表现出非常老的CMAKE风格的公认答案,但有关编译时间参数,应如何构造任何新的CMAKE代码,请参阅@vitaut的答案
Harald Scheirich

1
string(APPEND CMAKE_EXE_LINKER_FLAGS "new_value")set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} new_value")
血腥

165

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

target_compile_options(first-test PRIVATE -fexceptions)

这种方法的优点是,您可以通过PUBLIC和控制选项向其他目标的传播PRIVATE

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


2
我尝试使用它:target_compile_options(main_static PRIVATE --static)但是它似乎不起作用,知道为什么吗?
帕维尔Szczur

2
-static可能是一个链接器,而不是编译器选项。尝试将其传递给target_link_libraries
vitaut 2016年

9
哦,target_link_libraries我已经错过了文档的那一部分:“指定链接给定目标时要使用的库或标志。”。谢谢。
帕维尔Szczur

3
最近添加的内容:CMake 3.13 target_link_options作为一种更干净的方法来指定链接器标志。您应该避免以后再使用target_link_libraries链接器标志,target_link_options而应改用。
ComicSansMS


46

尝试设置变量CMAKE_CXX_FLAGS而不是CMAKE_C_FLAGS

set (CMAKE_CXX_FLAGS "-fexceptions")

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

将标志添加到CMAKE_EXE_LINKER_FLAGS是多余的。


我试过了,但仍然给出错误。是设置(CMAKE_CXX_FLAGS“ -fexceptions”)指定编译器标志的唯一方法。
solti 2012年

3
我解决了问题,但不是很好的解决方法..我在命令行中使-DCMAKE_CXX_FLAGS =“ -fexceptions”。由于某些原因,cmake无法从.cmake文件中读取标志。:( ..谢谢您sakra的回答..
solti 2012年

8
-DCMAKE_CXX_FLAGS =“ -fexceptions” =和“之间不应有空格
evandrix 2012年

关于您所说的内容:“由于某些原因,cmake不会从.cmake文件中读取标志。” 确保清除现有缓存。这可以通过在再次执行cmake之前从构建目录中删除所有内容来完成。
zaizen

1

您还可以使用LINK_FLAGS属性将链接器标志添加到特定目标:

set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " ${flag}")

如果要将此更改传播到其他目标,则可以创建要链接到的虚拟目标。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.