Skip to content

CMake构建项目的方式

直接写入源码路径

  • add_executable中直接写入相对路径
  • 在源码中引入头文件时需要写相对路径

直接测试

现在有以下目录结构及代码环境

shell
$ tree
.
├── CMakeLists.txt
├── animal
   ├── dog.cpp
   └── dog.h
└── main.cpp

2 directories, 4 files
cpp
#pragma once

#include <string>

class Dog {
private:
    std::string name_;
    std::string bark_;

public:
    Dog(std::string name, std::string bark = "Wang! Wang wang wang");
    void barking();
};
cpp
#include "dog.h"
#include <iostream>

Dog::Dog(std::string name, std::string bark) : name_(name), bark_(bark) {}

void Dog::barking() {
    std::cout << bark_ << std::endl;
}
cpp
#include "./animal/dog.h"
#include <iostream>

int main(int argc, char *argv[]) {
    Dog dog("旺财");
    dog.barking();

    return 0;
}
cmake
# 配置CMake的最小版本
cmake_minimum_required(VERSION 3.20.0)

# 配置项目名称
project(test)

# 配置生成和可执行程序名称和依赖的源文件
add_executable(test main.cpp animal/dog.cpp)

使用CMake进行构建并运行

shell
$ cmake -B build
-- The C compiler identification is GNU 12.3.0
-- The CXX compiler identification is GNU 12.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/zm/code/cmake/projects/test01/build

$ cmake --build build
[ 33%] Building CXX object CMakeFiles/test.dir/main.cpp.o
[ 66%] Building CXX object CMakeFiles/test.dir/animal/dog.cpp.o
[100%] Linking CXX executable test
[100%] Built target test

$ ./build/test 
Wang! Wang wang wang

调用CMake脚本的方式

  • include方法可以引入子目录中的CMake后缀的配置文件
  • 将配置加入add_executable

直接测试

现在有以下目录结构及代码环境

shell
$ tree
.
├── CMakeLists.txt
├── animal
   ├── animal.cmake
   ├── cat.cpp
   ├── cat.h
   ├── dog.cpp
   └── dog.h
└── main.cpp

2 directories, 7 files
cpp
#pragma once
#include <string>

class Cat {
private:
    std::string name_;
    std::string bark_;

public:
    Cat(std::string name, std::string bark = "Miao~ miao~");
    void bark();
};
cpp
#include "cat.h"
#include <iostream>

Cat::Cat(std::string name, std::string bark) : name_(name), bark_(bark) {}

void Cat::bark() {
    std::cout << bark_ << std::endl;
}
cpp
#pragma once

#include <string>

class Dog {
private:
    std::string name_;
    std::string bark_;

public:
    Dog(std::string name, std::string bark = "Wang! Wang wang wang");
    void barking();
};
cpp
#include "dog.h"
#include <iostream>

Dog::Dog(std::string name, std::string bark) : name_(name), bark_(bark) {}
void Dog::barking() {
    std::cout << bark_ << std::endl;
}
cmake
# 设置变量
set(animal_source animal/dog.cpp animal/cat.cpp)
cpp
#include "./animal/cat.h"
#include "./animal/dog.h"

int main(int argc, char *argv[]) {
    Dog dog("旺财");
    dog.barking();

    Cat cat("小橘");
    cat.bark();

    return 0;
}
cmake
# 配置CMake的最小版本
cmake_minimum_required(VERSION 3.20.0)

# 配置项目名称
project(test)

# 引入配置文件
include(animal/animal.cmake)

# 配置生成和可执行程序名称和依赖的源文件
add_executable(test
 main.cpp
 ${animal_source}
)

使用CMake进行构建并运行

shell
$ cmake -B build
-- The C compiler identification is GNU 12.3.0
-- The CXX compiler identification is GNU 12.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/zm/code/cmake/projects/test02/build

$ cmake --build build
[ 25%] Building CXX object CMakeFiles/test.dir/main.cpp.o
[ 50%] Building CXX object CMakeFiles/test.dir/animal/dog.cpp.o
[ 75%] Building CXX object CMakeFiles/test.dir/animal/cat.cpp.o
[100%] Linking CXX executable test
[100%] Built target test

$ ./build/test 
Wang! Wang wang wang
Miao~ miao~

CMakeLists嵌套

使用CMake最常见的一种方式,也是用的最多的一种方式

  • target_include_directories():头文件目录的声明
  • target_link_libraries():链接库文件
  • add_subdirectory():添加子目录
  • add_library():生成库文件
    • 默认STATIC library

直接测试

现在有以下目录结构及代码环境

除了 CMakelists.txtmain.cpp 有变动,其余与上个案例一致

shell
$ tree
.
├── CMakeLists.txt
├── animal
   ├── CMakeLists.txt
   ├── cat.cpp
   ├── cat.h
   ├── dog.cpp
   └── dog.h
└── main.cpp

2 directories, 7 files
cpp
#pragma once
#include <string>

class Cat {
private:
    std::string name_;
    std::string bark_;

public:
    Cat(std::string name, std::string bark = "Miao~ miao~");
    void bark();
};
cpp
#include "cat.h"
#include <iostream>

Cat::Cat(std::string name, std::string bark) : name_(name), bark_(bark) {}

void Cat::bark() {
    std::cout << bark_ << std::endl;
}
cpp
#pragma once

#include <string>

