阅读导引

  • 1.cmake简介
  • 2.cmake语法
  • 3.构建方式
  • 4.CMAKE_EXPORT_COMPILE_COMMANDS选项
  • 5.CMake命令
  • 5.1 cmake_minimum_required 命令
  • 5.2 project 命令
  • 5.3 set命令
  • 5.4 message命令
  • 5.5 find_package命令
  • 5.6 include_directories命令
  • 5.7 add_executable命令
  • 5.8 add_library命令
  • 5.9 target_link_libraries 命令
  • 6.补充



1.cmake简介

CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性。CMake的所有的语句都写在CMakeLists.txt的文件中。


2.cmake语法

  • 变量使用${}方式取值,但是在 IF 控制语句中是直接使用变量名;
  • 指令(参数 1 参数 2…),参数使用括弧括起,参数之间使用空格或分号分开;
  • 指令是大小写无关的,参数和变量是大小写相关的。但推荐你全部使用大写指令。
  • 以#开头,到行末尾的是注释
  • cmake的构建指令为"cmake path [参数选项]"

3.构建方式

cmake有两种构建方式

1.内部构建

cmake .
make

2.外部构建 推荐使用

mkdir build
cd build
cmake ..
make

两种方法最大的不同在于执行cmake和make的工作路径不同。
第一种方法中,cmake生成的所有中间文件和可执行文件都会存放在项目目录中;称为“内部构建”。而第二种方法中,中间文件和可执行文件都将存放再build目录中。

第二种方法的优点显而易见,它最大限度的保持了代码目录的整洁。同时由于第二种方法的生成、编译和安装是发生在不同于项目目录的其他目录中,所以第二种方法就叫做“外部构建”。cmake强烈推荐使用外部构建的方法。


4.CMAKE_EXPORT_COMPILE_COMMANDS选项

默认不开启,开启的两种方法:

在CMakeLists.txt中添加 set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
在命令行中添加-DCMAKE_EXPORT_COMPILE_COMMANDS=on
开启后,其生成的文件compile_commands.json,包含所有编译单元所执行的指令,
简单理解,就是一个保存编译链接过程的详细信息的文件 如下所示:

[
{
  "directory": "/home/cheng/Downloads/location_detection/2bu",
  "command": "/usr/bin/c++  -I/home/cheng/Downloads/location_detection/include -I/home/cheng/somelib/libtorch/include -std=c++14 -O2  -msse4 -g -o CMakeFiles/location_detection.dir/src/cotek_location_detection.cc.o -c /home/cheng/Downloads/location_detection/src/cotek_location_detection.cc",
  "file": "/home/cheng/Downloads/location_detection/src/cotek_location_detection.cc"
},
{
  "directory": "/home/cheng/Downloads/location_detection/2bu",
  "command": "/usr/bin/c++ -DAT_PARALLEL_OPENMP=1 -I/home/cheng/Downloads/location_detection/include -isystem /home/cheng/somelib/libtorch/include -isystem /home/cheng/somelib/libtorch/include/torch/csrc/api/include -isystem /usr/local/include/opencv -std=c++14 -O2  -msse4 -g -D_GLIBCXX_USE_CXX11_ABI=1 -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-write-strings -Wno-unknown-pragmas -Wno-missing-braces -fopenmp -o CMakeFiles/detection.dir/src/cotek_detection_node.cc.o -c /home/cheng/Downloads/location_detection/src/cotek_detection_node.cc",
  "file": "/home/cheng/Downloads/location_detection/src/cotek_detection_node.cc"
}
]

5.CMake命令

5.1 cmake_minimum_required 命令

如下所示

cmake_minimum_required(VERSION 3.1.0)

该命令规定了cmake程序的最低版本。这行命令是可选的,我们可以不写这句话,但在有些情况下,如果CMakeLists.txt文件中使用了一些高版本cmake特有的一些命令的时候,就需要加上这样一行,提醒用户升级到该版本之后再执行cmake。

5.2 project 命令

如下所示

project(location_detection)

制定项目工程的名称,这里注意该名称并不是最后编译完成后生成可执行文件的名称,而是给项目起的命名,项目最终编译生成的可执行文件名称则是由ADD_EXECUTABLE命令来指定的。

5.3 set命令

SET命令可以用来显式的定义变量。如:

set(CMAKE_BUILD_TYPE "Debug")

代表将 CMAKE_BUILD_TYPE赋值为“Debug”

5.4 message命令

主要用来产生一系列信息,类似与cmake过程中输出的日志,方便我们进行debug调试,可以打印出变量值。
语法
message([<mode>] "message text" ...)

