简单的cmake使用
使用CMakeLists.txt生成可执行文件
编写一个最简单的CMakeLists以生成可执行文件,仅需要以下三步
- 指明最小支持的cmake版本
cmake_minimum_required
- 指明项目的代号或者说名称
project
- 使用
add_executable
来生成可执行文件
其中
add_executable参数为可执行文件名称,后面跟着源文件列表
例如
add_executable(hello main.cpp add.cpp ......)
库的生成与链接
在执行add_executable
后,若想使用一些外部库,则需要链接库文件来将库和可执行文件链接起来。
add_library(${LIBRARY_NAME} 可选参数 ${LIBRARY_SOURCES})
使用add_library
用于通过源文件生成库文件,${LIBRARY_NAME}
为库的名称,${LIBRARY_SOURCES}
为库的源文件列表。其中中间有些可选参数。如STATIC
表示生成静态库,SHARED
表示生成动态库。
然后在add_executable
后使用target_link_libraries
来链接库文件。
target_link_libraries(hello ${LIBRARY_NAME})
这里${LIBRARY_NAME}
为库的名称,可以是系统库,也可以是自己编译的库。
对于.so后缀的动态库以及.a后缀的静态库,以及以lib为前缀的库文件,只需要写其名称即可,不需要写后缀以及lib
前缀。
注意的是,如果是自己编译的库一般会找不到,因为target_link_libraries
仅从指定路径/usr/bin/ld
中寻找库,若是自己的库可以选择软链接到该路径或者填写绝对路径
外部依赖库的使用
对于不是自己编译的库,可以使用find_package
命令来查找系统中已安装的库。
find_package(库名称 REQUIRED)
这里的库名称可以是OpenCV
、Boost
、Eigen
等等。而REQUIRED参数使得当未找到该库时,会直接推出make而报错。
对于库名称,在安装库时,库会同时安装一份XXXXConfig.cmake或者findxxxx.cmake文件,该文件包含了库的相关信息,包括头文件路径、库文件路径、依赖库等。所以库名称匹配的就是这个XXXX。而使用find_package命令时,CMake会在系统路径下查找该文件,并读取其信息,从而找到库的相关信息。同时在该文件中也规定或者定义了库的一些变量,比如库的路径、头文件路径等。
以OpenCV为例,在CMakeLists.txt中使用如下命令:
cmake_minimum_required(VERSION 3.6)
project(simple_cmake)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(hello main.cpp add.cpp)
target_link_libraries(hello ${OpenCV_LIBS})
其中${OpenCV_INCLUDE_DIRS}
以及${OpenCV_LIBS}
是OpenCVConfig.cmake中定义的变量,分别表示头文件路径和库文件路径。可以使用message
命令打印这些变量的值来验证。如
message(OpenCV_LIBS)
而对于一些未显式给出的库如TensorRT,大可以自己去写一份FindTensorRT.cmake文件,然后使用find_package
命令查找,正如上交所做。
变量的使用
CMakeLists.txt中可以使用变量来简化代码,提高可读性。
使用set
命令可以定义并初始化变量。
set(变量名 值)
这里的值可以是字符串、数字等,可以有多个值,用空格隔开。
set(SRC_FILES main.cpp add.cpp)
add_executable(hello ${SRC_FILES})
target_link_libraries(hello ${LIBRARY_NAME})
这里${SRC_FILES}
是一个变量,其值为main.cpp
和add.cpp
,可以简化代码。
而SRC_FILES
是变量名,而使用$
代表取其值,这一点和shell命令类似。
指定编译选项
- 指定编译模式
set(CMAKE_BUILD_TYPE Debug|Release)
- 指定编译器路径
set(CMAKE_CXX_COMPILER /usr/bin/g++)
- 指定编译选择的c++标准
set(CMAKE_CXX_STANDARD 11)
or
set(CMAKE_CXX_FLAGS "std=c++11 -O3")
等等