CMake快速入门

img

CMake 官网:CMake

  • CMake 是一个 跨平台 的安装编译工具,可以用简单的语句来描述 所有平台 的安装(编译过程)
  • CMake 可以说已经成为 大部分C++开源项目的标配

1. 为什么要使用CMake?

比如说有一个开源项目,里面有很多 C++ 的源代码文件和头文件,想在的电脑上编译这个项目并运行它。但是的电脑上安装的编译器和 IDE 可能和项目开发者使用的不一样。这就会导致编译和构建项目的问题,因为的 IDE 或构建系统可能无法识别源代码的文件结构和参数等。如果没有足够的经验和技能手动调整工程文件,那么将无法编译和运行这个开源项目

但是,如果这个开源项目使用了 CMake 作为构建工具,那么就可以使用 CMake 自动生成针对的 IDE 或构建系统的项目文件,并在的电脑上轻松地编译和构建该项目,不必去手动配置项目和解决构建问题

2. 创建第一个 CMake 工程

步骤:

  1. 在工作目录中创建一个 .cpp 文件
#include <iostream>

int main() {
	std::cout << "hello world" << std::endl;
}
  1. 编写 CMakeLists.txt 文件
# CMakeLists.txt
project (HELLO)
set(SRC_LIST main.cpp)
message(STATUS "This is BINARY dir " ${HELLO_BINARY_DIR})
message(STATUS "This is SOURCE dir" ${HELLO_SOURCE_DIR})
add_executable(hello ${SRC_LIST})

注意:指令建议使用小写

  1. 使用 CMake 命令,生成 makefile 文件
# 配置项目
cmake -S . -B build

# 构建项目
cmake --build build
  1. 编译文件
cmake .

3. CMake 指令介绍

  • 基本语法格式介绍:指令 (参数1 参数2)
    • 参数使用 括号包裹
    • 参数之间使用 空格分号 分开
  • 变量使用 ${} 方式取值,但是在 IF控制语句中是直接使用变量名的
# 在一般的指令中使用变量都需要用 ${}
add_executable(hello main.cpp ${HELLO})

# 但在IF语句中,变量可以直接使用
IF(HELLO)

以上一个文件CMakeLists.txt为例

3.1 cmake_minimum_required 指令

在CMake中,cmake_minimum_required 是一个用于指定最低CMake版本要求的指令,它用于确保构建系统具有所需的最低CMake版本

语法:

cmake_minimum_required(VERSION <major>[.<minor>[.<patch>[.<tweak>]]] [FATAL_ERROR])

参数:

  • VERSION:指定所需的最低CMake版本。它由主版本号、次版本号、补丁版本号和调整版本号(可选)组成。这些版本号都是整数,并且必须按照从左到右的顺序指定。例如,3.20.1表示主版本号为3,次版本号为20,补丁版本号为1
  • FATAL_ERROR(可选):如果设置了这个参数,当CMake版本低于指定的最低版本时,CMake将会产生一个致命错误并停止配置过程

示例:

cmake_minimum_required(VERSION 3.20.1 FATAL_ERROR)

在上面的示例中,它指定了至少需要CMake版本3.20.1。如果当前的CMake版本低于指定的最低版本,配置过程将会停止并显示一个错误信息

通过使用cmake_minimum_required指令,可以确保构建系统在配置过程中使用的CMake版本符合要求,以避免由于版本不兼容而导致的问题


3.2 project 指令

在CMake中,project 指令用于定义一个项目,并设置项目的名称、版本号以及可选的语言支持

语法:

project(<project_name> [VERSION <version>] [LANGUAGES <language>...])

参数:

  1. <project_name>是项目��名称,可以是任意字符串
  2. <version>是可选的项目版本号,可以是任意字符串
  3. <language>是可选的项目所支持的语言,可以是多个语言,用空格分隔

示例:

project(MyProject VERSION 1.0 LANGUAGES CXX)

在这个示例中,项目名称是"MyProject",版本号是"1.0",项目支持的语言是C++


