CMake:学习笔记,包含一些指令函数功能
cmake是 kitware 公司以及一些开源开发者在开发几个工具套件(VTK)的过程中所产生的衍生品。后来经过发展,最终形成体系,在2001年成为一个独立的开放源代码项目。
下载地址(官方)www.cmake.org,可以通过访问官方网站来获得更多关于cmake的信息,而且目前官方的英文文档比以前有了很大的改进,可以作为实践中的参考手册。
创建一个项目目录,例如创建一个CMake文件(我的目录为user_name/my_work/cmake),在cmake目录中新建 hello_cmake.c、CMakeLists.txt文件以及build文件夹,内容如下:
hello_cmake.c:
#include
int main() { printf("Hello CMake\n"); return 0; }
CMakeLists.txt:
cmake_minimum_required (VERSION 2.8) project (HelloCMake) add_executable(HelloCMake hello_cmake.c)
ubuntu系统中,alt+ctrl+T打开一个终端,cd my_work/cmake/build(移动至build目录),cmake .. ,make ,./HelloCMake 运行可执行文件,在Unix系列的操作系统上,使用CMake步骤分为:
CMake命令行说明:(终端内输入cmake --help查看。更详尽的解释可以查看CMake的官方手册)
- cmake [
] ( | ) - cmake [(-D =
)...] -P - cmake --build
[ ...] [-- ...] - cmake -E
[ ...] - cmake --find-package
...
常见的使用方式是上述第一种,这里也主要介绍这种方式。
[
],表示option为可选的。path-to-source 和 path-to-existing-build二选一,分别表示一个CMakeLists.txt所在的路径和一个已存在的构建工程所在的路径。例如: cmake .
其中option常用的有
-G
、-D :
等,如:-Torch_DIR=/pytorch/torch/lib . ,会在CMakeCache.txt中添加一条= , -D = set(Torch_DIR /pytorch/torch/lib) # 这样,可以在CMakeLists.txt文件中使用该变量的值。
3.1 set()
其功能为将一个变量设置为给定值,函数原型:
# 将一个CMAKE变量设置为给定值 set(
... [PARENT_SCOPE]) 例子-CMakelists.txt:
set(COCOS2D_ROOT ${CMAKE_SOURCE_DIR}/cocos2d) # 这个命令完成了这么一件事情: # 定义了一个变量COCOS2D_ROOT,并且变量的值为${CMAKE_SOURCE_DIR}/cocos2d # CMAKE_SOURCE_DIR为源码树的顶层路径
3.2 find_package()
例子-CMakelists.txt:
project(test_pytorch) set(CMAKE_CXX_STANDARD 11) # libtorch set(Torch_DIR /home/xxx/libtorch/share/cmake/Torch) find_package(Torch REQUIRED) add_executable(test_pytorch test_pytorch.cpp) target_link_libraries(test_pytorch ${TORCH_LIBRARIES})
概括来说,以Torch为例:find_package()函数,如果找到了相关的头文件和库文件,则会相应保存在
${Torch_INCLUDE_DIRS} 和${Torch_LIBRARIES }中。
函数原型:
find_package(
[version] [EXACT] [QUIET] [MODULE] [REQUIRED] [[COMPONENTS] [components...]] [OPTIONAL_COMPONENTS components...] [NO_POLICY_SCOPE]) 下面我们说一说find_package()的语法:
- Version 和 EXACT : 都是可选的,version指定的是版本,如果指定就必须检查找到的包的版本是否和version兼容。如果指定EXACT则表示必须完全匹配的版本而不是兼容版本就可以。
- QUIET : 可选字段,表示如果查找失败,不会在屏幕进行输出(但是如果指定了REQUIRED字段,则QUIET无效,仍然会输出查找失败提示语)。
- MODULE : 可选字段。前面提到说“如果Module模式查找失败则回退到Config模式进行查找”,但是假如设定了MODULE选项,那么就只在Module模式查找,如果Module模式下查找失败并不回落到Config模式查找。
- CONFIG : 可选字段。直接在Config模式中查找。下文会介绍什么是Moudule模式什么是Config模式。
- REQUIRED : 可选字段。表示一定要找到包,找不到的话就立即停掉整个cmake。而如果不指定REQUIRED则cmake会继续执行。
- COMPONENTS : 可选字段,表示查找的包中必须要找到的组件(components),如果有任何一个找不到就算失败,类似于REQUIRED,导致cmake停止执行。上面的例子中find_package( PCL REQUIRED COMPONENT common io )我们就利用了该关键字寻找了common和io包。
- OPTIONAL_COMPONENTS : 可选的模块,找不到也不会让cmake停止执行。
find_package工作原理
cmake本身不提供任何搜索库的便捷方法,所有搜索库并给变量赋值的操作必须由cmake代码完成,比如FindXXX.cmake 和 XXXConfig.cmake。只不过,开源的库通常会提供这两个文件,以方便使用者调用。
[1] find_package采用两种模式搜索库:
- Module模式:搜索CMAKE_MODULE_PATH指定路径下的FindXXX.cmake文件,执行该文件从而找到XXX库。其中,具体查找库并给XXX_INCLUDE_DIRS和XXX_LIBRARIES两个变量赋值的操作由FindXXX.cmake模块完成(先搜索当前项目里面的Module文件夹里面提供的FindXXX.cmake,然后再搜索系统路径/usr/local/share/cmake-x.y/Modules/FindXXX.cmake)
- Config模式:搜索XXX_DIR指定路径下的XXXConfig.cmake文件,执行该文件从而找到XXX库。其中具体查找库并给XXX_INCLUDE_DIRS和XXX_LIBRARIES两个变量赋值的操作由XXXConfig.cmake模块完成。
[2] 此外:
- 对于可能没有***.cmake和***Config.cmake的库文件,可以直接找到其头文件和库文件所在文件夹,直接进行路径赋值:
set(LAPACK_DIR /usr/local/lib/) set(LAPACK_INCLUDE_DIRS /usr/local/include) set(LAPACK_LIBRARIES /usr/local/lib)
3.3 install命令
install用于指定在安装时运行的规则。它可以用来安装很多内容,可以包括目标二进制、动态库、静态库以及文件、目录、脚本等:
install(TARGETS ... [...])
install({FILES | PROGRAMS} ... [...])
install(DIRECTORY ... [...])
install(SCRIPT [...])
install(CODE [...])
install(EXPORT [...])
有时候,也会用到一个非常有用的变量CMAKE_INSTALL_PREFIX
,用于指定cmake install时的相对地址前缀。用法如:
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
目标文件的安装:
install(TARGETS targets... [EXPORT ]
[[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|
PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE]
[DESTINATION ]
[PERMISSIONS permissions...]
[CONFIGURATIONS [Debug|Release|...]]
[COMPONENT ]
[NAMELINK_COMPONENT ]
[OPTIONAL] [EXCLUDE_FROM_ALL]
[NAMELINK_ONLY|NAMELINK_SKIP]
] [...]
[INCLUDES DESTINATION [ ...]]
)
参数中的TARGET
可以是很多种目标文件,最常见的是通过ADD_EXECUTABLE或ADD_LIBRARY定义的目标文件,即可执行二进制、动态库、静态库:
为了符合一般的默认安装路径,如果设置了DESTINATION
参数,推荐配置在安装目录变量下的文件夹。
例如:
INSTALL(TARGETS myrun mylib mystaticlib
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
上面的例子会将:可执行二进制 myrun
安装到 ${CMAKE_INSTALL_BINDIR}
目录,动态库 libmylib.so
安装到${CMAKE_INSTALL_LIBDIR}
目录,静态库 libmystaticlib.a
安装到 ${CMAKE_INSTALL_LIBDIR}
目录。