tartarus's bolg tartarus's bolg
  • Linux and Unix Guide
  • CMake
  • gcc
  • gdb
  • bash
  • GNU Make
  • DDCA-ETH
  • CS106L
  • CS144
  • NJU PA
  • NJU OS(jyy)
  • C
  • C++
  • Python
  • reveal-md
  • LaTex
  • Paper Reading
  • TBD
  • Linux and Unix Guide
  • CMake
  • gcc
  • gdb
  • bash
  • GNU Make
  • DDCA-ETH
  • CS106L
  • CS144
  • NJU PA
  • NJU OS(jyy)
  • C
  • C++
  • Python
  • reveal-md
  • LaTex
  • Paper Reading
  • TBD
  • pdb

  • make

  • cmake

    • Introduction
    • Basic Intro
    • Basic 01-hello-cmake
    • Basic 02-hello-headers
      • 介绍
      • 概念解释
        • 文件夹路径变量
        • 源文件变量
        • 使用target_include_directories()包含编译目录
      • 构建本例
    • Basic 03-static-library
    • Basic 04-shared-library
    • Basic 05-installing
    • Basic 06-build-type
    • Basic 07-complie-flags
    • Basic 08-third-party-library
    • Basic 09-compiling-with-clang
    • Basic 10-building-with-ninjia
    • Basic 11-cpp-standard
    • Intermediate sub-projects
    • Intermediate static-analysis
    • packge-management 04-conan
    • packge-management 05-vcpkg
    • Offical Tutorial(未完成)
  • Linux and Unix

  • Basic_Software
  • cmake
tartarus
2023-04-15
目录

Basic 02-hello-headers

# 介绍

构建一个最简单的 Hello world 项目,但是源文件和包含的文件不在同一个文件中。

本例的目录🌲:

B-hello-headers$ tree
.
├── CMakeLists.txt # 包含了本项目运行所需要的CMake命令
├── include
│   └── Hello.h    # main.cpp, Hello.cpp包含的头文件
└── src
    ├── Hello.cpp  # Hello.h头文件对应的cpp文件
    └── main.cpp   # main不需要解释了吧😁 
1
2
3
4
5
6
7
8

关于源文件和头文件各自的作用和区别见为什么我们需要头文件

# 概念解释

# 文件夹路径变量

CMake 的语法规定了很多的变量 (opens new window)其中下面是一些有用的指定一些文件夹的目录:

Variable Info
CMAKE_SOURCE_DIR The root source directory
CMAKE_CURRENT_SOURCE_DIR The current source directory if using sub-projects and directories.
PROJECT_SOURCE_DIR The source directory of the current cmake project.
CMAKE_BINARY_DIR The root binary / build directory. This is the directory where you ran the cmake command.
CMAKE_CURRENT_BINARY_DIR The build directory you are currently in.
PROJECT_BINARY_DIR The build directory for the current project.

# 源文件变量

创建一个包含源文件的变量可以更清晰地了解这些文件,并且可以轻松地将它们添加到多个命令中 (这也是我们在 GNU Make 中经常做的)。比如添加到 add_executable 中

# Create a sources variable with a link to all cpp files to compile
set(SOURCES
    src/Hello.cpp
    src/main.cpp
)
add_executable(${PROJECT_NAME} ${SOURCES})
1
2
3
4
5
6

注意

一个替代在 SOURCES 变量中设置所有源文件名为变量的方法是使用 GLOB 命令使用通配符 (wildcard pattern) 匹配查找文件。

file(GLOB SOURCES "src/*.cpp")
1

使用建议

对于现代的 CMake,不建议使用变量来存储源文件 (sources),而是直接在 add_xxx 函数中声明源文件。
这对于使用 GLOB 命令查找源文件尤其重要,因为如果添加了新的源文件,则可能无法正确显示结果。

因为 file (GLOB) 命令只在执行一次时进行评估,并且在目录内容发生变化时不会自动更新

举例说明:
比如你有一个目录 src ,其中包含了 foo.cpp 、 bar.cpp 和 baz.cpp 三个源文件。你可以使用以下方式来定义这些源文件:

file(GLOB SOURCES "src/*.cpp")
1

这会搜索 src 目录中所有以 .cpp 结尾的文件,并将它们的路径保存到 SOURCES 变量中。然后,你可以在 add_executable 调用中使用 SOURCES 变量来指定源文件列表:

add_executable(my_executable ${SOURCES})
1

这样, my_executable 目标就会编译 src 目录中的所有 .cpp 文件,包括 foo.cpp 、 bar.cpp 和 baz.cpp 。

但是,如果你在之后向 src 目录中添加了一个新的 .cpp 文件 qux.cpp ,那么它不会被自动包含在 SOURCES 变量中,因为 file(GLOB) 命令已经在之前执行过了,它不会自动更新。所以如果你在 add_executable 调用中仍然使用 SOURCES 变量来指定源文件列表,那么 qux.cpp 就不会被编译进 my_executable 目标中。这就是为什么建议直接在 add_executable 调用中列出源文件,而不是使用 file(GLOB) 命令来搜索源文件的原因。

