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_libraries
command but can't find anything else.
我尝试使用 CMAKE_SHARED_LINKER_FLAGS
(以及相应的 exe、模块等变量)变量,但没有成功.
I tried using CMAKE_SHARED_LINKER_FLAGS
(and corresponding var for exe, module,..) variable with no success.
更新:
事实证明这与 cmake 版本无关,使用 CMAKE_CXX_FLAGS_XXX
变量可以正常工作,除了第一个 make 命令.如果第二次运行 make
(在 CmakeList 中进行修改),则会出现标志.
It turns out that this has nothing to do with cmake version, things work correctly with CMAKE_CXX_FLAGS_XXX
variables, 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
- 在
project()
命令之前用set(... CACHE ...)
预填充缓存 - 一般使用
set(... CACHE ... FORCE)
来强制/覆盖 - 在
project()
命令之后移动set()
以隐藏或附加到缓存变量
- prefill the cache with
set(... CACHE ...)
before theproject()
command - generally use the
set(... CACHE ... FORCE)
to force/overwrite - move the
set()
after theproject()
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.
相关文章