Linux下CMakeLists.txt编译多模块C++程序
一、代码结构
hello_world/
├── bin/ # 存放生成的可执行文件
├── lib/ # 存放生成的库文件(此项目中未实际使用)
├── build/ # 构建目录(用于存放 CMake 生成的构建文件)
├── src/ # 存放源文件
│ ├── main.cpp # 主程序源文件
│ └── hello_world.cpp # HelloWorld 类的实现文件
├── include/ # 存放头文件
│ └── hello_world.h # HelloWorld 类的声明文件
└── CMakeLists.txt # CMake 构建系统配置文件
二、前置准备
创建文件夹
mkdir hello_world && cd hello_world
mkdir bin # 存放生成的可执行文件
mkdir lib # 存放生成的库文件
mkdir build # 构建目录
mkdir src # 存放源文件
mkdir include # 存放头文件
touch CMakeLists.txt
在src目录下创建源文件
touch main.cpp
touch hello_world.cpp
在include中创建头文件
touch hello_world.h
编写hello_world.h头文件
// hello_world.h
#include <iostream>
class HelloWorld
{
public:
HelloWorld(const std::string message);
~HelloWorld();
void print_someinfo();
private:
std::string msg_;
};
编写源文件
// hello_world.cpp
#include "hello_world.h"
HelloWorld::HelloWorld() : msg_(message)
{
std::cout << "调用了构造函数" << std::endl;
}
HelloWorld::~HelloWorld()
{
std::cout << "调用了析构函数" << std::endl;
}
HelloWorld::print_someinfo()
{
std::cout << "msg: " << msg_ << std::endl;
}
// main.cpp
#include <hello_world.h>
int main()
{
HelloWorld hw("欢迎你,Hello World!");
hw.print_someinfo();
return 0;
}
编写CMakeLists.txt
cmake_minimum_required(version 3.5)
project(hello_world LANGUAGES CXX)
# 设置可执行文件的保存地址
set(EXECTUABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
# 设置库文件保存路径
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
# 添加头文件搜索路径
include_directories(
${PROJECT_SOURCE_DIR}/include
)
# 添加所有要编译的源文件
set(SOURCE
src/main.cpp
src/hello_world.cpp
)
# 生成可执行文件
add_executable(hello_world ${SOURCE})
三、编译并运行
cd build
cmake ..
make -j8
执行
四、多模块编译
在开发时,往往将整个项目划分为多个模块,每个模块各司其职,然后组合起来形成完整的项目。
在python和Java中都有包的概念,因此划分多模块很简单,而C++中是没有包的概念的,如果想要以多模块的形式进行开发,可以使用CMake来实现。
在上述代码的基础上,修改代码如下,去除了src和include文件夹,新增了utils模块、hello_world模块和hello_world2模块.
在顶层CMakeLists.txt中
添加三个子模块
cmake_minimum_required(version 3.5)
project(hello_world LANGUAGES CXX)
# 设置可执行文件的保存地址
set(EXECTUABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
# 设置库文件保存路径
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
add_subdirectory(utils)
add_subdirectory(hello_world)
add_subdirectory(hello_world2)
# 添加所有要编译的源文件
set(SOURCE
main.cpp
)
# 生成可执行文件
add_executable(main ${SOURCE})
# 连接模块到主程序
target_link_libraries(main utils hello1 hello2)
target_include_directories(main
PRIVATE
&{CMAKE_CURRENT_SOURCE_DIR}/hello_world/include
&{CMAKE_CURRENT_SOURCE_DIR}/hello_world2/include
&{CMAKE_CURRENT_SOURCE_DIR}/utils/include
)
在子模块CMakeLists.txt
主函数
五、不同模块之间相互引用
模块之间的引用通常通过头文件和链接库来实现。假设你的 hello_world
模块需要引用 hello_world2
模块中的某些功能,你需要确保 hello_world
模块的源文件能够包含 hello_world2
模块的头文件,并且在编译时链接到 hello_world2
模块生成的库。
# hello_world cmakelist.txt
# 添加模块 hello_world 的头文件搜索路径
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/hello_world2/include # 添加 hello_world2 模块的头文件路径
)
# 添加模块 hello_world的源文件
set(SOURCE
src/hello_world.cpp
)
# 生成模块 hello1 的静态库
add_library(hello1 STATIC ${SOURCE})
# 链接 hello_world2 模块的库
target_link_libraries(hello1 hello2)
# hello_world2 cmakelist.txt
# 添加模块 hello_world2 的头文件搜索路径
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/include
)
# 添加模块 hello_world2 的源文件
set(SOURCE
src/hello_world2.cpp
)
# 生成模块 hello2 的静态库
add_library(hello2 STATIC ${SOURCE})
在 hello_world.cpp
中,你可以包含 hello_world2
模块的头文件,并使用其功能:
#include "hello_world.h"
#include "hello_world2.h" // 包含 hello_world2 模块的头文件
HelloWorld::HelloWorld(const std::string message) : msg_(message) {
std::cout << "调用了构造函数" << std::endl;
}
HelloWorld::~HelloWorld() {
std::cout << "调用了析构函数" << std::endl;
}
void HelloWorld::print_someinfo() {
std::cout << "msg: " << msg_ << std::endl;
// 使用 hello_world2 模块的功能
printWorldMessage();
}
Linux下CMakeLists.txt编译多模块C++程序
http://47.92.222.121:8090/archives/KFshJUEF