C++ CMake中的平台检测

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9742003/
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:15:00  来源:igfitidea点击:

Platform detection in CMake

c++cmakeboost-asio

提问by 2NinerRomeo

I've added some functionality from boost::asio, which has precipitated some compiler "warnings":

我已经从 中添加了一些功能boost::asio,这导致了一些编译器“警告”:

Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately.

请适当定义 _WIN32_WINNT 或 _WIN32_WINDOWS。

That problem was dealt with here. I'd like to have CMake detect when I am building on Windows and make the appropriate definitions or command line arguments.

那个问题在这里得到了处理。当我在 Windows 上构建时,我想让 CMake 检测并进行适当的定义或命令行参数。

回答by karlphillip

Inside the CMakeLists.txt file you can do:

在 CMakeLists.txt 文件中,您可以执行以下操作:

IF (WIN32)
  # set stuff for windows
ELSE()
  # set stuff for other systems
ENDIF()

回答by KneLL

Here is a simple solution.

这是一个简单的解决方案。

macro(get_WIN32_WINNT version)
    if (WIN32 AND CMAKE_SYSTEM_VERSION)
        set(ver ${CMAKE_SYSTEM_VERSION})
        string(REPLACE "." "" ver ${ver})
        string(REGEX REPLACE "([0-9])" "0\1" ver ${ver})

        set(${version} "0x${ver}")
    endif()
endmacro()

get_WIN32_WINNT(ver)
add_definitions(-D_WIN32_WINNT=${ver})

回答by squareskittles

Here's an expanded version of KneLL's answer, also checking for Windows 10.

这是 KneLL 答案的扩展版本,还检查了 Windows 10。

if(WIN32)
    macro(get_WIN32_WINNT version)
        if(CMAKE_SYSTEM_VERSION)
            set(ver ${CMAKE_SYSTEM_VERSION})
            string(REGEX MATCH "^([0-9]+).([0-9])" ver ${ver})
            string(REGEX MATCH "^([0-9]+)" verMajor ${ver})
            # Check for Windows 10, b/c we'll need to convert to hex 'A'.
            if("${verMajor}" MATCHES "10")
                set(verMajor "A")
                string(REGEX REPLACE "^([0-9]+)" ${verMajor} ver ${ver})
            endif()
            # Remove all remaining '.' characters.
            string(REPLACE "." "" ver ${ver})
            # Prepend each digit with a zero.
            string(REGEX REPLACE "([0-9A-Z])" "0\1" ver ${ver})
            set(${version} "0x${ver}")
        endif()
    endmacro()

    get_WIN32_WINNT(ver)
    add_definitions(-D_WIN32_WINNT=${ver})
endif()

回答by ComicSansMS

As karlphilip pointed out, you can use if(WIN32)for platform detection.

正如 karlphilip 指出的那样,您可以if(WIN32)用于平台检测。

You'll have a number of possibilities for passing preprocessor defines to the application:

您将有多种将预处理器定义传递给应用程序的可能性:

  • Use a configure header that gets preprocessed by CMake's configure_file. This approach has the advantage that all #defines are actually part of the code and not of the build environment. The disadvantage is that it requires an (automatic) preprocessing step by CMake
  • Use add_definitions. This will add the preprocessor flag for all source files in the project, so it's more of a quick and dirty approach.
  • Use the COMPILE_DEFINITIONSproperty. This allows fine grained control over the defines on a per-file (and even per-config) basis: set_property(SOURCE ${YOUR_SOURCE_FILES} APPEND PROPERTY COMPILE_DEFINITIONS YOUR_FLAG1 YOUR_FLAG2)

    In modern CMake versions (2.8.12 and higher) you can also use the more convenient target_compile_definitionscommand for this.

  • 使用由 CMake 的configure_file预处理的配置标头。这种方法的优点是所有#defines 实际上都是代码的一部分,而不是构建环境的一部分。缺点是它需要 CMake 的(自动)预处理步骤
  • 使用add_definitions。这将为项目中的所有源文件添加预处理器标志,因此它更像是一种快速而肮脏的方法。
  • 使用COMPILE_DEFINITIONS属性。这允许在每个文件(甚至每个配置)的基础上对定义进行细粒度控制: set_property(SOURCE ${YOUR_SOURCE_FILES} APPEND PROPERTY COMPILE_DEFINITIONS YOUR_FLAG1 YOUR_FLAG2)

    在现代 CMake 版本(2.8.12 及更高版本)中,您还可以target_compile_definitions为此使用更方便的命令。

I usually prefer the latter, but that's mostly a matter of personal taste.

我通常更喜欢后者,但这主要是个人品味的问题。

回答by Twonky

An improved version of KneLLs answer:

KneLLs 的改进版本回答:

macro(get_WIN32_WINNT version)
    if (WIN32 AND CMAKE_SYSTEM_VERSION)
        set(ver ${CMAKE_SYSTEM_VERSION})
        string(REGEX REPLACE "^([0-9])[.]([0-9]).*" "0\10\2" ver ${ver})
        set(${version} "0x${ver}")
    endif()
endmacro()

get_WIN32_WINNT(ver)
add_definitions(-D_WIN32_WINNT=${ver})

KneLLs version did no work in my case, because CMAKE_SYSTEM_VERSIONwas 6.3.9600which resulted in ${ver}=0x060306090000

KneLLs版本的确在我的情况下,没有工作,因为CMAKE_SYSTEM_VERSION6.3.9600这导致${ver}=0x060306090000

This version will fail for Windows 10 and later, though. One has to check if the first number is bigger than 9 and convert it to the correct hexadecimal value.

但是,此版本将无法用于 Windows 10 及更高版本。必须检查第一个数字是否大于 9 并将其转换为正确的十六进制值。

回答by 2NinerRomeo

This is what I have come up with:

这是我想出的:

if(${WIN32})
#this method adds the necessary compiler flag
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_WIN32_WINNT=0x0501")
#this adds a preprocessor definition to the project
add_definitions(-D_WIN32_WINNT=0x0501)
endif()

For dealing with the boost::asio "warning" either the preprocessor definition or the command line flag gets the job done.

为了处理 boost::asio “警告”,预处理器定义或命令行标志可以完成工作。