3.3 set 指令

在CMake中,set指令用于设置变量的值

set(<variable> <value> [CACHE <type> <docstring> [FORCE]])

参数:

  1. <variable>是变量的名称,可以是任意字符串
  2. <value>是变量的值,可以是字符串、列表或布尔值
  3. CACHE是可选的指令,用于将变量设置为缓存变量,可以在CMake缓存中进行持久化存储
  4. <type>是可选的类型,用于指定变量的类型,比如STRINGBOOLFILEPATH
  5. <docstring>是可选的文档字符串,用于描述变量的用途和说明
  6. FORCE是可选的指令,用于强制设置变量的值,即使它已经被设置过

示例:

设置一个字符串变量:

set(my_var "Hello, World!")

设置一个列表变量:

set(my_list_var "apple" "banana" "orange")

设置一个缓存变量:

set(my_cache_var "Hello, CMake!" CACHE STRING "A variable stored in the cache")

设置一个布尔变量:

set(my_bool_var TRUE)

强制设置一个变量的值:

set(my_var "New value" CACHE STRING "A variable with a new value" FORCE)

3.4 message 指令

在CMake中,message指令用于在构建过程中打印消息或调试信息

语法:

message([<mode>] "message to display" ...)

参数:
<mode>是可选的参数,用于指定消息的类型。常用的消息类型有以下几种:

  • STATUS:打印消息作为构建过程的状态信息
  • WARNING:打印警告消息
  • AUTHOR_WARNING:打印作者级别的警告消息
  • SEND_ERROR:打印错误消息,并停止构建过程
  • FATAL_ERROR:打印致命错误消息,并停止构建过程
  • DEPRECATION:打印废弃警告消息

"message to display"中,可以包含要打印的消息内容,可以是字符串常量、变量或表达式。可以通过使用${}语法来引用变量或表达式

示例:

message("Hello, World!")  # 打印普通消息

set(name "John")
message("Hello, ${name}!")  # 打印包含变量的消息

message(STATUS "This is a status message.")  # 打印状态消息

message(WARNING "This is a warning message.")  # 打印警告消息

message(SEND_ERROR "This is an error message.")  # 打印错误消息并停止构建

message(FATAL_ERROR "This is a fatal error message.")  # 打印致命错误消息并停止构建

3.5 add_executable 指令

在CMake中,add_executable 指令用于定义一个可执行文件的构建规则

语法:

add_executable(<target> [WIN32] [MACOSX_BUNDLE]
               [EXCLUDE_FROM_ALL]
               source1 [source2 ...])

参数:

  • <target>是要创建的可执行文件的名称。可以自定义名称,但通常与源文件的名称相关联。例如,如果有一个源文件main.cpp,那么可以将目标名称设置为myapp

可选参数包括:

  • WIN32:指定可执行文件在Windows上作为窗口应用程序运行
  • MACOSX_BUNDLE:指定可执行文件在macOS上作为应用程序捆绑包运行
  • EXCLUDE_FROM_ALL:指定可执行文件不会被默认构建,除非显式指定

source1 [source2 ...]中,指定了用于构建可执行文件的源文件列表。可以指定一个或多个源文件,它们将被编译并链接到可执行文件中

示例:

add_executable(myapp main.cpp utils.cpp)  # 创建一个名为myapp的可执行文件,使用main.cpp和utils.cpp作为源文件

在这个示例中,main.cpputils.cpp是源文件,它们将被编译并链接到名为myapp的可执行文件中

使用add_executable指令,可以定义一个或多个可执行文件的构建规则,并指定它们所需的源文件。这样,CMake将根据这些规则生成相应的构建系统文件,以编译和链接可执行文件


3.6 add_subdirectory 指令

在CMake中,add_subdirectory指令用于向当前CMakeLists.txt文件中添加子目录

语法:

add_subdirectory(<子目录> [二进制目录])

参数:

  1. <子目录>是要添加的子目录的路径,可以是相对路径或绝对路径
  2. [二进制目录]是可选参数,用于指定子目录的二进制输出目录

