cmake常用命令以qgis源码编译中CMakeLists.txt为例子

参考文档:https://blog.csdn.net/wzzfeitian/article/details/40963457
cmake指令官网:https://cmake.org/cmake/help/v3.0/command/foreach.html?highlight=foreach

1.CMake编译原理

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

2.学习CMakeLists.txt


下面的示“例”内容全部来自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)

cmake常用命令以qgis源码编译中CMakeLists.txt为例子_第1张图片

  • 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
    LINK_DIRECTORIES(dir1 dir2 …)
    添加非标准的共享库搜索路径
    例:
LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/src/core ${CMAKE_BINARY_DIR}/src/gui)
  • ADD_DEFINITIONS
    向C/C++编译器添加-D定义
    ADD_DEFINITIONS(-DENABLE_DEBUG -DABC),参数之间用空格分隔
    控制宏的开启和关闭.
    例:
ADD_DEFINITIONS(-DWITH_QTWEBKIT)
  • INCLUDE
    INCLUDE(file [OPTIONAL]) 用来载入CMakeLists.txt文件
    INCLUDE(module [OPTIONAL])用来载入预定义的cmake模块
    OPTIONAL参数的左右是文件不存在也不会产生错误
    可以载入一个文件,也可以载入预定义模块(模块会在CMAKE_MODULE_PATH指定的路径进行搜索)
    载入的内容将在处理到INCLUDE语句时直接执行
    例:
  INCLUDE(Flex)
  • FIND_
    FIND_FILE( name path1 path2 …)
    VAR变量代表找到的文件全路径,包含文件名
    FIND_LIBRARY( name path1 path2 …)
    VAR变量代表找到的库全路径,包含库文件名
    FIND_PATH( name path1 path2 …)
    VAR变量代表包含这个文件的路径
    FIND_PROGRAM( name path1 path2 …)
    VAR变量代表包含这个程序的全路径
    例:
 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
    Evaluate a group of commands while a condition is true
    条件为真时计算一组命令
while(condition)
  COMMAND1(ARGS ...)
  COMMAND2(ARGS ...)
  ...
endwhile(condition)

与if的判断条件相同。

  • FOREACH
    为列表中的每个值计算一组命令。
    例:
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
    if使用语法示例,如果结果为true,则调用THEN部分中的命令。否则,将调用else节中的命令。elseif和else节是可选的。您可能有多个elseif子句。注意,else和endif子句中的表达式是可选的。可以使用长表达式,并且有传统的优先顺序。
    例:
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)))
	首先评估括号内的表达式,然后像前面的示例一样评估其余的表达式。如果嵌套了括号,则最里面的内容将作为包含它们的表达式的一部分进行评估。

你可能感兴趣的:(cmake)