查看cmake版本: cmake --version
,Ubuntu自带的是3.5.1
cmake和qmake都用于产生Makefile,然后执行make
命令进行编译,make还有其他参数,叫做make目标
升级 CMake
1 | sudo apt-get install -y build-essential libssl-dev |
报错: Could not find CMAKE_ROOT !!! CMake has most likely not been installed correctly. 先执行hash -r
再使用
还可参考: cmake源码安装 安装CMake和cmake-gui,
cmake-gui
在where is the source code
里选择源代码位置,在where to build the binaries
里选择编译出的文件,一般是在源代码目录里新建build
文件夹。
先点一次Configure
,出现配置对话框,选默认或者交叉编译(最后一个选项)。如果出现红色区域,再点一次。直到没有红色区域之后,点击configure
,配置完成后点击generate
,会在build文件夹下生成工程文件,然后去build文件夹里执行make
常见的make目标
1 | make all:编译程序、库、文档等(等同于make) |
注释方法: CMake 3.0以上版本的多行注释:从#[[
开始,在块注释的另一端以]]
结束。但是并不好用,似乎和Tab对齐有关。
语法规则:
- 变量使用${}方式取值, 但是在IF控制语句中是直接使用变量名
- 环境变量使用$ENV{}方式取值, 使用SET(ENV{VAR} VALUE)赋值
- 指令(参数1 参数2…) 参数使用括弧括起, 参数之间使用空格或分号分开
有时候看到一些工程有一个cmake
文件夹,里面放几个cmake文件,打开发现是一些cmake的命令。这是因为工程规模太大,有些库比如PCL在每个CMakeLists
里使用,每次都添加太麻烦,所以做成文件形式,在用到的时候在CMakeLists
里 include(cmake/PCL.cmake)
基本规则
预定义变量,设置方式是set(VARIABLE value)
,大小写都是敏感的,可以用message函数查看:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20PROJECT_NAME #通过PROJECT指令定义的项目名称
PROJECT_SOURCE_DIR #工程的根目录
PROJECT_BINARY_DIR #运行cmake命令的目录,通常是${PROJECT_SOURCE_DIR}/build
CMAKE_CURRENT_SOURCE_DIR #当前处理的CMakeLists.txt所在的路径
EXECUTABLE_OUTPUT_PATH #目标可执行文件的存放位置
LIBRARY_OUTPUT_PATH #目标链接库文件的存放位置
CMAKE_MAJOR_VERSION #cmake主版本号,如2.8.6中的2
CMAKE_MINOR_VERSION #cmake次版本号,如2.8.6中的8
CMAKE_PATCH_VERSION #cmake补丁等级,如2.8.6中的6
CMAKE_SYSTEM #系统名称,包含内核版本,例如Linux-2.6.22
CAMKE_SYSTEM_NAME #不包含版本的系统名,如Linux
UNIX #在所有的类UNIX平台为TRUE,包括OS X和cygwin
WIN32 #在所有的win32平台为TRUE,包括cygwin
BUILD_SHARED_LIBS #控制默认的库编译方式,默认编译生成的库都是静态库
CMAKE_C_COMPILER/CMAKE_CXX_COMPILER #指定C/C++编译器
CMAKE_CXX_FLAGS # 设置C++编译选项
CMAKE_BUILD_TYPE # 常用的编译类型 Debug Release
BUILD_SHARED_LIBS # 编译动态链接库(ON,OFF)
add_compile_options
下面的代码里,foo
不会按照-Wall
编译,但是bar
会。1
2
3add_library(foo ...)
add_compile_options(-Wall 03)
add_library(bar ...)-Wall
显示所有警告。O3
(字母O)是编译优化的程度选择,有O1 O2 O3。数字越大编译优化越多,程序执行速度越快 但编译时间越长,不过一般程序看不出来。
CMAKE_CXX_STANDARD
CMake 3.1或者更高版本可使用set(CMAKE_CXX_STANDARD 11)
,不能用17
最好把add_compile_options(-std=c++17)
改为跨平台的写法: set(CMAKE_CXX_STANDARD 17)
,也就是x86
跨arm
平台
./configure命令
一般第三方库里都有个configure
文件,它是个Shell脚本,内容很多../configure 是用来检测你的安装平台的目标特征的,比如它会检测你是不是有CC或GCC。主要功能是生成 Makefile,为下一步的编译做准备,你可以通过在./configure
后加上参数来对安装进行控制,比如./configure --prefix=/usr
是将该软件安装在 /usr 下面,执行文件就会安装在/usr/bin
(而不是默认的 /usr/local/bin
),资源文件就会安装在 /usr/share
(而不是默认的/usr/local/share)
message函数
1 | message(STATUS "12345") #如果不加STATUS,不会在前面加--标志 |
如果在执行cmake时,遇到一个错误情况需要停止执行,可以用FATAL_ERROR
:1
2
3if( SOME_COND )
message( FATAL_ERROR "You can not do this at all, CMake will exit." )
endif()
如果出现这种情况还要继续编译,那么就换成SEND_ERROR
指令最好全用大写
路径名中不要用\,而是用/,例如include_directories(F:/Eigen)
常用命令
1 | # 这必须是CMakeLists的第一行,限定cmake版本,Catkin需要2.8.3或更高版本 |
获取环境变量
获取bash.rc中的环境变量,通过ENV前缀来访问环境变量,读取环境变量使用$ENV{JAVA_HOME}
,查看环境变量:1
message(STATUS " java home: $ENV{JAVA_HOME}" )
写环境变量如下:1
set( ENV{PATH} /home/martink )
cmake判断操作系统和架构
1 | message(${CMAKE_HOST_SYSTEM_NAME}) |
获得include的文件路径
1 | include_directories( |
指定生成文件的输出路径
使用SET命令重新定义EXECUTABLE_OUTPUT_PATH
和LIBRARY_OUTPUT_PATH
变量来指定最终的二进制文件的位置1
2SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
上面的两条命令通常紧跟ADD_EXECUTABLE
和ADD_LIBRARY
,与其写在同一个CMakeLists.txt即可
include_directories 和 target_include_directories
都是添加头文件搜索路径。差别:
include_directories
的影响范围最大,可以为CMakelists.txt后的所有项目添加头文件目录。一般写在最外层CMakelists.txt中影响全局影响范围可以自定义,加关键子
PRIVATE
或PUBLIC
。一般引用库路径使用这个命令,作为外部依赖项引入进来,target是自己项目生成的lib。
PRIVATE
:target对应的源文件使用PUBLIC
:target对应的头文件、源文件都使用
如果有不同目录相同名称的头文件会产生影响,所以这里建议针对特定的 target 使用 target_include_directories