cmake - 全局链接器标志设置(用于目录中的所有目标) [英] cmake - Global linker flag setting (for all targets in directory)

查看:162
本文介绍了cmake - 全局链接器标志设置(用于目录中的所有目标)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to pass linker flags to all sub-projects (sub-directory CMakeList) in my project.

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

Before switching to new cmake 3.3, I was using the following code (cmake 3.2) which was working well, adding flags for both compilation and linking :

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 语法:

With cmake 3.3 this no longer works and set the flags only for compilation step. I updated the CMakeList to use a more "modern" cmake syntax :

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_libraries 命令在目标基础上添加链接器标志,但找不到其他任何东西.

This set compilation flags for all sub-projects, is there a similar way of doing this for linker flags ? I know one can add linker flags on a target basis with target_link_librariescommand but can't find anything else.

我尝试使用 CMAKE_SHARED_LINKER_FLAGS(以及 exe、模块等的相应 var)变量但没有成功.

I tried using CMAKE_SHARED_LINKER_FLAGS (and corresponding var for exe, module,..) variable with no success.

更新:

事实证明,这与 cmake 版本无关,除了第一个 make 命令外,CMAKE_CXX_FLAGS_XXX 变量可以正常工作.如果第二次运行 make(在 CmakeList 中进行了修改),就会出现标志.

It turns out that this has nothing to do with cmake version, things work correctly with CMAKE_CXX_FLAGS_XXXvariables, except on first make command. If one run make a second time (with a modification in CmakeList), flags are presents.

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

I think I found a solution while testing with a simple CMakeList : if flags are declared after the project command it just work as expected. I don't know if it's a requirement from cmake itself or just a weird behavior.

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 版本无关.

Your problems are/were not related to a specific CMake version.

CMake 中的所有链接器/编译器标志变量都是一样的.因为这些变量是缓存变量并使用 project()/enable_language() 命令设置(详情请参阅 这里),你要么必须

It's the same for all linker/compiler flag variables in CMake. Because those variables are cached variables and set with the project()/enable_language() command (details see here), you either have to

  1. project() 命令之前用 set(... CACHE ...) 预填充缓存
  2. 一般使用set(... CACHE ... FORCE)来强制/覆盖
  3. set() 移动到 project() 命令之后以隐藏或附加到缓存的变量
  1. prefill the cache with set(... CACHE ...) before the project() command
  2. generally use the set(... CACHE ... FORCE) to force/overwrite
  3. move the set() after the project() command to hide or append to the cached variables

以下是 CMAKE_EXE_LINKER_FLAGS 的示例,显示了所有三个变体:

Here is an example for CMAKE_EXE_LINKER_FLAGS showing all three variants:

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 - 为库设置编译标志设置和使用变量的 CMake 语法是什么?).

Whatever the values of those variables are at the end of your any given CMakeLists.txt file will be applied to all corresponding targets in the same CMakeLists.txt file as defaults (see CMAKE - setting compile flags for libraries and What's the CMake syntax to set and use variables?).

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

The first variant has the disadvantage that it's really only the initial value. The second and third variant would most likely need an if (CMAKE_COMPILER_IS_GNUCXX) around it, so I prefer the second variant with moving those settings to its own initial-cache file:

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() 命令.

And yes - for the global and per compiler settings - I prefer the global cached variables over the add_compile_options() command. I think add_compile_options() haven't replaced the global variables, it was mainly introduced to prevent people putting compiler options in add_definitions() commands.

这篇关于cmake - 全局链接器标志设置(用于目录中的所有目标)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