cmake简介
cmake是什么
CMake是个一个开源的跨平台自动化建构系统,用来管理软件建置的程序,并不依赖于某特定编译器,并可支持多层目录、多个应用程序与多个库。 它用配置文件控制建构过程(build process)的方式和Unix的make相似,只是CMake的配置文件取名为CMakeLists.txt。CMake并不直接建构出最终的软件,而是产生标准的建构档(如Unix的Makefile或Windows Visual C++的projects/workspaces),然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件,这种可以使用各平台的原生建构系统的能力是CMake和SCons等其他类似系统的区别之处。 CMake配置文件(CMakeLists.txt)可设置源代码或目标程序库的路径、产生适配器(wrapper)、还可以用任意的顺序建构可执行文件。CMake支持in-place建构(二进档和源代码在同一个目录树中)和out-of-place建构(二进档在别的目录里),因此可以很容易从同一个源代码目录树中建构出多个二进档。CMake也支持静态与动态程序库的建构。
“CMake”这个名字是"Cross platform Make"的缩写。虽然名字中含有"make",但是CMake和Unix上常见的“make”系统是分开的,而且更为高端。 它可与原生建置环境结合使用,例如:make、ninja、苹果的Xcode与微软的Visual Studio。
cmake优点
- 跨平台: windows、linux、macos均支持。
- 主流IDE普遍支持:windows可以构建vs工程,vs2019已原生支持,可以直接打开cmake构建项目。 qtcreator、clion、vscode(需搭配插件)。
- 协同开发:基于cmake跨平台、跨ide特性,可以实现一套代码不同系统、不同开发工具协同开发体验,实现协同开发之间只需关心编码部分无线关心系统平台、开发工具或第三方库的差异和限制。
- c++主流第三方库普遍提供cmake支持,引入第三方库方便快捷。Qt、OpencCV、PCL、boost等都提供cmake支持。
安装cmake
windows
官网下载链接
https://cmake.org/download/
下载安装包
设置环境变量,如果未设置环境变量则无法在命令行终端中使用cmake
linux
如何使用cmake构建已有项目
GUI构建VS工程
-
选择项目包含CMakeLists.txt源码根目录与VS生成目录
-
Configure
-
Generate
命令行构建
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# 进入项目包含CMakeLists.txt源码根目录
cd project_root_dir
# 创建build目录存放生成的VS工程
mkdir build
# 生成VS工程
cmake -G "Visual Studio 15 2017" .. # 默认32位
cmake -G "Visual Studio 16 2019" .. # 默认64位
cmake -G "Visual Studio 16 2019" Win32 ..
# 或
cmake -G "Visual Studio 16 2019" -A Win32 .. # 指定生成vs2019 32位工程
cmake -G "Visual Studio 15 2017" Win64 .. # 指定生成vs2017 64位工程
|
cmake基本语法
- 构建文件命名CMakeLists.txt
- 支持大写、小写、混合大小写的命令
- 注释格式
1
|
set(SOURCE_DIR "./src") # 设置SOURCE_DIR路径变量
|
格式为:
1
2
|
set(INCLUDE_DIR "./src") # 设置INCLUDE_DIR路径变量
include_directories(${INCLUDE_DIR})
|
1
2
3
4
5
|
if( ... )
#分支1
elseif( ... )
#分支2
endif()
|
1
|
cmake_minimum_required(VERSION 3.14)
|
如果CMake的当前版本低于指定的版本,它会停止处理工程文件,并报告错误。
1
|
project(project_name CXX)
|
为本工程设置一个工程名。而且,该命令还将变量<projectName>
_BINARY_DIR和<projectName>
_SOURCE_DIR设置为对应值。后面的可选项还可以让你指定你的工程可以支持的语言。比如CXX(即C++),C,Fortran,等等。在默认条件下,支持C和CXX语言。例如,如果你没有C++编译器,你可以通过列出你想要支持的语言,例如C,来明确地禁止对它的检查。使用特殊语言"NONE",针对任何语言的检查都会被禁止。
- add_executable(
<name>
main.cpp)
引入一个名为<name>
的可执行目标,该目标会由调用该命令时在源文件列表中指定的源文件来构建。<name>
对应于逻辑目标名字,并且在工程范围内必须是全局唯一的。被构建的可执行目标的实际文件名将根据具体的本地平台创建出来(比如<name>
.exe或者仅仅是<name>
)。
- target_link_libraries(
executable_name>
<libs>
)
1
2
|
# 链接OpenCV库
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})
|
最基础项目的CMakeLists.txt
项目目录:
1
2
|
CMakeLists.txt
main.cpp
|
1
2
3
4
5
6
7
8
|
# 最低cmake版本要求
cmake_minimum_required(VERSION 3.14)
# 项目名称
project(simple_project_demo)
# 编译生成可执行文件
add_executable(${PROJECT_NAME} main.cpp)
|
多文件
1
2
3
4
5
6
7
8
9
10
11
|
# 最低cmake版本要求
cmake_minimum_required(VERSION 3.14)
# 项目名称
project(multiple_files_demo)
# 包含当前目录
include_directories(./)
# 编译生成可执行文件
add_executable(${PROJECT_NAME} main.cpp add.cpp)
|
多项目多目录
项目根目录CMakeLists.txt
1
2
3
4
5
6
7
|
cmake_minimum_required(VERSION 3.14)
# 项目名称
project(multi_project)
add_subdirectory(project1_dir)
add_subdirectory(project1_dir)
|
子项目1: CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
|
# 最低cmake版本要求
cmake_minimum_required(VERSION 3.14)
# 项目名称
project(subproject1)
# 包含当前目录
include_directories(./)
# 编译生成可执行文件
add_executable(${PROJECT_NAME} main.cpp)
|
子项目2: CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
|
# 最低cmake版本要求
cmake_minimum_required(VERSION 3.14)
# 项目名称
project(subproject2)
# 包含当前目录
include_directories(./)
# 编译生成可执行文件
add_executable(${PROJECT_NAME} main.cpp)
|
生成动/静态库
1
2
3
4
5
6
7
8
|
cmake_minimum_required(VERSION 3.14)
project(add)
# 生成静态库
add_library(${PROJECT_NAME} STATIC add.h add.cpp)
# 生成动态库
# add_library(${PROJECT_NAME} SHARED add.h add.cpp)
|
引用第三方库
OpenCV
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# 最低cmake版本要求
cmake_minimum_required(VERSION 3.14)
# 项目名称
project(import_opencv_demo)
# 查找OpenCV
find_package(OpenCV REQUIRED)
# 包含OpenCV头文件目录
include_directories(${OpenCV_INCLUDE_DIRS})
# 编译生成可执行文件
add_executable(${PROJECT_NAME} main.cpp)
# 链接OpenCV库文件
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})
|
OpenMP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# 最低cmake版本要求
cmake_minimum_required(VERSION 3.14)
# 项目名称
project(import_openmp)
# 搜索OpenMP
find_package(OpenMP)
# 编译main.cpp文件生成可执行文件
add_executable(${PROJECT_NAME} "main.cpp")
# 链接OpenMP
if(OpenMP_CXX_FOUND)
target_link_libraries(${PROJECT_NAME} PUBLIC OpenMP::OpenMP_CXX)
endif()
|
Qt
文件目录如下:
1
2
3
4
5
|
│ CMakeLists.txt
│ main.cpp
│ mainwindow.cpp
│ mainwindow.h
│ mainwindow.ui
|
CMakeLists.txt脚本文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
# cmake最低版本号要求
cmake_minimum_required(VERSION 3.14)
# 项目名称
project(import_qt_demo)
# qt相关设置,设置moc、rcc、uic
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON) #打开全局rcc,本示例中没有使用qrc,此句可以去掉
set(CMAKE_AUTOUIC ON)
# 包含当前目录
include_directories(./)
# 搜索Qt5
find_package(Qt5 COMPONENTS Widgets REQUIRED)
# 编译生成可执行文件
add_executable(${PROJECT_NAME}
main.cpp
mainwindow.cpp
mainwindow.ui
)
# 链接qt库文件
target_link_libraries(${PROJECT_NAME} Qt5::Widgets)
|
PCL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
# 最低cmake版本要求
cmake_minimum_required(VERSION 3.12)
# 项目名称
project(import_pcl)
# 搜索PCL
find_package(PCL REQUIRED)
include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})
# 编译main.cpp文件生成可执行程序
add_executable(${PROJECT_NAME} main.cpp)
# 链接PCL库
target_link_libraries(${PROJECT_NAME} ${PCL_LIBRARIES})
|
任意
有些第三方库并未基于CMake构建而得,提供SDK的时候并未提供PackageConfig.cmake文件,往往只提供了库文件和包含头文件。此时可以通过编写FindXXX.cmake文件实现对第三方库的引入。SDK目录一般如下结构
1
2
3
4
5
6
|
---root:
include: # 存放头文件
lib: # lib文件
debug:
release:
bin: # dll文件
|
此时在SDK根目录新建一个cmake目录存放FindXXX.cmake文件:
1
2
3
4
5
6
7
|
---root:
cmake:
include: # 存放头文件
lib: # lib文件
debug:
release:
bin: # dll文件
|
以OpenCV为例,假如所得OpenCV安装包只有头文件和库文件,通过以下方法可以引入OpenCV。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
|-cmake
| FindOpenCV.cmake
├─bin
│ opencv_ffmpeg3410_64.dll
│
├─include
...#头文件
└─lib
├─debug
│ opencv_world3410d.lib
│
└─release
opencv_world3410.lib
|
其中FindOpenCV.cmake内容为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
#--------------------使用示例--------------------
#
# set(CMAKE_MODULE_PATH = ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
# project(import_OpenCV_demo)
# find_package(OpenCV REQUIRED)
# include_directories(${OpenCV_INCLUDE_DIRS})
# add_executable(${PROJECT_NAME} main.cpp)
# target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBRARIES})
#
# ---------------------------------------------
#
# 最低版本号要求
cmake_minimum_required(VERSION 3.12)
#
if(NOT OpenCV_FOUND)
# 设置头文件目录、库目录路径(相对路径)
set(OpenCV_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/../include")
set(OpenCV_LIBRARIE_DIR_DEBUG "${CMAKE_CURRENT_LIST_DIR}/../lib/debug" ) #debug
set(OpenCV_LIBRARIE_DIR_RELEASE "${CMAKE_CURRENT_LIST_DIR}/../lib/release" ) #release
set(OpenCV_LIBRARIES_DIR ${OpenCV_LIBRARIE_DIR_DEBUG} ${OpenCV_LIBRARIE_DIR_RELEASE})
#
# 搜索debug库文件
find_library(opencv_world3410d_LIBRARY_DEBUG NAMES opencv_world3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
#
# 搜索release库文件
find_library(opencv_world3410_LIBRARY_DEBUG NAMES opencv_world3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
#
# 合并debug、release库文件只一个变量(cmake会自动区分配置debug和release)
include(SelectLibraryConfigurations)
select_library_configurations( opencv_world3410d )
set(OpenCV_LIBRARIES ${opencv_world3410d_LIBRARY} )
#
# 将搜索所得变量签名,并标记为高级变量,以供CMakeLists.txt引入使用
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OpenCV DEFAULT_MSG OpenCV_INCLUDE_DIRS OpenCV_LIBRARIES_DIR OpenCV_LIBRARIES)
mark_as_advanced(OpenCV_INCLUDE_DIRS OpenCV_LIBRARIES_DIR OpenCV_LIBRARIES)
endif()
|
编写FindXXX.cmake这种方式适用于任意的第三方库引入,但缺点是每次都需重新编写。一旦库文件比较多写起来就非常麻烦。为此斜率一个脚本自动生成。只需要将改脚本放置第三方库根目录运行即可:
1
2
3
4
5
6
7
8
9
10
11
12
|
├─bin
│ .. # dll
│
├─include
...#头文件
└─lib
├─debug
│ ... # lib文件debug
│
└─release
... # lib文件release
|- auto_generate_findxxx_cmake.py
|
运行脚本即可自动生成,以下为自动生成的FindOpenCV.cmake。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
#--------------------demo--------------------
#
# set(CMAKE_MODULE_PATH = ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
# project(import_OpenCV_demo)
# find_package(OpenCV REQUIRED)
# include_directories(${OpenCV_INCLUDE_DIRS})
# add_executable(${PROJECT_NAME} main.cpp)
# target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBRARIES})
#
# ---------------------------------------------
#
cmake_minimum_required(VERSION 3.12)
#
if(NOT OpenCV_FOUND)
set(OpenCV_INCLUDE_DIRS "${CMAKE_CURRENT_LIST_DIR}/../include")
set(OpenCV_LIBRARIE_DIR_DEBUG "${CMAKE_CURRENT_LIST_DIR}/../lib/debug" ) #debug
set(OpenCV_LIBRARIE_DIR_RELEASE "${CMAKE_CURRENT_LIST_DIR}/../lib/release" ) #release
set(OpenCV_LIBRARIES_DIR ${OpenCV_LIBRARIE_DIR_DEBUG} ${OpenCV_LIBRARIE_DIR_RELEASE})
#
#find and set the debug libraries.
find_library(opencv_calib3d3410d_LIBRARY_DEBUG NAMES opencv_calib3d3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
find_library(opencv_core3410d_LIBRARY_DEBUG NAMES opencv_core3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
find_library(opencv_dnn3410d_LIBRARY_DEBUG NAMES opencv_dnn3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
find_library(opencv_features2d3410d_LIBRARY_DEBUG NAMES opencv_features2d3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
find_library(opencv_flann3410d_LIBRARY_DEBUG NAMES opencv_flann3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
find_library(opencv_highgui3410d_LIBRARY_DEBUG NAMES opencv_highgui3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
find_library(opencv_imgcodecs3410d_LIBRARY_DEBUG NAMES opencv_imgcodecs3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
find_library(opencv_imgproc3410d_LIBRARY_DEBUG NAMES opencv_imgproc3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
find_library(opencv_ml3410d_LIBRARY_DEBUG NAMES opencv_ml3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
find_library(opencv_objdetect3410d_LIBRARY_DEBUG NAMES opencv_objdetect3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
find_library(opencv_photo3410d_LIBRARY_DEBUG NAMES opencv_photo3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
find_library(opencv_shape3410d_LIBRARY_DEBUG NAMES opencv_shape3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
find_library(opencv_stitching3410d_LIBRARY_DEBUG NAMES opencv_stitching3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
find_library(opencv_superres3410d_LIBRARY_DEBUG NAMES opencv_superres3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
find_library(opencv_video3410d_LIBRARY_DEBUG NAMES opencv_video3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
find_library(opencv_videoio3410d_LIBRARY_DEBUG NAMES opencv_videoio3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
find_library(opencv_videostab3410d_LIBRARY_DEBUG NAMES opencv_videostab3410d PATHS ${OpenCV_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib)
#
#find and set the release libraries.
find_library(opencv_calib3d3410_LIBRARY_DEBUG NAMES opencv_calib3d3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
find_library(opencv_core3410_LIBRARY_DEBUG NAMES opencv_core3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
find_library(opencv_dnn3410_LIBRARY_DEBUG NAMES opencv_dnn3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
find_library(opencv_features2d3410_LIBRARY_DEBUG NAMES opencv_features2d3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
find_library(opencv_flann3410_LIBRARY_DEBUG NAMES opencv_flann3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
find_library(opencv_highgui3410_LIBRARY_DEBUG NAMES opencv_highgui3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
find_library(opencv_imgcodecs3410_LIBRARY_DEBUG NAMES opencv_imgcodecs3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
find_library(opencv_imgproc3410_LIBRARY_DEBUG NAMES opencv_imgproc3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
find_library(opencv_ml3410_LIBRARY_DEBUG NAMES opencv_ml3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
find_library(opencv_objdetect3410_LIBRARY_DEBUG NAMES opencv_objdetect3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
find_library(opencv_photo3410_LIBRARY_DEBUG NAMES opencv_photo3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
find_library(opencv_shape3410_LIBRARY_DEBUG NAMES opencv_shape3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
find_library(opencv_stitching3410_LIBRARY_DEBUG NAMES opencv_stitching3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
find_library(opencv_superres3410_LIBRARY_DEBUG NAMES opencv_superres3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
find_library(opencv_video3410_LIBRARY_DEBUG NAMES opencv_video3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
find_library(opencv_videoio3410_LIBRARY_DEBUG NAMES opencv_videoio3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
find_library(opencv_videostab3410_LIBRARY_DEBUG NAMES opencv_videostab3410 PATHS ${OpenCV_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib)
#
# merge debug and release libs to OpenCV_LIBRARIES
include(SelectLibraryConfigurations)
select_library_configurations( opencv_calib3d3410d )
select_library_configurations( opencv_core3410d )
select_library_configurations( opencv_dnn3410d )
select_library_configurations( opencv_features2d3410d )
select_library_configurations( opencv_flann3410d )
select_library_configurations( opencv_highgui3410d )
select_library_configurations( opencv_imgcodecs3410d )
select_library_configurations( opencv_imgproc3410d )
select_library_configurations( opencv_ml3410d )
select_library_configurations( opencv_objdetect3410d )
select_library_configurations( opencv_photo3410d )
select_library_configurations( opencv_shape3410d )
select_library_configurations( opencv_stitching3410d )
select_library_configurations( opencv_superres3410d )
select_library_configurations( opencv_video3410d )
select_library_configurations( opencv_videoio3410d )
select_library_configurations( opencv_videostab3410d )
set(OpenCV_LIBRARIES ${opencv_calib3d3410d_LIBRARY} ${opencv_core3410d_LIBRARY} ${opencv_dnn3410d_LIBRARY} ${opencv_features2d3410d_LIBRARY} ${opencv_flann3410d_LIBRARY} ${opencv_highgui3410d_LIBRARY} ${opencv_imgcodecs3410d_LIBRARY} ${opencv_imgproc3410d_LIBRARY} ${opencv_ml3410d_LIBRARY} ${opencv_objdetect3410d_LIBRARY} ${opencv_photo3410d_LIBRARY} ${opencv_shape3410d_LIBRARY} ${opencv_stitching3410d_LIBRARY} ${opencv_superres3410d_LIBRARY} ${opencv_video3410d_LIBRARY} ${opencv_videoio3410d_LIBRARY} ${opencv_videostab3410d_LIBRARY} )
#
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OpenCV DEFAULT_MSG OpenCV_INCLUDE_DIRS OpenCV_LIBRARIES_DIR OpenCV_LIBRARIES)
mark_as_advanced(OpenCV_INCLUDE_DIRS OpenCV_LIBRARIES_DIR OpenCV_LIBRARIES)
endif()
|
自动生成脚本,使用之前一般只需要更改变量lib_name为库名称即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
# 自动生成FindXXX.cmake脚本
import sys, getopt
import os
def write_help_info(file, lib_name):
file.writelines("#--------------------demo--------------------\n")
file.writelines("# \n")
file.writelines("# set(CMAKE_MODULE_PATH = ${CMAKE_CURRENT_SOURCE_DIR}/cmake) \n")
file.writelines("# project(import_" + lib_name + "_demo) \n")
file.writelines("# find_package(" + lib_name + " REQUIRED) \n")
file.writelines("# include_directories(${" + lib_name + "_INCLUDE_DIRS}) \n")
file.writelines("# add_executable(${PROJECT_NAME} main.cpp) \n")
file.writelines("# target_link_libraries(${PROJECT_NAME} ${" + lib_name + "_LIBRARIES}) \n")
file.writelines("# \n")
file.writelines("# ---------------------------------------------\n")
def search_lib_files(file_dir):
libs = []
for root, dirs, files in os.walk(file_dir):
for file in files:
if os.path.splitext(file)[1] == '.lib':
libs.append(os.path.splitext(file)[0])
return libs
def generate_cmake_file(argv):
lib_name = "OpenCV"
mini_cmake_version = "3.12"
include_dir_name = "include"
debug_lib_dir = "lib/debug"
release_lib_dir = "lib/release"
file = open("Find" + lib_name + ".cmake","a")
write_help_info(file, lib_name)
file.writelines("# \n")
file.writelines("cmake_minimum_required(VERSION " + mini_cmake_version + ") \n")
file.writelines("# \n")
file.writelines("if(NOT " + lib_name + "_FOUND) \n")
file.writelines(" set(" + lib_name +"_INCLUDE_DIRS \"${CMAKE_CURRENT_LIST_DIR}/../" + include_dir_name + "\")\n")
file.writelines(" set(" + lib_name +"_LIBRARIE_DIR_DEBUG \"${CMAKE_CURRENT_LIST_DIR}/../" + debug_lib_dir + "\" ) #debug \n")
file.writelines(" set(" + lib_name +"_LIBRARIE_DIR_RELEASE \"${CMAKE_CURRENT_LIST_DIR}/../" + release_lib_dir + "\" ) #release \n")
file.writelines(" set(" + lib_name +"_LIBRARIES_DIR ${" + lib_name + "_LIBRARIE_DIR_DEBUG} ${" + lib_name + "_LIBRARIE_DIR_RELEASE}) \n")
current_dir = os.getcwd()
debug_libs = search_lib_files(current_dir + "/" + debug_lib_dir)
release_libs = search_lib_files(current_dir + "/" + release_lib_dir)
file.writelines("# \n")
file.writelines(" #find and set the debug libraries. \n")
for d_lib in debug_libs:
file.writelines(" find_library(" + d_lib + "_LIBRARY_DEBUG NAMES " + d_lib + " PATHS ${" + lib_name + "_LIBRARIE_DIR_DEBUG} PATH_SUFFIXES lib) \n")
file.writelines("# \n")
file.writelines(" #find and set the release libraries. \n")
for r_lib in release_libs:
file.writelines(" find_library(" + r_lib + "_LIBRARY_DEBUG NAMES " + r_lib + " PATHS ${" + lib_name + "_LIBRARIE_DIR_RELEASE} PATH_SUFFIXES lib) \n")
file.writelines("# \n")
file.writelines(" # merge debug and release libs to " + lib_name + "_LIBRARIES \n")
file.writelines(" include(SelectLibraryConfigurations) \n")
str_libs = ""
for lib in debug_libs:
file.writelines(" select_library_configurations( " + lib + " ) \n")
str_libs = str_libs + " ${" + lib + "_LIBRARY} "
file.writelines(" set(" + lib_name + "_LIBRARIES " + str_libs + ") \n")
file.writelines("# \n")
file.writelines(" include(FindPackageHandleStandardArgs) \n")
file.writelines(" find_package_handle_standard_args(" + lib_name +" DEFAULT_MSG " + lib_name +"_INCLUDE_DIRS "+ lib_name +"_LIBRARIES_DIR "+ lib_name +"_LIBRARIES) \n")
file.writelines(" mark_as_advanced("+ lib_name +"_INCLUDE_DIRS "+ lib_name + "_LIBRARIES_DIR "+ lib_name +"_LIBRARIES) \n")
file.writelines("endif() \n")
file.close()
if __name__ == '__main__':
generate_cmake_file(sys.argv[1:])
|
设置c++语言标准
1
2
|
# 设置c++标准为11
set(CMAKE_CXX_STANDARD 11)
|
生成静态库或动态库
1
2
3
4
5
6
|
cmake_minimum_required(VERSION 3.14)
project(add)
add_library(${PROJECT_NAME} STATIC add.h add.cpp)
# add_library(${PROJECT_NAME} SHARED add.h add.cpp)
|
系统平台判断
1
2
3
4
5
6
7
8
9
|
if (CMAKE_SYSTEM_NAME matches "Linux")
message(STATUS "current platform: Linux ")
elseif (CMAKE_SYSTEM_NAME matches "Windows")
message(STATUS "current platform: Windows")
elseif (CMAKE_SYSTEM_NAME matches "FreeBSD")
message(STATUS "current platform: FreeBSD")
else ()
message(STATUS "other platform: ${CMAKE_SYSTEM_NAME}")
endif()
|
1
2
3
4
5
6
7
|
if(WIN32)
message(STATUS "current platform: Windows")
elseif(APPLE)
elseif(UNIX)
endif()
|
添加预处理器宏定义
1
|
add_definitions(-DTEST -D_TEST)
|
设置Visual Studio字符集为Unicode
1
2
3
|
if(WIN32)
add_definitions(-DUNICODE -D_UNICODE)
endif()
|
设置Visual Studio子系统选项
qt相关
windows环境变量设置
qml项目
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
# 最低cmake版本要求
cmake_minimum_required(VERSION 3.14)
# 项目名称
project(qt_quick_demo)
# qt相关设置,设置moc、rcc、uic
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
# 包含当前目录
include_directories(./)
# 搜索qt core quick模块
find_package(Qt5 COMPONENTS Core Quick REQUIRED)
# 编译生成可执行文件
add_executable(${PROJECT_NAME} "main.cpp" "qml.qrc")
# 链接qt相关模块
target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Quick)
|
添加软件ico
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
# cmake最低版本号要求
cmake_minimum_required(VERSION 3.14)
# 项目名称
project(add_ico_in_qt_demo)
# qt相关设置,设置moc、rcc、uic
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
# 包含当前目录
include_directories(./)
# 搜索Qt5
find_package(Qt5 COMPONENTS Widgets REQUIRED)
# 设置ico
if(WIN32)
set(app_WINRC app_win32.rc)
set_property(SOURCE app_win32.rc APPEND PROPERTY OBJECT_DEPENDS app_logo.ico)
endif()
# 编译生成可执行文件
add_executable(${PROJECT_NAME}
main.cpp
mainwindow.cpp
mainwindow.ui
${app_WINRC}
)
# 链接qt库文件
target_link_libraries(${PROJECT_NAME} Qt5::Widgets)
|
编译选项
1
2
3
4
5
6
7
|
project(test)
option(TEST_DEBUG "option for debug" OFF)
if (TEST_DEBUG)
add_definitions(-DTEST_DEBUG)
endif()
# ...
|
1
2
3
4
5
|
#include "test.h"
#ifdef TEST_DEBUG
//...
#endif
|
1
2
|
cmake -DTEST_DEBUG=ON .
cmake --build .
|
交叉编译
- 编写toolchain.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
# 设置目标系统、处理器架构
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
# 设置工具链目录
set(TOOL_CHAIN_DIR ${CMAKE_CURRENT_LIST_DIR}/../)
set(TOOL_CHAIN_INCLUDE ${TOOL_CHAIN_DIR}/arm-linux-gnueabihf/include ${TOOL_CHAIN_DIR}/arm-linux-gnueabihf/libc/usr/include)
set(TOOL_CHAIN_LIB ${TOOL_CHAIN_DIR}/arm-linux-gnueabihf/lib ${TOOL_CHAIN_DIR}/arm-linux-gnueabihf/libc/usr/lib)
# 设置编译器位置
set(CMAKE_C_COMPILER "${TOOL_CHAIN_DIR}/bin/arm-linux-gnueabihf-gcc.exe")
set(CMAKE_CXX_COMPILER "${TOOL_CHAIN_DIR}/bin/arm-linux-gnueabihf-g++.exe")
# 设置cmake查找主路径
set(CMAKE_FIND_ROOT_PATH ${TOOL_CHAIN_DIR}/arm-linux-gnueabihf)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# 只在指定目录下查找库文件
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
# 只在指定目录下查找头文件
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# 只在指定目录下查找依赖包
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# 包含工具链文件
include_directories(
${TOOL_CHAIN_DIR}/arm-linux-gnueabihf/include
${TOOL_CHAIN_DIR}/arm-linux-gnueabihf/libc/usr/include)
# 设置CMAKE_INCLUDE_PATH
set(CMAKE_INCLUDE_PATH ${TOOL_CHAIN_INCLUDE})
# 设置CMAKE_LIBRARY_PATH
set(CMAKE_LIBRARY_PATH ${TOOL_CHAIN_LIB})
|
- 构建
相关参考和学习资料
官方文档
https://cmake.org/cmake/help/v3.20/
中文手册
https://www.zybuluo.com/khan-lau/note/254724