参考文档:https://blog.csdn.net/wzzfeitian/article/details/40963457
cmake指令官网:https://cmake.org/cmake/help/v3.0/command/foreach.html?highlight=foreach
CMake是一种跨平台编译工具。CMake主要是编写CMakeLists.txt文件,CMake是一种跨平台编译工具。CMake主要是编写CMakeLists.txt文件, 然后用cmake命令将CMakeLists.txt文件转化为make所需要的makefile文件,最后用make命令编译源码生成可执行程序或共享库(so(shared object))。
cmake 指向CMakeLists.txt所在的目录,例如cmake … 表示CMakeLists.txt在当前目录的上一级目录。cmake后会生成很多编译的中间文件以及makefile文件,所以一般建议新建一个新的目录,专门用来编译;
例:
mkdir build-master
cd build-master
cmake ..
make
下面的示“例”内容全部来自qgis中的cmakelists.txt
qgis 源码信息
1.SET(CPACK_PACKAGE_VERSION_MAJOR "3") qgis主版本号,如3.4.7中的3
2.SET(CPACK_PACKAGE_VERSION_MINOR "4") qgis次版本号,如3.4.7中的4
3.SET(CPACK_PACKAGE_VERSION_PATCH "7") qgis补丁等级,如3.4.7中的7
4.SET(COMPLETE_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}) 拼接版本号,如3.4.7
5.PROJECT(qgis VERSION ${COMPLETE_VERSION}) 指定项目的名称和版本号,如qgis Version3.4.7
Cmake常用命令
基本语法规则:
1.cmake变量使用${}方式取值,在IF控制语句中是直接使用变量名,也可以使用${}方式取值
例:
IF (${CMAKE_HOST_SYSTEM_NAME} MATCHES "BSD$")
OPTION(USE_OPENCL "Use OpenCL" OFF)
ELSE (${CMAKE_HOST_SYSTEM_NAME} MATCHES "BSD$")
OPTION(USE_OPENCL "Use OpenCL" ON)
ENDIF (${CMAKE_HOST_SYSTEM_NAME} MATCHES "BSD$")
例:
IF (APPLE)
SET(QGIS_APP_NAME "QGIS")
ELSE (APPLE)
SET(QGIS_APP_NAME "qgis")
ENDIF (APPLE)
2.环境变量使用$ENV{}方式取值,使用SET(ENV{VAR} VALUE)赋值
SET(CXX_EXTRA_FLAGS "$ENV{CXX_EXTRA_FLAGS}")
a.普通变量
set(<variable> <value>... [PARENT_SCOPE])
设置变量<variable> 的值为 <value>
例:
SET(CPACK_PACKAGE_VERSION_PATCH "7")
SET(COMPLETE_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH})
b.设置缓存条目
<type> 必须是下列类型之一:
BOOL
Boolean、ON/OFF、cmake-gui 提供一个复选框。
FILEPATH
文件路径、 cmake-gui提供一个文件对话框。
STRING
一行文字、 cmake-gui提供文本字段或下拉选择。
INTERNAL
一行文字。 cmake-gui不显示内部条目。
例:
SET (WITH_CORE TRUE CACHE BOOL "Determines whether QGIS core should be built.")
c.设置环境变量
设置环境变量<variable>的值为<value>. 后面使用 $ENV{<variable>} 可以获取该值.
例:
SET(OpenCL_INCLUDE_DIRS ${OpenCL_INCLUDE_DIR})
部分常用命令列表:
PROJECT
PROJECT(projectname [CXX] [C] [Java])
指定工程名称,并可指定工程支持的语言。支持语言列表可忽略,默认支持所有语言
例:
PROJECT(qgis VERSION ${COMPLETE_VERSION}) //指定项目的名称和版本号
MESSAGE
MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] “message to display” …)
向终端输出用户定义的信息或变量的值,也可以输出日志
SEND_ERROR:产生错误,生成过程被跳过
STATUS: 输出前缀为—的信息
FATAL_ERROR: 立即终止所有cmake过程
例:
MESSAGE (SEND_ERROR "openpty not found!")
MESSAGE(STATUS "Qt WebKit support DISABLED.")
MESSAGE(FATAL_ERROR "Desktop cannot be built without gui. Enable WITH_GUI or disable WITH_DESKTOP.")
CMAKE_MINIMUM_REQUIRED
CMAKE_MINIMUM_REQUIRED(VERSION version_number [FATAL_ERROR])
声明CMake的版本要求
例:
CMAKE_MINIMUM_REQUIRED(VERSION 3.1.0) //指定cmake最低版本
ADD_SUBDIRECTORY
ADD_SUBDIRECTORY(src_dir [binary_dir] [EXCLUDE_FROM_ALL])
向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制的存放位置
EXCLUDE_FROM_ALL含义:将这个目录从编译过程中排除
例:
ADD_SUBDIRECTORY(doc)
ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(images)
ADD_SUBDIRECTORY(resources)
ADD_SUBDIRECTORY(i18n)
INCLUDE_DIRECTORIES
INCLUDE_DIRECTORIES([AFTER | BEFORE] [SYSTEM] dir1 dir2 … )
向工程添加多个特定的头文件搜索路径,路径之间用空格分隔,如果路径包含空格,可以使用双引号将它括起来,默认的行为为追加到当前头文件 搜索路径的后面。有如下两种方式可以控制搜索路径添加的位置:
CMAKE_INCLUDE_DIRECTORIES_BEFORE,通过SET这个cmake变量为on,可以将添加的头文件搜索路径放在已有路径的前面
通过AFTER或BEFORE参数,也可以控制是追加还是置前
例:
INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR})
INCLUDE_DIRECTORIES(SYSTEM ${QT_INCLUDE_DIR})
LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/src/core ${CMAKE_BINARY_DIR}/src/gui)
ADD_DEFINITIONS(-DWITH_QTWEBKIT)
INCLUDE(Flex)
FIND_PROGRAM(
CLANG_TIDY_EXE
NAMES "clang-tidy"
DOC "Path to clang-tidy executable"
)
FIND_PACKAGE( [major.minor] [QUIET] [NO_MODULE] [[REQUIRED | COMPONENTS] [componets …]])
用来调用预定义在CMAKE_MODULE_PATH下的Find.cmake模块,你也可以自己定义Find
模块,通过SET(CMAKE_MODULE_PATH dir)将其放入工程的某个目录供工程使用
例:
set(CMAKE_PREFIX_PATH "/opt/Qt5.11.2/5.11.2/gcc_64")
set(Qt5_DIR "${CMAKE_PREFIX_PATH}/lib/cmake/Qt5")
FIND_PACKAGE(Qt5Core QUIET)
FIND_PACKAGE(Qt5Gui REQUIRED)
FIND_PACKAGE(Qt5Widgets REQUIRED)
FIND_PACKAGE(Qt5Network REQUIRED
while(condition)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
endwhile(condition)
与if的判断条件相同。
FOREACH (GRASS_SEARCH_VERSION 7)
# Legacy note:
# For GRASS 6 there were used cached variables without version suffix so that existing caches didn't have to be reconfigured.
# Cached variables were: WITH_GRASS, WITH_GRASS7, GRASS_PREFIX, GRASS_PREFIX7, GRASS_INCLUDE_DIR, GRASS_INCLUDE_DIR7
# Everywhere else each variable has version major appended.
# Normal variables were: GRASS_FOUND6, GRASS_FOUND7, GRASS_MAJOR_VERSION6, GRASS_MAJOR_VERSION7, etc.
# In addition there is also GRASS_FOUND, which is TRUE if at least one version of GRASS was found
SET (GRASS_CACHE_VERSION ${GRASS_SEARCH_VERSION})
SET (WITH_GRASS${GRASS_CACHE_VERSION} TRUE CACHE BOOL "Determines whether GRASS ${GRASS_SEARCH_VERSION} plugin should be built")
IF (WITH_GRASS${GRASS_CACHE_VERSION})
FIND_PACKAGE(GRASS ${GRASS_SEARCH_VERSION})
SET (GRASS_PREFIX${GRASS_CACHE_VERSION} ${GRASS_PREFIX${GRASS_SEARCH_VERSION}} CACHE PATH "Path to GRASS ${GRASS_SEARCH_VERSION} base directory")
ENDIF (WITH_GRASS${GRASS_CACHE_VERSION})
ENDFOREACH (GRASS_SEARCH_VERSION)
if(expression)
# then section.
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
elseif(expression2)
# elseif section.
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
else(expression)
# else section.
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
endif(expression)
可能的表达式是:
1.if(<constant>)
true :常数是1,ON,YES,TRUE,Y,或一个非零数。
false :常数0,OFF, NO,FALSE,N,IGNORE,NOTFOUND,空字符串,或后缀结尾-NOTFOUND。
命名的布尔常量不区分大小写。
如果参数不是这些常量之一,则将其视为变量。
2.if(<variable>)
如果将变量定义为非假常量的值,则为True。否则为False。(请注意,宏参数不是变量。)
3.if(NOT <expression>)
与第一项相反。
4.if(<expr1> AND <expr2>)
俩个表达式都为真,则为真。
5.if(<expr1> OR <expr2>)
如果表达式一个为真,则为真
6.if(COMMAND command-name)
如果cmd命令可调用,则为真
7.if(POLICY policy-id)
如果给定名称是现有策略(格式为CMP<NNNN>),则为True 。
8.if(TARGET target-name)
如果给定的名字是现有的逻辑目标的名称,如那些由所创建的add_executable(),add_library()或者 add_custom_target()命令。
9.if(EXISTS path-to-file-or-directory)
如果指定的文件或目录存在,则为True。仅针对完整路径定义行为。
10.if(file1 IS_NEWER_THAN file2)
如果file1比file2更新或两个文件之一不存在,则为true。仅针对完整路径定义行为。如果文件时间戳完全相同,则IS_NEWER_THAN比较将返回true,这样,在出现平局的情况下将发生任何相关的生成操作。这包括为file1和file2传递相同文件名的情况。
11.if(IS_DIRECTORY path-to-directory)
如果给定名称是目录,则为True。仅针对完整路径定义行为。
12.if(IS_SYMLINK file-name)
如果给定名称是符号链接,则为True。仅针对完整路径定义行为。
13.if(IS_ABSOLUTE path)
如果给定路径是绝对路径,则为True。
14,if(<variable|string> MATCHES regex)
如果给定的字符串或变量的值与给定的正则表达式匹配,则为true。
15.if(<variable|string> LESS <variable|string>)
如果给定的字符串或变量的值是有效数字且小于右边的数字,则为true。
16.if(<variable|string> GREATER <variable|string>)
如果给定的字符串或变量的值是有效数字并且大于右侧的数字,则为true。
17.if(<variable|string> EQUAL <variable|string>)
如果给定的字符串或变量的值是有效数字并且等于右侧的数字,则为true。
18.if(<variable|string> STRLESS <variable|string>)
如果给定的字符串或变量的值在字典上小于右侧的字符串或变量,则为true。
19.if(<variable|string> STRGREATER <variable|string>)
如果给定的字符串或变量的值在字典上大于右侧的字符串或变量,则为true。
20.if(<variable|string> STREQUAL <variable|string>)
如果给定的字符串或变量的值在字典上等于右侧的字符串或变量,则为true。
21.if(<variable|string> VERSION_LESS <variable|string>)
逐组件整数版本号比较(版本格式为 major[.minor[.patch[.tweak]]])。
22.if(<variable|string> VERSION_EQUAL <variable|string>)
逐组件整数版本号比较(版本格式为 major[.minor[.patch[.tweak]]])。
23.if(<variable|string> VERSION_GREATER <variable|string>)
逐组件整数版本号比较(版本格式为 major[.minor[.patch[.tweak]]])。
24.if(DEFINED <variable>)
如果定义了给定变量,则为True。只要设置了变量,变量是true还是false都没有关系。(请注意,宏参数不是变量。)
25.if((expression) AND (expression OR (expression)))
首先评估括号内的表达式,然后像前面的示例一样评估其余的表达式。如果嵌套了括号,则最里面的内容将作为包含它们的表达式的一部分进行评估。