Linux下CMakeLists.txt编译多模块C++程序
编程 服务器 Linux C++ 16

一、代码结构

hello_world/
├── bin/                # 存放生成的可执行文件
├── lib/                # 存放生成的库文件(此项目中未实际使用)
├── build/              # 构建目录(用于存放 CMake 生成的构建文件)
├── src/                # 存放源文件
│   ├── main.cpp        # 主程序源文件
│   └── hello_world.cpp # HelloWorld 类的实现文件
├── include/            # 存放头文件
│   └── hello_world.h   # HelloWorld 类的声明文件
└── CMakeLists.txt      # CMake 构建系统配置文件

二、前置准备

  1. 创建文件夹

mkdir hello_world && cd hello_world
mkdir bin # 存放生成的可执行文件
mkdir lib  # 存放生成的库文件
mkdir build  # 构建目录

mkdir src  # 存放源文件
mkdir include # 存放头文件

touch CMakeLists.txt

  1. 在src目录下创建源文件

touch main.cpp
touch hello_world.cpp

  1. 在include中创建头文件

touch hello_world.h

  1. 编写hello_world.h头文件

// hello_world.h
#include <iostream>

class HelloWorld
{
public:
  HelloWorld(const std::string message);
  ~HelloWorld();

  void print_someinfo();

private:
  std::string msg_;
};

  1. 编写源文件

// 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;
}

  1. 编写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模块.

  1. 在顶层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

)

  1. 在子模块CMakeLists.txt

  1. 主函数

五、不同模块之间相互引用

模块之间的引用通常通过头文件和链接库来实现。假设你的 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
作者
禧语许
发布于
更新于
许可