Modern CMake 简单使用

Modern CMake 简单使用

目录结构

├── CMakeLists.txt
├── main.cpp
└── threadpool
├── CMakeLists.txt
├── threadpool.cpp
└── threadpool.h

第1个CMakeLists.txt

#设置cmake最小版本
cmake_minimum_required(VERSION 3.21)

#设置工程名 版本
project(test_tp VERSION 0.0.1)

message("PROJECT_NAME: ${PROJECT_NAME}")
message("PROJECT_VERSION: ${PROJECT_VERSION}")
message("PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}")
message("PROJECT_BINARY_DIR: ${PROJECT_BINARY_DIR}")
message("test_tp_VERSION:${test_tp_VERSION}")
message("test_tp_SOURCE_DIR: ${test_tp_SOURCE_DIR}")
message("test_tp_BINARY_DIR:${test_tp_BINARY_DIR}")

if (PROJECT_BINARY_DIR STREQUAL PROJECT_SOURCE_DIR)
    message(MARNING "The binary directory of CMake cannot be the same as source directory.")
endif ()

#设置成Release模式
set(CMAKE_BUILD_TYPE Release)

#设置C++标准版本--C++20
set(CMAKE_CXX_STANDARD 20)
#CMAKE_CXX_STANDARD_REQUIRED--默认OFF。表示是否一定要支持你指定的 C++ 标准
#如果为OFF则CMake检测到编译器不支持C++20时不报错,会使用上一版本;为ON则发现不支持报错,更安全。
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#CMAKE_CXX_EXTENSIONS默认为ON。设为ON表示启用GCC特有的一些扩展功能;OFF则关闭GCC的扩展功能,只使用标准的C++。
#要兼容其他编译器(如 MSVC)的项目,都会设为OFF防止不小心用了GCC才有的特性。
set(CMAKE_CXX_EXTENSIONS OFF)

#添加子目录
add_subdirectory(threadpool)

#设置目标编译成二进制可执行文件,文件名为test_tp
add_executable(test_tp)

#链接源文件
#CMAKE_CURRENT_SOURCE_DIR表示当前CMakeLists.txt所在的目录
#target_sources(test_tp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
#或者
#aux_source_directory(< dir > < variable >) 查找在某个路径下的所有源文件
aux_source_directory(. SRC_LIST) # 搜索当前目录下的所有.cpp文件
target_sources(test_tp PRIVATE ${SRC_LIST})

#链接库
target_link_libraries(test_tp PRIVATE ThreadPool)

第2个CMakeLists.txt

message("threadpool CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")

#设置作为对象库(OBJECT)--对象库类似于静态库,但不生成 .a 文件,只由 CMake 记住该库生成了哪些对象文件对象库是 CMake 自创的,绕开了编译器和操作系统的各种繁琐规则,保证了跨平台统一性。
#SHARED--编译动态库--add_library(ThreadPool SHARED)
#STATIC--编译静态库--add_library(ThreadPool STATIC)
add_library(ThreadPool OBJECT)

#查找依赖库
find_package(Threads REQUIRED)

#链接源文件
#CMAKE_CURRENT_SOURCE_DIR表示当前CMakeLists.txt所在的目录
target_sources(ThreadPool PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/threadpool.cpp)

#链接库
target_link_libraries(ThreadPool PRIVATE Threads::Threads)

#设置让引用或者依赖ThreadPool的能自动包含当前目录
#主要是设置当前库的头文件对依赖它的生效,让其他依赖这个库的,能找到相关头文件
#INTERFACE意味着消费者需要但生产者不需要的东西
target_include_directories(ThreadPool INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

常用命令:

  1. cmake -B build 在源码目录用 -B 直接创建 build 目录并生成 build/Makefile
  2. cmake --build build -j4 自动调用本地的构建系统在 build 里构建,即:make -C build -j4
  3. sudo cmake --build build --target install 调用本地的构建系统执行 install 这个目标,即安装

CMAKE_BUILD_TYPE 构建的类型,调试模式还是发布模式

  • CMAKE_BUILD_TYPE 是 CMake 中一个特殊的变量,用于控制构建类型,他的值可以是:
  • Debug 调试模式,完全不优化,生成调试信息,方便调试程序
  • Release 发布模式,优化程度最高,性能最佳,但是编译比 Debug 慢
  • MinSizeRel 最小体积发布,生成的文件比 Release 更小,不完全优化,减少二进制体积
  • RelWithDebInfo 带调试信息发布,生成的文件比 Release 更大,因为带有调试的符号信息
  • 默认情况下 CMAKE_BUILD_TYPE 为空字符串,这时相当于 Debug。

操作:

  1. 在配置build时,cmake -B build -DCMAKE_BUILD_TYPE=Release. 注意:在配置阶段可以通过 -D 设置缓存变量。第二次配置时,之前的 -D 添加仍然会被保留。也就是如果设置了Release后,要变回Debug,需要再次执行cmake -B build -DCMAKE_BUILD_TYPE=Debug
  2. 在CMakeLists.txt中设置set(CMAKE_BUILD_TYPE Release)

PUBLIC,PRIVATE,INTERFACE,定义了Target属性的传递范围

  • PUBLIC 对于可执行文件而言意义不大,对于库来说,它让 CMake 知道链接这个目标的目标也需要这个。也就是 “我自己要用,其他链接我的也要用”,具有传递性
  • PRIVATE 表示 “我自己用,其他人不用”
  • INTERFACE 表示 “我自己不用,其他链接我的要用”

其他小操作:

FetchContent

使用FetchContent的步骤总结起来就是:

  • 在cmake文件写入 include(FetchContent)
  • 使用FetchContent_Declare(三方库) 获取项目。可以是一个URL也可以是一个Git仓库。
  • 使用FetchContent_MakeAvailable(三方库) 获取我们需要库,然后引入项目。
  • 使用 target_link_libraries(targetName PRIVATE 库名)

列子

include(FetchContent)

FetchContent_Declare(
        doctest
        GIT_REPOSITORY https://github.com/doctest/doctest.git
        GIT_TAG v2.4.9
        GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(doctest)

add_executable(Test01 test_01.cpp)

target_link_libraries(Test01 PRIVATE doctest_with_main)
posted @ 2022-03-19 22:31  DarkH  阅读(471)  评论(0编辑  收藏  举报