0. 变量
变量使用 ${ } 的方式取值,但是在if控制语句中直接使用变量名。
1. project
project ( project_name [CXX] [C] [Java] )
用来指定工程名称和工程语言(可省略),指令隐式定义了projectname_BINARY_DIR和projectname_SOURCE_DIR两个变量(写在cmake_cache里面),指的是编译发生的当前目录。
2. set
set ( VAR [VALUE] )
用来显式定义变量,如set (SRC_LIST main.c t1.c t2.c) 。(竟然不用套括号?)
3. message
message ( [SEND_ERROR | STATUS | FATAL_ERROR] “message to display” VAR )
用来向终端输出用户定义的信息。
4. add_executable
add_executable ( executable_filename [source_filename] )
生成名字为executable_filename的可执行文件,相关的源文件 [source_filename] 可以是一个源文件列表。
5. 清理构建结果
make clean
对构建出的可执行文件进行清理。
6. 外部构建
1 | mkdir build |
所有编译动作发生在编译目录,对原有工程没有任何影响。
7. add_subdirectory
add_subdirectory ( source_dir [binary_dir] [EXCLUDE_FROM_ALL] )
向当前工程目录添加存放源文件的子目录source_dir,并指定存放中间二进制文件和目标二进制文件的位置binary_dir。指令隐式修改 EXECUTABLE_OUTPUT_PATH 和 LIBRARY_OUTPUT_PATH 两个变量。
8. 更加像一个工程
- 创建工程根目录,创建CMakeLists.txt。
1 | # 指定最低编译版本 |
- 添加子目录src,用来存放源文件,为子目录创建CMakeLists.txt。
1 | # 在根目录CMakeLists.txt中添加子目录声明 |
1 | # 编写当前子目录的CMakeLists.txt |
- 添加子目录build,作为外部编译文件夹( ${PROJECT_BINARY_DIR} ),存放编译的过程和目标文件。
1 | cd build |
- 添加子目录doc,用来存放工程文档hello.txt。
- 添加文本文件README,COPYRIGHT。
- 添加runhello.sh脚本,用来调用可执行文件hello。
9. 打包安装
- 在根目录的CMakeList.txt中添加安装信息
1 | # 安装COPYRIGHT/README到<prefix>/share/doc/cmake/t2 |
- 在子目录的CMakeList.txt中添加安装信息
1 | # 安装脚本要调用的可执行文件hello到<prefix>/bin, |
- 安装程序包
1 | cd build |
10. add_library
add_library ( name [SHARED | STATIC | MODULE] [source_filename] )
生成名字为libname.X的库文件。
- SHARED,动态库,libname.dylib
- STATIC,静态库,libname.a
设置目标动态库和静态库同名 set_target_properties
1 | # 设置目标动静态库同名 |
防止构建中清理同名文件 set_target_properties
cmake在构建一个target时,会尝试清理掉其他使用这个名字的库——在构建libhello.a时会清理掉libhello.dylib。
我实际操作时候会保留两个库文件,但是在作为第三方被引用的时候会报错:
dyld: Library not loaded: libhello.dylib
Reason: image not found
1 | SET_TARGET_PROPERTIES(hello |
设置动态版本号 set_target_properties
1 | # 设置动态库版本号 |
编译文件夹下生成了libhello.1.2.dylib、libhello.1.dylib、libhello.dylib三个动态库文件,只有一个是真的,另外两个是替身。
安装共享库和头文件
修改库的源文件夹下的CMakeLIsts.txt
1 | # 库文件 |
11. include_directories
include_directories( dir1 dir2 … )
用来向工程添加多个特定的头文件搜索路径
12. link_directories & target_link_libraries
link_directories( dir1 dir2 … )
添加非标准的共享库搜索路径
target_link_libraries( target lib1 lib2 … )
用来为目标target添加需要链接的共享库,target可以是一个可执行文件,也可以是一个库文件。
查看生成目标的库依赖情况
1 | 生成的目标可执行文件为main |
只能列出动态库。
13. 常用变量
PROJECT_BINARY_DIR:编译发生的目录
PROJECT_SOURCE_DIR:工程顶层目录
CMAKE_CURRENT_SOURCE_DIR:当前CMakeLists.txt所在目录
CMAKE_MODULE_PATH:自定义的cmake模块所在路径
LIBRARY_OUTPUT_PATH:重定义目标库文件存放目录
EXECUTABLE_OUTPUT_PATH:重定义目标可执行文件存放目录
14. findNAME.cmake模块
- 在工程目录中创建cmake文件夹,并创建FindHELLO.cmake模块:
1 | # 示例 |
- 在主目录CMakeLists.txt中添加cmake模块所在路径:
1 | # 为find_package()指令成功执行 |
- 然后就可以在源文件CMakeLists.txt中调用 find_package:
find_package ( name [QUIET] [REQUIRED] )
用来调用预定义在CMAKE_MODULE_PATH下的Find\
每一个模块都会定义以下几个变量:
- NAME_FOUND
- NAME_INCLUDE_DIR or NAME_INCLUDES
- NAME_LIBRARY or NAME_LIBRARIES
根据指令后面的参数还会有以下变量:
NAME_FIND_QUIETLY,如果指定了QUIET参数,就不会执行如下语句:
1
MESSAGE(STATUS "Found Hello: ${NAME_LIBRARY}")
NAME_FIND_REQUIRED,如果指定了REQUIRED参数,就是指这个共享库是工程必须的,如果找不到,工程就不能编译,对应地会执行如下语句:
1
MESSAGE(FATAL_ERROR "Could not find NAME library")
可以通过\
15. find_指令
find_path
find_path ( VAR name1 path1 path2 … )
VAR变量代表包含name1文件的路径——路径。
find_library
find_library ( VAR name1 path1 path2 …)
VAR变量包含找到的库的全路径,包括库文件名——路径下的所有文件。