如果不指定二进制目录,CMake会在子目录中创建一个默认的二进制输出目录

当使用add_subdirectory时,CMake会在指定的子目录中查找一个名为CMakeLists.txt的文件,并执行该文件中的指令。这样,可以将一个大型项目分成多个子目录,每个子目录都有自己的CMakeLists.txt文件来管理

在子目录的CMakeLists.txt文件中,可以定义该子目录的构建规则、目标、变量等。子目录可以使用父目录中定义的变量和属性,也可以定义自己的变量和属性

使用add_subdirectory指令可以帮助管理复杂项目的结构,使得项目的构建更加模块化和可维护。通过将不同功能模块或子项目放在不同的子目录中,可以更好地组织代码和资源

需要注意的是,add_subdirectory指令必须在当前CMakeLists.txt文件中的project命令之后使用


3.7 add_library 指令

在CMake中,add_library 指令用于向CMake项目中添加一个库文件

语法:

add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            source1 source2 ... sourceN)

参数:

  1. <name>是库文件的名称
  2. source1 source2 ... sourceN是构建库文件所需的源文件

add_library指令有几个参数选项:

  • STATIC:指定库文件为静态库。静态库在链接时会被完整地复制到可执行文件中
  • SHARED:指定库文件为共享库(动态库)。共享库在运行时被动态加载,可被多个可执行文件共享
  • MODULE:指定库文件为模块库。模块库在运行时被动态加载,类似于共享库,但在某些平台上具有不同的加载方式
  • EXCLUDE_FROM_ALL:指定该库文件不会被默认构建。这在希望将库文件作为可选组件时非常有用

下面是一个示例:

add_library(MyLibrary STATIC source1.cpp source2.cpp)

在这个示例中,CMake将使用source1.cppsource2.cpp两个源文件构建一个名为MyLibrary的静态库


3.8 add_compile_options 指令

在CMake中,add_compile_options 指令用于向编译器添加编译选项。它的语法如下:

add_compile_options([target] <options>...)

参数:

  • target是可选的,表示要为特定目标添加编译选项。如果没有指定target,则编译选项将应用于整个项目

options是要添加的编译选项列表,可以是一个或多个选项。每个选项都是一个字符串,用于指定要传递给编译器的具体选项

下面是一些常见的编译选项示例:

  • -Wall:启用所有警告。
  • -Werror:将警告视为错误。
  • -O2:启用优化等级2。
  • -std=c++11:指定使用C++11标准。

示例:

# 添加编译选项到整个项目
add_compile_options(-Wall -Werror)

# 添加编译选项到特定目标
add_executable(myapp main.cpp)
target_compile_options(myapp PRIVATE -O2)

在上述示例中,通过add_compile_options-Wall-Werror选项添加到整个项目中的所有目标。然后,使用target_compile_options-O2选项添加到名为myapp的特定目标

通过使用add_compile_options指令,可以轻松地向CMake项目中的目标添加编译选项,以满足特定的编译需求


3.9 include_directories 指令

在CMake中,include_directories 是一个用于指定包含目录的指令。它用于告诉CMake编译器在编译过程中搜索头文件的位置

include_directories的语法如下:

include_directories([AFTER|BEFORE] [SYSTEM] <directory1> [<directory2> ...])

参数:

  • AFTERBEFORE(可选):指定包含目录的添加位置相对于已有的包含目录。默认情况下,新的包含目录会添加到已有目录的末尾。如果指定了AFTER,则新的目录将添加到已有目录的末尾;如果指定了BEFORE,则新的目录将添加到已有目录的开头
  • SYSTEM(可选):指定包含的目录是系统级别的目录,这意味着编译器在搜索头文件时会将其视为系统级别的目录,而不是项目级别的目录
  • <directory1> [<directory2> ...]:指定要添加的包含目录的路径。可以指定一个或多个目录,用空格分隔

使用include_directories指令的示例:

include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories(AFTER ${PROJECT_SOURCE_DIR}/third-party/include)
include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/system-include)

在上面的示例中,第一行将${PROJECT_SOURCE_DIR}/include目录添加为项目级别的包含目录。第二行使用AFTER指令将${PROJECT_SOURCE_DIR}/third-party/include目录添加到已有目录的末尾。第三行使用SYSTEM指令将${PROJECT_SOURCE_DIR}/system-include目录添加为系统级别的包含目录

通过使���include_directories指令,可以��定项目中需要搜索头文件的目录,以便编译器能够正确找到并包含所需的头文件


当在CMake中构建一个项目时,可能需要链接一些库文件。link_directories 指令用于指定链接库文件的目录

语法:

link_directories(directory1 directory2 ...)

参数:

  • directory1, directory2, ... 是链接库文件的目录路径

link_directories 指令告诉CMake在链接阶段搜索库文件时应该查找的目录。这样,就可以在代码中使用库文件而无需指定完整的路径

下面是一个示例:

link_directories(/path/to/lib1 /path/to/lib2)

在这个示例中,CMake将在链接阶段搜索/path/to/lib1/path/to/lib2目录中的库文件

需要注意的是,使用link_directories指令并不会自动链接库文件,它只是告诉CMake在链接阶段搜索库文件的位置。要链接库文件,还需要使用target_link_libraries指令

下面是一个完整的示例:

cmake_minimum_required(VERSION 3.0)
project(MyProject)

# 指定链接库文件的目录
link_directories(/path/to/lib1 /path/to/lib2)

# 添加可执行文件
add_executable(MyExecutable main.cpp)

# 链接库文件
target_link_libraries(MyExecutable lib1 lib2)

在这个示例中,CMake将在��接阶段搜索/path/to/lib1/path/to/lib2目录中的库文件,并将lib1lib2链接到MyExecutable可执行文件中


在CMake中,target_link_libraries指令用于将库文件链接到目标(可执行文件、共享库等)

语法:

target_link_libraries(<target> [item1] [item2] [...])

参数:

  • target是要链接库的目标,可以是可执行文件、共享库或静态库
  • item1, item2, ...是要链接的库文件或目标。可以指定一个或多个库文件或目标

示例:

# 链接共享库
add_executable(myapp main.cpp)
target_link_libraries(myapp mylib)

# 链接多个库文件
target_link_libraries(myapp lib1 lib2 lib3)

# 链接系统库
target_link_libraries(myapp pthread)

在上述示例中,通过target_link_libraries将名为mylib的共享库链接到myapp可执行文件。然后,使用target_link_libraries链接了多个库文件lib1lib2lib3myapp。最后,通过target_link_libraries链接了系统库pthreadmyapp

除了库文件,还可以使用其他目标作为参数。这允许将一个目标链接到另一个目标,以构建更复杂的项目结构

需要注意的是,CMake会自动处理库文件之间的依赖关系,因������需手动指定依赖关系的顺序


3.12 aux_source_directory 指令

当使用CMake构建项目时,aux_source_directory 指令用于将指定目录下的源文件自动添加到一个变量中

语法:

aux_source_directory(dir variable)

参数:

  • dir是要搜索源文件的目录路径
  • variable是用于存储找到的源文件列表的变量名

aux_source_directory指令会自动查找指定目录下的所有源文件,并将它们的完整路径添加到variable变量中。这样,就可以在后续的构建过程中使用这个变量来引用这些源文件

需要注意的是,aux_source_directory指令只会自动查找指定目录下的源文件,而不会查找子目录中的源文件。如果希望递归地查找源文件,可以使用aux_source_directory指令的增强版aux_source_directory_recursive

示例:

aux_source_directory(src SOURCES)
add_executable(myapp ${SOURCES})

在上面的示例中,aux_source_directory指令会查找src目录下的所有源文件,并将它们的路径存储在SOURCES变量中。然后,我们可以使用add_executable指令将这些源文件编译为一个可执行文件


3.13 install 指令

