最简单的情况
main.cpp
1 |
|
hellp.cpp
1 |
|
CMakeLists.txt
1 | cmake_minimum_required(VERSION 3.12) |
将 hello.cpp 和 main.cpp 生成一个可执行文件
库
静态库
静态库可以当成多个 .o 文件的打包,相当于直接把代码插入到生成的可执行文件中,会导致生成的可执行文件体积变大。
而动态库则只在生成的可执行文件中生成“插桩”函数,当可执行文件被加载时会读取指定目录中的 .dll 文件(或 .so),加载到内存中空闲的位置,并且替换相应的“插桩”指向的地址为加载后的地址,这个过程称为“重定向”。
CMakeLists.txt
1 | cmake_minimum_required(VERSION 3.12) |
通过 add_library 生成一个静态库,add_executable 生成可执行文件,target_link 将静态库链接到可执行文件
动态库
CMakeLists.txt
1 | cmake_minimum_required(VERSION 3.12) |
此处会生成一个动态库 libhellolib.so,编译后,通过命令 ldd a.out 可见:
1 | linux-vdso.so.1 (0x00007ffe8b96d000) |
头文件递归引用
容易出现“菱形”引用问题,解决方法有两种,一种是在每个头文件的开始都加入 #pragma once,另一种用宏定义的方式。
CMake中的子模块
1 | ── CMakeLists.txt |
hellolib/CMakeLists.txt
1 | add_library(hellolib STATIC hello.cpp) |
根目录下 CMakeLists.txt
1 | cmake_minimum_required(VERSION 3.12) |
要在根目录使用,可以用 CMake 的 add_subdirectory 添加子目录,子目录也包含一个 CMakeLists.txt,其中定义的库在 add_subdirectory 之后就可以在外面使用
因为 hello.h 被移到了 hellolib 子文件夹里,因此 main.cpp 里也要改成 #include "hellolib/hello.h"的形式。如果要避免修改代码,可以通过 target_include_directories指定 a.out 的头文件搜索目录。
这样甚至可以用 #include <hello.h> 来引用这个头文件。
hellolib/CMakeLists.txt
1 | add_library(hellolib STATIC hello.cpp) |
根目录下 CMakeLists.txt
1 | cmake_minimum_required(VERSION 3.12) |
只需在生成 hellolib 库的时候定义头文件搜索路径,引用他的可执行文件 CMake 会自动添加这个路径。
其他选项
target_include_directories(myapp PUBLIC /usr/include/eigen3) # 添加头文件搜索目录
target_link_libraries(myapp PUBLIC hellolib) # 添加要链接的库
target_add_definitions(myapp PUBLIC MY_MACRO=1) # 添加一个宏定义
target_compile_options(myapp PUBLIC -fopenmp) # 添加编译器命令行选项
target_sources(myapp PUBLIC hello.cpp other.cpp) # 添加要编译的源文件
以及可以通过以下指令(不推荐使用),把选项加到所有接下来的目标去:
include_directories(/opt/cuda/include) # 添加头文件搜索目录
link_directories(/opt/cuda) # 添加库文件的搜索路径
add_definitions(MY_MACRO=1) # 添加一个宏定义
add_compile_options(-fopenmp) # 添加编译器命令行选项
这些命令是全局的。
引用系统中预安装的第三方库,如使用 apt 或 pacman 等安装的库,可以使用下面的方式:
1 | find_package(fmt REQUIRED) |
现代 CMake 认为一个package可以提供多个components,如TBB这个包,就包含了tbb, tbbmalloc, tbbmalloc_proxy 这三个components,为避免冲突,每个package都享有一个独立的名字空间,以 :: 分割。可以手动指定需要的组件:
1 | find_package(TBB REQUIRED COMPONENTS tbb tbbmalloc REQUIRED) |

