我们承担ROS,FastDDS等中间件以及C++,cmake等技术的项目开发和专业指导和培训,有10年+工作经验,质量有保证,如有需要请私信联系。
构建系统
- make:cmake默认使用make构建系统,会生成相应的makefile用于编译代码
- ninja
- 首先确保已经安装了Ninja。可以通过包管理器进行安装,例如在Ubuntu上可以使用
sudo apt-get install ninja-build
cmake -G Ninja ..
通过-G
参数指定nanja构建系统
- 首先确保已经安装了Ninja。可以通过包管理器进行安装,例如在Ubuntu上可以使用
检测操作系统
使用变量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有这些值