记录学习CMake管理C++工程的过程(使用.cmake文件)。
CMake的更多命令详解
cmake_minimum_required
//指定 cmake 的最小版本cmake_minimum_required(VERSION 3.4.1)
注: 这行命令是可选的,我们可以不写这句话,但在有些情况下,如果 CMakeLists.txt 文件中使用了一些高版本 cmake 特有的一些命令的时候,就需要加上这样一行,提醒用户升级到该版本之后再执cmake。
-
project
//指定项目信息project( Demo LANGAGES CXX C DESCRIPTION "My own game code" VERSION 0.1.0)
注: 这个命令不是强制性的,但最好都加上。 第一个参数是必须的,其他可选。 当你定义了项目名称之后,CMake 会自动生成以下两个变量:
demo_BINARY_DIR
demo_SOURCE_DIR
这两个变量分别表示项目的二进制输出目录和源代码目录。 此外,CMake 还会定义两个通用变量:
PROJECT_BINARY_DIR
PROJECT_SOURCE_DIR
这两个变量与 demo_BINARY_DIR 和 demo_SOURCE_DIR 等价,区别在于它们是更通用的写法,不依赖于项目名称。
-
add_executable
//用于在项目中添加一个可执行文件的目标add_executable(<name> <options>... <sources>...) # for example: add_executable(demo demo.cpp) # 生成可执行文件
<name>
:指定可执行文件的名称。这个名称将用作生成的可执行文件的名称,并且也将用于在 CMake 中引用该目标。<options>
:可选参数,用于指定特定的选项或属性。例如,可以使用 -D 选项定义预处理宏,或者使用 -I 选项指定额外的包含目录等。<sources>
:指定源文件的列表,用于构建可执行文件。这可以是一个或多个源文件,可以包括 C、C++、汇编等类型的源文件。
生成静态库示例:
add_library(<静态库目标名> STATIC <源文件列表>) add_library(mylib_static STATIC src/mylib.cpp)
生成动态库示例:
add_library(<动态库目标名> SHARED <源文件列表>) add_library(mylib_shared SHARED src/mylib.cpp)
-
set
//用于设置变量的值set(<variable> <value>... [PARENT_SCOPE]) # for example: set(far "Hello, CMake!") set(CMAKE_CXX_STANDARD 11) // 设置使用 C++ 11 标准
-
message
//用于在 cmake 中打印相应的信息message([<mode>] "message text" [arg1 [arg2 ...]]) # for example: message(STATUS "hello cmake")
- mode 用于指定输出消息的模式,常用的模式如下:
- STATUS:以普通信息的形式输出。
- WARNING:以警告信息的形式输出。
- AUTHOR_WARNING:以作者警告信息的形式输出。
- SEND_ERROR:以错误信息的形式输出,并停止构建过程。
- FATAL_ERROR:以致命错误信息的形式输出,并立即终止构建过程。
- mode 用于指定输出消息的模式,常用的模式如下:
-
get_filename_component
//用于对文件路径进行解析,从而提取出文件名、目录、扩展名等相关信息get_filename_component(<VAR> <FileName> <COMPONENT> [CACHE]) # for example: # CMAKE_CURRENT_LIST_DIR 表示当前正在处理的cmake变量 get_filename_component(CURRENT_DIR_PATH "${CMAKE_CURRENT_LIST_DIR}" ABSOLUTE) # 从完整路径中提取目录名称 get_filename_component(CURRENT_DIR_NAME "${CURRENT_DIR_PATH}" NAME) project(${CURRENT_DIR_NAME})
<VAR>
:这是一个变量名,用于存储解析后的结果。<FileName>
:要进行解析的文件路径,可以是绝对路径,也可以是相对路径。<COMPONENT>
:指定要提取的文件路径信息的组件,常见的取值有以下几种:- PATH:提取文件路径中的目录部分。
- NAME:提取文件的完整名称,包含扩展名。
- NAME_WE:提取文件的名称,但不包含扩展名。
- EXT:提取文件的扩展名。
- ABSOLUTE:将相对路径转换为绝对路径。
[CACHE]
:这是一个可选参数,若指定了该参数,解析结果会被存储到 CMake 缓存中。# 获取当前子CMake文件所在目录的完整路径
# 获取当前子CMake文件所在目录的完整路径 # CMAKE_CURRENT_LIST_DIR 表示当前正在处理的cmake变量 get_filename_component(CURRENT_DIR_PATH "${CMAKE_CURRENT_LIST_DIR}" ABSOLUTE) # 从完整路径中提取目录名称 get_filename_component(CURRENT_DIR_NAME "${CURRENT_DIR_PATH}" NAME) project(${CURRENT_DIR_NAME})
-
aux_source_directory
//发现目录中所有的文件# 用法示例 aux_source_directory(<dir> <variable>)
# for example cmake_minimum_required(VERSION 3.28) project(firstproject) aux_source_directory(. SRCS) # 当前目录中的文件路径 都存储到 SRCS message(STATUS ${SRCS}) #add_executable(firstproject main.cpp calc.h calc.cpp) add_executable(firstproject ${SRCS})
-
target_include_directories
// 指定要包含的头文件目录,头文件目录包含了用于编译源代码的头文件 。
针对目标添加头文件,对于保持项目的组织结构清晰、解决头文件依赖问题非常有用include_directories(<target> [SYSTEM] [AFTER|BEFORE] <INTERFACE|PUBLIC|PRIVATE> dir1 [dir2 ...]) target:目标的名称,必须是通过 add_executable() 或 add_library() 等命令 先创建出来的可执行文件或库。 SYSTEM:可选参数,指定被包含的目录是系统目录,这会告诉编译器将这些目录视为系统的标准头文件目录, 避免编译器产生警告 AFTER 或 BEFORE:可选关键字,BEFORE 指定包含目录应该在默认目录之前被添加到编译器的搜索路径; AFTER 则是默认情况,将包含目录添加到已有的包含目录之后 <INTERFACE|PUBLIC|PRIVATE>:指定包含目录的范围和传播方式 PRIVATE:目录仅对该目标可见,不会影响依赖该目标的其他目标,即只对当前目标的源文件使用。 INTERFACE:目录不会添加到该目标的编译选项中,但会添加到链接该目标的其他目标中,即目标对应的头文件使用。 PUBLIC:目录既会添加到该目标的编译选项中,也会添加到链接该目标的其他目标中,即目标对应的头文件、源文件都使用 dir1,ir2:要添加为包含目录的路径列表,可以是目录名、绝对路径或相对路径 # for example set(HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../Person) target_include_directories(${PROJECT_NAME} PRIVATE ${HEADER_DIR})
实例2引入
CMake 构建方法2:调用子目录中的cmake脚本方法 include方法可以引入子目录中的cmake后缀的配置文件 将配置加入add_executable中
工程目录
KCircle
|-----KCircle.cpp
|-----KCircle.h
|-----KCircle.cmake
KCircleMain
|-----CMakeLists.txt
|-----main.cpp
CMakeLists.txt 编写
cmake_minimum_required(VERSION 3.10)
Project(KCircle)
#设置默认的编译模式为 Debug
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
include(../KCircle/KCircle.cmake)
# 添加可执行文件
add_executable(${PROJECT_NAME} main.cpp ${SOURCES_FILE})
# 生成${PROJECT_NAME}.exe
# add_subdirectory(KCircle)
#add_executable(${PROJECT_NAME} main.cpp ${SOURCES_FILE})
# 向工程添加多个特定头文件的搜索路径 -I
target_include_directories(${PROJECT_NAME} PRIVATE ${HEADER_DIR})
# 显式添加源文件,使其在IDE中可
target_sources(${PROJECT_NAME} PRIVATE ${HEADERS_FILE})
.cmake 文件的编写
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# 定义源文件和头文件列表,CMAKE_CURRENT_SOURCE_DIR表的CMakeLists.txt的路径
set(SOURCES_FILE
${CMAKE_CURRENT_SOURCE_DIR}/../KCircle/KCircle.cpp
)
set(HEADERS_FILE
${CMAKE_CURRENT_SOURCE_DIR}/../KCircle/KCircle.h
)
set(HEADER_DIR
${CMAKE_CURRENT_SOURCE_DIR}/../KCircle
)
生成工程文件以及编译文件
在项目的文件夹下输入构建命令:
call "F:\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsamd64_x86.bat" # 这里的路径是在Visual Studio的安装路径中找的
mkdir Debug
cd Debug
# 把代码构建xx.sln文件
cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_BUILD_TYPE=Debug ../KCircleMain
# 编译xx.sln 生成xx.exe
msbuild /m KCircleMain.sln /p:Platform=x64 /p:Configuration=Debug
编译成功之后,可以进入Debug目录下的Debug目录,运行exe文件,就可以执行工程: