CMake教程版本号:3.16.3
英文原文链接: https://cmake.org/cmake/help/latest/guide/tutorial/index.html#id2
github示例代码 https://github.com/sxpsxp12/cmake-learning-exampes
自定义库
第二课内容是讲解为我们的项目添加库。首先需要创建我们自己的库。
cmake_minimum_required(VERSION 3.0.0)
project(sayhello VERSION 0.1.0)
add_library(sayhello helloworld.cpp)
库目录树为:
.
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ ├── compile_commands.json
│ ├── CPackConfig.cmake
│ ├── CPackSourceConfig.cmake
│ ├── CTestTestfile.cmake
│ ├── DartConfiguration.tcl
│ ├── libhelloworld.a
│ ├── Makefile
│ └── Testing
├── CMakeLists.txt
└── helloworld.cpp
3 directories, 11 files
- 构建项目,即可看到build目录下生成的库
cd build
cmake ..
make
使用自定义库
示例项目目录树为:
.
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ ├── compile_commands.json
│ ├── config.h
│ ├── helloworld
│ └── Makefile
├── CMakeLists.txt
├── config.h.in
├── main.cpp
└── sayhellolibrary
├── CMakeLists.txt
├── helloworld.cpp
└── helloworld.h
3 directories, 12 files
- 首先创建项目目录,然后将自定义库目录放置到根目录下
- 在根目录创建CMakefile.txt文件,添加命令,以便库能够得到编译
add_subdirectory(sayhellolibrary)
- 在根目录的CMakefile.txt文件中,添加指令,以搜索找到自定义库的头文件
target_include_directories(helloworld PUBLIC
"${PROJECT_BINARY_DIR}"
"${PROJECT_SOURCE_DIR}/sayhellolibrary"
)
- 为可执行程序链接库
target_link_libraries(helloworld PUBLIC sayhello)
最终我们看到的根目录的CMakefile.txt内容为:
cmake_minimum_required(VERSION 3.0.0)
project(helloworld VERSION 0.1.0)
add_executable(helloworld main.cpp)
add_subdirectory(sayhellolibrary)
target_include_directories(helloworld PUBLIC
"${PROJECT_BINARY_DIR}"
"${PROJECT_SOURCE_DIR}/sayhellolibrary"
)
target_link_libraries(helloworld PUBLIC sayhello)
最后构建并运行可执行程序
cd build
cmake ..
make
构建可选项
可以通过开关项,来决定库是否启用,在大型项目中,该功能非常有用。
- 首先在根目录的CMakefile.txt文件中添加可选项
option(USE_SAYHELLO "use say hello to provide info" OFF)
#配置一个头文件,以便将CMake的配置传递到源代码中
configure_file(config.h.in config.h)
- 在根目录创建config.h.in文件,并将配置传递到源代码中
#cmakedefine USE_MYMATH
- USE_SAYHELLO这个可选项可以控制是否启用该库,这个配置项会存储到Cache中,因此不需要每次构建的时候都设置该值。
- 接下来在根目录的CMakefile.txt文件中添加条件逻辑
if(USE_SAYHELLO)
#添加子CMakefile.txt目录,以便能够build
add_subdirectory(sayhellolibrary)
#将库添加到变量EXTRA_LIBS
list(APPEND EXTRA_LIBS sayhello)
#将头文件路径添加到变量EXTRA_INCLUDES中
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/sayhellolibrary")
endif(USE_SAYHELLO)
target_include_directories(helloworld PUBLIC
"${PROJECT_BINARY_DIR}"
${EXTRA_INCLUDES}
)
target_link_libraries(helloworld PUBLIC ${EXTRA_LIBS})
- 修改源代码,以使用可选项
#ifdef USE_SAYHELLO
#include "helloworld.h"
#endif
...
完整的CMakefile.txt为:
cmake_minimum_required(VERSION 3.0.0)
project(helloworld VERSION 0.1.0)
add_executable(helloworld main.cpp)
option(USE_SAYHELLO "use say hello to provide info" OFF)
#配置一个头文件,以便将CMake的配置传递到源代码中
configure_file(config.h.in config.h)
if(USE_SAYHELLO)
#添加子CMakefile.txt目录,以便能够build
add_subdirectory(sayhellolibrary)
#将库添加到变量EXTRA_LIBS
list(APPEND EXTRA_LIBS sayhello)
#将头文件路径添加到变量EXTRA_INCLUDES中
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/sayhellolibrary")
endif(USE_SAYHELLO)
target_include_directories(helloworld PUBLIC
"${PROJECT_BINARY_DIR}"
${EXTRA_INCLUDES}
)
target_link_libraries(helloworld PUBLIC ${EXTRA_LIBS})
最终构建并运行
cd build
cmake ..
make
可自行修改可选项USE_SAYHELLO的值,可删除构建缓冲,重新构建运行看看效果
总结
这一节,我们新学习的cmake指令如下
add_library
所属:项目命令,只能用于CMake项目
使用指定的源文件将库添加到项目中。
普通的库
add_library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
[source1] [source2 ...])
根据命令中的源文件构建一个名为的库(如果源文件在之后使用target_sources()添加,那么此处可以忽略),必须是一个合规的名字,并且必须在项目中是唯一的。
STATIC, SHARED, or MODULE这三个关键字可以指定生成库的类型。静态库是目标文件的归档,以便其他目标链接使用。共享库动态链接,并在运行时加载。MODULE库是一个插件,不会链接到其他目标,但是可以动态加载。
如果关键字没有设置,取决于当前变量BUILD_SHARED_LIBS
是否是ON, 关键字SHARED和MODULE的配置,会自动将可执行程序的属性POSITION_INDEPENDENT_CODE(是否创建一个路径无关的可执行程序或者库)设置为ON。
导入的库
add_library(<name> <SHARED|STATIC|MODULE|OBJECT|UNKNOWN> IMPORTED
[GLOBAL])
一个IMPORTED库表示一个位于项目以外的库文件。没有规则构建它,且IMPORTED属性是True。
对象库
add_library(<name> OBJECT <src>...)
创建一个对象库,它会编译源文件,但是不会是源文件的归档或者链接这些文件到库中。
别名库
add_library(<name> ALIAS <target>)
创建一个别名目标,以便可用于在后续命令中引用。 不会作为生成目标出现在生成的构建系统中。
接口库
add_library(<name> INTERFACE [IMPORTED [GLOBAL]])
创建一个接口库。 INTERFACE库目标虽然可以设置属性,并且可以安装,导出和导入,但它不会直接创建构建输出
更多信息请查看: https://cmake.org/cmake/help/latest/command/add_library.html
add_subdirectory
所属:项目命令,只能用于CMake项目
添加要构建的子目录
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
source_dir表示CMakefile.txt和代码文件所在的目录。相对路径是基于当前路径,也可以是绝对路径。binary_dir表示输出文件的路径。如果是相对路径,是基于当前输出路径的相对路径,也可以是绝对路径。
target_link_libraries
所属:项目命令,只能用于CMake项目
指定给定可执行程序的链接库或者标志。
target_link_libraries(<target> ... <item>... ...)
有多种形式,具体信息可查看: https://cmake.org/cmake/help/latest/command/target_link_libraries.html
option
所属:脚本指令,总是可用的
提供可选项,供用户选择
option(<variable> "<help_text>" [value])
提供一个可选项,供用户选择ON或者OFF.[value]默认是OFF。
欢迎各位大佬右侧关注、点赞、打赏,我们再会。。。