一、语法介绍

来源:从零开始详细介绍CMake

1.语法基本原则

  • 变量使用${}方式获取值,但在IF控制语句中直接使用变量名
  • 指令(参数1 参数2 …):参数使用圆括弧括起来,参数之间使用空格或分号分开
  • 指令大小写无关,参数和变量大小写相关,推荐全部使用大写方式

SET(SRC_LIST main.cpp)与SET(SRC_LIST “main.cpp”)等价,但当源文件名中含有空格时必须加引号

2.基本关键词

  • PROJECT关键字

指定工程名字和支持语言,默认支持所有语言

PROJECT(HELLO) 指定工程名字且支持所有语言

PROJECT(HELLO CXX) 指定工程名字,支持C++

PROJECT(HELLO C CXX) 指定工程名字,支持C和C++

上面PROJECT关键字隐式定义了两个CMAKE变量:

1
2
<projectname>_BINARY_DIR:上面的例子是HELLO_BINARY_DIR
<projectname>_SOURCE_DIR:上面的例子是HELLO_SOURCE_DIR

MESSAGE关键字可以直接使用上述两个变量,若修改工程名则上述两个变量名也会改变;因此定义变量PROJECT_BINARY_DIRPROJECT_SOURCE_DIR来替换上述两个变量

  • SET关键字

设置变量的值,若变量值不止一个则使用空格分隔

SET(SRC_LIST main.cpp)

  • MESSAGE关键字

向终端输出用户自定义信息,主要包含以下三种信息:

  • SEND_ERROR:产生错误,生成过程被跳过
  • STATUS:输出前缀为-- 的信息
  • FATAL_ERROR:立即终止所有cmake过程
  • ADD_EXECUTABLE关键字

生成可执行文件

ADD_EXECUTABLE(hello ${SRC_LIST}) 生成可执行文件名为hello,源文件读取变量SRC_LIST中的内容

内部构建和外部构建

  • 内部构建:直接在源文件所在目录执行cmake .从而生成的中间文件都在源文件所在目录

  • 外部构建:在源文件所在目录中创建build目录并在该目录中执行cmake ..从而使生成的中间文件都在build目录下

  • 工程目录下每个文件夹尽量都放一个CMakeLists.txt

ADD_SUBDIRECTORY(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

该指令用于向当前工程中添加存放源文件的子目录,并且可以指定中间二进制和目标二进制文件的存放位置

EXCLUDE_FROM_ALL将写的目录从编译中排除,如程序中的example

ADD_SUBDIRECTORY(src bin):将src子目录加入工程并指定编译输出为bin目录;若不指定编译输出目录则编译结构都存放于build/src目录中

  • 静态库和动态库创建
1
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})

hello:生成的库名字,默认会在其前面添加lib,最终产生文件是libhello.so

SHARED:动态库 STATIC:静态库

${LIBHELLO_SRC}:源文件

SET_TARGET_PROPERTIES():设置输出名称,还能指定动态库版本和API版本,如:

SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.0 SOVERSION 1)

其中VERSION指代动态库版本,SOVERSION指代API版本

1
2
3
4
5
6
7
8
9
10
11
12
# 同时创建动态库和静态库
SET(LIBHELLO_SRC hello.cpp)

ADD_LIBRARY(hello_staticSTATIC ${LIBHELLO_SRC})
//对hello_static重名为hello
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
/cmake在构建一个新的target时,会尝试清理掉其他使用这个名字的库,因为,在构建libhello.so时,就会清理掉libhello.a
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)

ADD LIBRARY(hello SHARED S{LIBHELLO SRC})
SET_TARGET_PROPERTIES(hello PROPERTIES OUTPUT_NAME "hello")
SET TARGET_PROPERTIES(hello PROPERTIES CLEAN DIRECT_OUTPUT 1)

安装

  • 代码编译后使用make install安装
  • 指定目录安装:make install DESTDIR=/tmp/test./configure --prefix=/usr

CMake安装

CMAKE_INSTALL_PREFIX:安装路径

  • 安装文件
1
INSTALL(FILES COPYRIGHT README DESTINATION share/doc/cmake/)

FILES:需要安装的文件

DESTINATION:绝对路径或相对路径

相对路径:${CMAKE_INSTALL_PREFIX}/share/doc/cmake/ 其中${CMAKE_INSTALL_PREFIX}默认为/usr/local

cmake -D CMAKE_INSTALL_PREFIX=/usr .. 表示在cmake时指定CMAKE_INSTALL_PREFIX变量的值即安装路径

  • 安装脚本
1
INSTALL(PROGRAMS runhello.sh DESTINATION bin)

PROGRAMS:非目标文件的可执行程序安装(例如脚本)

上述bin也是相对路径,实际为/usr/local/bin

  • 安装目录中的文件
1
INSTALL(DIRECTORY doc/ DESTINATION share/doc/cmake)

注意:doc和doc/区别如下

目录名不以/结尾(doc):该目录将会被安装到目标路径下

目录名以/结尾(doc/):该目录下的所有内容将会被安装到目标路径下

  • 安装共享库和头文件
1
2
3
4
5
6
//文件放到该目录下
INSTALL(FILES hello.h DESTINATION include/hello)

//二进制,静态库,动态库安装都用TARGETS
//ARCHIVE特指静态库,LIBRARY特指动态库,RUNTIME特指可执行目标二进制。
INSTALL(TARGETS hello hello_static LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)

共享库调用

向工程中添加多个特定头文件搜索路径,路径之间使用空格分隔

1
INCLUDE_DIRECTORY(/usr/include/hello)

解决:找到引用的函数问题

报错信息:undefined reference to`HelloFunc()’

LINK_DIRECTORIES: 添加非标准的共享库搜索路径(指定第三方库所在路径LINK_DIRECTORIES(/PATH))

TARGET_LINK_LIBRARIES: 添加需要链接的共享库(只需要给出动态链接库的名字就行)

在CMakeLists..txt中插入链接共享库,主要要插在executablel的后面

  • debug版本(可调试版本)

cmake .. -D CMAKE_BUILD_TYPE=debug