前言
CMake允许开发者编写一种平台无关的 CMakeList.txt 文件来定制整个编译流程,然后再根据目标用户的平台进一步生成所需的本地化 Makefile 和工程文件,如 Unix 的 Makefile 或 Windows 的 Visual Studio 工程。从而做到“Write once, run everywhere”。
CMake 是一个跨平台的自动化建构系统,它使用一个名为 CMakeLists.txt 的文件来描述构建过程,可以产生标准的构建文件,如 Unix 的 Makefile 或Windows Visual C++ 的 workspaces 。文件 CMakeLists.txt 需要手工编写,也可以通过编写脚本进行半自动的生成。在 linux 平台下使用 CMake 生成 Makefile 并编译的流程如下:
- 编写 CmakeLists.txt。
- 执行命令“cmake PATH”或者“ccmake PATH”生成 Makefile ( PATH 是 CMakeLists.txt 所在的目录 )。
- 使用 make 命令进行编译
简而言之,就是用来管理项目,编译项目的一个工具,可以用简单的语句描述所有平台的编译过程,拥有很好的跨平台特性。
cmake基本命令
project name:指定项目名称,生成的VC项目的名称;
例:PROJECT( project name ),使用${CMAKE_SOURCE_DIR}表示 cmakelist.txt 所在的目录
include_directories :指定头文件的搜索路径,相当于指定gcc的-I参数
例: include_directories (${HELLO_SOURCE_DIR}/Hello) #增加Hello目录为include的目录
link_directories :动态链接库或静态链接库的搜索路径,相当于gcc的-L参数
例: link_directories (${HELLO_BINARY_DIR}/Hello) #增加Hello为link目录
add_subdirectory:包含子目录
例: add_subdirectory (Hello)
add_executable :编译可执行程序,指定编译
例:add_executable (helloDemo demo.cxx demo_b.cxx) #将cxx编译成可执行文件——
add_definitions :添加编译参数
例:add_definitions(-DDEBUG) #在gcc命令行添加DEBUG宏定义;
例:add_definitions( “-Wall -ansi –pedantic –g”) #在gcc命令行添加编译参数;
target_link_libraries :添加链接库,相同于指定-l参数
例: target_link_libraries(demo Hello) #将可执行文件与Hello连接成最终文件demo
add_library:
例:add_library(Hello hello.cxx) #将hello.cxx编译成静态库如 libHello.a
set :设置环境变量值
例:SET( TEST_DIR ${DIR_SRCS})
看一篇 cmakelist.txt 实例
通过了解常用命令,可以轻松阅读一篇不复杂的 cmakelist.txt 并做简单修改,通过实例继续解释语法规则和结构,实例如下:
cmake_minimum_required(VERSION 2.8)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_BUILD_TYPE Release)
set(CMAKE_C_COMPILER gcc)
set(CMAKE_CXX_COMPILER g++)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
include_directories(
${CMAKE_SOURCE_DIR}/3rdparty/opencv/include
${CMAKE_SOURCE_DIR}/rknn_api/include
)
set(link_libs ${CMAKE_SOURCE_DIR}/3rdparty/opencv/lib64/libopencv_core.so
${CMAKE_SOURCE_DIR}/3rdparty/opencv/lib64/libopencv_highgui.so
${CMAKE_SOURCE_DIR}/3rdparty/opencv/lib64/libopencv_imgcodecs.so
${CMAKE_SOURCE_DIR}/3rdparty/opencv/lib64/libopencv_imgproc.so
${CMAKE_SOURCE_DIR}/rknn_api/lib64/librknn_api.so
pthread
)
add_executable(yolov3_tiny yolov3_tiny.cpp)
target_link_libraries(yolov3_tiny ${link_libs})
add_executable(yolov3 yolov3.cpp)
target_link_libraries(yolov3 ${link_libs})
可以看到,有一些名词,如 CMAKE_SYSTEM_NAME 是作为已声明的内置变量使用,下面介绍常用的内置变量。
常用内置变量
CMAKE_C_COMPILER:指定c编译器
CMAKE_CXX_COMPILER:指定c++编译器
CMAKE_C_FLAGS:编译c文件时的选项,如-g;也可以通过add_definitions添加编译选项
CMAKE_CXX_FLAGS:编译c++文件时的选项,如-std=c++11;
EXECUTABLE_OUTPUT_PATH:可执行文件的存放路径
LIBRARY_OUTPUT_PATH:库文件路径
CMAKE_BUILD_TYPE:build 类型(Debug, Release, ...)
PROJECT_SOURCE_DIR:工程的根目录;
CMAKE_SOURCE_DIR: CMakeLists.txt 所在的目录
CMAKE_SYSTEM_NAME :系统名称
CMAKE_CURRENT_SOURCE_DIR:当前处理的 CMakeLists.txt 所在的路径
CMAKE_CURRENT_BINARY_DIR:target 编译目录
CMAKE_CURRENT_LIST_DIR:CMakeLists.txt 的完整路径
EXECUTABLE_OUTPUT_PATH:重新定义目标二进制可执行文件的存放位置
内置变量的使用:
>> 在CMakeLists.txt中指定,使用set
>> cmake命令中使用,如cmake -DBUILD_SHARED_LIBS=OFF
部分语法
# :注释
变量:使用set命令显式定义及赋值,在非if语句中,使用${}引用,if中直接使用变量名引用;后续的set命令会清理变量原来的值;
command (args ...) :命令不分大小写,参数使用空格分隔,使用双引号引起参数中空格
set(var a;b;c) <=> set(var a b c) :定义变量var并赋值为a;b;c这样一个string list
Add_executable(${var}) <=> Add_executable(a b c) :变量使用${xxx}引用
条件语句:
if(var) #var 非empty 0 N No OFF FALSE... #非运算使用NOT
…
else()/elseif() … endif(var)
循环语句1:
Set(VAR a b c)
Foreach(f ${VAR}) …Endforeach(f)
循环语句2:
WHILE() … ENDWHILE()
参考:
https://blog.csdn.net/qq_36983118/article/details/79213543
https://blog.csdn.net/gsls181711/article/details/40376701
https://www.cnblogs.com/lidabo/p/7359422.html