class Dog {
private:
    std::string name_;
    std::string bark_;

public:
    Dog(std::string name, std::string bark = "Wang! Wang wang wang");
    void barking();
};
cpp
#include "dog.h"
#include <iostream>

Dog::Dog(std::string name, std::string bark) : name_(name), bark_(bark) {}
void Dog::barking() {
    std::cout << bark_ << std::endl;
}
cmake
add_library(AnimalLib cat.cpp dog.cpp)
cpp
#include "cat.h"
#include "dog.h"

int main(int argc, char *argv[]) {
    Dog dog("旺财");
    dog.barking();

    Cat cat("小橘");
    cat.bark();

    return 0;
}
cmake
# 配置CMake的最小版本
cmake_minimum_required(VERSION 3.20.0)

# 配置项目名称
project(test)

# 添加子目录
add_subdirectory(animal)

# 配置生成和可执行程序名称和依赖的源文件
add_executable(test
    main.cpp
)

# 在子目录中生成静态库,在该文件中引入子目录中生成的静态库
target_link_libraries(test PUBLIC AnimalLib)

# 添加了头文件引入目录,编写代码的时间可以省略目录前缀了
target_include_directories(test PUBLIC ${PROJECT_SOURCE_DIR}/animal)

使用CMake进行构建并运行

shell
$ cmake -B build
-- The C compiler identification is GNU 12.3.0
-- The CXX compiler identification is GNU 12.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/zm/code/cmake/projects/test03/build

$ cmake --build build
[ 20%] Building CXX object animal/CMakeFiles/AnimalLib.dir/cat.cpp.o
[ 40%] Building CXX object animal/CMakeFiles/AnimalLib.dir/dog.cpp.o
[ 60%] Linking CXX static library libAnimalLib.a
[ 60%] Built target AnimalLib
[ 80%] Building CXX object CMakeFiles/test.dir/main.cpp.o
[100%] Linking CXX executable test
[100%] Built target test

$ ./build/test 
Wang! Wang wang wang
Miao~ miao~

Object Libraries

  • add_library OBJECT

    Object Library是一个特殊的库类型,它将目标文件编译成一个库,但不会生成最终的链接文件。这意味着你可以在后续的add_library()add_executable()命令中,将Object Library做为源文件进行链接,从而生成最终的可执行文件或库文件。

    使用它的最低版本是3.12

  • target_include_directories移入到CMakeLists.txt中

直接测试

现在有以下目录结构及代码环境

除了 CMakelists.txt 有变动,其余与上个案例一致

shell
$ tree
.
├── CMakeLists.txt
├── animal
   ├── CMakeLists.txt
   ├── cat.cpp
   ├── cat.h
   ├── dog.cpp
   └── dog.h
└── main.cpp

2 directories, 7 files
cpp
#pragma once
#include <string>

class Cat {
private:
    std::string name_;
    std::string bark_;

public:
    Cat(std::string name, std::string bark = "Miao~ miao~");
    void bark();
};
cpp
#include "cat.h"
#include <iostream>

Cat::Cat(std::string name, std::string bark) : name_(name), bark_(bark) {}

void Cat::bark() {
    std::cout << bark_ << std::endl;
}
cpp
#pragma once

#include <string>

class Dog {
private:
    std::string name_;
    std::string bark_;

public:
    Dog(std::string name, std::string bark = "Wang! Wang wang wang");
    void barking();
};
cpp
#include "dog.h"
#include <iostream>

Dog::Dog(std::string name, std::string bark) : name_(name), bark_(bark) {}
void Dog::barking() {
    std::cout << bark_ << std::endl;
}
cmake
# 方式一 生成一个target
# add_library(AnimalLib OBJECT cat.cpp dog.cpp)
# target_include_directories(AnimalLib PUBLIC .)

# 方式二 生成两个target
add_library(cat OBJECT cat.cpp)
target_include_directories(cat PUBLIC .)
add_library(dog OBJECT dog.cpp)
target_include_directories(dog PUBLIC .)
cpp
#include "cat.h"
#include "dog.h"

int main(int argc, char *argv[]) {
    Dog dog("旺财");
    dog.barking();

    Cat cat("小橘");
    cat.bark();

    return 0;
}
cmake
# 配置CMake的最小版本
cmake_minimum_required(VERSION 3.20.0)

# 配置项目名称
project(test)

# 添加子目录
add_subdirectory(animal)

# 配置生成和可执行程序名称和依赖的源文件
add_executable(test
    main.cpp
)

# 在子目录中生成静态库,在该文件中引入子目录中生成的静态库

# 方式一 生成一个target
# target_link_libraries(test PUBLIC AnimalLib)
# 方式二 生成两个target
target_link_libraries(test PUBLIC cat dog)

使用CMake进行构建并运行

shell
$ cmake -B build
-- The C compiler identification is GNU 12.3.0
-- The CXX compiler identification is GNU 12.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/zm/code/cmake/projects/test04/build

$ cmake --build build
[ 25%] Building CXX object animal/CMakeFiles/dog.dir/dog.cpp.o
[ 25%] Built target dog
[ 50%] Building CXX object animal/CMakeFiles/cat.dir/cat.cpp.o
[ 50%] Built target cat
[ 75%] Building CXX object CMakeFiles/test.dir/main.cpp.o
[100%] Linking CXX executable test
[100%] Built target test

$ ./build/test 
Wang! Wang wang wang
Miao~ miao~