CMake中的平台检测
Platform detection in CMake
我从boost::asio
中添加了一些功能,这引发了一些编译器"警告":
请适当定义_WIN32_WINNT或_WIN32_PINDOWS。
这个问题在这里得到了解决。当我在Windows上构建时,我想让CMake检测,并做出适当的定义或命令行参数。
在CMakeLists.txt文件中,您可以执行以下操作:
IF (WIN32)
# set stuff for windows
ELSE()
# set stuff for other systems
ENDIF()
这里有一个简单的解决方案。
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})
这是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()
我想澄清一个还没有人提到的细节。这一点在交叉编译时尤其适用,但在其他情况下也是有效的。
CMAKE_HOST_WIN32
是在Windows上编译时设置的变量。
WIN32
是编译FOR Windows目标平台时设置的变量。
因此CCD_ 4是考虑OP的问题时使用的正确标志;当我在Windows上构建时";。在许多情况下,WIN32
和CMAKE_HOST_WIN32
是等效的,但并非在所有情况下都是等效的。
在非Windows的Windows上交叉编译时,WIN32
也会在一开始被设置,但在CMake执行期间的某个时刻会被隐式取消设置(我相信在project
调用内部)。上次我检查WIN32
是在执行toolchain.cmake时设置的,但在以后没有设置。因此,在这些情况下,这个标志可能很危险,因为它的状态在执行过程中会发生变化。您不应该在工具链文件中使用WIN32
!
如果您需要有关正在构建的平台的详细信息,可以尝试变量CMAKE_HOST_SYSTEM_NAME
和CMAKE_HOST_SYSTEM_VERSION
MESSAGE("CMAKE_HOST_SYSTEM_NAME ${CMAKE_HOST_SYSTEM_NAME}")
MESSAGE("CMAKE_HOST_SYSTEM_VERSION ${CMAKE_HOST_SYSTEM_VERSION}")
给我以下输出(在CMake 3.19.2版上)
CMAKE_HOST_SYSTEM_NAME Windows
CMAKE_HOST_SYSTEM_VERSION 10.0.19044
还有CMAKE_HOST_SYSTEM
,它在工具链文件中给了我空白,但在project
调用后,它给出了"0";Windows-10.0.19044";
正如karlphilip所指出的,您可以使用if(WIN32)
进行平台检测。
您将有许多将预处理器定义传递给应用程序的可能性:
- 使用由CMake的config_file预处理的配置标头。这种方法的优点是,所有
#define
实际上都是代码的一部分,而不是构建环境的一部分。缺点是它需要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
命令进行此操作。
我通常更喜欢后者,但这主要是个人品味的问题。
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的版本在我的情况下不起作用,因为CMAKE_SYSTEM_VERSION
是6.3.9600
,这导致了${ver}=0x060306090000
不过,此版本将在Windows 10及更高版本中失败。必须检查第一个数字是否大于9,并将其转换为正确的十六进制值。
可能是支持Win10的最简洁的版本,需要CMake 3.13+
macro(get_win_hex outvar)
string(REGEX MATCH "^([0-9]+)\.([0-9]+)" ${outvar} ${CMAKE_SYSTEM_VERSION})
math(EXPR ${outvar} "(${CMAKE_MATCH_1} << 8) + ${CMAKE_MATCH_2}" OUTPUT_FORMAT HEXADECIMAL)
endmacro()
if(WIN32)
get_win_hex(winver)
add_compile_definitions(_WIN32_WINNT=${winver})
endif()
这就是我所想到的:
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()
对于处理boost::asio"警告",预处理器定义或命令行标志可以完成任务。
- 正在查找文档以获得PS4平台的C++中的设备信息
- 使用CMake检测支持的C++标准
- 当套接字连接断开时检测C/C++Unix
- C/C++预处理器是否可以检测一些编译器选项
- WMI检测进程创建事件-c++
- 基于树莓pi的tensorflow lite量化ssd目标检测
- 下面是我为检测链接列表中的循环而制作的代码
- 落砂模拟碰撞检测C++和SFML
- 我可以检测和更改 gcc/g++ 中结构的当前数据对齐设置吗?
- 为什么C++编译器没有检测到正确声明的类?
- 检测win32服务创建和删除的最佳方法
- 正在LLVM中检测整数比较条件
- 如何在鼠标挂钩过程中检测拖动
- 如何在 Linux/MacOs 平台中检测到内存泄漏?
- 通用 Windows 平台上的内存泄漏检测
- CMake中的平台检测
- 用C++检测Windows环境下的片上系统(SOC)平台
- c++的平台独立性.检测和编译
- 在unix平台上使用curses检测c++中的箭头键输入在调用系统命令后不起作用
- 如何在Linux平台上使用gTest在C++中检测内存泄漏