CMake之环境依赖

文章介绍了如何利用CMake变量和命令来检测目标操作系统的名称,如Linux、Windows,处理器的位数(32位或64位)以及处理器体系结构,如i386、x86_64。同时,它展示了如何根据不同的编译器ID(如Intel、GNU)定义预编译宏,以便在代码中处理不同平台和编译器的差异。
摘要由CSDN通过智能技术生成


我们承担ROS,FastDDS等中间件以及C++,cmake等技术的项目开发和专业指导和培训,有10年+工作经验,质量有保证,如有需要请私信联系。

构建系统

  • make:cmake默认使用make构建系统,会生成相应的makefile用于编译代码
  • ninja
    • 首先确保已经安装了Ninja。可以通过包管理器进行安装,例如在Ubuntu上可以使用sudo apt-get install ninja-build
    • cmake -G Ninja .. 通过-G参数指定nanja构建系统

检测操作系统

使用变量CMAKE_SYSTEM_NAME 检测操作系统。
CMake为目标操作系统定义的该变量,此变量的值为uname -s的输出,在Linux和Windows上分别是"Linux"和"Windows"

include(CMakePrintHelpers)
cmake_print_variables(CMAKE_SYSTEM_NAME)
## 输出:
CMAKE_SYSTEM_NAME="Linux"

处理不同平台的代码

使用命令target_compile_definitions定义预编译宏,在代码中使用预编译宏区分不同平台。
理想情况下,应该避免依赖于平台的源代码。如果必须要区分平台代码,可以通过命令target_compile_definitions,让预处理器知道系统的名称,然后在代码中进行预编译。检测操作系统依然使用变量 CMAKE_SYSTEM_NAME

if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
  target_compile_definitions(hello-world PUBLIC "IS_LINUX")
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  target_compile_definitions(hello-world PUBLIC "IS_MACOS")
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
  target_compile_definitions(hello-world PUBLIC "IS_WINDOWS")
endif()

然后,在代码中可以这样使用

std::string say_hello() {
#ifdef IS_WINDOWS
  return std::string("Hello from Windows!");
#elif IS_LINUX
  return std::string("Hello from Linux!");
#elif IS_MACOS
  return std::string("Hello from macOS!");
#else
  return std::string("Hello from an unknown system!");
#endif
}

检测处理器体系结构

  • 使用变量CMAKE_SIZEOF_VOID_P 了解CPU是32位还是64位。CMAKE_SIZEOF_VOID_P 为void指针的大小,会告诉我们CPU是32位还是64位,或者其他,在CMake配置时进行查询,以便修改目标或目标编译定义。
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
  message(STATUS "Target is 64 bits")
else()
  message(STATUS "Target is 32 bits")
endif()
  • 使用变量CMAKE_HOST_SYSTEM_PROCESSOR 了解当前运行的处理器的名称。CMAKE_HOST_SYSTEM_PROCESSOR的值为“i386”、“i686”、“x86_64”、“AMD64”等,取决于当前的CPU。CMake还定义了CMAKE_SYSTEM_PROCESSOR。两者区别:
    • CMAKE_HOST_SYSTEM_PROCESSOR 是当前运行的CPU在CMake的名称
    • CMAKE_SYSTEM_PROCESSOR 当前正在为其构建的CPU的名称。自验证这两个变量打印都为x86_64
if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "i386")
    message(STATUS "i386 architecture detected")
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "i686")
    message(STATUS "i686 architecture detected")
elseif(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "x86_64")
    message(STATUS "x86_64 architecture detected")
else()
    message(STATUS "host processor architecture is unknown")
endif()

应当尽量避免这种使用依赖,在处理遗留代码或交叉编译时,这种依赖是有用的。

处理不同编译器

使用变量CMAKE_<lang>_COMPILER_ID 了解是哪个编译器。这个变量指定了编译器供应商,以下方式通过该变量知道编译器的名称和供应商后再使用target_compile_definitions命令定义预处理宏:

target_compile_definitions(hello-world PUBLIC "COMPILER_NAME=\"${CMAKE_CXX_COMPILER_ID}\"")
if(CMAKE_CXX_COMPILER_ID MATCHES Intel)
  target_compile_definitions(hello-world PUBLIC "IS_INTEL_CXX_COMPILER")
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES GNU)
  target_compile_definitions(hello-world PUBLIC "IS_GNU_CXX_COMPILER")
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES PGI)
  target_compile_definitions(hello-world PUBLIC "IS_PGI_CXX_COMPILER")
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES XL)
  target_compile_definitions(hello-world PUBLIC "IS_XL_CXX_COMPILER")
endif()

以上代码也可以通过以下简化:

target_compile_definitions(hello-world
  PUBLIC "IS_${CMAKE_CXX_COMPILER_ID}_CXX_COMPILER"
  )

这里的前提是必须要知道CMAKE_CXX_COMPILER_ID有哪些值,要在代码中硬编码这些预处理宏。CMAKE_CXX_COMPILER_ID参考这里

检测处理器指令集

使用命令cmake_host_system_information查询运行CMake的主机系统的系统信息。

cmake_host_system_information(RESULT <variable> QUERY <key> ...)

在CMake运行时查询key,将值存储到variable中。key有这些值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值