linux之cmake 为了阅读mysql安装中的编译细节
################
Mysql下载地址:https://downloads.mysql.com/archives/community/
cmake命令格式:
command(<target> [E] <A|B|C>)
- 尖括号
<>
: 必选变量,<target>
; - 方括号
[]
: 可选变量,[E]
; - 竖线
|
: 或的意思,A|B|C
;
变量:CMAKE_INCLUDE_PATH 和 CMAKE_LIBRARY_PATH:
添加头文件和动态文件所在的搜索路径。这两个是环境变量而不是 cmake 变量,通过设置环境变量能够使得指定的路径先于系统路径被搜索。
# cat ~/profile export CMAKE_INCLUDE_PATH=/home/work/include export CMAKE_LIBRARY_PATH=/home/work/lib
cmake内置变量:CMAKE_开头的变量或以_CMAKE开头的变量。
指定编程语言的版本:CMAKE_C_STANDARD,CMAKE_CXX_STANDARD
set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 11)
这里设置的变量都是CMAKE_
开头(包括project
命令自动设置的变量),这类变量都是CMake的内置变量,正是通过修改这些变量的值来配置CMake构建的行为
配置编译选项:add_compile_options
通过命令add_compile_options
命令可以为所有编译器配置编译选项(同时对多个编译器生效); 通过设置变量CMAKE_C_FLAGS
可以配置c编译器的编译选项; 而设置变量CMAKE_CXX_FLAGS
可配置针对c++编译器的编译选项。 比如:
add_compile_options(-Wall -Wextra -pedantic -Werror) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pipe -std=c99") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe -std=c++11")
配置编译类型:CMAKE_BUILD_TYPE
通过设置变量CMAKE_BUILD_TYPE
来配置编译类型,可设置为:
Debug
Release
RelWithDebInfo
MinSizeRel
等
比如:
set(CMAKE_BUILD_TYPE Debug)
当然,更好的方式应该是在执行cmake
命令的时候通过参数-D
指定:
cmake -B build -DCMAKE_BUILD_TYPE=Debug
如果设置编译类型为Debug
,那么对于c编译器,CMake会检查是否有针对此编译类型的编译选项CMAKE_C_FLAGS_DEBUG
,如果有,则将它的配置内容加到CMAKE_C_FLAGS
中。
可以针对不同的编译类型设置不同的编译选项,比如对于Debug
版本,开启调试信息,不进行代码优化:
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -O0") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -O0")
对于Release
版本,不包含调试信息,优化等级设置为2:
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")
默认安装路径:CMAKE_INSTALL_PREFIX=/usr/local
cmake的预定义变量设置:
cmake -DCMAKE_INSTALL_PREFIX=/home/work
在cmake文件CMakeLists.txt中设置CMAKE_INSTALL_PREFIX变量:
set(CMAKE_INSTALL_PREFIX "/home/work")
在cmake文件CMakeLists.txt中利用install指令:
变量:CMAKE_MODULE_PATH:
这个变量用来定义自己的 cmake 模块所在的路径。如果你的工程比较复杂,有可能会自己编写一些 cmake 模块,这些 cmake 模块是随你的工程发布的,为了让 cmake 在处理CMakeLists.txt 时找到这些模块,你需要通过 SET 指令,将自己的 cmake 模块路径设置一下。比如
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/mycmake)
这时候你就可以通过 INCLUDE 指令来调用自己的模块了。
camke中判断操作系统平台有两种方法:
- 通过系统变量:CMAKE_SYSTEM_NAME
MESSAGE(STATUS "operation system is ${CMAKE_SYSTEM}") 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 (CMAKE_SYSTEM_NAME MATCHES "Linux" ) MESSAGE(STSTUS"###################################")
- 通过系统变量:WIN32,APPLE,UNIX,LINUX
IF (WIN32) MESSAGE(STATUS "Now is windows " )
ELSEIF (APPLE) MESSAGE(STATUS "Now is Apple systens. " )
ELSEIF (UNIX) MESSAGE(STATUS "Now is UNIX-like os 's. " )
ENDIF ()
安装:CMAKE_INSTALL_PREFIX
对于安装来说,其实就是要指定当前项目在执行安装时,需要安装什么内容:可执行文件、库文件、头文件、归档文件的安装位置等
- 通过
install
命令来说明需要安装的内容及目标路径; - 通过设置
CMAKE_INSTALL_PREFIX
变量说明安装的路径,CMAKE_INSTALL_PREFIX
在不同的系统上有不同的默认值,使用的时候最好显式指定路径; cmake3.15
往后的版本可以使用cmake --install --prefix <install-path>
覆盖指定安装路径。
比如,在示例项目中,把math
和demo
两个目标按文件类型安装:
install(TARGETS math demo RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
说明:
- 这里通过
TARGETS
参数指定需要安装的目标列表; - 参数
RUNTIME DESTINATION
、LIBRARY DESTINATION
、ARCHIVE DESTINATION
分别指定可执行文件、库文件、归档文件分别应该安装到安装目录下个哪个子目录。 - 如果指定
CMAKE_INSTALL_PREFIX
为/usr/local
,那么math
库将会被安装到路径/usr/local/lib/
目录下;而demo
可执行文件则在/usr/local/bin
目录下。
- 同时,还可以使用
install
命令安装头文件:
file(GLOB_RECURSE MATH_LIB_HEADERS src/c/math/*.h) install(FILES ${MATH_LIB_HEADERS} DESTINATION include/math)
调用或执行shell脚本或命令:execute_process:
以下情况可能需要在CMake中执行shell脚本:
- cmake未提供的功能而实际构建中又需要时,如获取Linux发行版本;
- 项目构建时需要执行脚本才能完成,如boost构建过程;
有的需要shell脚本的返回值,而有的不需要,这个关系不大。本文主要关注的是在cmake中执行shell脚本的方法。
主要涉及三个命令:execute_process、add_custom_target和add_custom_command。
通过execute_process方法可以执行多个子进程。
原型如下:
execute_process(COMMAND <cmd1> [<arguments>] [COMMAND <cmd2> [<arguments>]]... [WORKING_DIRECTORY <directory>] [TIMEOUT <seconds>] [RESULT_VARIABLE <variable>] [RESULTS_VARIABLE <variable>] [OUTPUT_VARIABLE <variable>] [ERROR_VARIABLE <variable>] [INPUT_FILE <file>] [OUTPUT_FILE <file>] [ERROR_FILE <file>] [OUTPUT_QUIET] [ERROR_QUIET] [COMMAND_ECHO <where>] [OUTPUT_STRIP_TRAILING_WHITESPACE] [ERROR_STRIP_TRAILING_WHITESPACE] [ENCODING <name>] [ECHO_OUTPUT_VARIABLE] [ECHO_ERROR_VARIABLE] [COMMAND_ERROR_IS_FATAL <ANY|LAST>])
命令COMMAND会并行执行,每个子进程的标准输出映射到下一个进程的标准输入上,所有进程共用standard error管道。
各选项说明如下:
- COMMAND: 子进程的命令行,直接使用操作系统api执行。可以提供多个command,它们会并行执行。如果需要多个命令顺序执行,可以调用execute_process多次
- WORKING_DIRECTORY:在该目录下执行COMMAND命令
- TIMEOUT:超时时间,过了这个时间,所有子进程会被终止,RESULT_VARIABLE会被设置为“timeout”
- RESULT_VARIABLE:最后一个子进程的返回值(正常是0,异常是其他整数),或者描述发生错误的字符串
- RESULTS_VARIABLE:对应于每个子进程的返回值,使用分号分割的列表
- OUTPUT_VARIABLE:对应于standard output的内容
- ERROR_VARIABLE:对应于standard error的内容
- INPUT_FILE:第一个子进程的standard input
- OUTPUT_FILE:最后一个子进程的standard output
- ERROR_FILE:所有子进程的standard error
- OUTPUT_QUIET/ERROR_QUIET:忽略standard output 和 standard error
- COMMAND_ECHO:重显命令到指定的标准设备,如STDERR、STDOUT、NONE。使用CMAKE_EXECUTE_PROCESS_COMMAND_ECHO变量来修改它的行为
- OUTPUT_STRIP_TRAILING_WHITESPACE/ERROR_STRIP_TRAILING_WHITESPACE:删除空白字符
- ENCODING:在windows系统上指定进程输出时的解码方式,默认是utf-8,其他平台会忽略该参数
- ECHO_OUTPUT_VARIABLE/ECHO_ERROR_VARIABLE:输出将被复制,它将被发送到配置的变量中,也会在标准输出或标准错误中,3.18版本支持
- COMMAND_ERROR_IS_FATAL:触发致命错误并终止进程执行,方式取决于参数。ANY表示任意命令执行失败都触发,LAST表示最后一个进程执行失败才触发,3.19版本支持
cmake_minimum_required(VERSION 3.1) project(cmake_test) execute_process(COMMAND echo "hello world" WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} TIMEOUT 3 RESULT_VARIABLE result_var OUTPUT_VARIABLE output_var ERROR_VARIABLE error_var OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE) message(STATUS "result: ${result_var}") message(STATUS "output: ${output_var}") message(STATUS "error: ${error_var}")
条件地执行一组命令:if,elseif,else,endif
- if(<constant>),如果常量是
1
,ON
,YES
,TRUE
,Y
, 或非零数则为真。如果常量是0
,OFF
,NO
,FALSE
,N
,IGNORE
,NOTFOUND
, 空字符串,或者以后缀 结尾,则为假-NOTFOUND
。命名的布尔常量不区分大小写。 - 如果参数不是这些特定常量之一,则将其视为变量或字符串并使用签名:
if(<variable|string>) ,
如果给定的变量定义为非假常量的值,则为真。否则为假。(注意宏参数不是变量。)
if(<condition>) <commands> elseif(<condition>) <commands> else() <commands> endif()
逻辑运算符:NOT、 AND,OR;
if(NOT <condition>) 如果条件不为真,则为真。 if(<cond1> AND <cond2>) 如果两个条件都被认为是真的,则为真。 if(<cond1> OR <cond2>) 如果任一条件为真,则为真。 if((condition) AND (condition OR (condition))) 首先评估括号内的条件,然后像其他示例一样评估其余条件。在有嵌套括号的地方,最里面的括号被评估为评估包含它们的条件的一部分。
文件操作:
if(EXISTS path-to-file-or-directory) 如果指定的文件或目录存在则为真。行为仅针对显式完整路径进行了明确定义(前导~/未扩展为主目录,而是被视为相对路径)。解析符号链接,即如果指定的文件或目录是符号链接,如果符号链接的目标存在,则返回 true。 if(file1 IS_NEWER_THAN file2) file1 如果更新于file2或两个文件之一不存在则为真。行为仅针对完整路径进行了明确定义。如果文件时间戳完全相同,则IS_NEWER_THAN比较返回 true,以便在出现平局时会发生任何相关的构建操作。这包括为 file1 和 file2 传递相同文件名的情况。 if(IS_DIRECTORY path-to-directory) 如果给定名称是目录,则为真。行为仅针对完整路径进行了明确定义。 if(IS_SYMLINK file-name) 如果给定名称是符号链接,则为真。行为仅针对完整路径进行了明确定义。 if(IS_ABSOLUTE path) 如果给定路径是绝对路径,则为真。注意以下特殊情况:
-
空的
path
计算结果为 false。 -
在 Windows 主机上,任何
path
以驱动器号和冒号(例如C:
)、正斜杠或反斜杠开头的都将计算为真。这意味着像这样的路径C:no\base\dir
将评估为真,即使路径的非驱动器部分是相对的。 -
在非 Windows 主机上,任何
path
以波浪号 (~
) 开头的都计算为真。
比较大小:
if(<variable|string> MATCHES regex) 如果给定的字符串或变量的值与给定的常规条件匹配,则为真。有关正则表达式格式,请参阅正则表达式规范。版本 3.9 中的新功能:()组被捕获CMAKE_MATCH_<n>变量。 if(<variable|string> LESS <variable|string>) 如果给定的字符串或变量的值是有效数字并且小于右边的数字,则为真。 if(<variable|string> GREATER <variable|string>) 如果给定的字符串或变量的值是有效数字并且大于右边的数字,则为真。 if(<variable|string> EQUAL <variable|string>) 如果给定的字符串或变量的值是有效数字并且等于右边的数字,则为真。 if(<variable|string> LESS_EQUAL <variable|string>) 3.7 新版功能:如果给定的字符串或变量的值是有效数字并且小于或等于右边的数字,则为真。 if(<variable|string> GREATER_EQUAL <variable|string>) 3.7 新版功能:如果给定的字符串或变量的值是有效数字并且大于或等于右边的数字,则为真。
if(<variable|string> STRLESS <variable|string>) 如果给定的字符串或变量的值按字典顺序小于右侧的字符串或变量,则为真。 if(<variable|string> STRGREATER <variable|string>) 如果给定的字符串或变量的值在字典序上大于右侧的字符串或变量,则为真。 if(<variable|string> STREQUAL <variable|string>) 如果给定的字符串或变量的值在字典序上等于右侧的字符串或变量,则为真。 if(<variable|string> STRLESS_EQUAL <variable|string>) 3.7 新版功能:如果给定字符串或变量的值按字典顺序小于或等于右侧的字符串或变量,则为真。 if(<variable|string> STRGREATER_EQUAL <variable|string>) 3.7 新版功能:如果给定字符串或变量的值在字典序上大于或等于右侧的字符串或变量,则为真。
版本比较:
if(<variable|string> VERSION_LESS <variable|string>) Component-wise integer version number comparison(版本格式为 major[.minor[.patch[.tweak]]],省略的组件被视为零)。任何非整数版本组件或版本组件的非整数尾随部分都会在该点有效截断字符串。 if(<variable|string> VERSION_GREATER <variable|string>) Component-wise integer version number comparison(版本格式为 major[.minor[.patch[.tweak]]],省略的组件被视为零)。任何非整数版本组件或版本组件的非整数尾随部分都会在该点有效截断字符串。 if(<variable|string> VERSION_EQUAL <variable|string>) Component-wise integer version number comparison(版本格式为 major[.minor[.patch[.tweak]]],省略的组件被视为零)。任何非整数版本组件或版本组件的非整数尾随部分都会在该点有效截断字符串。 if(<variable|string> VERSION_LESS_EQUAL <variable|string>) 3.7 新版功能: Component-wise integer version number comparison (version format is major[.minor[.patch[.tweak]]], 省略的组件被视为零). 任何非整数版本组件或版本组件的非整数尾随部分都会在该点有效截断字符串。 if(<variable|string> VERSION_GREATER_EQUAL <variable|string>) 3.7 新版功能: Component-wise integer version number comparison (version format is major[.minor[.patch[.tweak]]], 省略的组件被视为零). 任何非整数版本组件或版本组件的非整数尾随部分都会在该点有效截断字符串。
循环:foreach,endforeach,break,continue
为列表中的每个值评估一组命令。
foreach(<loop_var> <items>) <commands> endforeach()
其中<items>
是由分号或空格分隔的项目列表。foreach
和匹配之间的所有命令endforeach
都被记录下来而不被调用。进行endforeach
评估后,将为 中的每个项目调用一次记录的命令列表<items>
。在每次迭代开始时,变量loop_var
将被设置为当前项目的值。命令break()
和continue()
提供逃离正常控制流的方法。
根据遗产,endforeach()
命令接受一个可选<loop_var>
参数。如果使用,它必须逐字重复打开命令的参数 foreach
。
foreach(<loop_var> RANGE <stop>)
在此变体中,foreach
迭代数字 0、1、...直到(并包括)非负整数<stop>
。
foreach(<loop_var> RANGE <start> <stop> [<step>])
在此变体中,以 的步长迭代从最多到最多的foreach
数字 。如果不指定,则步长为1。三个参数必须均为非负整数,且不得小于;否则,您将进入可能在未来版本中更改的未记录行为的危险区域。<start>
<stop>
<step>
<step>
<start>
<stop>
<step>
<stop>
<start>
foreach(<loop_var> IN [LISTS [<lists>]] [ITEMS [<items>]])
在此变体中,<lists>
是一个空格或分号分隔的列表值变量列表。该foreach
命令遍历每个给定列表中的每个项目。以下<items>
关键字ITEMS
的处理方式与命令的第一个变体相同foreach
。形式和是等价的。LISTS A
ITEMS ${A}
set(A 0;1) set(B 2 3) set(C "4 5") set(D 6;7 8) set(E "") foreach(X IN LISTS A B C D E) message(STATUS "X=${X}") endforeach()
指令:cmake_minimum_required:
作用:设置cmake的最低版本限制,一般为。极为重要,否则后果自负!!!
cmake_minimum_required(VERSION <min>[...<max>] [FATAL_ERROR])
指令:project:
作用:设置项目名称。必用指令。
project(<PROJECT-NAME> [<language-name>...]) project(<PROJECT-NAME> [VERSION <major>[.<minor>[.<patch>[.<tweak>]]]] [DESCRIPTION <project-description-string>] [HOMEPAGE_URL <url-string>] [LANGUAGES <language-name>...])
- 设置项目的名称,并将其存储在变量中
PROJECT_NAME
. - 当从顶层调用时,
CMakeLists.txt
还将项目名称存储在变量中CMAKE_PROJECT_NAME
. - 还设置了变量:
PROJECT_BINARY_DIR
,<PROJECT-NAME>_BINARY_DIR
指令:cmake_host_system_information:
作用:获取主机相关信息。
cmake_host_system_information(RESULT <variable> QUERY <key> ...)
指令:message:
作用:打印信息。
# vim CMakeLists.txt message("1234567890") message(STATUS "STATUS") message(DEBUG "DEBUG") message(WARNING "WARNING") message(FATAL_ERROR "FATAL_ERROR")
举例说明:
# cmake . 1234567890 -- STATUS CMake Warning at CMakeLists.txt:101 (message): WARNING CMake Error at CMakeLists.txt:102 (message): FATAL_ERROR
- STATUS:打印出“--”开头的一行;
- WARNING:先打印一行“CMake Warning at CMakeLists.txt:101 (message):”,再另起一行打印出后面的内容;
- FATAL_ERROR:先打印一行“CMake Error at CMakeLists.txt:102 (message):”,再另起一行打印出后面的内容;
指令:set:
作用:给普通、缓存、环境变量设置值。
(1)给普通变量赋值:
set(<variable> <value>... [PARENT_SCOPE])
每一个新的目录或者函数都会创建一个新的作用域,普通变量的作用域,如果不使用PARENT_SCOPE
选项,只能从外层往内层传递。
<variable>
在当前函数或目录范围内设置给定。
如果PARENT_SCOPE
给出该选项,变量将被设置在当前范围之上的范围内。每个新目录或function()
命令创建一个新的范围。也可以使用以下命令创建范围 block()
命令。
此命令会将变量的值设置到父目录、调用函数或包含范围(以适用于手头的情况为准)。变量值的先前状态在当前范围内保持不变(例如,如果它之前未定义,它仍然是未定义的,如果它有一个值,它仍然是那个值)。
这block(PROPAGATE)
和return(PROPAGATE)
命令可以用作替代方法set(PARENT_SCOPE)
和 unset(PARENT_SCOPE)
更新父范围的命令。
(2)给缓存变量赋值:
set(<variable> <value>... CACHE <type> <docstring> [FORCE])
由于缓存条目旨在提供用户可设置的值,因此默认情况下这不会覆盖现有的缓存条目。使用该FORCE
选项覆盖现有条目。
必须<type>
指定为以下之一:
BOOL:
布尔ON/OFF
值。cmake-gui(1)
提供一个复选框。
FILEPATH:
磁盘上文件的路径。cmake-gui(1)
提供一个文件对话框。
PATH:
磁盘上目录的路径。cmake-gui(1)
提供一个文件对话框。
STRING:
一行文字。cmake-gui(1)
如果STRINGS
缓存条目属性已设置。
INTERNAL:
一行文字。cmake-gui(1)
不显示内部条目。它们可用于跨运行持久存储变量。使用这种类型意味着FORCE
.
必须为<docstring>
指定一行文本,提供选项的快速摘要以呈现给cmake-gui(1)
用户。
如果在调用之前缓存条目不存在或FORCE
给出了选项,则缓存条目将设置为给定值。
缓存条目可能在调用之前就已存在,但如果它是在cmake(1)
用户通过-D<var>=<value>
选项在未指定类型的情况下使用命令行。在这种情况下,该set
命令将添加类型。另外,如果命令行提供的<type>
is PATH
or FILEPATH
and是相对路径,那么该命令会将路径视为相对于当前工作目录,并将其转换为绝对路径。<value>
set
(3)给环境变量赋值:
set(ENV{<variable>} [<value>])
设置一个Environment Variable
到给定的值,后续调用$ENV{<variable>}
将返回此新值。
- 该命令设置的环境变量只在当前的cmake进程生效,既不会影响调用者的环境变量,也不会影响系统环境变量;
- 若参数
ENV{<variable>}后面为空
或者<value>
是空字符串,则此命令将清除环境变量的任何现有值; 若<value>后面还有参数,则后面的这些参数
被忽略,且会发出警告;
举例说明:
# CMakeLists.txt cmake_minimum_required (VERSION 3.10.2) project (apple) message (">>> value = $ENV{CMAKE_PREFIX_PATH}") set (ENV{CMAKE_PREFIX_PATH} "/apple/ipad") message (">>> value = $ENV{CMAKE_PREFIX_PATH}") set (ENV{CMAKE_PREFIX_PATH}) message (">>> value = $ENV{CMAKE_PREFIX_PATH}") set (ENV{CMAKE_PREFIX_PATH} "/apple/ipad/") message (">>> value = $ENV{CMAKE_PREFIX_PATH}") set (ENV{CMAKE_PREFIX_PATH} "") message (">>> value = $ENV{CMAKE_PREFIX_PATH}")
# 输出 >>> value = >>> value = /apple/ipad >>> value = >>> value = /apple/ipad >>> value =
指令:add_executable:
作用:添加一个可执行目标:
add_executable(<name> [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
[source1] [source2 ...])
- 对应
<name>
在项目中必须是全局唯一的。构建的可执行文件的实际文件名是根据本机平台的约定(例如<name>.exe
或<name>
)构造的。
- 3.1 新版功能:源参数
add_executable
可以使用语法为“生成器表达式”$<...>
。见cmake-generator-expressions(7)
可用表达式手册。
- 3.11 版新功能:如果稍后添加源文件,则可以省略源文件
target_sources()
.
- 默认情况下,可执行文件将在与调用命令的源树目录相对应的构建树目录中创建。请参阅文档
RUNTIME_OUTPUT_DIRECTORY
target 属性来改变这个位置。请参阅文档OUTPUT_NAME
target 属性改变<name>
最终文件名的一部分。 - 如果
WIN32
被赋予财产WIN32_EXECUTABLE
将设置在创建的目标上。有关详细信息,请参阅该目标属性的文档。 - 如果
MACOSX_BUNDLE
给定,将在创建的目标上设置相应的属性。请参阅文档MACOSX_BUNDLE
目标属性的详细信息。 - 如果
EXCLUDE_FROM_ALL
给定,将在创建的目标上设置相应的属性。请参阅文档EXCLUDE_FROM_ALL
目标属性的详细信息。
给可执行目标取别名:
add_executable(<name> ALIAS <target>)
- 创建一个Alias Target,这样可以在后续命令中
<name>
引用。<target>
不会<name>
作为生成目标出现在生成的构建系统中。可能<target>
不是ALIAS
.
- 3.11 新版功能:可以将导入的目标
ALIAS
作为目标GLOBAL;
- 3.18 新版功能:可以
ALIAS
将非GLOBAL
导入目标作为目标。这种别名的范围是创建它的目录和子目录。这ALIAS_GLOBAL
target 属性可用于检查别名是否为全局别名;
ALIAS
targets 可以用作从自定义命令和自定义目标的可执行文件中读取属性的目标。它们也可以通过常规测试是否存在if(TARGET)
子命令。不能<name>
用于修改 的属性<target>
,即不能用作 的操作数set_property()
,set_target_properties()
,target_link_libraries()
等。ALIAS
目标可能无法安装或导出。
指令:add_definitions:
作用:将 -D 定义标志添加到源文件的编译中。
add_definitions(-DFOO -DBAR ...)
将定义添加到当前目录及以下目录中的目标的编译器命令行(无论是在调用此命令之前还是之后添加)。
此命令可用于添加任何标志,但它旨在添加预处理器定义(请参阅add_compile_options()
命令添加其他标志)。
以 -D 或 /D 开头的看起来像预处理器定义的标志会自动添加到COMPILE_DEFINITIONS
当前目录的目录属性。
出于向后兼容性的原因,具有重要值的定义可能会留在标志集中而不是被转换。请参阅文档 directory
, target
, source file
COMPILE_DEFINITIONS
有关将预处理器定义添加到特定范围和配置的详细信息的属性。
指令:add_compile_options:
作用:添加编译参数:
- 在原CMAKE_CXX_FLAGS、CMAKE_C_FLAG基础上新加编译选项:
用法: 单独设置C++或C的编译选项,编译选项放在“”内,同时要将“${CMAKE_C_FLAGS}字段保留
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}-Werror ")
- 针对所有编译器设置编译选项:
add_compile_options(-std=c++11)
比如添加编译参数:-wall -std=c++11
add_compile_options(-wall -std=c++11 -o2)
给指定目标target添加编译定义:target_compile_definitions
target_compile_definitions(<target>
<INTERFACE|PUBLIC|PRIVATE> [items1...]
[<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
指定编译给定<target>
. named<target>
必须是由命令创建的,例如 add_executable()
或者add_library()
并且不能是 ALIAS 目标。
需要INTERFACE
,PUBLIC
和PRIVATE
关键字来指定以下参数的范围。 PRIVATE
和PUBLIC
项目将填充COMPILE_DEFINITIONS
的财产 <target>
。PUBLIC
和INTERFACE
项目将填充 INTERFACE_COMPILE_DEFINITIONS
的财产<target>
。以下参数指定编译定义。
如,以下都是等价的:重复调用相同的<target>会按调用顺序追加项
target_compile_definitions(foo PUBLIC FOO) target_compile_definitions(foo PUBLIC -DFOO) # -D removed target_compile_definitions(foo PUBLIC "" FOO) # "" ignored target_compile_definitions(foo PUBLIC -D FOO) # -D becomes "", then ignored
指令:find_package:
作用:用来查找依赖包。cmake并不是直接去查找包本身,而是通过查找包对应的配置文件来查找包。这个文件说明了包相关的一些信息,比如版本、目录等。在不同模式下,配置文件可能不同,但是只要目标包有对应的.cmake文件且存在于cmake的查找路径中,就可以被find_package直接使用。
背景:
理论上只要符合find_package命令的查找条件,能让该命令识别的包或者库都会被支持。在实际使用时,我们可以把这些包分成三类:
- 官方预定义的包。为了方便我们查找依赖包,cmake为我们包含了许多默认的依赖包,这些包是cmake发行版的一部分,也就是说可以直接在CMakeLists.txt文件中引用,不需要额外安装。它们的位置通常是在cmake安装目录的Module目录下(比如我的系统内是:/usr/share/cmake-3.17/Modules),也可以通过变量CMAKE_MODULE_PATH来指定。
cmake预支持的包可以查看cmake-modules;
- 非官方但支持cmake的包。这一类包虽然不在cmake的预支持列表中,但是自行下载使用cmake编译安装后也能被cmake识别,使用方法与官方预定义包一致。比如glog包。
- 默认不支持cmake的包。最典型的是我们自己编写的库文件,这类文件既不在cmake的官方列表,安装时默认也不会被cmake搜索到,此时就需要我们自行编写相应的配置文件并放到对应的路径中去。
在我们实际开发过程中,经常不可避免会使用到第三方开源库,这些开源库可能是通过dnf install命令自动安装到系统目录中,也可能是由我们自己下载库的源码然后通过编译安装到指令目录下的。
不管哪种方式安装的库文件,如果我们需要自己的项目中使用这些库,首先面临的第一个问题就是如何找到这些库。所谓“找到”这些库,其实是根据我们的需要找到指定版本的库头文件包含路径、链接库路径等,从而能够满足我们开发项目的编译链接需要。
在没有CMake的时代,这种库查找链接的工作都需要借助MakeFile中的各种命令来完成,非常的繁琐,而且不方便移植,到了CMake时代,CMake给我们提供了find_package()命令用来查找依赖包,
理想情况下,一句find_package()命令就能把一整个依赖包的头文件包含路径、库路径、库名字、版本号等情况都获取到,后续只管用就好了。但实际使用过程可能会出现这样那样的问题,因此需要我们对find_package这个强大的命令有个大概的理解。
如果编译软件使用了外部库,事先并不知道它的头文件和链接库的位置。得在编译命令中加上包含它们的查找路径。CMake使用 find_package 命令来解决这个问题。
find_package()命令是用来查找依赖包的,理想情况下,一句find_package()把一整个依赖包的头文件包含路径、库路径、库名字、版本号等情况都获取到。
- CMAKE_PREFIX_PATH:是以分号分隔的列表,供find_package(), find_program(), find_library(), find_file()和find_path()使用,初始为空,由用户设定。
- CMAKE_MODULE_PATH:是以分号分隔的列表,供include()或 find_package()使用。初始为空,由用户设定。这个变量用来定义自己的 cmake 模块所在的路径,这些 cmake 模块是随你的工程发布的,为了让 cmake 在处理CMakeLists.txt 时找到这些模块,你需要通过 SET 指令,比如SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake),这时候你就可以通过 INCLUDE 指令来调用自己的模块了。
两者的选择,优先使用CMAKE_PREFIX_PATH
cmake定义了一系列的路径去查找包的配置文件,同时会定义一下变量:
- <package_name>_FOUND,可判断模块是否被找到。若为假,根据需要可给出提醒或中止编译;若为真,则可利用下面的变量添加头文件和库,INCLUDE_DIRECTORIES
- <package_name>_INCLUDE_DIR
- <package_name>_INCLUDES _LIBRARY
- <package_name>_LIBRARIES
- 以及其他变量等来保存包的查找状态。
MODULE模式的查找路径
在MODULE模式下,cmake通过查找名为Find<PackageName>.cmake的文件来查找包。
- 首先在变量CMAKE_MODULE_PATH对应的路径中去查找
- 如果该变量为空或者在该路径下没有找到,则进入cmake的安装目录下查找(比如我这里是/usr/share/cmake_3.17/Module)。
- 如果以上两个路径下没有找到指定包,则根据命令的MODULE参数设置与否决定是否进入CONFIG模式下继续查找。
默认查找目录:
<package_name>_DIR
CMAKE_PREFIX_PATH
CMAKE_FRAMEWORK_PATH
CMAKE_APPBUNDLE_PATH
PATH
其中,PATH中的路径如果以bin或sbin结尾,则自动回退到上一级目录。
找到根目录后,cmake会检查这些目录下的
<prefix>/(lib/<arch>|lib|share)/cmake/<name>*/ (U)
<prefix>/(lib/<arch>|lib|share)/<name>*/ (U)
<prefix>/(lib/<arch>|lib|share)/<name>*/(cmake|CMake)/ (U)
cmake找到这些目录后,会开始依次找<package>Config.cmake或Find<package>.cmake文件。找到后即可执行该文件并生成相关链接信息。
在CONFIG模式下,查找路径比MODULE多得多,而且查找的目标配置文件以<PackageName>Config.cmake 或者<lower-case-package-name>-config.cmake命名
查找顺序为:
- 在cmake变量或者环境变量_ROOT指定的路径下查找,如果命令中设置了NO_CMAKE_FIND_ROOT_PATH或者CMAKE_FIND_USE_PACKAGE_ROOT_PATH变量设置为false则会跳过此路径;如果定义了
<PackageName>_DIR
cmake变量,那么<PackageName>_ROOT
不起作用
- 在特定的cmake缓存变量指定的位置查找:
CMAKE_PREFIX_PATH
CMAKE_FRAMEWORK_PATH
CMAKE_APPBUNDLE_PATH
(如果设置了NO_CMAKE_PATH参数或者将变量CMAKE_FIND_USE_CMAKE_PATH设置为False,那么会跳过这一步)
- cmake特定的环境变量:
<PackageName>_DIR
CMAKE_PREFIX_PATH
CMAKE_FRAMEWORK_PATH
CMAKE_APPBUNDLE_PATH
可以通过NO_CMAKE_ENVIRONMENT_PATH来跳过。
- HINT字段指定的路径
- 搜索标准的系统环境变量PATH。
其中如果是以/bin或者/sbin结尾的,会自动转化为其父目录。
通过指定NO_SYSTEM_ENVIRONMENT_PATH来跳过。
- 存储在cmake的"User Package Registry"(用户包注册表)中的路径。
通过设定NO_CMAKE_PACKAGE_REGISTRY,或者:设定CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY为true,
来避开。
- 设定为当前系统定义的cmake变量:
CMAKE_SYSTEM_PREFIX_PATH
CMAKE_SYSTEM_FRAMEWORK_PATH
CMAKE_SYSTEM_APPBUNDLE_PATH
通过设定NO_CMAKE_SYSTEM_PATH来跳过。
- 在cmake的"System Package Registry"(系统包注册表)中查找。
通过设定NO_CMAKE_SYSTEM_PACKAGE_REGISTRY跳过。
或者通过设定CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY为true。- 从PATHS字段指定的路径中查找。
find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE]
[REQUIRED] [[COMPONENTS] [components...]]
[OPTIONAL_COMPONENTS components...]
[REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)]
[GLOBAL]
[NO_POLICY_SCOPE]
[BYPASS_PROVIDER])
find_package(<PackageName> [version] [EXACT] [QUIET] [REQUIRED] [[COMPONENTS] [components...]] [OPTIONAL_COMPONENTS components...] [CONFIG|NO_MODULE] [GLOBAL] [NO_POLICY_SCOPE] [BYPASS_PROVIDER] [NAMES name1 [name2 ...]] [CONFIGS config1 [config2 ...]] [HINTS path1 [path2 ... ]] [PATHS path1 [path2 ... ]] [REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)] [PATH_SUFFIXES suffix1 [suffix2 ...]] [NO_DEFAULT_PATH] [NO_PACKAGE_ROOT_PATH] [NO_CMAKE_PATH] [NO_CMAKE_ENVIRONMENT_PATH] [NO_SYSTEM_ENVIRONMENT_PATH] [NO_CMAKE_PACKAGE_REGISTRY] [NO_CMAKE_BUILDS_PATH] # Deprecated; does nothing. [NO_CMAKE_SYSTEM_PATH] [NO_CMAKE_INSTALL_PREFIX] [NO_CMAKE_SYSTEM_PACKAGE_REGISTRY] [CMAKE_FIND_ROOT_PATH_BOTH | ONLY_CMAKE_FIND_ROOT_PATH | NO_CMAKE_FIND_ROOT_PATH])
version:指定版本,如果指定就必须检查找到的包的版本是否与
version
兼容;EXACT
: 表示必须完全匹配的版本而不是兼容版本就可以;
QUIET
:表示如果查找失败,不会在屏幕进行输出(但是如果指定了REQUIRED
字段,则QUIET
无效,仍然会输出查找失败提示语)。MODULE
:前面提到说“如果Module模式查找失败则回退到Config模式进行查找”,但是假如设定了MODULE
选项,那么就只在Module模式查找,如果Module模式下查找失败并不会到Config模式查找。REQUIRED
:表示一定要找到包,找不到的话就立即停掉整个cmake。而如果不指定REQUIRED
则cmake会继续执行。COMPONENTS:
表示查找的包中必须要找到的组件,如果有任何一个找不到就算失败,类似于REQUIRED
,导致cmake停止执行。OPTIONAL_COMPONENTS:表示
找不到列出的组件也不会让cmake停止执行。
无论使用何种模式,<PackageName>_FOUND
都会设置一个变量来指示是否找到包。
搜索模式:
- Module模式是默认工作模式;
- Config模式则更复杂高级些;
find_package()
的第一步,应当判断它是Module模式还是Config模式find_package()
把一整个依赖包的头文件包含路径、库路径、库名字、版本号等情况都获取到,后续只管用就好了。但实际中往往CMake失败就是出在find_package()
的失败上(这里不考虑后续make/nmake/msbuild以及编译器、链接器直接执行时的编译、链接出错,只讨论cmake根据CMakeLists.txt执行时候的情况),例如:Module模式下是要查找到名为Find<PackageName>.cmake
的文件。
先在CMAKE_MODULE_PATH
变量对应的路径中查找。如果路径为空,或者路径中查找失败,则在cmake module directory(cmake安装时的Modules目录,比如/usr/local/share/cmake/Modules
)查找
其中具体查找库并给XXX_INCLUDE_DIRS
和XXX_LIBRARIES
两个变量赋值的操作由XXXConfig.cmake模块完成。
指令: find_library:
主要用于查找单个库文件。如果你只需要使用某个库文件而不需要配置整个第三方软件包,那么可以使用 find_library ()来查找该库文件并设置库路径、链接选项等。
<var>
用于存储该命令执行的结果,也就是找到的库的全路径(包含库名);- <var>可以是普通变量(需要指定NO_CACHE选项),也可以是缓存条目(意味着会存放在CMakeCache.txt中,不删除该文件或者用set重新设置该变量,其存储的值不会再刷新);
- <var>当库能被找到,<var>会被存放正常的库路径;当库未被找到,<var>中存放的值为"<var>-NOTFOUND"。
- 只要<var>中的值不是"<var>-NOTFOUND",那么即使多次调用find_library,<var>也不会再刷新;
name
用于指定待查找的库名称,库名称可以使用全称,例如libmymath.a
(优先会当成全名搜索);也可以不带前缀(例如前缀lib
)和后缀(例如Linux
中的.so
、.a
,Mac
中的.dylib
等),直接使用mymath
;path
用于指定库的查找的路径;
库的搜索路径分为两大类:默认搜索路径和附加搜索路径。
(1)库的搜索路径:以CMAKE开头的一些变量、系统环境变量、HINTS、PATHS:
- CMAKE_LIBRARY_ARCHITECTURE,如果该变量被设置,那么会搜索目录${CMAKE_PREFIX_PATH}/lib/${CMAKE_LIBRARY_ARCHITECTURE};
- CMAKE_PREFIX_PATH,默认值为空,如果前缀有多个,需要以分号分割的列表方式提供。一旦该变量非空,那么会搜索该变量提供的目录,以及${CMAKE_PREFIX_PATH}/lib。例如CMAKE_PREFIX_PATH=A;B,那么find_library会从A、B以及A/lib、B/lib中搜索库是否存在;
- CMAKE_LIBRARY_PATH,默认值为空;
- CMAKE_FRAMEWORK_PATH(指定macOS的框架作为搜索路径);
- 标准的系统环境变量(例如系统环境变量LIB和PATH定义的路径);
- 系统的默认的库安装路径(例如/usr、/usr/lib等);
- 附加搜索路径,即find_library命令中通过HINTS或PATHS指定的路径;
当指定NO_DEFAULT_PATH选项时,默认搜索路径不会生效,只会用到附加搜索路径。修改顶层的CMakeLists.txt,在find_library中指定选项NO_DEFAULT_PATH,可以看到即使指定了CMAKE_XXX_PATH的值,也会被忽略,下面的代码执行cmake .
(建议在执行之前rm CMakeCache.txt删除)会提示错误,而去除NO_DEFAULT_PATH选项后能正常找到库的路径。
// 顶层CMakeLists.txt
set (CMAKE_LIBRARY_PATH "./mylib")
find_library (libvar mymath ./mylib2 NO_DEFAULT_PATH)
// 执行"cmake ."后的提示
CMake Error at CMakeLists.txt:23 (message):
required mymath library but not found!
当未指定NO_DEFAULT_PATH选项时,搜索路径按照优先级从高到低依次是:
通过命令行使用-D指定的CMAKE_XXX_PATH变量,也就是形如cmake . -DCMAKE_XXX_PATH=paths的格式。其中CMAKE_XXX_PATH包含如下几个:
CMAKE_PREFIX_PATH:
查找包命令:
生成库文件(动态库.so、静态库.a等):add_library
指令:configure_file:
作用:生成一个.h头文件。将文件复制到另一个位置并修改其内容,用于自定义编译选项或者自定义宏。通常情况下,输入文件以.h.in为后缀,输出文件以.h为后缀。
configure_file(<input> <output> [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS | FILE_PERMISSIONS <permissions>...] [COPYONLY] [ESCAPE_QUOTES] [@ONLY] [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
configure_file命令会根据options
指定的规则,自动对input
文件中cmakedefine
关键字及其内容进行转换,生成outputfile:
- 将input文件中的
@var@
或者${var}
替换成cmake中指定的值。将input文件中的#cmakedefine var
关键字替换成#define var
或者#undef var
,取决于cmake是否定义了var。 <input>:输入文件的路径,必须是文件,而不是目录。相对路径是根据以下值处理的
CMAKE_CURRENT_SOURCE_DIR
. 输入路径。<output>:
输出文件或目录的路径。相对路径是根据以下值处理的CMAKE_CURRENT_BINARY_DIR
. 如果路径命名为现有目录,则输出文件将放置在该目录中,文件名与输入文件相同。- COPYONLY:仅拷贝 < input> 文件里面的内容到 < output> 文件, 不进行变量的替换
- ESCAPE_QUOTES:用反斜杠转义任何替换的引号(c风格)。
- @ONLY:限制替换, 仅仅替换 @VAR@ 变量, 不替换 ${VAR} 变量
- NEWLINE_STYLE style:指定输入文件的新行格式, 例如:Unix 中使用的是 \n, windows 中使用的 \r\n。注意 : COPYONLY 和 NEWLINE_STYLE 是冲突的,不能同时使用;
# cmakedefine VAR
# cmakedefine01 VAR
VAR
如果已定义,将被替换为:
# define VAR # define VAR 1
考虑一个包含foo.h.in
文件的源代码树:
#cmakedefine FOO_ENABLE #cmakedefine FOO_STRING "@FOO_STRING@"
相邻的CMakeLists.txt
可用于configure_file
配置标头:
option(FOO_ENABLE "Enable Foo" ON) if(FOO_ENABLE) set(FOO_STRING "foo") endif() configure_file(foo.h.in foo.h @ONLY)
这将foo.h
在与此源目录对应的构建目录中创建一个。如果该FOO_ENABLE
选项打开,配置的文件将包含:
#define FOO_ENABLE #define FOO_STRING "foo"
否则它将包含:
/* #undef FOO_ENABLE */ /* #undef FOO_STRING */
然后可以使用include_directories()
命令将输出目录指定为包含目录:
include_directories(${CMAKE_CURRENT_BINARY_DIR})
以便源可能包含标头作为#include <foo.h>
指令:include_directories:
作用:将指定目录添加到编译器的搜索头文件的路径中去,相当于gcc选项中的-I(大写i)参数,也相当于环境变量中增加路径到C_INCLUDE_PATH变量的作用。可结合find_package使用。
相对路径被解释为相对于当前源目录。会为当前CMakeLists.txt的所有目标,以及之后添加的所有子目录的目标添加头文件搜索路径,因此,慎用,因为会影响全局target。
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
举例说明:
include_directories("/data/MATLAB/R2012a/extern/include")
包含目录被添加到INCLUDE_DIRECTORIES
当前CMakeLists
文件的目录属性。它们也被添加到INCLUDE_DIRECTORIES
当前文件中每个目标的目标属性CMakeLists
。目标属性值是生成器使用的值。
默认情况下,指定的目录附加到当前目录列表中。可以通过设置更改此默认行为 CMAKE_INCLUDE_DIRECTORIES_BEFORE
到ON
。通过使用 AFTER
或BEFORE
显式,您可以独立于默认值在附加和前置之间进行选择。
如果SYSTEM
给出该选项,编译器将被告知这些目录在某些平台上是系统包含目录。发出此设置信号可能会达到编译器跳过警告等效果,或者这些固定安装的系统文件在依赖项计算中不被考虑 - 请参阅编译器文档。
的参数include_directories
可以使用语法为“$<...>”的“生成器表达式”。见cmake-generator-expressions(7)
可用表达式手册。见cmake-buildsystem(7)
有关定义构建系统属性的更多信息,请参见手册。笔记
target_include_directories()
命令将包含目录添加到各个目标,并可选择将它们传播/导出到依赖项。在Linux下,C编译器默认搜索路径为:
/usr/include
/usr/local/include
如果我们项目根目录下,有个公共头文件目录include1、include2需要添加到C编译器的默认搜索路径,可以在CMakeLists.txt中添加:
include_directories(include1) # 注意当前CMakeLists.txt和include1相对路径关系, 此时必须是在同一个目录下
include_directories(${PROJECT_SOURCE_DIR}/include2) # 通过源码根目录来定位include2
指令:target_include_directories:
作用:只会为指定目标包含头文件搜索路径。如果想为不同目标设置不同的搜索路径,那么用target_include_directories更合适。
target_include_directories(<target> [SYSTEM] [AFTER|BEFORE]
<INTERFACE|PUBLIC|PRIVATE> [items1...]
[<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
指令:link_directories:
作用:指定要链接的库文件的路径,它相当于gcc命令的-L选项,也相当于环境变量中增加LD_LIBRARY_PATH的路径的作用。该指令有时候不一定需要。
- 因为find_package和find_library指令可以得到库文件的绝对路径;
- 不过你自己写的动态库文件放在自己新建的目录下时,可以用该指令指定该目录的路径以便工程能够找到。
举例说明:
link_directories("/data/MATLAB/R2012a/bin/glnxa64")
指令:add_library:
作用:将指定的源文件生成链接文件,然后添加到工程中去。
add_library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
[<source>...])
- STATIC:静态库,在链接其它目标的时候使用;
- SHARED:动态库,会被动态链接,在运行时会被加载;
- MODULE:是一种不会被链接到其它目标中的插件,但是可能会在运行时使用dlopen-系列的函数;
其中表示库文件的名字,该库文件会根据命令里列出的源文件来创建。而STATIC、SHARED和MODULE的作用是指定生成的库文件的类型。STATIC库是目标文件的归档文件,在链接其它目标的时候使用。SHARED库会被动态链接(动态链接库),在运行时会被加载。MODULE库是一种不会被链接到其它目标中的插件,但是可能会在运行时使用dlopen-系列的函数。默认状态下,库文件将会在于源文件目录树的构建目录树的位置被创建,该命令也会在这里被调用。
而语法中的source1 source2分别表示各个源文件。
添加库的别名:
add_library(<name> ALIAS <target>)
指令:link_libraries:
作用:添加需要链接的库文件的全路径,即绝对路径。在add_executable前面位置。
举例说明:
link_libraries("/data/MATLAB/R2012a/bin/glnxa64/libeng.so") link_libraries("/data/MATLAB/R2012a/bin/glnxa64/libmx.so") 也可以写成: link_libraries("/data/MATLAB/R2012a/bin/glnxa64/libeng.so" "/data/MATLAB/R2012a/bin/glnxa64/libmx.so")
指令:target_link_libraries:
作用:将目标文件与库文件进行链接。设置要链接的库文件的名称。可写库名称,也可以是库文件的全路径,配合link_directories指令。target_link_libraries 可以在add_executable后面位置。默认情况下,库依赖项是传递的
target_link_libraries(<target> ... <item>... ...)
<target>
必须是由命令创建的,例如add_executable()
或者add_library()
,并且不能是 ALIAS 目标;
举例说明:以下等价。
target_link_libraries(my_project hello)
target_link_libraries(my_project libhello.a)
target_link_libraries(my_project libhello.so)
target_link_libraries(my_project -lhello)
指令: find_program:
作用:查找程序(program)
- 其格式如下:将创建一个由<VAR>命名的缓存条目即cache变量,将<VAR>的值存入CMakeCache.txt中;
- 如果指定了NO_CACHE,由<VAR>命名的普通变量来存储此命令的结果,这种情况下,<VAR>的值将不会存入CMakeCache.txt中;
- 如果找到程序,则结果将存储在<VAR>中,除非清除<VAR>,否则不会重复搜索;
- 如果没找到,结果将为<VAR>-NOTFOUND;
find_program (<VAR> name1 [path1 path2 ...])
find_program ( <VAR> name | NAMES name1 [name2 ...] [NAMES_PER_DIR] [HINTS [path | ENV var]... ] [PATHS [path | ENV var]... ] [REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)] [PATH_SUFFIXES suffix1 [suffix2 ...]] [VALIDATOR function] [DOC "cache documentation string"] [NO_CACHE] [REQUIRED] [NO_DEFAULT_PATH] [NO_PACKAGE_ROOT_PATH] [NO_CMAKE_PATH] [NO_CMAKE_ENVIRONMENT_PATH] [NO_SYSTEM_ENVIRONMENT_PATH] [NO_CMAKE_SYSTEM_PATH] [NO_CMAKE_INSTALL_PREFIX] [CMAKE_FIND_ROOT_PATH_BOTH | ONLY_CMAKE_FIND_ROOT_PATH | NO_CMAKE_FIND_ROOT_PATH] )
- HINTS:先搜索HINTS指定的路径,然后再搜索系统路径。
find_program(var NAMES cmake HINTS /usr/local/bin)
- PATHS: 先搜索系统路径,然后再搜索PATHS指定的路径。
find_program(myvar NAMES cmake PATHS /usr/local/bin)
注意HINTS与PATHS区别:HINTS是在搜索系统路径之前先搜索HINTS指定的路径;PATHS是先搜索系统路径,然后再搜索PATHS指定的路径
- NO_DEFAULT_PATH:如果指定了此选项,则不会向搜索中添加其它路径。默认搜索路径将失效,只会搜索PATHS和HINTS指定的路径。
- NO_CACHE:3.21版本中引入。搜索结果将存储在普通变量中而不是缓存条目中。如果变量在调用之前已经设置(作为普通变量或缓存变量),则搜索将不会发生。应谨慎使用此选项,因为它会大大增加重复配置步骤的成本。
- REQUIRED:3.18版本中引入。如果未找到任何内容,则停止处理并触发错误消息,否则下次使用相同的变量调用find_program时将再次尝试搜索。
unset(myvar CACHE)
find_program(myvar NAMES valgrind) # 找不到会继续后续的执行
message("myvar: ${myvar}") # myvar: myvar-NOTFOUND
unset(myvar CACHE)
find_program(myvar NAMES valgrind REQUIRED) # 将触发error,停止后续的执行:CMake Error at test_find_program.cmake:68 (find_program): Could not find var using the following names: valgrind
举例说明:cmake一般在/usr/bin/cmake,但是centos中的cmake版本太低了,因此我卸载了系统的cmake,安装了新版本的cmake,可执行文件默认安装到usr/local/bin中,所以我的cmake可执行文件就在/usr/local/bin/cmake
find_program(myvar NAMES cmake) # myvar: /usr/local/bin/cmake message("myvar= ${myvar}")
cmake报错信息:
- 需要的包有没有的问题:如果没有就需要安装,安装新软件包有两种:yum和源码安装。一般只有在yum无法安装时才会选择源码安装,毕竟源码安装需要操心软件包位置、下载、编译、安装等。
- 如果mysql需要的包有,那就核对版本有没有问题,有些依赖包版本高了不行,低了也不行,总之包的版本必须符合要求:如果版本符合要求,那么就需要升级或降级,有时候也可先卸载现有版本,再安装符合要求的版本。
-
-DWITH_CURL=
xxx,指定curl包的位置,配置成system即可,还是必须填写的项, -
The location of the curl library.
curl_type
can besystem
(use the system curl library) or a path name to the curl library.
################################
################################