C++ 如何使用 CMake 在特定构建配置中为特定目标设置特定编译器标志?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10199904/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:45:00  来源:igfitidea点击:

How can I set specific compiler flags for a specific target in a specific build configuration using CMake?

c++visual-c++cmake

提问by Billy ONeal

I've got a CMakeLists where I want to build some targets using the dynamic version of the C runtime, and some other targets using the static version.

我有一个 CMakeLists,我想在其中使用 C 运行时的动态版本构建一些目标,并使用静态版本构建其他一些目标。

Because this needs to be set per target, the default method of setting CMAKE_CXX_FLAGS_<Config>does not work; this overrides for all targets.

因为这个需要按target设置,默认的设置方法是CMAKE_CXX_FLAGS_<Config>不行的;这将覆盖所有目标。

To that end, I tried something like the following:

为此,我尝试了以下操作:

# @fn       set_target_dynamic_crt
# @brief    Sets the given target to use the dynamic version of the CRT (/MD or
#           /MDd)
# @param    ...  A list of targets to which this setting should be applied.
function( set_target_dynamic_crt )
    if ( MSVC )
        message (WARNING ${CMAKE_BUILD_TYPE})
        if (CMAKE_BUILD_TYPE STREQUAL "Debug")
            set_target_properties ( ${ARGN} PROPERTIES COMPILE_FLAGS "/MDd" )
        else()
            set_target_properties ( ${ARGN} PROPERTIES COMPILE_FLAGS "/MD" )
        endif()
    endif()
endfunction()

However, this always chooses the release version (/MD) and when I query for the build type (the messagecall above) I get the empty string. (I suspect this is because I'm using the Visual Studio generator; I've seen more than one reference that says CMAKE_BUILD_TYPEis for makefiles only...)

但是,这总是选择发布版本 ( /MD),当我查询构建类型(message上面的调用)时,我得到空字符串。(我怀疑这是因为我使用的是 Visual Studio 生成器;我已经看到不止一个参考资料说CMAKE_BUILD_TYPE仅用于 makefile ......)

How can I set compile options like this per target?

如何为每个目标设置这样的编译选项?

回答by steveire

In CMake 2.8.12 I added a target_compile_options command to address this need:

在 CMake 2.8.12 中,我添加了一个 target_compile_options 命令来解决这个需求:

http://public.kitware.com/Bug/view.php?id=6493

http://public.kitware.com/Bug/view.php?id=6493

http://www.cmake.org/cmake/help/git-master/manual/cmake-generator-expressions.7.html

http://www.cmake.org/cmake/help/git-master/manual/cmake-generator-expressions.7.html

target_compile_options(tgt PRIVATE "/MD$<$<CONFIG:Debug>:d>")

See

http://www.cmake.org/cmake/help/git-next/manual/cmake-buildsystem.7.html#build-specification-with-generator-expressions

http://www.cmake.org/cmake/help/git-next/manual/cmake-buildsystem.7.html#build-specification-with-generator-expressions

for more relating to CMAKE_BUILD_TYPE and several reasons why the generator expression is better (eg IMPORTED target config mapping).

有关 CMAKE_BUILD_TYPE 的更多信息以及生成器表达式更好的几个原因(例如 IMPORTED 目标配置映射)。

回答by Fraser

The only option I know of for this scenario is to split your project into subdirectories on a per-target basis and use add_subdirectory.

对于这种情况,我所知道的唯一选择是基于每个目标将您的项目拆分为子目录并使用add_subdirectory.

Depending on how your project is currently set up, this could be a painful process I guess.

根据您的项目目前的设置方式,我猜这可能是一个痛苦的过程。

The result would be a top-level CMakeLists.txt that looked like e.g.

结果将是一个顶级的 CMakeLists.txt,看起来像

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(Test)
add_subdirectory(libB)
add_subdirectory(libA)
add_executable(main_exe "main.cpp")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd")
target_link_libraries(main_exe lib_a lib_b)

then libA/CMakeLists.txtcould specify MDand MDdflags:

然后libA/CMakeLists.txt可以指定MDMDd标记:

project(LibA)
add_library(lib_a a.cpp a.hpp)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd")

and libB/CMakeLists.txtfor MTand MTdflags:

libB/CMakeLists.txt对于MTMTd标志:

project(LibB)
add_library(lib_b b.cpp b.hpp)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")

You can of course add all targets needing linked to the static CRT in the one subdirectory and CMakeLists.txt and all the dynamic CRT ones in the other if you have a lot of targets.

如果您有很多目标,您当然可以在一个子目录和 CMakeLists.txt 中添加所有需要链接到静态 CRT 的目标,并在另一个中添加所有动态 CRT。

回答by phb

CMAKE_BUILD_TYPEis only valid for single-configuration generators. The multi-configuration generators (MSVC and Xcode) can build for multiple configurations in one build-directory and as such the CMAKE_BUILD_TYPEflag wouldn't have a meaning.

CMAKE_BUILD_TYPE仅对单配置生成器有效。多配置生成器(MSVC 和 Xcode)可以在一个构建目录中为多个配置构建,因此该CMAKE_BUILD_TYPE标志没有意义。

The COMPILE_FLAGS target property does not distinguish different configurations (See kitware bugtrackerfor more information).

COMPILE_FLAGS 目标属性不区分不同的配置(有关更多信息,请参阅kitware bugtracker)。

A workaround would be to have two build-directories, similar to how people use the Makefile generators, and define an additional flag when building binaries for distribution. (ie, the Release configuration)

一种解决方法是拥有两个构建目录,类似于人们使用 Makefile 生成器的方式,并在构建二进制文件以进行分发时定义一个额外的标志。(即Release配置)

回答by kucer

Assume that I want to add -Onoptions to vmovq_n_u8.c and generate vmovq_O3.out and vmovq_O0.out. I had it done with target_compile_optionsby following:

假设我想向-Onvmovq_n_u8.c添加选项并生成 vmovq_O3.out 和 vmovq_O0.out。我target_compile_options通过以下方式完成了它:

add_executable(vmovq_O3.out vmovq_n_u8.c)
add_executable(vmovq_O0.out vmovq_n_u8.c)

target_compile_options(vmovq_O3.out PRIVATE -O3)
target_compile_options(vmovq_O0.out PRIVATE -O0)