在CMake中,安装是指将构建生成的文件(可执行文件、库文件、头文件等)复制到��定位��,以便用户可以在系统上使用。CMake提供了一系列命令和变量,用于定义安装规则和目标

首先,需要在CMakeLists.txt文件中使用install命令来定义安装规则

基本语法如下:

install(<文件/目录> ... DESTINATION <目标路径>
        [PERMISSIONS <权限>]
        [CONFIGURATIONS [Debug|Release|...]]
        [COMPONENT <组件>]
        [OPTIONAL]
)

参数:

  1. <文件/目录>表示要安装的文件或目录的路径。可以使用相对路径或绝对路径,并可以使用通配符进行模式匹配。可以指定多个文件或目录,以空格分隔
  2. DESTINATION指定了目标路径,即要将文件/目录安装到的位置。可以使用绝对路径或相对路径。相对路径是相对于CMAKE_INSTALL_PREFIX变量定义的路径。可以使用${CMAKE_INSTALL_PREFIX}变量来引用CMAKE_INSTALL_PREFIX
  3. PERMISSIONS是可选参数,用于设置安装文件的权限。可以使用UNIX风格的权限表示,如OWNER_READ、GROUP_WRITE等
  4. CONFIGURATIONS是可选参数,用于指定只在特定构建配置下安装文件。可以使用Debug、Release等构建配置名称
  5. COMPONENT是可选参数,用于指定安装文件所属的组件。组件可以用于将安装文件分组,方便用户选择安装哪些组件

OPTIONAL是可选参数,���示安装文件是可选的。如果文件不存在��将不会引发错误

除了install命令,还可以使用其他命令来定义安装规则,如install(DIRECTORY)用于安装目录,install(TARGETS)用于安装目标(可执行文件、库文件等)

在CMakeLists.txt文件中,可以使用CMAKE_INSTALL_PREFIX变量来定义安装的根目录。默认情况下,CMAKE_INSTALL_PREFIX被设置为/usr/local,但可以通过命令行参数或CMake GUI进行修改

安装时,可以使用以下命令来执行构建和安装:

cmake <源码目录>
make
make install

执行make命令会根据CMakeLists.txt文件中定义的构建规则进行构建。执行make install命令会将构建生成的文件安装到指定位置

需要注意的是,安装目录需要有足够的权限才能进行安装。对于系统级的安装,可能需要使用管理员权限进行安装

4. CMake 常用变量

在CMake中,有一些常用的预定义变量,它们提供了关于项目、系统和构建环境的信息

下面是一些常见的CMake变量及其描述:

变量名 描述
CMAKE_SOURCE_DIR 项目根目录的绝对路径
CMAKE_BINARY_DIR 构建目录的绝对路径
CMAKE_CURRENT_SOURCE_DIR 当前处理的源文件目录的绝对路径
CMAKE_CURRENT_BINARY_DIR 当前处理的二进制目录的绝对路径
CMAKE_C_COMPILER C编译器的路径
CMAKE_CXX_COMPILER C++编译器的路径
CMAKE_INCLUDE_PATH 需要搜索的附加头文件路径
CMAKE_LIBRARY_PATH 需要搜索的附加库文件路径
CMAKE_INSTALL_PREFIX 安装目录的前缀路径
CMAKE_BUILD_TYPE 构建类型,例如Debug、Release等
CMAKE_C_FLAGS C编译器的附加编译选项
CMAKE_CXX_FLAGS C++编译器的附加编译选项,一般在后面会追加 std=c++11
CMAKE_EXE_LINKER_FLAGS 可执行文件链接器的附加选项
CMAKE_SHARED_LINKER_FLAGS 共享库链接器的附加选项
CMAKE_MODULE_PATH CMake模块文件的搜索路径
CMAKE_FIND_ROOT_PATH 用于交叉编译时指定依赖库的根目录
CMAKE_SYSTEM_NAME 目标系统的名称,用于交叉编译时指定目标系统
CMAKE_SYSTEM_VERSION 目标系统的版本号,用于交叉编译时指定目标系统版本

5. CMake 的语法规则

