在 CMake 中,使用 add_subdirectory()
函数可以将一个子目录添加到构建过程中,从而可以在子目录中包含自己的 CMakeLists.txt
文件。这种方法对于管理大型项目尤其有效,因为它可以将不同的模块或库分开,使项目结构更清晰。
同时可以使用 option()
函数来控制是否在构建过程中包括某些库或功能。这对于使项目的构建过程更加灵活非常有用。
使用 add_subdirectory()
的基本步骤
1. 项目结构
首先,考虑一个示例项目的目录结构:
MyProject/
├── CMakeLists.txt
├── src/
│ ├── CMakeLists.txt
│ └── main.cpp
└── lib/
├── CMakeLists.txt
└── my_lib.cpp
2. 根目录的 CMakeLists.txt
在根目录的 CMakeLists.txt
文件中,你可以设置项目的基本信息并使用 add_subdirectory()
来添加子目录。
cmake
cmake_minimum_required(VERSION 3.10)
project(MyProject)
# 添加 lib 子目录
add_subdirectory(lib)
# 添加 src 子目录
add_subdirectory(src)
# 其他全局设置
3. lib
目录的 CMakeLists.txt
在 lib
目录中,你可以定义一个库,比如一个共享库或静态库。
cmake
# lib/CMakeLists.txt
# 定义一个选项来控制是否构建库
option(USE_MY_LIB "Use my_lib library" ON)
if(USE_MY_LIB)
# 创建一个库
add_library(my_lib my_lib.cpp)
# 如果需要,设置库的包含目录
target_include_directories(my_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
else()
message(STATUS "my_lib library is disabled")
endif()
4. src
目录的 CMakeLists.txt
在 src
目录中,你可以定义可执行文件,并将之前创建的库链接到这个可执行文件。
cmake
# src/CMakeLists.txt
# 创建一个可执行文件
add_executable(my_executable main.cpp)
# 如果 USE_MY_LIB 被启用,则链接库
if(USE_MY_LIB)
target_link_libraries(my_executable PRIVATE my_lib)
endif()
5. main.cpp
示例
在 src/main.cpp
中,你可以使用库的功能:
cpp
#include <iostream>
#ifdef USE_MY_LIB
#include "my_lib.h" // 假设你有相应的头文件
#endif
int main() {
std::cout << "Hello, World!" << std::endl;
#ifdef USE_MY_LIB
// 调用库中的函数
std::cout<<"MyAdd result:" << MyAdd(3,4) << std::endl;
#else
std::cout<<"Add result:" << 3+4 << std::endl;
#endif
return 0;
}
6. 构建项目
在项目的根目录下,可以使用以下命令生成构建文件:
使用-D参数设置 USE_MY_LIB
选项的值。
- 启用my_lib库
bash
mkdir build
cd build
cmake ../ -DUSE_MY_LIB=OFF
make
-
禁用my_lib库
mkdir build
cd build
cmake ../ -DUSE_MY_LIB=ON
make
总结
add_subdirectory()
: 用于将子目录添加到构建中,并在该子目录中查找CMakeLists.txt
文件。- 结构化管理: 这种方法使得大项目的结构更加清晰,便于维护。
- 目标链接: 你可以在子目录中定义库,并在其他子目录中链接这些库,形成良好的模块化结构。
- 设置选项 : 在 CMake 命令行中使用
-D
参数来设置选项的值
示例完整代码
根目录 CMakeLists.txt
cmake
cmake_minimum_required(VERSION 3.10)
project(MyProject)
# 添加 lib 和 src 子目录
add_subdirectory(lib)
add_subdirectory(src)
# 其他全局设置
lib/CMakeLists.txt
cmake
# lib/CMakeLists.txt
# 定义一个选项来控制是否构建库
option(USE_MY_LIB "Use my_lib library" ON)
if(USE_MY_LIB)
# 创建一个库
add_library(my_lib my_lib.cpp)
# 如果需要,设置库的包含目录
target_include_directories(my_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
else()
message(STATUS "my_lib library is disabled")
endif()
src/CMakeLists.txt
cmake
# src/CMakeLists.txt
# 创建一个可执行文件
add_executable(my_executable main.cpp)
# 如果 USE_MY_LIB 被启用,则链接库
if(USE_MY_LIB)
target_link_libraries(my_executable PRIVATE my_lib)
endif()
src/main.cpp
cpp
#include <iostream>
#ifdef USE_MY_LIB
#include "my_lib.h" // 假设你有相应的头文件
#endif
int main() {
std::cout << "Hello, World!" << std::endl;
#ifdef USE_MY_LIB
// 调用库中的函数
std::cout<<"MyAdd result:" << MyAdd(3,4) << std::endl;
#else
std::cout<<"Add result:" << 3+4 << std::endl;
#endif
return 0;
}
这样,你就可以成功使用 add_subdirectory()
将多个子模块集成到你的 CMake 项目中。