cmake - 全局链接器标志设置(针对目录中的所有目标)
cmake - Global linker flag setting (for all targets in directory)
我想将链接器标志传递给我项目中的所有子项目(子目录 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 以使用更多 "modern" 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_libraries
命令在目标基础上添加链接器标志,但找不到其他任何东西。
我尝试使用 CMAKE_SHARED_LINKER_FLAGS
(以及 exe、模块等的相应 var)变量,但没有成功。
更新:
事实证明这与 cmake 版本无关,使用 CMAKE_CXX_FLAGS_XXX
变量可以正常工作,除了第一个 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 .
您的问题are/were与特定 CMake 版本无关。
CMake 中所有 linker/compiler 标志变量都是一样的。因为这些变量是缓存变量并使用 project()
/enable_language()
命令设置(详细信息请参阅 ),您要么必须
- 在
project()
命令 之前用 set(... CACHE ...)
预填充缓存
- 一般使用
set(... CACHE ... FORCE)
到force/overwrite
- 在
project()
命令之后移动 set()
以隐藏或附加到缓存变量
这里是 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
文件中的所有相应目标(参见 and ).
第一个变体的缺点是它实际上只是初始值。第二个和第三个变体很可能需要一个 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()
命令中。
我想将链接器标志传递给我项目中的所有子项目(子目录 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 以使用更多 "modern" 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_libraries
命令在目标基础上添加链接器标志,但找不到其他任何东西。
我尝试使用 CMAKE_SHARED_LINKER_FLAGS
(以及 exe、模块等的相应 var)变量,但没有成功。
更新:
事实证明这与 cmake 版本无关,使用 CMAKE_CXX_FLAGS_XXX
变量可以正常工作,除了第一个 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 .
您的问题are/were与特定 CMake 版本无关。
CMake 中所有 linker/compiler 标志变量都是一样的。因为这些变量是缓存变量并使用 project()
/enable_language()
命令设置(详细信息请参阅
- 在
project()
命令 之前用 - 一般使用
set(... CACHE ... FORCE)
到force/overwrite - 在
project()
命令之后移动set()
以隐藏或附加到缓存变量
set(... CACHE ...)
预填充缓存
这里是 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
文件中的所有相应目标(参见
第一个变体的缺点是它实际上只是初始值。第二个和第三个变体很可能需要一个 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()
命令中。