mode 的值包括 FATAL_ERROR、WARNING、AUTHOR_WARNING、STATUS、VERBOSE等。
我主要使用其中的 2 个——FATAL_ERROR、STATUS。

FATAL_ERROR:产生 CMake Error,会停止编译系统的构建过程;

STATUS:最常用的命令,常用于查看变量值,类似于编程语言中的 DEBUG 级别信息。

"message text"为显示在终端的内容。

如下例子:

message(STATUS "Pytorch status:")
message(STATUS "    libraries: ${TORCH_LIBRARIES}")

进行cmake时会打印出

Pytorch status:
--     libraries: torch;torch_library;/home/cheng/somelib/libtorch/lib/libc10.so
5.5 find_package命令

命令是用来查找依赖包的,理想情况下,一句find_package()把一整个依赖包的头文件包含路径、库路径、库名字、版本号等情况都获取到,后续只管用就好了。如下

# 添加torch库
set(CMAKE_PREFIX_PATH /home/cheng/somelib/libtorch/share/cmake/Torch)
find_package(Torch REQUIRED)
find_package(OpenCV 3 REQUIRED)

注意这里我的opencv是通过make && make install 方式安装的,所以cmake回去内部对应的查找opencv,而我的torch并没有安装,只是下载deb包解压了,所以首先需要,找到包含torch的cmake文件,一般在解压的库中,如下地址/home/cheng/somelib/libtorch/share/cmake/Torch

5.6 include_directories命令

如下所示

include_directories(
    include
    /home/cheng/somelib/libtorch/include
    ${OpenCV_INCLUDE_DIRS}
    /usr/include
)

INCLUDE_DIRECTORIES类似gcc中的编译参数“-I”,指定编译过程中编译器搜索头文件的路径,通常用来指定头文件搜索目录。
注意:如果在cmake过程中,提示你某个.h文件找不到,多半是这里出问题了,请详细检查该处命令。

5.7 add_executable命令

使用给定的源文件,为工程引入一个可执行文件。如下所示

add_executable(detection src/get.cc)

使用指定的 /src/get.cc 源文件,生成一个名为detection的可执行文件。

5.8 add_library命令

主要作用就是将指定的源文件生成链接文件,然后添加到工程中去。
如下

add_library(${PROJECT_NAME} src/ck_detection.cc)

这里是将, /src/ck_detection.cc源文件生成链接文件,然后取PROJECT_NAME的值,即前面我们定义的location_detection项目,将该链接文件添加到location_detection工程中去。

5.9 target_link_libraries 命令

该指令的作用为将目标文件与库文件进行链接。如下所示

target_link_libraries(
    detection
    ${TORCH_LIBRARIES}
    ${OpenCV_LIBS}
    ${DEPENDENCIES}
    -lpthread 
)

这里的detection 是我们通过add_executable指令生成的已经创建的可执行文件。


6.补充

其他还有很多知识,暂时没用到,上述知识足够构建一个简单的项目了,挖坑,以后补

上述教程完整CMakeLists.txt

cmake_minimum_required(VERSION 3.1.0)
project(location_detection)

set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_FLAGS "-std=c++14 -O2 ${SSE_FLAGS} -msse4")


# 添加torch库
set(CMAKE_PREFIX_PATH /home/cheng/somelib/libtorch/share/cmake/Torch)
find_package(Torch REQUIRED)
find_package(OpenCV 3 REQUIRED)

if(NOT Torch_FOUND)
    message(FATAL_ERROR "Pytorch not found")
endif(NOT Torch_FOUND)


if(NOT OpenCV_FOUND)
    find_package(OpenCV 2.4.3 QUIET)
    if(NOT OpenCV_FOUND)
        message(FATAL_ERROR "OpenCV > 2.4.3 not found.")
    endif()
endif()


message(STATUS "Pytorch status:")
message(STATUS "    libraries: ${TORCH_LIBRARIES}")

message(STATUS "OpenCV library status:")
message(STATUS "    version: ${OpenCV_VERSION}")
message(STATUS "    libraries: ${OpenCV_LIBS}")
message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")

include_directories(
    include
    /home/cheng/somelib/libtorch/include
    #${OpenCV_INCLUDE_DIRS}
    /usr/include
)

#message(">>> include_dirs=${dirs}") #打印一下目录情况


add_executable(detection src/cotek_detection_node.cc)
add_library(${PROJECT_NAME} src/cotek_location_detection.cc)
target_link_libraries(
    detection
    ${PROJECT_NAME}
    ${TORCH_LIBRARIES}
    ${OpenCV_LIBS}
    ${DEPENDENCIES}
    -lpthread 
)