# 使用 target_include_directories() 包含编译目录

当您有不同的包含文件夹时,可以使用 target_include_directories() 函数使编译器意识到它们。在编译此目标时,将使用 -I 标志将这些目录添加到编译器中,例如 -I/directory/path (注意 - I 和后面的文件夹路径不能用空格分开)。

target_include_directories(target
    PRIVATE
        ${PROJECT_SOURCE_DIR}/include
)
1
2
3
4

PRIVATE 标志符指定了 include 的搜索范围,具体请看 TBD

# 构建本例

$ mkdir build

$ cd build

$ cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/lib/ccache/cc
-- Check for working C compiler: /usr/lib/ccache/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/lib/ccache/c++
-- Check for working CXX compiler: /usr/lib/ccache/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/build

$ make
Scanning dependencies of target hello_headers
[ 33%] Building CXX object CMakeFiles/hello_headers.dir/src/Hello.cpp.o
[ 66%] Building CXX object CMakeFiles/hello_headers.dir/src/main.cpp.o
[100%] Linking CXX executable hello_headers
[100%] Built target hello_headers
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

在之前的例子中,当运行 make 命令时,输出只显示构建的状态。为了查看完整的输出以进行调试,可以在运行 make 命令时添加 VERBOSE=1 标志。

$ make clean

$ make VERBOSE=1
/usr/bin/cmake -S/home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers -B/home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/build/CMakeFiles /home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/build'
make -f CMakeFiles/hello_headers.dir/build.make CMakeFiles/hello_headers.dir/depend
make[2]: Entering directory '/home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/build'
cd /home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers /home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers /home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/build /home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/build /home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/build/CMakeFiles/hello_headers.dir/DependInfo.cmake --color=
make[2]: Leaving directory '/home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/build'
make -f CMakeFiles/hello_headers.dir/build.make CMakeFiles/hello_headers.dir/build
make[2]: Entering directory '/home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/build'
[ 33%] Building CXX object CMakeFiles/hello_headers.dir/src/Hello.cpp.o
/usr/lib/ccache/c++   -I/home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/include   -o CMakeFiles/hello_headers.dir/src/Hello.cpp.o -c /home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/src/Hello.cpp
[ 66%] Building CXX object CMakeFiles/hello_headers.dir/src/main.cpp.o
/usr/lib/ccache/c++   -I/home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/include   -o CMakeFiles/hello_headers.dir/src/main.cpp.o -c /home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/src/main.cpp
[100%] Linking CXX executable hello_headers
/usr/bin/cmake -E cmake_link_script CMakeFiles/hello_headers.dir/link.txt --verbose=1
/usr/lib/ccache/c++     CMakeFiles/hello_headers.dir/src/Hello.cpp.o CMakeFiles/hello_headers.dir/src/main.cpp.o  -o hello_headers 
make[2]: Leaving directory '/home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/build'
[100%] Built target hello_headers
make[1]: Leaving directory '/home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/build'
/usr/bin/cmake -E cmake_progress_start /home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/build/CMakeFiles 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

下面是从中摘取的一些关键信息:

  • 输出中的绿色部分就可以看到包含目录被添加到了 C++ 编译器命令中,这就是target_include_directories 的作用。
  • 输出中的蓝色部分就可以看到链接过程,这就是源文件变量小节说的add_excutable 的作用。

/usr/lib/ccache/c++ -I/home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/include -o CMakeFiles/hello_headers.dir/src/Hello.cpp.o -c /home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/src/Hello.cpp

/usr/lib/ccache/c++ -I/home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/include -o CMakeFiles/hello_headers.dir/src/main.cpp.o -c /home/tartarus/cmake/cmake-examples/01-basic/B-hello-headers/src/main.cpp

/usr/lib/ccache/c++ CMakeFiles/hello_headers.dir/src/Hello.cpp.o CMakeFiles/hello_headers.dir/src/main.cpp.o -o hello_headers
( /usr/lib/ccache/c++ 是因为我使用了 ccache 加快编译的速度,它会保存目标文件,下次编译过程中如果没有发生改变就直接进行替换。)

提示

这里也可以使用 cmake --build . 命令来替换 make ,两者的区别在于:前者更加通用,无论你使用的构建工具是 make 还是 ninja 还是...,都可以运行该命令进行构建编译。后者只是在使用 make 作为构建工具的平台 (比如 Linux) 适用,但是看起来更加直观。

上次更新: 12/27/2023, 8:55:47 AM
Basic 01-hello-cmake
Basic 03-static-library

← Basic 01-hello-cmake Basic 03-static-library→

Theme by Vdoing | Copyright © 2023-2023 tartarus | CC BY-NC-SA 4.0
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式