cmake - 全局链接器标志设置(适用于目录中的所有目标)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cmake - 全局链接器标志设置(适用于目录中的所有目标)相关的知识,希望对你有一定的参考价值。

我想将链接器标志传递给我项目中的所有子项目(子目录CMakeList)。

在切换到新的cmake 3.3之前,我使用了以下代码(cmake 3.2),它运行良好,为编译和链接添加了标志:

set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -stdlibc++")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -stdlibc++")

使用cmake 3.3,这不再起作用,只为编译步骤设置标志。我更新了CMakeList以使用更“现代”的cmake语法:

set(MY_DEBUG_OPTIONS -g -stdlib=libstdc++ -Wfatal-errors)
set(MY_RELEASE_OPTIONS -O3 -stdlib=libstdc++ -Wfatal-errors)

add_compile_options(
  "$<$<CONFIG:DEBUG>:${MY_DEBUG_OPTIONS}>"
  "$<$<CONFIG:RELEASE>:${MY_RELEASE_OPTIONS}>")

这为所有子项目设置了编译标志,是否有类似的方法为链接器标志执行此操作?我知道可以使用target_link_librariescommand在目标基础上添加链接器标志,但找不到任何其他内容。

我尝试使用CMAKE_SHARED_LINKER_FLAGS(和相应的var for exe,module,..)变量没有成功。

更新:

事实证明,这与cmake版本无关,使用CMAKE_CXX_FLAGS_XXXvariables正常工作,除了第一个make命令。如果第二次运行make(在CmakeList中进行修改),则会显示标志。

我想我在使用简单的CMakeList进行测试时找到了一个解决方案:如果在project命令之后声明了标志,它就会按预期工作。我不知道这是cmake本身的要求还是仅仅是一种奇怪的行为。

cmake_minimum_required (VERSION 3.2)

set(PROJECT Test_Project)

# Not working (on first run)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -stdlib=libstdc++ -Wfatal-errors")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -stdlib=libstdc++ -Wfatal-errors")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -stdlib=libstdc++ -Wfatal-errors")

project(${PROJECT})

# Declare here instead...

add_executable(Test test.cpp)

MESSAGE( STATUS "Config flags : " ${CMAKE_CXX_FLAGS_RELEASE})

使用:

cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release .
答案

您的问题与特定的CMake版本无关。

对于CMake中的所有链接器/编译器标志变量,它是相同的。因为这些变量是缓存变量并使用project() / enable_language()命令设置(详细信息请参阅here),您要么必须

  1. set(... CACHE ...)命令之前使用project()预填充缓存
  2. 通常使用set(... CACHE ... FORCE)强制/覆盖
  3. set()命令之后移动project()以隐藏或附加到缓存的变量

以下是CMAKE_EXE_LINKER_FLAGS显示所有三种变体的示例:

的CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

# 1. prefill
#set(CMAKE_EXE_LINKER_FLAGS "-Wl,-Map=output.map" CACHE INTERNAL "")

project(Test_Project CXX)

# 2. force
set(CMAKE_EXE_LINKER_FLAGS "-Wl,-Map=output.map" CACHE INTERNAL "" FORCE)

# 3. hide
#set(CMAKE_EXE_LINKER_FLAGS "-Wl,-Map=output.map")
# 3. or append
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=output.map")

# TODO: Remove, this is just for testing
file(WRITE "foo.cpp" "int main() {}") 

add_executable(${PROJECT_NAME} foo.cpp)

无论这些变量的值是在任何给定的CMakeLists.txt文件的末尾,都将应用于相同CMakeLists.txt文件中的所有相应目标作为默认值(请参阅CMAKE - setting compile flags for librariesWhat's the CMake syntax to set and use variables?)。

第一个变体的缺点是它实际上只是初始值。第二个和第三个变体很可能需要围绕它的if (CMAKE_COMPILER_IS_GNUCXX),所以我更喜欢第二个变体将这些设置移动到它自己的初始缓存文件:

MyGNUSettings.cmake

set(CMAKE_CXX_FLAGS "-stdlib=libstdc++ -Wfatal-errors" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS_DEBUG "-g" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE "-O3" CACHE INTERNAL "" FORCE)
set(CMAKE_EXE_LINKER_FLAGS "-Wl,-Map=output.map" CACHE INTERNAL "" FORCE)

使用例如

cmake -G "Unix Makefiles" -C MyGNUSettings.cmake -DCMAKE_BUILD_TYPE=Release  .

是的 - 对于全局和每个编译器设置 - 我更喜欢add_compile_options()命令的全局缓存变量。我认为add_compile_options()没有替换全局变量,它主要是为了防止人们在add_definitions()命令中放置编译器选项。

以上是关于cmake - 全局链接器标志设置(适用于目录中的所有目标)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 CMake 的 try_compile 函数中为 OpenMP 设置链接器标志

库中的 CMake 链接目录

如何使用 cmake 设置 g++ 的标志,以便 gprof 可以解散?

CMake:隐藏子目标的-WShadow全局编译标志

gcov 与 CMake 使用单独的构建目录

如何在 CMake 中为外部 INTERFACE_SOURCES 设置编译标志?