C++编译之级联cmake

发布时间:2023年12月18日

在一个项目中,可能存在多个子项目或者模块,每个子项目有自己的 CMake 配置,而外层的 CMake 文件则负责整体的构建和协调各个子项目的编译过程。这种结构通常被称为多级 CMake 构建。

连接外层 CMake 和内层 CMake 的关键是使用 add_subdirectory 命令。这个命令用于将其他目录中的 CMakeLists.txt 文件包含到当前项目中。这样,当执行外层的 CMake 时,它会递归地处理子目录中的 CMakeLists.txt 文件,将子项目的构建规则整合到主项目中。
当创建一个包含内外层 CMake 和简单测试项目的多级 CMake 项目时,我们可以考虑以下结构。假设你的项目包含一个主应用程序和两个子模块。

首先,创建一个顶层目录 MyProject,并在该目录下创建以下文件:

CMakeLists.txt(外层 CMake 文件):

# 外层 CMakeLists.txt

cmake_minimum_required(VERSION 3.12)
project(MyProject)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)

# 添加子目录
add_subdirectory(submodule1)
add_subdirectory(submodule2)

# 外层项目的源文件
set(SOURCE_FILES main.cpp)

# 外层项目的可执行文件
add_executable(main_exec ${SOURCE_FILES})

# 连接外层项目和子模块
target_link_libraries(main_exec submodule1_lib submodule2_lib)

main.cpp(外层项目的源文件):

// main.cpp

#include <iostream>

int main() {
    std::cout << "Hello from main_exec!" << std::endl;
    return 0;
}
submodule1/CMakeLists.txt(第一个子模块的 CMake 文件):

# submodule1/CMakeLists.txt

# 子模块1的配置...

# 子模块1的源文件
set(SOURCE_FILES_submodule1 submodule1.cpp)

# 子模块1的库
add_library(submodule1_lib ${SOURCE_FILES_submodule1})

# 子模块1的头文件路径
target_include_directories(submodule1_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
submodule1/submodule1.cpp(第一个子模块的源文件):

// submodule1.cpp

#include <iostream>

void submodule1_function() {
    std::cout << "Hello from submodule1_lib!" << std::endl;
}
submodule2/CMakeLists.txt(第二个子模块的 CMake 文件):

# submodule2/CMakeLists.txt

# 子模块2的配置...

# 子模块2的源文件
set(SOURCE_FILES_submodule2 submodule2.cpp)

# 子模块2的库
add_library(submodule2_lib ${SOURCE_FILES_submodule2})

# 子模块2的头文件路径
target_include_directories(submodule2_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
submodule2/submodule2.cpp(第二个子模块的源文件):

// submodule2.cpp

#include <iostream>

void submodule2_function() {
    std::cout << "Hello from submodule2_lib!" << std::endl;
}

这个示例项目包含一个主应用程序和两个子模块。外层 CMake 文件 CMakeLists.txt 配置了主应用程序,连接了两个子模块的库。每个子模块有自己的 CMake 文件,负责配置子模块的构建规则。

你可以通过在项目的根目录下执行 cmake . 和 make 命令(或相应平台上的构建工具)来测试整个项目,或者新建build文件后在build执行cmake…和make命令。这将构建主应用程序以及两个子模块的库,并最终生成可执行文件 main_exec。
外层项目通过 target_link_libraries 命令将两个子模块的库连接到主应用程序。这意味着外层项目 main_exec 会使用子模块1的库 submodule1_lib 和子模块2的库 submodule2_lib。

具体而言,这里是关键的部分:


# 外层 CMakeLists.txt

# 添加子目录
add_subdirectory(submodule1)
add_subdirectory(submodule2)

# ...

# 外层项目的可执行文件
add_executable(main_exec ${SOURCE_FILES})

# 连接外层项目和子模块
target_link_libraries(main_exec submodule1_lib submodule2_lib)

这段代码使用 target_link_libraries 将 submodule1_lib 和 submodule2_lib 连接到 main_exec 可执行文件。这表示在构建 main_exec 时,链接器将链接 submodule1_lib 和 submodule2_lib 提供的功能。

因此,如果在 main.cpp 中调用了来自子模块的函数,如:

#include <iostream>
#include "submodule1/submodule1.cpp"
#include "submodule2/submodule2.cpp"

int main() {
    std::cout << "Hello from main_exec!" << std::endl;
    
    submodule1_function();
    submodule2_function();
    
    return 0;
}

在运行 main_exec 时,它将输出 “Hello from submodule1_lib!” 和 “Hello from submodule2_lib!”,表示主应用程序成功地与两个子模块相互连接。
例程包:

文章来源:https://blog.csdn.net/qq_42244167/article/details/135013439
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。