(六)构建可执行文件

20 阅读3分钟

定义构建目标: add_executable()命令

在CMake中,构建目标(Build Target)是构建系统的基本产出单元,最常见的两种目标就是可执行文件(Executable)和库文件(Library)。add_executable()命令正是用于告诉CMake,"我想要从这里列出的源代码文件,构建出一个可以运行的程序"

命令基本语法 add_executable()命令有两种主要形式:

使用源文件列表

add_executable(<target_name> [source1] [source2] ...)

平台默认行为

  • <target_name> : 你希望生成的可执行文件的名字。这是一个你自己定义的标识符,在同一个CMake项目中必须是唯一的。
  • [source1] [source2] ... : 构建这个可执行文件所需要的所有源文件(如 .cpp , .c , .cc等),用空格或换行分隔。

使用源文件列表(带选项的形式) add_executable(<target_name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] [source1] [source2] ...)

  • <target_name> 和源文件列表的含义与第一种形式相同
  • 其他是可选的关键字,用于指定特定平台的属性: WIN32:在Windows上构建时,表示这是一个GUI应用程序(子系统为 Windows),而不是控制台应用程序。 MACOSX_BUNDLE:在macOS上构建时,会将可执行文件打包成一个 .app 应用程序包。 EXCLUDE_FROM_ALL:如果设置,意味着这个目标不会被包含在默认的 all 目标中。除非你显式构建它,否则它不会被编译。

命令的核心作用 当CMake在执行配置阶段遇到add_executable()命令时,它会执行一系列关键操作,其内部处理流程可以概括为下图:

image.png 简单示例:

    # 定义一个名为“hello_world”的可执行文件,由一个源文件构成
    add_executable(hello_world main.cpp)

执行构建后,你将会在构建输出目录中得到一个名为 hello_world(在Windows上可能是 hello_world.exe)的可执行文件。

管理源代码文件列表

对于简单的示例,直接在add_executable()中列出所有源文件是可行的。但对于任何有实际意义的项目,源文件数量都会增长,如何有效的管理它们就变得至关重要。

方法一:直接列出源文件(适用于小型项目)

image.png 缺点:当项目规模扩大,需要添加或删除文件时,必须手动修改 CMakeLists.txt,容易出错和遗漏。

方法二:使用变量存储文件列表(推荐)

使用 set() 命令将一个文件列表赋值给一个变量,然后在 add_executable() 中引用这个变量。

image.png

优势:

  • 集中管理:所有源文件在一个地方定义,一目了然。
  • 易于修改:添加或删除文件只需在一个列表中进行。
  • 可复用:这个变量可以在其他地方被使用,例如用于生成文档、安装文件等。

方法三:使用 file() 命令自动收集源文件

对于模块化结构清晰的大型项目,可以使用 file(GLOB ...) 命令让CMake自动在指定目录下匹配并收集源文件。

image.png 关于 file(GLOB) 的争议与最佳实践:

  • 优点:方便!添加新文件时,无需修改 CMakeLists.txt。
  • 缺点:

a. CMake不会自动检测新增文件:如果只是添加了一个新的 .cpp 文件而没有重新运行 cmake,构建系统将不知道它的存在。你必须手动重新运行CMake来更新文件列表。 b. 不够精确:可能会匹配到你不希望编译的源文件(如测试文件、备用实现等)。

实战:构建一个包含多个源文件的可执行程序

项目结构: TodoList项目,目录结构如下:

image.png

  • TodoList 和 TodoManager:包含具体实现。
  • main.cpp:包含 main() 函数,是程序的入口。
  • README.md:一般完整项目都要有一个README.md
  • CMakeLists.txt:我们只有一个文件,正常如果项目非常复杂的话,肯定是不止一个的,每个文件夹下都会有一个

编写 CMakeLists.txt

现在,我们来编写顶层的 CMakeLists.txt 文件

image.png

image.png

image.png