5.1 语法的规则

  1. 命令(Command):CMake的语法由一系列命令组成,每个命令都以小写字母开头,并且以括号包围参数。例如,message("Hello, World!")是一个命令,它将在构建过程中输出"Hello, World!"

  2. 参数(Arguments):命令的参数可以是字符串、变量或表达式。参数之间使用空格分隔。例如,message("The answer is ${answer}")中的${answer}是一个变量

  3. 变量(Variables):CMake中的变量用于存储和传递数据。变量的名称由字母、数字和下划线组成,并且区分大小写。变量的值可以是字符串、列表或布尔值。可以使用set命令来设置变量的值,例如set(my_variable "Hello")

  4. 注释(Comments):在CMake中,使用#符号来添加注释。注释可以出现在一行的开头或中间,用于解释代码的作用或提供其他相关信息

  5. 条件语句(Conditionals):CMake支持条件语句,用于根据不同的条件执行不同的代码块。常用的条件语句有ifelseendif。例如:

if(condition)
    # code block
else()
    # code block
endif()
  1. 循环语句(Loops):CMake提供了几种循环语句来重复执行代码块。常用的循环语句有foreachwhile。例如:
foreach(item IN LISTS list_variable)
    # code block
endforeach()
  1. 函数(Functions):CMake允许定义和调用函数来组织代码并实现代码的复用。函数可以接受参数,并可以返回值。例如:
function(my_function arg1 arg2)
    # code block
endfunction()

5.2 语法注意事项

当使用CMake编写脚本时,有一些语法注意事项需要注意。以下是一些常见的注意事项:

  1. 大小写敏感:CMake是大小写敏感的,因此变量名、命令和函数名必须与其在脚本中的使用方式完全匹配

  2. 空格和括号:在CMake中,命令和函数之间需要有空格,并且命令和函数的参数需要用括号括起来,如果源文件名中有空格,那么需要把文件名用双引号括起来

  3. 注释:CMake使用“#”符号来表示注释。可以使用注释来解释代码的目的或提供其他相关信息

  4. 变量:在CMake中,变量使用${}语法进行引用。变量可以是全局变量���也可以是局部变量。在使用变量之前,通��需要使用set()命令来定义变量

  5. 条件语句:CMake支持条件语句,可以使用if()else()endif()来进行条件判断。条件语句可以根据变量的值或其他条件来执行不同的操作

  6. 循环语句:CMake支持循环语句,可以使用foreach()while()endforeach()等命令来进行循环操作。循环语句可以用于遍历列表或执行一系列重复的操作

  7. 函数:CMake支持自定义函数,可以使用function()endfunction()命令来定义函数。函数可以接受参数,并且可以在脚本中多次调用

  8. 文件包含:CMake允许通过使用include()命令来包含其他CMake脚本文件。这可以帮助组织和复用代码

  9. 路径处理:CMake提供了一些用于处理路径的命令,如get_filename_component()file()命令。这些命令可以用于获取文件名、目录名或扩展名,以及执行其他与文件和目录相关的操作

  10. 错误处理:CMake提供了一些命令和变量来处理错误和警告。例如,可以使用message()命令输出消息,使用FATAL_ERROR选项终止脚本的执行

6. 内部构建和外部构建

CMake支持两种主要的构建方式:内部构建(in-source build)和外部构建(out-of-source build)。它们在项目的构建目��和源代码目录之间有所区别

6.1 内部构建(In-Source Build):

  • 内部构建是指在源代码目录中直接进行构建,生成的构建文件和中间文件与源代码文件混在一起
  • 在内部构建中,CMake生成的构建系统文件(如Makefile或Visual Studio项目文件)将与源代码文件放在同一个目录中
  • 这种方式简单方便,适用于小型项目或快速测试,但不推荐在实际项目中使用,因为会导致构建文件和源代码文件混乱,难以清理和管理

