关于CMakeLists文件
CMakeLists.txt文件是CMake的编译配置文件,它定义了一个C++如何编译源代码,如何链接库文件,以及如何生成可执行文件。
最简单的CMakeLists.txt文件
对于简单的、依赖关系明确的项目,文件中最少需要包含下面三行
CMake |
---|
| cmake_minimum_required(VERSION 3.1.0) # CMake版本要求
project(myproject) # 项目名称
add_executable(myproject main.cpp) # 生成的可执行文件名称 与 用到的源代码文件名(可以多个,空格隔开)
|
常用变量
工程名
在用project()
定义工程名后,${PROJECT_NAME}
会指向该工程名,后续文件中可以用${PROJECT_NAME}
来引用工程名。
CMake |
---|
| project(myproject)
add_executable(${PROJECT_NAME} main.cpp) # ${PROJECT_NAME}会被替换为myproject
|
工程根路径
PROJECT_SOURCE_DIR
/CMAKE_SOURCE_DIR
/_SOURCE_DIR
为包含project()
命令的最近一个CMakeLists.txt文件所在的文件夹路径。
CMake |
---|
| set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/dependencies/opencv-4.11.0/build)
find_package(OpenCV 4.11.0 REQUIRED)
|
工程构建目录
PROJECT_BINARY_DIR
/CMAKE_BINARY_DIR
/_BINARY_DIR
为运行cmake命令的目录,即工程编译发生的路径,一般是build
文件夹。
最终可执行文件的生成路径
EXECUTABLE_OUTPUT_PATH
用于指定最终的可执行文件的位置。
CMake |
---|
| set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
|
库文件的生成路径
CMake |
---|
| SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
|
以上两个变量在新版本中已被CMAKE_RUNTIME_OUTPUT_DIRECTORY
和CMAKE_ARCHIVE_OUTPUT_DIRECTORY
代替。
在系统环境中查找指定依赖
当项目中包含第三方库(源码不在工程目录下的库)时,需要添加查找命令。
对于全局安装且环境变量配置正确的库,CMake会自动找到。
CMake |
---|
| find_package(OpenCV) # 如果找不到该库,报错但是继续编译
find_package(OpenCV REQUIRED) # 如果找不到该库,报错并停止编译
find_package(OpenCV QUIET) # 静默模式,找不到该库时不报错
find_package(OpenCV 4.2) # 指定版本,找不到该版本时报错
|
如果无法自动识别,可以手动指定查找路径。
CMake |
---|
| find_package(SomeLib REQUIRED
PATHS "/path/to/somelib"
"/another/path") # 在查找命令后面直接指定
set(SomeLib_DIR "/path/to/somelib/cmake") # 指定查找目录
find_package(SomeLib REQUIRED) # 然后再查找
set(CMAKE_PREFIX_PATH
"/path/to/custom/libs;/another/path") # 指定全局查找路径
find_package(SomeLib REQUIRED) # 然后再查找
|
参考博客:CMake 中配置 find_package 的搜索路径
指定头文件搜索路径
在C++项目中一般会将头文件和源文件分开存放,此时需要我们指定包含头文件的目录名。
CMake |
---|
| include_directories(
include/
${OpenCV_INCLUDE_DIRS} # 正确执行find_package(OpenCV)后该变量会自动指向OpenCV的头文件目录
)
|
使用存储匹配文件列表的变量名
例如项目中存在大量的源文件,需要都添加到add_executable()
命令中,一个一个输入将非常麻烦。
此时可以将所有的源文件存储到一个变量中,然后再添加到add_executable()
命令里面。
CMake |
---|
| # GLOB表示从根目录开始全局查找,SOURCES是变量名,后面跟着要匹配的文件,可以多个,空格隔开,*号是通配符
file(GLOB SOURCES src/*.cpp)
add_executable(${PROJECT_NAME}
${SOURCES}
ui/widget.ui include/widget.hpp
)
|
潜在问题
使用file(GLOB ···)
生成构建文件后,在make
编译时不会自动检测匹配的源文件的增减和改动,因此在添加或删除源文件后,需要手动重新运行 CMake 然后再make
编译才会更新。
链接库文件到指定目标
当项目中引入了第三库时,不仅需要寻找依赖库来让编译器知道相关代码如何编译,往往还需要将生成的可执行文件和引用的库文件(例如Linux系统中的以.so
为后缀名的动态链接库)链接起来,这样才能运行。
CMake |
---|
| target_link_libraries(${PROJECT_NAME} # 可执行文件(目标)名
Qt5::Widgets Qt5::Core Qt5::Gui # 需要链接的库名
${OpenCV_LIBS} # 正确执行find_package(OpenCV)后该变量会自动指向OpenCV的库文件
)
|