CMake 项目模块化布局
Contents
在 C\C++ 项目中,通常会有不止一个可执行程序,或者需要将一些调用封装成动态或静态库,来实现项目的模块化,本文就讲解一种支持这种项目布局的方法。
CMake 支持子目录构建(add_subdirectory
指令),本文介绍的布局方法就是基于这个功能来实现。
项目
项目根目录编写一个 CMakeLists.txt
,主要描述项目名称,也可以将一些项目级别的配置写入,来影响所有项目构建目标。比如编译的警告级别设置,如果要在项目级别上统一,可以写入,如果要针对不同构建目标来设置,可以留到构建目标 CMakeLists.txt
文件中写入。
项目的各个构建目标作为子目录存放在项目根目录下,每个子目录均包含相应的构建 CMakeLists.txt
文件。使用 add_subdirectory
指令将构建目标子目录添加到项目 CMakeLists.txt
中,构建目标间可以相互引用,只要在添加子目录到项目 CMakeLists.txt
时保持依赖顺序即可。
项目 CMakeLists.txt
示例:
|
|
项目 TestApps
中包含4个构建目标目录,2 个库 staticlib
和 sharelib
,依赖库的 1 个应用程序 testapp
,以及配置文件类目标 config
。4 个目标的输出文件均统一到了构建目录下,按类型分类,这样便于构建结果的归档处理。
通常将构建目标子目录名与目标名一致,这样便于项目管理。
目标
每个构建目标对应在项目根目录下的各个子目录,每个子目录中都有一个 CMakeLists.txt
文件,记录着对应的构建配置。这些构建配置均会继承项目 CMakeLists.txt
文件中的配置。
以下针对示例项目,讲解各个子目录的 CMakeLists.txt
,用以理解如何进行具体的项目布局。
目标 staticlib
(静态库编译示例):
|
|
add_library
指令添加一个库目标,参数 STATIC
表示编译成静态库,该目标链接时需要链接数学库。
目标 sharelib
(动态库编译示例):
|
|
与目标 staticlib
差不多,只是add_library
参数 SHARED
表示编译成动态库。
目标 testapp
(执行程序编译示例):
|
|
add_executable
指令添加一个可执行目标,其依赖于静态库 staticlib
和动态库 sharelib
。
目标 config
(配置文件示例):
|
|
config
目标是一个特殊目标,其不构建库或可执行程序,而是执行一个文件拷贝工作,在此示例中,将 config
目录下的文件(除 CMakeLists.txt
和 README.md
)都拷贝到可执行输出目录中。这个用法一般用于拷贝程序的默认配置文件。这样做的好处在于可以将默认配置文件纳入版本管理,也方便打包程序以及测试部署,既能将代码与输出分离,又能实现自动化整合。
结语
CMake 是一个很便利的跨平台构建工具,使用模块化布局方法可以更契合多人共享开发模式,促进项目复用代码,方便上下游库协同管理。如果与 Git 的 submodule 配合,就更能体现出模块化。