3.2指令和命令
3.2.2定义语言和元数据
cmake project(<project-name> [<lang-name>...])
e.g.
cmake project(demo CXX C)
cmake project(<project-name> [VERSION <maj>.<min>.<patch>.<tweak>] [DESCRIPTION <project-descrip-string>] [HOMEPAGE_URL <url-string>] [LANGUAGES <lang-name>...] )
e.g.
project(moderncmake
VERSION 0.0.0.1
DESCRIPTION "modern cmake for cpp"
HOMEPAGE_URL "www.baidu.com"
LANGUAGES CXX C CUDA
)
project()命令会自动创建内置变量,包括
PROJECT_NAME
CMAKE_PROJECT_NAME 顶层CMakeLists.txt可见
PROJECT_SOURCE_DIR, <PROJECT_NAME>_SOURCE_DIR
PROJECT_BINARY_DIR, <PROJECT_NAME>_BINARY_DIR
指定VERSION时,会创建以下变量
PROJECT_VERSION, <PROJECT_NAME>_VERSION
CMAKE_PROJECT_NAME (只有在顶层 CMakeLists.txt 中)
PROJECT_VERSION_MAJOR, <PROJECT_NAME>_VERSION_MAJOR
PROJECT_VERSION_MINOR, <PROJECT_NAME>_VERSION_MINOR
PROJECT_VERSION_PATCH, <PROJECT_NAME>_VERSION_PATCH
PROJECT_VERSION_TWEAK, <PROJECT_NAME>_VERSION_TWEAK
3.3划分项目
??????????????
cmake add_subdirectory(source_dir [binary_dir] [EXECLUDE_FROM_ALL])
e.g.
# 顶层CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
project(moderncmake
VERSION 0.0.0.1
DESCRIPTION "modern cmake for cpp"
HOMEPAGE_URL "www.baidu.com"
LANGUAGES CXX C
)
set(CMAKE_CXX_STANDARD 17)
add_executable(moderncmake main.cpp)
add_executable(main1 main.cpp)
add_executable(main2 main.cpp)
add_subdirectory(car)
target_link_libraries(main1 PRIVATE cars)
# car目录下CMakeLists.txt
add_library(cars OBJECT
car.cpp
) # 生成cars目标,全局可见?怎么就全局可见了 虽然是add_library,但不是库因为用了OBJECT关键字
target_include_directories(cars PUBLIC .) # 将cars目录添加到其公共包括目录中? 这样main.cpp就能包含cars.h文件不用提供相对路径了??? 这样操作之后并没有能这样#include"car.h"
3.4项目结构
推荐的项目结构
cmake:宏和函数,查找模块和一次性脚本 src:将存储的二进制文件和库的源代码 doc:用于构建文档 extern:从源代码构建的外部项目的配置 test:包含自动测试的代码
其中CMakeLists.txt文件应该存在于以下目录中:顶级项目目录、src、doc、extern和test
其中可执行文件和库的文件结构如下:
可执行文件的目录结构:
库的目录结构:
3.5 环境范围
3.5.1 识别操作系统
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
内建变量
CMAKE_SYSTEM_NAME
在进行交叉编译的时候,CMAKE_HOST_SYSTEM_NAME CMAKE_HOST_SYSTEM_PROCESSOR CMAKE_HOST_SYSTEM_VERSION指代宿主机的信息,?不带有HOST的应该是指代目标系统
3.5.3 更多系统版本相关内建变量
ANDROID APPLE CYGWIN UNIX IOS WIN32 WINCE WINDOWS_PHONE CMAKE_HOST_APPLE CMAKE_HOST_SOLARIS CMAKE_HOST_UNIX CMAKE_HOST_WIN3
UNIX适用于Linux macOS 和 Cygwin,其中在32位或64位的Windows和MSYS中,WIN32和CMAKE_HOST_WIN32均为真。
使用cmake查询主机系统信息
cmake_host_system_information(RESULT <VARIABLE> QUERY <KEY>...)
3.6配置工具链
3.6.1设定C++标准
根据每个目标设置语言标准
set_property(TARGET <target> PROPERTY CXX_STANDARD <standard>)
也可以在整个项目中采用一个标准
set(CMAKE_CXX_STANDARD CXX13)
强制要求项目的语言标准,也就是基于项目设置的语言标准对编译器进行检查。
set(CMAKE_CXX_STANDARD_REQUIRED ON)
3.6.3特定于供应商的扩展
编译器实现的特性不尽相同,希望项目是扩展无关的可以关掉扩展
set(CMAKE_CXX_EXTENSIONS OFF)
3.6.4过程间优化
现代编译器能够在链接执行时进行优化,称为连接时优化。cmake支持查看是否支持连接时优化并开启优化。
include(CheckIPOSupported)
check_ipo_supported(RESULT ipo_supported)
if(ipo_supported)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION True)
endif()
3.6.5检查支持的编译器特性
检查编译器是否支持某种特性
list(FIND CMAKE_CXX_COMPILER_FEATURES cxx_variable_teplates result)
if(result EQUAL -1)
message(FATAL_ERROR "I really need variable templates.")
endif()
通常是建议直接查是否支持某个标准,例如:cxx_std_98、cxx_std_11、cxx_std_14、cxx_std_17、cxx_std_20 和 cxx_std_23。也可以在文档:cmake.org/cmake/help/… 中找到。
3.6.6编译测试文件
使用try_run或者try_compile测试。
3.7禁用项目内构建
建议使用:
if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
message(FATAL_ERROR "In-source builds are not allowed")
endif()