一、命令简介
该命令用来操作路径,仅仅是语义概念上的处理,并不会在文件系统上执行任何交互。路径可以不存在,甚至是当前系统不允许的路径。如果想要了解与文件系统交互的命令,参考file()
。
注意:
cmake_path
会将路径以CMake
所运行的构建系统(例如,主机平台)的格式处理,而不是目标系统。在交叉编译过程中,如果路径包含的元素在CMake
运行的系统上无法表示(例如路径是C:\\
,但是系统并不是Windows
),那么结果不可预测。
cmake_path
分为以下几个子命令:分解、查询、修改、生成、转换、哈希。
该命令有如下约定:
-
<path-var>
:变量名,如果作为命令中的输入,该变量必须存在并且是单个路径。 -
<input>
:字符串字面值,可以包含一个路径、路径的一部分、以分号分割的多个路径。 -
<input>...
:0
或多个字符串字面的参数。 -
<out-var>
:存储命令的结果。
路径结构和术语:
一个路径的组成如下(都是可选的,但是可能存在某些限制):
root-name root-directory-separator (item-name directory-separator)\* filename
-
root-name
:支持多个根路径的系统的(例如Windows
)根路径名称,可选。例如C:
或者//myserver
等。 -
root-directory-separator
:目录分隔符,如果存在表明路径是绝对路径,如果确实该分隔符,并且第一个部分不是root-name
,是item-name
,那么它是一个相对路径。 -
item-name
:一个字符组成的序列,不能是目录分隔符,该名称可能标识一个文件、或一个目录,或软连接,或硬链接,有连个特殊的情况: 1)包含单个点.
,表示当前目录 2)包含两个点..
,表示父目录(item-name directory-separator)*
表示0个或多个item-name
,以目录分隔符分割,()*
不是路径的一部分。 -
directory-separator
:目录分隔符,即/
,连续的多个/
会被当成一个/
处理,例如/usr/////lib
与/usr/lib
相同。 -
filename
:文件名。如果路径不是以/
结束,路径中的最后一个item-name
就是文件名,它可以是文件、软硬链接、目录。文件名还可以包含扩展,默认情况下,扩展是从最左边的.
分隔符开始,例如file.dat1.dat2
,那么.dat1.dat2
就是扩展名。filename
除去扩展部分被称为stem
,因此默认情况下file.dat1.dat2
的stem
就是file
。可以使用LAST_ONLY
关键字来指定扩展从filename
最右边的.
开始。例外情况是:1)如果第一个字符就是.
,那么解析为无扩展,例如.profile
;或2)如果是.
或..
同样认为没有扩展。
创建一个路径变量
可以使用set
命令来创建一个路径,推荐用cmake_path(SET)
,因为后者会自动转换路径为要求的格式。cmake_path(APPEND)
是另一个适合通过将多个片段拼接成一个路径的子命令,下面三个命令都是创建同一个路径:
set(path1 "${CMAKE_CURRENT_SOURCE_DIR}/data")
cmake_path(SET path2 "${CMAKE_CURRENT_SOURCE_DIR}/data")
cmake_path(APPEND path3 "${CMAKE_CURRENT_SOURCE_DIR}" "data")
修改和生成子命令可以将结果存入输入路径变量中,也可以使用OUTPUT_VARIABLE
指定输出路径的变量。其他子命令都强制将结果存储在<out-var>
中。
规范化
一些子命令支持规范化一个路径,规范一个路径的算法如下:
-
如果路径为空,命令终止(即空路径规范化后仍是空路径)
-
替换多个连续的
/
分隔符为单个/
分隔符,例如//a/b///c
规范化后为/a/b/c
。 -
移除在分隔符后的单个
.
,例如/a/./b/c/.
规范化后为/a/b/c
。 -
如果
item-name
后面紧跟着是..
,那么删除该item-name
、..
以及跟在他们之后的分隔符/
,例如/a/b/../c
规范化后为/a/c
。 -
如果路径包含根路径,并且根路径后面紧跟的是
..
,那么移除..
和跟在它后面的/
,因为根目录的父路径仍是它自己。例如/../a
规范化后为/a
. -
如果最后一个
item-name
是..
,那么移除..
之后的分隔符/
,例如../
规范化后为..
。 -
经过上述规范化后的路径仍为空,那么规范化后的路径为
.
(./
的规范化路径也是.
).
二、子命令详解
2.1 分解
cmake_path(GET)
子命令从一个路径中获取不同的部分。如果待获取的部分在路径中不存在,那么该子命令会将空字符串结果存于<out-var>
中,例如只有在Windows
中才存在root-name
的概念,因此,如果CMake
运行的系统非Windows
,获取ROOT_NAME
会得到一个空字符串。如果HAS_RELATIVE_PART
子命令结果为false
,那么获取PARENT_NAME
的结果就是<path-var>
,由于根路径的父路径是它自己,当HAS_RELATIVE_PART
子命令结果为true
时,表明<path-var>
至少包含一个元素。
子命令形式为:
cmake_path(GET <path-var> ROOT_NAME <out-var>)
cmake_path(GET <path-var> ROOT_DIRECTORY <out-var>)
cmake_path(GET <path-var> ROOT_PATH <out-var>)
cmake_path(GET <path-var> FILENAME <out-var>)
cmake_path(GET <path-var> EXTENSION [LAST_ONLY] <out-var>)
cmake_path(GET <path-var> STEM [LAST_ONLY] <out-var>)
cmake_path(GET <path-var> RELATIVE_PART <out-var>)
cmake_path(GET <path-var> PARENT_PATH <out-var>)
-
cmake_path(GET <path-var> [ROOT_NAME|ROOT_DIRECTORY|ROOT_PATH] <out-var>)
:获取根名称、目录、路径,我的系统非Windows
,因此ROOT_NAME
为空。
set(path "/usr/bin")
cmake_path(GET path ROOT_NAME rootName)
cmake_path(GET path ROOT_DIRECTORY rootDirectory)
cmake_path(GET path ROOT_PATH rootPath)
message("root name is: ${rootName}")
message("root directory is: ${rootDirectory}")
message("root path is: ${rootPath}")
运行结果: root name is: root directory is: / root path is: /
-
cmake_path(GET <path-var> FILENAME <out-var>)
:获取文件名。
set(path "/usr/bin")
cmake_path(GET path FILENAME filename)
message("filename is: ${filename}")
set(path "/a/b/")
cmake_path(GET path FILENAME filename)
message("filename is: ${filename}")
运行结果: filename is: bin filename is:
-
cmake_path(GET <path-var> [EXTENSION|STEM] <out-var>)
:获取扩展或stem
信息。默认情况下,扩展是从最左边的.
分隔符开始,例如file.dat1.dat2
,那么.dat1.dat2
就是扩展名。filename
除去扩展部分被称为stem
,因此默认情况下file.dat1.dat2
的stem
就是file
。可以使用LAST_ONLY
关键字来指定扩展从filename
最右边的.
开始。
set(path "name.ext1.ext2")
# 默认扩展是取最左侧的.到尾部的部分
cmake_path(GET path EXTENSION fullExt)
cmake_path(GET path STEM fullStem)
message("full extension: ${fullExt}")
message("full stem: ${fullStem}")
# 指定LAST_ONLY后,扩展取的是最右侧的.到尾部的部分
cmake_path(GET path EXTENSION LAST_ONLY lastExt)
cmake_path(GET path STEM LAST_ONLY lastStem)
message("last extension: ${lastExt}")
message("last stem: ${lastStem}")
set(dotPath "/a/.")
set(dotDotPath "/a/..")
set(someMorePath "/a/.some.more")
# filename是.的特例:扩展为空
cmake_path(GET dotPath EXTENSION dotExt)
cmake_path(GET dotPath STEM dotStem)
# filename是..的特例:扩展为空
cmake_path(GET dotDotPath EXTENSION dotDotExt)
cmake_path(GET dotDotPath STEM dotDotStem)
cmake_path(GET someMorePath EXTENSION someMoreExt)
cmake_path(GET someMorePath STEM someMoreStem)
message("Dot extension is ${dotExt}")
message("Dot stem is ${dotStem}")
message("Dot-dot extension is ${dotDotExt}")
message("Dot-dot stem is ${dotDotStem}")
message(".some.more extension is ${someMoreExt}")
message(".some.more stem is ${someMoreStem}")
运行结果 full extension: .ext1.ext2 full stem: name last extension: .ext2 last stem: name.ext1 Dot extension is Dot stem is . Dot-dot extension is Dot-dot stem is . .some.more extension is .more .some.more stem is .some
-
cmake_path(GET <path-var> RELATIVE_PART <out-var>)
:获取相对路径信息。
set(path "/usr/local/bin")
cmake_path(GET path RELATIVE_PART relativePath)
message("relative path: ${relativePath}")
set(path "usr/local/bin") # 如果本身就是相对路径,那么RELATIVE_PART子命令获取到的就是它本身
cmake_path(GET path RELATIVE_PART relativePath)
message("relative path: ${relativePath}")
set(path "/")
cmake_path(GET path RELATIVE_PART relativePath)
message("relative path: \"${relativePath}\"")
运行于
macOS
下的结果 relative path: usr/local/bin relative path: usr/local/bin relative path: ""
-
cmake_path(GET <path-var> PARENT_PATH <out-var>)
:获取父目录。
set(path "/usr/local/bin")
cmake_path(GET path PARENT_PATH parentPath)
message("parent path: ${parentPath}")
set(path "usr/local/bin")
cmake_path(GET path PARENT_PATH parentPath)
message("parent path: ${parentPath}")
set(path "usr/local/bin/") # 如果filename为空,则父目录就是自身
cmake_path(GET path PARENT_PATH parentPath)
message("parent path: ${parentPath}")
set(path "/")
cmake_path(GET path PARENT_PATH parentPath)
message("parent path: ${parentPath}")
运行结果 parent path: /usr/local parent path: usr/local parent path: usr/local/bin parent path: /
2.2 查询
查询分为三大类,形式分别为HAS_XXX
、IS_XXX
、COMPARE
。
1、HAS_XXX
查询子命令
每一个cmake_path(GET)
子命令都对应一个HAS_XXX
子命令,以便判定GET
子命令获取的路径信息是否存在。HAS_XXX
的子命令格式如下:
cmake_path(HAS_ROOT_NAME <path-var> <out-var>)
cmake_path(HAS_ROOT_DIRECTORY <path-var> <out-var>)
cmake_path(HAS_ROOT_PATH <path-var> <out-var>)
cmake_path(HAS_FILENAME <path-var> <out-var>)
cmake_path(HAS_EXTENSION <path-var> <out-var>)
cmake_path(HAS_STEM <path-var> <out-var>)
cmake_path(HAS_RELATIVE_PART <path-var> <out-var>)
cmake_path(HAS_PARENT_PATH <path-var> <out-var>)
如果查询的路径信息存在,则<out-var>
返回true
,两个特例为:
-
对于
HAS_ROOT_PATH
子命令,只有当root-name
或root-directory
其中一个为非空时返回true
。 -
对于
HAS_PARENT_PATH
子命令,根目录的父目录是根目录自身,因此除非路径仅包含filename
,否则该子命令返回true
。
set(path "/usr/local/bin/myfile.ext1.ext2")
cmake_path(HAS_ROOT_NAME path hrn)
cmake_path(HAS_ROOT_DIRECTORY path hrd)
cmake_path(HAS_ROOT_PATH path hrp)
cmake_path(HAS_FILENAME path hfn)
cmake_path(HAS_EXTENSION path hext)
cmake_path(HAS_STEM path hstem)
cmake_path(HAS_RELATIVE_PART path hrelative)
cmake_path(HAS_PARENT_PATH path hpp)
message("${path} has root name? --- ${hrn}")
message("${path} has root directory? --- ${hrd}")
message("${path} has root path? --- ${hrp}")
message("${path} has filename? --- ${hfn}")
message("${path} has extension? --- ${hext}")
message("${path} has stem? --- ${hstem}")
message("${path} has relative part? --- ${hrelative}")
message("${path} has parent path? --- ${hpp}")
运行结果 /usr/local/bin/myfile.ext1.ext2 has root name? --- OFF /usr/local/bin/myfile.ext1.ext2 has root directory? --- ON /usr/local/bin/myfile.ext1.ext2 has root path? --- ON /usr/local/bin/myfile.ext1.ext2 has filename? --- ON /usr/local/bin/myfile.ext1.ext2 has extension? --- ON /usr/local/bin/myfile.ext1.ext2 has stem? --- ON /usr/local/bin/myfile.ext1.ext2 has relative part? --- ON /usr/local/bin/myfile.ext1.ext2 has parent path? --- ON
2、IS_XXX
查询子命令
IS_XXX
查询子命令的格式如下:
cmake_path(IS_ABSOLUTE <path-var> <out-var>)
cmake_path(IS_RELATIVE <path-var> <out-var>)
cmake_path(IS_PREFIX <path-var> <input> [NORMALIZE] <out-var>)
-
cmake_path(IS_ABSOLUTE <path-var> <out-var>)
:如果是绝对路径,<out-var>
结果为true
。绝对路径唯一标识一个文件的位置。在Windows
下,绝对路径必须包含root-name
和目录分隔符(例如C:/
)。其他平台下,只需要目录分隔符即可(例如Linux
下的/
)。
set(path "/usr/local/bin")
cmake_path(IS_ABSOLUTE path result)
message("${path} is absolute? --- ${result}")
set(path "usr/local/bin")
cmake_path(IS_ABSOLUTE path result)
message("${path} is absolute? --- ${result}")
运行结果: /usr/local/bin is absolute? --- ON usr/local/bin is absolute? --- OFF
-
cmake_path(IS_RELATIVE <path-var> <out-var>)
:判断路径是否是相对路径。
set(path "/usr/local/bin")
cmake_path(IS_RELATIVE path result)
message("${path} is relative? --- ${result}")
set(path "usr/local/bin")
cmake_path(IS_RELATIVE path result)
message("${path} is relative? --- ${result}")
运行结果: /usr/local/bin is relative? --- OFF usr/local/bin is relative? --- ON
-
cmake_path(IS_PREFIX <path-var> <input> [NORMALIZE] <out-var>)
:判断路径<path-var>
是否是<input>
的前缀,如果指定了NORMALIZE
选项,<path-var>
和<input>
在比较前会进行路径规范化。
set(path "/usr/local/bin")
cmake_path(IS_PREFIX path "/usr/local/bin/myfile" result)
message("if ${path} is prefix of /usr/local/bin/myfile? --- ${result}")
cmake_path(IS_PREFIX path "/usr/local" result)
message("if ${path} is prefix of /usr/local? --- ${result}")
set(path "/usr/../tmp/dir")
cmake_path(IS_PREFIX path "/tmp/dir/myfile" NORMALIZE result)
message("if ${path} is prefix of /tmp/dir/myfil? --- ${result}")
运行结果: if /usr/local/bin is prefix of /usr/local/bin/myfile? --- ON if /usr/local/bin is prefix of /usr/local? --- OFF if /usr/../tmp/dir is prefix of /tmp/dir/myfil? --- ON
3、COMPARE
查询子命令
-
cmake_path(COMPARE <input1> EQUAL <input2> <out-var>) cmake_path(COMPARE <input1> NOT_EQUAL <input2> <out-var>)
:比较两个路径是否相同或者不同,路径被当做字符串字面值进行比较,注意该子命令的两个输入路径都不会进行路径规范化。
cmake_path(COMPARE "/usr/local/bin" EQUAL "/usr/local/bin" cmpResult)
message("CMP result: ${cmpResult}")
cmake_path(COMPARE "/usr/local/bin/" NOT_EQUAL "/usr/local/bin" cmpResult)
message("CMP result: ${cmpResult}")
运行结果: CMP result: ON CMP result: ON
2.3 修改
修改包含设置、追加、移除、替换等子命令操作,具体格式如下:
cmake_path(SET <path-var> [NORMALIZE] <input>)
cmake_path(APPEND <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>])
cmake_path(APPEND_STRING <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>])
cmake_path(REMOVE_FILENAME <path-var> [OUTPUT_VARIABLE <out-var>])
cmake_path(REPLACE_FILENAME <path-var> <input> [OUTPUT_VARIABLE <out-var>])
cmake_path(REMOVE_EXTENSION <path-var> [LAST_ONLY] [OUTPUT_VARIABLE <out-var>])
cmake_path(REPLACE_EXTENSION <path-var> [LAST_ONLY] <input> [OUTPUT_VARIABLE <out-var>])
1、设置
子命令
-
cmake_path(SET <path-var> [NORMALIZE] <input>)
:将<input>
赋值给<input-var>
,注意<input>
应该是一个变量(用$
取变量符号),否则会当成一个字符串。如果指定了NORMALIZE
关键字,那么在执行赋值前会先对路径进行规范化。
set(path "/usr/local/bin")
cmake_path(SET result ${path}) # 如果此处不是用${path}而是path,那么result的结果是"path"
message("${path} set to ${result}")
set(path "/usr/../local////bin/.")
cmake_path(SET result NORMALIZE ${path})
message("${path} normalized set to ${result}")
运行结果: /usr/local/bin set to /usr/local/bin /usr/../local////bin/. normalized set to /local/bin/
2、追加
子命令
-
cmake_path(APPEND_STRING <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>])
:顺序遍历多个<input>
路径,用/
拼接后,结果存入<path-var>
。在遍历过程中,根据<input>
的具体内容,通过前面<input>
计算得到的<input-var>
可能会被丢弃。规则如下:
-
如果当前的
<input>
是绝对路径,则使用<input>
替换<path-var>
,拼接过程结束。 -
<input>
存在ROOT_NAME
并且与<path-var>
的ROOT_NAME
不相同,那么使用<input>
替换<path-var>
,拼接过程结束。 -
如果
<input>
的ROOT_DIRECTORY
存在,那么移除<path-var>
任意的ROOT_DIRECTORY
和整个相对路径。 -
如果
<input>
不存在ROOT_DIRECTORY
且<path-var>
存在filename
,或<path-var>
是非绝对路径且不存在ROOT_DIRECTORY
,那么将/
拼接到<path-var>
。 -
将
<input>
拼接到<path-var>
,忽略ROOT_NAME
。
cmake_path(APPEND result "/usr/local/bin" "test/myfile" "myfile2")
message("path result is : ${result}")
cmake_path(APPEND result1 "usr/local" "/tmp/myfile")
message("path result1 is : ${result1}")
cmake_path(APPEND result2 "usr/local/" "mydir1" "mydir2")
message("path result2 is : ${result2}")
运行结果: path result is : /usr/local/bin/test/myfile/myfile2 path result1 is : /tmp/myfile path result2 is : usr/local/mydir1/mydir2
-
cmake_path(APPEND_STRING <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>])
:将<input>
拼接到path-var
,不会额外添加任何目录分隔符。注意:该命令下<path-var>
需要已经定义。
set(rs "")
cmake_path(APPEND_STRING rs "/usr/" "local" "bin")
message("APPEND_STRING: ${rs}")
运行结果: APPEND_STRING: /usr/localbin
-
cmake_path(REMOVE_FILENAME <path-var> [OUTPUT_VARIABLE <out-var>])
:将路径中的filename
移除(也就是通过GET ... FILENAME
获取到的内容),移除后尾部的目录分隔符/
会被保留。如果没有定义OUTPUT_VARIABLE
,那么执行该子命令后,对<path-var>
执行HAS_FILENAME
会返回false
。
set(path "/usr/local/bin/myfile")
cmake_path(REMOVE_FILENAME path)
message("For ${path} remove filename is: ${path}")
cmake_path(HAS_FILENAME path hfn)
message("For ${path} has filename? --- ${hfn}")
set(path "/usr/local/bin/myfile")
cmake_path(REMOVE_FILENAME path OUTPUT_VARIABLE output) # 有OUTPUT_VARIABLE,原始路径path不会被修改
message("For ${path} remove filename is: ${output}, orignal path is ${path}")
cmake_path(HAS_FILENAME path hfn)
message("For ${path} has filename? --- ${hfn}")
运行结果: For /usr/local/bin/ remove filename is: /usr/local/bin/ For /usr/local/bin/ has filename? --- OFF For /usr/local/bin/myfile remove filename is: /usr/local/bin/, orignal path is /usr/local/bin/myfile For /usr/local/bin/myfile has filename? --- ON
-
cmake_path(REPLACE_FILENAME <path-var> <input> [OUTPUT_VARIABLE <out-var>])
:用<input>
替代路径<path-var>
中的filename
,如果<path-var>
中没有filename
,那么<path-var>
不会有任何变化(如果定义了OUTPUT_VARIABLE
,也不会修改<path-var>
),该命令等价于以下逻辑:
-
使用
cmake_path(HAS_FILENAME path has_filename)
判断是否存在filename
; -
第一步的
has_filename
如果为真,那么依次执行cmake_path(REMOVE_FILENAME path)
和cmake_path(APPEND path input)
。
set(path "/usr/local/bin/myfile")
cmake_path(REPLACE_FILENAME path "replacefile" OUTPUT_VARIABLE output)
message("After replace ${path}, result is: ${output}")
# 等效的命令如下
set(path "/usr/local/bin/myfile")
cmake_path(HAS_FILENAME path has_filename)
if(has_filename)
cmake_path(REMOVE_FILENAME path OUTPUT_VARIABLE output)
cmake_path(APPEND output "replacefile")
message("After replace ${path} use combine commands, result is: ${output}")
endif()
运行结果: After replace /usr/local/bin/myfile, result is: /usr/local/bin/replacefile After replace /usr/local/bin/myfile use combine commands, result is: /usr/local/bin/replacefile
-
cmake_path(REMOVE_EXTENSION <path-var> [LAST_ONLY] [OUTPUT_VARIABLE <out-var>])
:移除扩展名,可以使用LAST_ONLY
指定从filename
最右边的.
开始移除。
set(path "/usr/local/bin/myfile.ext1.ext2")
cmake_path(REMOVE_EXTENSION path OUTPUT_VARIABLE output)
message("remove extersion of ${path} is ${output}")
cmake_path(REMOVE_EXTENSION path LAST_ONLY OUTPUT_VARIABLE output)
message("remove LAST_ONLY extersion of ${path} is ${output}")
运行结果: remove extersion of /usr/local/bin/myfile.ext1.ext2 is /usr/local/bin/myfile remove LAST_ONLY extersion of /usr/local/bin/myfile.ext1.ext2 is /usr/local/bin/myfile.ext1
-
cmake_path(REPLACE_EXTENSION <path-var> [LAST_ONLY] <input> [OUTPUT_VARIABLE <out-var>])
:替换扩展名,可以使用LAST_ONLY
指定从filename
最右边的.
开始替换。
set(path "/usr/local/bin/myfile.ext1.ext2")
cmake_path(REPLACE_EXTENSION path "dat1.dat2" OUTPUT_VARIABLE output)
message("use dat1.dat2 replace extersion of ${path} is ${output}")
cmake_path(REPLACE_EXTENSION path LAST_ONLY "dat1.dat2" OUTPUT_VARIABLE output)
message("user dat1.dat2 replace LAST_ONLY extersion of ${path} is ${output}")
运行结果: use dat1.dat2 replace extersion of /usr/local/bin/myfile.ext1.ext2 is /usr/local/bin/myfile.dat1.dat2 user dat1.dat2 replace LAST_ONLY extersion of /usr/local/bin/myfile.ext1.ext2 is /usr/local/bin/myfile.ext1.dat1.dat2
2.4 生成路径
分为规范化路径、产生相对路径、产生绝对路径三种。
-
cmake_path(NORMAL_PATH <path-var> [OUTPUT_VARIABLE <out-var>])
:规范化一个路径,具体规则参考本文前面索引处。具体例子不再赘述,参考其他例子中的规范化说明。 -
cmake_path(RELATIVE_PATH <path-var> [BASE_DIRECTORY <input>] [OUTPUT_VARIABLE <out-var>])
:将路径<path-var>
修改为相对于基路径(由BASE_DIRECTORY
指定)的路径,若未指定BASE_DIRECTORY
,那么默认的基路径从CMAKE_CURRENT_SOURCE_DIR
变量中获取。简而言之,可以理解为从基路径切换到<path-var>
路径需要经过的路径。
set(path "/usr/local/bin/myfile")
cmake_path(RELATIVE_PATH path BASE_DIRECTORY "/usr/local" OUTPUT_VARIABLE output)
message("the relative path ${path} for base /usr/local is ${output}")
cmake_path(RELATIVE_PATH path OUTPUT_VARIABLE output) # 未指定基路径,默认基路径为CMAKE_CURRENT_SOURCE_DIR变量存放的路径
message("the relative path ${path} for base ${CMAKE_CURRENT_SOURCE_DIR} is ${output}")
运行结果 the relative path /usr/local/bin/myfile for base /usr/local is bin/myfile the relative path /usr/local/bin/myfile for base /Users/XX1/XX2/XX3/XX4/XX5 is ../../../../../../usr/local/bin/myfile
-
cmake_path(ABSOLUTE_PATH <path-var> [BASE_DIRECTORY <input>] [NORMALIZE] [OUTPUT_VARIABLE <out-var>])
:如果<path-var>
是绝路径,那么结果就是<path-var>
;如果<path-var>
是相对路径,效果相当于将<path-var>
拼接在基路径之后,当然,如果未指定基路径,则从CMAKE_CURRENT_SOURCE_DIR
获取基路径。
set(path "/usr/local/bin/myfile") # 原路径是绝对路径,结果不变
cmake_path(ABSOLUTE_PATH path BASE_DIRECTORY "/usr/local" OUTPUT_VARIABLE output)
message("the absolute path ${path} for base /usr/local is ${output}")
cmake_path(ABSOLUTE_PATH path OUTPUT_VARIABLE output)
message("the absolute path ${path} for base ${CMAKE_CURRENT_SOURCE_DIR} is ${output}")
set(path "mydir/myfile") # 原路径是相对路径,拼接
cmake_path(ABSOLUTE_PATH path BASE_DIRECTORY "/usr/local" OUTPUT_VARIABLE output)
message("the absolute path ${path} for base /usr/local is ${output}")
cmake_path(ABSOLUTE_PATH path OUTPUT_VARIABLE output)
message("the absolute path ${path} for base ${CMAKE_CURRENT_SOURCE_DIR} is ${output}")
运行结果: the absolute path /usr/local/bin/myfile for base /usr/local is /usr/local/bin/myfile the absolute path /usr/local/bin/myfile for base /Users/XX1/XX2/XX3/XX4/XX5 is /usr/local/bin/myfile
the absolute path mydir/myfile for base /usr/local is /usr/local/mydir/myfile the absolute path mydir/myfile for base /Users/XX1/XX2/XX3/XX4/XX5 is /Users/XX1/XX2/XX3/XX4/XX5/mydir/myfile
2,5 原生转换
指的是转换成CMake
所在的构建平台路径规范,因此这里的原生
指交叉编译的构建平台,而不是目标平台。例如程序在windows
下构建,在嵌入式
设备上跑,那么原生
指的是Windows
平台。
-
cmake_path(NATIVE_PATH <path-var> [NORMALIZE] <out-var>)
:将路径转换成平台相关的斜杆(Windows
下的右斜杠\
,其他平台的左斜杠/
),还可以通过NORMALIZE
在转换前将路径规范化。
set(path "/usr/local/bin/myfile")
cmake_path(NATIVE_PATH path output)
message("the native path of ${path} is: ${output}")
运行结果(macOS): the native path of /usr/local/bin/myfile is: /usr/local/bin/myfile
运行结果(Windows): the native path of /usr/local/bin/myfile is: \usr\local\bin\myfile
-
cmake_path(CONVERT <input> TO_CMAKE_PATH_LIST <out-var> [NORMALIZE])
:将路径转换为cmake
风格的路径,cmake
风格的路径指的是以左斜杆/
作为连接符,多个路径之间以;
分隔。特别需要注意的是:CONVERT
子命令的输入路径被当成字符串文本值处理,而不是当成一个变量进行解析,因此使用当<input>
是多个路径时,不能直接使用${input}
变量,而需要使用"${input}
"确保得到的是一个字符串文本值。
set(path "/usr/local/bin/myfile" "/tmp/mydir") # cmake的set命令以`;`分隔多个值,${path}=/usr/local/bin/myfile;/tmp/mydir
cmake_path(CONVERT "${path}" TO_CMAKE_PATH_LIST output) # 注意要使用"${path}"而不是${path}变量
message("1: the native path ${path} to cmake-style: ${output}")
set(path "/usr/local/bin/myfile:/tmp/mydir") # 模拟以:分隔多个值,${path}="/usr/local/bin/myfile:/tmp/mydir"
cmake_path(CONVERT "${path}" TO_CMAKE_PATH_LIST output) # ${path}变量已经是一个字符串字面量,因此此处也可以用${path}
message("2: the native path ${path} to cmake-style: ${output}")
运行结果(macOS)(注意;和:的区别): 1: the native path /usr/local/bin/myfile;/tmp/mydir to cmake-style: /usr/local/bin/myfile;/tmp/mydir 2: the native path /usr/local/bin/myfile:/tmp/mydir to cmake-style: /usr/local/bin/myfile;/tmp/mydir
运行结果(Windows)(注意;和:的区别): 1: the native path /usr/local/bin/myfile;/tmp/mydir to cmake-style: /usr/local/bin/myfile:/tmp/mydir 2: the native path /usr/local/bin/myfile:/tmp/mydir to cmake-style: /usr/local/bin/myfile:/tmp/mydir
-
cmake_path(CONVERT <input> TO_NATIVE_PATH_LIST <out-var> [NORMALIZE])
:将cmake
风格的路径转换为原生路径,例如Windows
下的右斜杠\
,其他平台的左斜杠/
,当多个路径时候,Windows
下的以;
分隔,其他平台以:
分隔。特别需要注意的是:CONVERT
子命令的输入路径被当成字符串文本值处理,而不是当成一个变量进行解析,因此使用当<input>
是多个路径时,不能直接使用${input}
变量,而需要使用"${input}
"确保得到的是一个字符串文本值。
set(path "/usr/local/bin/myfile" "/tmp/mydir") # cmake的set命令以`;`分隔多个值,${path}=/usr/local/bin/myfile;/tmp/mydir
cmake_path(CONVERT "${path}" TO_NATIVE_PATH_LIST output) # 注意要使用"${path}"而不是${path}变量
message("the cmake-style path ${path} to native path: ${output}")
运行结果(macOS)(注意;和:的区别): the cmake-style path /usr/local/bin/myfile;/tmp/mydir to native path: /usr/local/bin/myfile:/tmp/mydir
运行结果(Windows)(注意;和:的区别): the cmake-style path /usr/local/bin/myfile;/tmp/mydir to native path: \usr\local\bin\myfile;\tmp\mydir
2.6 哈希
-
cmake_path(HASH <path-var> <out-var>)
:计算路径的哈希值,哈希结果存放在<out-var>
中。可用于比较两个路径是否相等(参考子命令COMPARE .. EQUAL
,两个路径相等时,其哈希值也相等)。在计算哈希值之前,路径会被规范化。
set(path "/usr/local/bin/myfile")
cmake_path(HASH path hash_path)
cmake_path(APPEND path2 "/usr/local" "bin/myfile")
cmake_path(HASH path2 hash_path2)
message("path1:${path}, path1 hash:${hash_path}")
message("path2:${path2}, path2 hash:${hash_path2}")
运行结果: path1:/usr/local/bin/myfile, path1 hash:5a17be211871fbe path2:/usr/local/bin/myfile, path2 hash:5a17be211871fbe
网友评论