CMake中的平台检测

2Ni*_*meo 20 c++ cmake boost-asio

我添加了一些功能boost::asio,这促成了一些编译器"警告":

请适当定义_WIN32_WINNT或_WIN32_WINDOWS.

这个问题在这里处理了.当我在Windows上构建并制作适当的定义或命令行参数时,我想要检测CMake.

kar*_*lip 29

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

IF (WIN32)
  # set stuff for windows
ELSE()
  # set stuff for other systems
ENDIF()
Run Code Online (Sandbox Code Playgroud)


Kne*_*eLL 22

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

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})
Run Code Online (Sandbox Code Playgroud)

  • 对于Windows 10问题,例如`Windows Kits\8.1\Include\shared\sdkddkver.h(255):错误C2177:常量太大`,请查看@squareskittles的答案如下. (2认同)

squ*_*les 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 ("${verMajor}" MATCHES "10")
            # 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(CMAKE_SYSTEM_VERSION)
    endmacro(get_WIN32_WINNT)

    get_WIN32_WINNT(ver)
    add_definitions(-D_WIN32_WINNT=${ver})
endif(WIN32)
Run Code Online (Sandbox Code Playgroud)

  • @fr4nk 是的,截至今天,CMake 没有提供任何开箱即用的东西来获取 WINNT 十六进制版本,因此需要这样的解决方案来支持 Windows 10 和旧版 Windows 版本(请参阅所有 [此处](https ://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=vs-2019#remarks))。当然,如果只需要支持Windows 10,那就简单多了:`-D_WIN32_WINNT=0x0A00` (2认同)

lla*_*nen 10

我想在这里澄清一个尚未有人提及的细节。这一点在交叉编译时尤其适用,但在其他情况下也有效。

CMAKE_HOST_WIN32是在 Windows 上编译时设置的变量。

WIN32是在编译 Windows 目标平台时设置的变量。

CMAKE_HOST_WIN32考虑到OP的问题“当我在Windows上构建时”,使用正确的标志也是如此。在许多情况下WIN32CMAKE_HOST_WIN32是等效的,但并非在所有情况下。

WIN32在 Windows 上对非 Windows 进行交叉编译时也会在开始时设置,但会在 CMake 执行期间的某个时刻隐式取消设置(我相信内部project调用)。上次我检查WIN32是在执行 toolchain.cmake 期间设置的,但后来没有设置。因此,在这些情况下,该标志可能很危险,因为其状态在执行过程中发生变化。您不应该WIN32在工具链文件内使用!

如果您需要有关正在构建的平台的详细信息,您可以尝试变量CMAKE_HOST_SYSTEM_NAMECMAKE_HOST_SYSTEM_VERSION

MESSAGE("CMAKE_HOST_SYSTEM_NAME ${CMAKE_HOST_SYSTEM_NAME}")
MESSAGE("CMAKE_HOST_SYSTEM_VERSION ${CMAKE_HOST_SYSTEM_VERSION}")
Run Code Online (Sandbox Code Playgroud)

给我以下输出(在 CMake 版本 3.19.2 上)

CMAKE_HOST_SYSTEM_NAME Windows
CMAKE_HOST_SYSTEM_VERSION 10.0.19044
Run Code Online (Sandbox Code Playgroud)

还有CMAKE_HOST_SYSTEM哪个内部工具链文件给了我空白,但project调用后它给出了“Windows-10.0.19044”


Com*_*sMS 5

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

您可以将预处理器定义传递给应用程序:

  • 使用由CMake的configure_file预处理的configure头.这种方法的优点是所有#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命令.

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