6.2 外部构建(Out-of-Source Build):

  • 外部构建是指在与源代码目录分离的地方进行构建,生成的构建文件和中间文件与源代码文件分开
  • 在外部构建中,需要创建一个单独的构建目录,并在该目录中运行CMake来生成构建系统文件
  • 这种方式将构建文件和源代码文件分开,使得项目结构更加清晰,也更容易进行清理和管理
  • 外部构建还允许同时使用多个不同的构建目录,用于构建不同的配置(例如Debug和Release)或不同的平台

使用外部构建的步骤如下:

  1. 创建一个单独的构建目录,例如在项目根目录下创建一个名为"build"的目录
  2. 进入构建目录,并在该目录中运行CMake命令,指定源代码目录的路径。例如:cmake /path/to/source_code
  3. CMake将在��建目录中生成构建系统文件,如Makefile或Visual Studio项目文件
  4. 使用生成的构建系统文件进行构建,例如使用Make命令或打开Visual Studio进行编译

通过使用外部构建,可以轻松地清理构建文件,同时也可以避免将构建文件与源代码文件混在一起。这种方式更加灵活和可维护,是在实际项目中推荐的构建方式

7. CMake 编译工程

CMake的目录结构通常包含以下几个重要的部分:

  1. 项目根目录:项目的根目录是CMakeLists.txt文件所在的目录。在这个目录下,你可以定义项目的全局设置和配置选项
  2. 子目录:项目可以被组织成多个子目录,每个子目录都可以有自己的CMakeLists.txt文件。这种组织方式可以帮助你将项目划分为更小的模块,提高代码的可维护性
  3. 源代码目录:源代码目录是存放项目源代码的目录,通常包含头文件(.h或.hpp文件)和源文件(.cpp文件)。你可以在CMakeLists.txt文件中使用add_executableadd_library指令来指定源代码目录
  4. 构建目录:构建目录是用于构建项目的目录,通常是在项目根目录外创建的。在构建目录中,CMake会生成构建系统所需的文件(如Makefile或Visual Studio项目文件),并在这个目录中执行构建操作

下面是一个简单的CMake项目的目录结构示例:

MyProject/
├── CMakeLists.txt
├── src/
│   ├── main.cpp
│   ├── utils.cpp
│   └── utils.h
└── build/

在这个示例中,MyProject是项目的根目录,其中包含了CMakeLists.txt文件。src目录是存放源代码的目录,包含了main.cpputils.cpputils.h文件。build目录是构建目录,
用于执行构建操作

7.1 Linux平台下的编译流程

在 Linux 平台下使用 CMake 构建 C/C++ 工程的流程如下:

  1. 在项目文件夹根目录下创建 CMakeLists.txt 文件
  2. 编写 CMakeLists.txt 文件
    1. 首先,通过 cmake_minimum_required 指令指定项目最低 CMake 版本
    2. 使用 project 指令指定工程名 (一般建议大写)
      • 首先需要选择是外部构建还是内部构建
    3. 使用 add_executable 指令指定可执行文件名和相关源文件序列
    4. 确定是外部构建
      1. 首先先创建 build 文件夹用来存放 CMake 编译后产生的文件
      2. 创建好文件夹后,通过 cmake CMakeLists.txt文件路径 指令编译
      3. 编译完成后,生成 Makefile 文件,使用 make Makefile文件所在路径 命令来构建项目生成可执行文件
      4. 最后在 build 目录中找到可执行文件并执行

注意:如果项目含有头文件,那么你需要在 CMakeLists.txt 中用指令 include_directories 指定头文件所在的文件目录 (绝对路径)

实操 CMake 构建工程

  1. 在 CMake 中设置源代码目录和构建后存放二进制文件的目录build
  2. 点击 Configure,选择工程的生成器,设置后点击 Finish
  3. 点击 Configure 后开始构建,之后点击 Generate 生成的工程文件会存放在 build 文件夹中
  4. build文件夹里可以找到helloworld.sln文件,用 Visual Studio 2022 打开,之后点击生成解决方案

posted @ 2023-06-27 13:30  sarexpine  阅读(88)  评论(0编辑  收藏  举报