1. 基础语法
(一) 基础语法
1. 指定cmake最低版本
cmake_minimum_required (VERSION 2.6)
2. 设置项目名称
project (LearnCMake)
3.创建可执行程序
add_executable函数用于创建一个可执行程序工程。
add_executable(
[EXCLUDE_FROM_ALL]
source1 [source2 …])
如下所示:
add_executable(FirstExecutable hello_world.cpp)
也可以添加多个源文件到工程中,如下:
add_executable(FirstExecutable main.cpp app_util.h app_util.cpp)
4. 创建库文件工程(a/so/lib/dll)
add_library函数用于创建一个库文件工程。
add_library(
[EXCLUDE_FROM_ALL]
source1 [source2 …])
如下所示:
add_library(SecondLibrary second_library.cpp)
和add_executable一样,也可以添加多个源文件。
add_library(SecondLibrary test.cpp app_util.h app_util.cpp)
默认的是静态库,也可以显式的设置库是否为静态库、动态库或者是模块。另外BUILD_SHARED_LIBS也可控制编译成哪种库。
add_library(SecondLibrary SHARED second_library.cpp)
5、set设置变量
前面的add_library和add_executable可以添加多个源文件,但是文件多了之后可能会一行占用很长,因此我们可以使用set函数来进行变量赋值,然后在调用add_library和add_executable生成项目。
如下所示,效果和前面的示例一样。
set(SOURCES |
使用set函数,还可以对变量值进行累加,如下AppUtilSrcs就代表3个文件了
set(AppUtilSrcs app_util.h app_util.cpp) |
除了文件名定义,set还用于变量定义
SET(CMAKE_BUILD_TYPE "Debug") |
6、代码控制
如果一个项目太大,文件成千上万,那么一个一个文件的添加太过于麻烦了,因此cmake使用aux_source_directory函数来添加目录到工程中。
如下所示,将目录下所有文件赋值给第一个变量,然后将这个变量加到工程中。
# find all source file in src |
除了添加文件目录外,我们经常还需要包含第三方库(头文件、库文件)等需求,添加头文件目录功能如下:
include_directories函数用于添加头文件包含目录。
link_directories函数用于添加需要链接文件的库目录。
link_libraries函数用于添加需要连接的库文件。
include_directories(${PROJECT_NAME} ${PROJECT_SOURCE_DIR}/inc) |
链接目标文件和的库文件,使用target_link_libraries函数,这里的目标文件是指通过add_executable()和add_library()指令生成已经创建的目标文件。所以target_link_libraries是在add_executable之后,而link_libraries是在add_executable之前。
target_include_directories(${PROJECT_NAME} PRIVATE ${OpenCV_INCLUDE_DIRS}) |
从编译文件列表中排除文件,可以使用cmake提供的list的REMOVE_ITEM功能来实现。
aux_source_directory(src lua_src) |
7、添加编译选项
cmake使用add_compile_options函数来添加编译选项,用add_definitions函数来为源文件的编译添加由-D定义的标志,示例如下:
add_compile_options(-std=gnu99) |
也可以通过设置变量添加编译选项
# specify the C++ standard |
注意,这两个选项都是针对所有平台、编译器,因此需要慎重使用,最好使用if来进行流程处理。
8、添加其他的CMakeLists.txt
一个CMakeLists.txt里面的target如果要链接其他CMakeLists.txt中的target,可以使用add_subdirectory函数,如下所示:
add_subdirectory(debug) |
9、find_package
find_package 为外部工程加载设置。
find_package(
[[REQUIRED|COMPONENTS] [components…]]
[NO_POLICY_SCOPE])
QUIET选项将会禁掉包没有被发现时的警告信息。REQUIRED选项表示如果报没有找到的话,cmake的过程会终止,并输出警告信息。
find_package可以根据cmake内置的.cmake的脚本去找相应的库的模块,调用了find_package成功之后,会有相应的变量“生成”有效。
比如调用了find_package(Qt5Widgets),返回之后就会有变量Qt5Widgets_FOUND,Qt5Widgets_INCLUDE_DIRS相应的变量生效。 然后就可以在CMakeLists.txt里面使用上述的变量了。
find_package( OpenCV REQUIRED ) |
10、条件、循环控制
If else结构
if(condition)
elseif(condition)
else()
endif()for循环
foreach(loop_var arg1 arg2 ...)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
endforeach(loop_var)while循环
while(condition)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
endwhile(condition)
11、Install指令
Install指令用于定义安装规则,安装的内容可以包括目标二进制、动态库、静态库以及文件、目录、脚本等。
参数中的TARGETS后面跟的就是我们通过ADD_EXECUTABLE或者ADD_LIBRARY定义的目标文件,可能是可执行二进制、动态库、静态库。
目标类型也就相对应的有三种,ARCHIVE特指静态库,LIBRARY特指动态库,RUNTIME特指可执行目标二进制。
INSTALL(TARGETS targets…
[[ARCHIVE|LIBRARY|RUNTIME]
[DESTINATION
[PERMISSIONS permissions…]
[CONFIGURATIONS
[Debug|Release|…]]
[COMPONENT
[OPTIONAL]
] […])
示例如下:
INSTALL(TARGETS myrun mylib mystaticlib |
可执行二进制myrun安装到${CMAKE_INSTALL_PREFIX}/bin目录
动态库libmylib安装到${CMAKE_INSTALL_PREFIX}/lib目录
静态库libmystaticlib安装到${CMAKE_INSTALL_PREFIX}/libstatic目录
特别注意的是你不需要关心TARGETS具体生成的路径,只需要写上TARGETS名称就可以了。
(二)使用cmake流程
1. linux下使用
apt-get update |
2. windows下使用
- 安装mingw
- 安装mingw安装package中的mingw32-gcc-g++-bin(用来编译),mingw32-gdb-bin(用来调试)
- 添加环境变量
- 最后运行
- 每次cmake之前删除build里的缓存
cd build
cmake -G "Unix Makefiles" ../
(非常重要)
(三)自动生成版本信息
1. 获取git信息:commit号和分支信息
通过git log -1 –pretty=format:%H获取commit号
通过git symbolic-ref –short -q HEAD获取分支信息
示例如下:
# get git version |
(四)opencv的集成
1. linux下集成opencv:
sudo apt-get update |
直接就可以编译了
2. windows下集成opencv
去官网下载opencv windows安装包,运行就生成一个文件夹。里面有两个目录,build和source,build放的是预编译好的库,source里面放的是源码。
把build\x64\vc15\lib加入到环境变量中,看下代码运行是否正确。
问题1:
正常来说会报mutux找不到定义的错误。
那是因为mingw多线程的库有问题,必须要特定64位版本的才能够安装
下载安装:MinGW-x64-4.8.1-release-posix-seh-rev5
并把mingw的bin文件加到环境变量中去,就可以运行了。
问题2:
确认自己的cmake把opencv的库加进去的情况下,还是找不到imread等常用函数路径。那很可能是预编译没有编译出适合你电脑系统的库,需要自己编译opencv库
在source文件夹下新建一个build目录。编译的时候用mingw32-make -j16多线程编译会比cmake –build .更快一点
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .. -G "MinGW Makefiles" |
问题3:
windows下编译的时候会出现这个问题:
gcc: error: long: No such file or directory
解决方法:
cmake -DOPENCV_ENABLE_ALLOCATOR_STATS=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .. -G "MinGW Makefiles" |
问题4:
编译完成后,用cmake编译opencv的样例的时候发现,cmake打印出来的include路径不对。
需要编译之后安装!
cmake --install . |
接着把生成的库绝对路径:sources\build\install\x64\mingw\lib加入环境变量,注意这个要看编译器,不同的编译器和系统产生的库路径不一样
问题5:
在本地电脑上运行样例程序,提示缺少dll库
需要把source/build/bin加入环境变量
cmake 模板
# TODO: Set the project name |
(五) QT的集成
类似opencv,但是不需要自己编译了
在官网下载安装包:https://download.qt.io/official_releases/
选择QT版本,不需要全部勾选,比如我是mingw64编译器,那就选择mingw64版本的
然后把安装路径的Qt\5.15.0\mingw81_64\lib\cmake和C:\Qt\5.15.0\mingw81_64\bin加入环境变量,QT的安装就算完成了
cmake模版:
cmake_minimum_required(VERSION 3.5) |