file是文件操作命令,用于文件或路徑的操作,結(jié)果也會(huì)在文件系統(tǒng)上進(jìn)行存儲(chǔ)。因此,與cmake_path命令只是語(yǔ)義概念上對(duì)路徑的處理不同,file會(huì)與文件系統(tǒng)進(jìn)行實(shí)際的交互。
一、命令格式
file命令包含讀、寫、文件系統(tǒng)、路徑轉(zhuǎn)換、傳輸、鎖、歸檔七個(gè)子命令,格式如下:
子命令:讀
file(READ <filename> <out-var> [...])
file(STRINGS <filename> <out-var> [...])
file(<HASH> <filename> <out-var>)
file(TIMESTAMP <filename> <out-var> [...])
file(GET_RUNTIME_DEPENDENCIES [...])
子命令:寫
file({WRITE | APPEND} <filename> <content>...)
file({TOUCH | TOUCH_NOCREATE} [<file>...])
file(GENERATE OUTPUT <output-file> [...])
file(CONFIGURE OUTPUT <output-file> CONTENT <content> [...])
子命令:文件系統(tǒng)
file({GLOB | GLOB_RECURSE} <out-var> [...] [<globbing-expr>...])
file(MAKE_DIRECTORY [<dir>...])
file({REMOVE | REMOVE_RECURSE } [<files>...])
file(RENAME <oldname> <newname> [...])
file(COPY_FILE <oldname> <newname> [...])
file({COPY | INSTALL} <file>... DESTINATION <dir> [...])
file(SIZE <filename> <out-var>)
file(READ_SYMLINK <linkname> <out-var>)
file(CREATE_LINK <original> <linkname> [...])
file(CHMOD <files>... <directories>... PERMISSIONS <permissions>... [...])
file(CHMOD_RECURSE <files>... <directories>... PERMISSIONS <permissions>... [...])
子命令:路徑轉(zhuǎn)換
file(REAL_PATH <path> <out-var> [BASE_DIRECTORY <dir>] [EXPAND_TILDE])
file(RELATIVE_PATH <out-var> <directory> <file>)
file({TO_CMAKE_PATH | TO_NATIVE_PATH} <path> <out-var>)
子命令:傳輸
file(DOWNLOAD <url> [<file>] [...])
file(UPLOAD <file> <url> [...])
子命令:鎖
file(LOCK <path> [...])
子命令:歸檔
file(ARCHIVE_CREATE OUTPUT <archive> PATHS <paths>... [...])
file(ARCHIVE_EXTRACT INPUT <archive> [...])
二、命令使用
在開始舉例說(shuō)明前,命令操作的文件/目錄樹說(shuō)明如下:
├── CMakeLists.txt
├── copy # 該目錄用于演示COPY子命令
│ └── myfile_read # COPY子命令拷貝的文件結(jié)果
├── myfile_download # 用于演示DOWNLOAD下載子命令
├── myfile_read # 用于演示READ子命令
├── myfile_write # 用于演示W(wǎng)RITE子命令
└── result.tar # 用于演示歸檔ARCHIVE_CREATE子命令
讀文件內(nèi)容
file(READ myfile_read out_var)
message("Content of myfile_read is: ${out_var}")
運(yùn)行結(jié)果:
Content of myfile_read is: This is a file for test
寫文件:如果文件不存在,會(huì)創(chuàng)建文件。
set(content "Write hello to file.")
file(WRITE myfile_write ${content}) # 文件不存在會(huì)創(chuàng)建,直接覆蓋文件寫
file(READ myfile_write out_var)
message("Content of myfile_write: ${out_var}")
file(APPEND myfile_write "\nAnother line.") # 文件不存在會(huì)創(chuàng)建,在文件末尾追加寫
file(READ myfile_write out_var)
message("Content of myfile_write: ${out_var}")
運(yùn)行結(jié)果:
Content of myfile_write: Write hello to file.
Content of myfile_write: Write hello to file.
Another line.
文件系統(tǒng)操作
file(COPY myfile_read DESTINATION ./copy) # 將文件拷貝到./copy目錄下
運(yùn)行
cmake .后,myfile_read會(huì)被復(fù)制一份到./copy目錄下。
路徑轉(zhuǎn)換
file(REAL_PATH "./copy" out_var BASE_DIRECTORY "/bin") # ./copy目錄基于base目錄/bin的路徑
message("./copy relative base /bin result: ${out_var}")
運(yùn)行結(jié)果:
./copy relative base /bin result: /bin/copy
文件傳輸操作
file(DOWNLOAD "https://sh.rustup.rs" myfile_download) # 下載文件
運(yùn)行
cmake .命令后,會(huì)將文件下載到本地,并命名為myfile_download
歸檔
file(ARCHIVE_CREATE OUTPUT "result.tar" PATHS myfile_read myfile_write myfile_download FORMAT gnutar) # 將myfile_read myfile_write myfile_download打包成tar文件格式
運(yùn)行
cmake .命令后,會(huì)生成一個(gè)result.tar文件,使用tar tvf result.tar命令查看文件內(nèi)容:-rw-r--r-- 0 XXX YYY 24 5 10 07:42 myfile_read
-rw-r--r-- 0 XXX YYY 34 5 10 08:23 myfile_write
-rw-r--r-- 0 XXX YYY 21102 5 10 08:23 myfile_download
三、子命令詳解
3.1 子命令:讀
-
file(READ <filename> <variable> [OFFSET <offset>] [LIMIT <max-in>] [HEX])
說(shuō)明:從文件
<filename>中讀取內(nèi)容,并將結(jié)果存入到<variable>中??梢灾付◤奈募?code><offset>處開始讀,最多讀取字節(jié)數(shù)(bytes)通過(guò)<max-in>參數(shù)指定。HEX選項(xiàng)會(huì)將讀取結(jié)果轉(zhuǎn)換成十六進(jìn)制表示(在讀取二進(jìn)制數(shù)據(jù)的時(shí)候非常有用),且十六進(jìn)制的輸出將按照小寫輸出(也就是或說(shuō)輸出a b c d e f)。
# CMakeLists.txt
# 從myfile_read的第5個(gè)字節(jié)偏移處開始讀,讀取4個(gè)字節(jié)
file(READ myfile_read content OFFSET 8 LIMIT 6)
message("read from myfile_read at offset 8 and read 6 bytes: ${content}")
# 讀取結(jié)果轉(zhuǎn)換成十六進(jìn)制表示,十六進(jìn)制表示中的ABCDEF將按照小寫輸出
file(READ myfile_read content_hex OFFSET 8 LIMIT 6 HEX)
message("read from myfile_read at offset 8 and read 6 bytes (HEX output): ${content_hex}")
myfile_read文件的原始內(nèi)容為:THIS IS A FILE FOR READ TEST.運(yùn)行結(jié)果:
read from myfile_read at offset 8 and read 6 bytes: A FILE
read from myfile_read at offset 8 and read 6 bytes (HEX output): 412046494c45
-
file(STRINGS <filename> <variable> [<options>...])
說(shuō)明
??按照ASCII編碼從文件中讀取并存儲(chǔ)在<variable>中。換行符會(huì)被忽略,如果是二進(jìn)制數(shù)據(jù),也會(huì)被忽略。默認(rèn)情況下是以換行符對(duì)讀取的內(nèi)容進(jìn)行分割,每一行讀取為輸出結(jié)果序列的一個(gè)子項(xiàng),不同子項(xiàng)以分號(hào)分割(也可以使用長(zhǎng)度進(jìn)行分割等,見(jiàn)下詳解)。該命令的選項(xiàng)詳解如下:
LENGTH_MAXIMUM <max-len>:每次讀取不超過(guò)給定長(zhǎng)度的字符串,如果某一行的字符超過(guò)指定長(zhǎng)度,會(huì)以指定長(zhǎng)度對(duì)該行進(jìn)行分割讀取。LENGTH_MINIMUM <min-len>:每次讀取不少于給定長(zhǎng)度的字符串,如果某一行的字符串長(zhǎng)度低于指定長(zhǎng)度,則不會(huì)讀取到結(jié)果中。LIMIT_COUNT <max-num>:限制提取的字符串子項(xiàng)個(gè)數(shù),例如默認(rèn)情況下是以換行分割讀取,假如<max-num>是5,如果輸入文件有6行,那么只會(huì)讀取前5行。LIMIT_INPUT <max-in>:限制從輸入文件的讀取的字節(jié)數(shù)。LIMIT_OUTPUT <max-out>:限制存入到<variable>中的總字節(jié)數(shù),當(dāng)解析得到最后一個(gè)字符串子項(xiàng)長(zhǎng)度累加后超過(guò)指定長(zhǎng)度時(shí)候,最后一個(gè)字符串子項(xiàng)會(huì)丟棄。NEWLINE_CONSUME:將換行符作為字符串內(nèi)容的一部分,而不是在換行時(shí)停止讀取。NO_HEX_CONVERSION:Intel十六進(jìn)制和Motorola的S-record文件會(huì)自動(dòng)轉(zhuǎn)換成二進(jìn)制,除非指定了本選項(xiàng)。REGEX <regex>:讀取匹配指定正則表達(dá)式的字符串。ENCODING <encoding-type>:3.1版本中引入。按照指定的編碼讀取字符串,當(dāng)前支持的編碼包括:UTF-8, UTF-16LE, UTF-16BE, UTF-32LE, UTF-32BE。此外,如果未指定本選項(xiàng)并且文件本身有字節(jié)順序標(biāo)記Byte Order Mark,那么會(huì)按照文件的字節(jié)順序標(biāo)記進(jìn)行解析。
# CMakeLists.txt
file(STRINGS myfile_read content_s) # 默認(rèn)會(huì)以換行將文件的內(nèi)容分割成多個(gè)子項(xiàng),按照分號(hào)序列的方式存儲(chǔ)
message("read myfile_read as STRINGS: ${content_s}")
# 限制每次提取的字符串長(zhǎng)度不超過(guò)10
file(STRINGS myfile_read content_s LENGTH_MAXIMUM 10)
message("read myfile_read as STRINGS - LMax: ${content_s}")
# 限制每次提取的字符串長(zhǎng)度至少為10,小于10會(huì)舍棄
file(STRINGS myfile_read content_s LENGTH_MINIMUM 10)
message("read myfile_read as STRINGS - LMin: ${content_s}")
# 限制提取的字符串子項(xiàng)數(shù)量最多為2個(gè)
file(STRINGS myfile_read content_s LIMIT_COUNT 2)
message("read myfile_read as STRINGS - LCount: ${content_s}")
# 限制只提取文件的前35個(gè)字符
file(STRINGS myfile_read content_s LIMIT_INPUT 35)
message("read myfile_read as STRINGS - LInput: ${content_s}")
# 限制輸出的總長(zhǎng)度為45
file(STRINGS myfile_read content_s LIMIT_OUTPUT 45)
message("read myfile_read as STRINGS - LOutput: ${content_s}")
# 不以換行進(jìn)行分割,輸出結(jié)果包含換行
file(STRINGS myfile_read content_s NEWLINE_CONSUME)
message("read myfile_read as STRINGS - Contain CR: ${content_s}")
myfile_read文件的原始內(nèi)容有三行:
THIS IS A FILE FOR READ TEST.
new line1
new line2運(yùn)行結(jié)果為:
read myfile_read as STRINGS: THIS IS A FILE FOR READ TEST.;new line1;new line2
read myfile_read as STRINGS - LMax: THIS IS A ;FILE FOR R;EAD TEST.;new line1;new line2
read myfile_read as STRINGS - LMin: THIS IS A FILE FOR READ TEST.
read myfile_read as STRINGS - LCount: THIS IS A FILE FOR READ TEST.;new line1
read myfile_read as STRINGS - LInput: THIS IS A FILE FOR READ TEST.;new l
read myfile_read as STRINGS - LOutput: THIS IS A FILE FOR READ TEST.;new line1
read myfile_read as STRINGS - Contain CR: THIS IS A FILE FOR READ TEST.
new line1
new line2
-
file(<HASH> <filename> <variable>)
說(shuō)明:計(jì)算文件的
hash結(jié)果,支持的hash算法可以參考string(<HASH>)。
# CMakeLists.txt
file(MD5 myfile_read content_hash)
message("Hash of myfile_read is: ${content_hash}")
運(yùn)行結(jié)果為:
Hash of myfile_read is: 6a4ff0158d402b69360ee52ba217faf3
-
file(TIMESTAMP <filename> <variable> [<format>] [UTC])
說(shuō)明:將文件的修改時(shí)間轉(zhuǎn)換成字符串表示,并存儲(chǔ)在結(jié)果
<variable>中。如果無(wú)法獲得時(shí)間戳,字符串將置為""。<format>和UTC選項(xiàng)的詳細(xì)使用方法見(jiàn)string(TIMESTAP)。未使用UTC選項(xiàng)時(shí),返回的時(shí)本地時(shí)間,默認(rèn)的格式為年-月-日T時(shí):分:秒;當(dāng)指定UTC選項(xiàng)時(shí),默認(rèn)格式為年-月-日T時(shí):分:秒Z。
# CMakeLists.txt
file(TIMESTAMP myfile_read time_string)
message("myfile_read modify time is(local time): ${time_string}")
file(TIMESTAMP myfile_read time_string UTC)
message("myfile_read modify time is(UTC): ${time_string}")
file(TIMESTAMP myfile_read time_string "%B.%d %Y-%H:%M:%S-%A")
message("myfile_read modify time is(format: 月.日 年-時(shí):分:秒-周): ${time_string}")
運(yùn)行結(jié)果為:
***myfile_read modify time is(local time): 2022-05-11T08:14:34
myfile_read modify time is(UTC): 2022-05-11T00:14:34Z
myfile_read modify time is(format: 月.日 年-時(shí):分:秒-周): May.11 2022-08:14:34-Wednesday*******
-
file(GET_RUNTIME_DEPENDENCIES[RESOLVED_DEPENDENCIES_VAR <deps_var>] [UNRESOLVED_DEPENDENCIES_VAR <unresolved_deps_var>] [CONFLICTING_DEPENDENCIES_PREFIX <conflicting_deps_prefix>] [EXECUTABLES [<executable_files>...]] [LIBRARIES [<library_files>...]] [MODULES [<module_files>...]] [DIRECTORIES [<directories>...]] [BUNDLE_EXECUTABLE <bundle_executable_file>] [PRE_INCLUDE_REGEXES [<regexes>...]] [PRE_EXCLUDE_REGEXES [<regexes>...]] [POST_INCLUDE_REGEXES [<regexes>...]] [POST_EXCLUDE_REGEXES [<regexes>...]] [POST_INCLUDE_FILES [<files>...]] [POST_EXCLUDE_FILES [<files>...]])
說(shuō)明:這個(gè)命令比較復(fù)雜,且根
install命令有關(guān),后續(xù)等install命令完成后返回來(lái)補(bǔ)充。
# CMakeLists.txt
運(yùn)行結(jié)果為:
3.2 子命令:寫
-
file(WRITE|APPEND <filename> <content>...)
說(shuō)明:將內(nèi)容寫入到指定的文件,如果文件不存在則創(chuàng)建文件;如果文件已經(jīng)存在,
WRITE選項(xiàng)會(huì)覆蓋原文件,而APPEND則將內(nèi)容添加在原文件的末尾。此外,文件filename路徑中不存在的目錄也會(huì)被創(chuàng)建出來(lái)。
# CMakeLists.txt
file(WRITE myfile_wirte "write one line\n")
file(READ myfile_wirte content)
message("file(user wirte): ${content}")
file(WRITE myfile_wirte "write another line\n")
file(READ myfile_wirte content)
message("file(user wirte): ${content}")
file(APPEND myfile_wirte "append one line\n")
file(READ myfile_wirte content)
message("file(user append): ${content}")
運(yùn)行結(jié)果為:
file(user wirte): write one linefile(user wirte): write another line
file(user append): write another line
append one line
-
file(TOUCH|TOUCH_NOCREATE [<files>...])
說(shuō)明:
3.12版本引入。
TOUCH會(huì)創(chuàng)建一個(gè)內(nèi)容為空的新文件,如果文件已經(jīng)存在,那么該命令不會(huì)對(duì)文件的內(nèi)容有任何影響,只會(huì)將文件的訪問(wèn)或者修改時(shí)間更新為該命令調(diào)用時(shí)間。TOUCH_NOCREATE選項(xiàng)不會(huì)創(chuàng)建新文件,如果文件不存在則會(huì)忽略,如果文件存在,那么則更新文件的訪問(wèn)或者修改時(shí)間為該命令調(diào)用的時(shí)間。該命令可以指定多個(gè)文件。
# CMakeLists.txt
file(TIMESTAMP myfile_read modify_time)
message("myfile_read modify time is: ${modify_time}")
file(TOUCH_NOCREATE myfile_read) # 如果myfile_read不存在,那么不會(huì)創(chuàng)建文件,如果myfile_read存在,則更新其訪問(wèn)/修改時(shí)間
file(TIMESTAMP myfile_read modify_time)
message("after touch(but not create) myfile_read modify time is: ${modify_time}")
file(TOUCH mynewfile) # 創(chuàng)建新文件
file(TIMESTAMP mynewfile modify_time)
message("create mynewfile time is: ${modify_time}")
運(yùn)行結(jié)果為:
myfile_read modify time is: 2022-05-11T08:14:34
after touch(but not create) myfile_read modify time is: 2022-05-12T22:18:51
create mynewfile time is: 2022-05-12T22:18:51
-
file(GENERATE OUTPUT output-file <INPUT input-file|CONTENT content> [CONDITION expression] [TARGET target] [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS | FILE_PERMISSIONS <permissions>...] [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
說(shuō)明:該命令跟
生成表達(dá)式有關(guān),待完成生成表達(dá)式后補(bǔ)充。
3.3 子命令:文件系統(tǒng)
-
file(GLOB <variable> [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS] [<globbing-expressions>...])
說(shuō)明:
??生成能匹配表達(dá)式<globbing-expressions>的一組文件,并將結(jié)果存入到<variable>中,結(jié)果按照字典序進(jìn)行排列(3.6版本及之后)。Globbing expressions與正則表達(dá)式類似,但是比正則表達(dá)式要簡(jiǎn)單很多。
??在Windows和macOS系統(tǒng)中,Globbing expressions是大小寫不敏感的(在匹匹配為之前會(huì)將文件名和Globbing expressions轉(zhuǎn)換為小寫);其他系統(tǒng)Globbing expressions是大小寫敏感的。
??具體的選項(xiàng)解析如下:
LIST_DIRECTORIES:默認(rèn)情況下,結(jié)果會(huì)將目錄也列出來(lái),如果將LIST_DIRECTORIES設(shè)置為false,那么目錄會(huì)被忽略,只會(huì)列出文件存入結(jié)果中。RELATIVE:指定該選項(xiàng),將返回匹配文件相對(duì)于RELATIVE指定的路徑。RELATIVE必須指定一個(gè)絕對(duì)路徑。CONFIGURE_DEPENDS:指定該選項(xiàng),CMake會(huì)在構(gòu)建時(shí)重新運(yùn)行該命令。
# CMakeLists.txt
file(GLOB result "matches/*") # 列出目錄matches下的所有文件,帶全路徑
message("all files in matches: ${result}")
file(GLOB result "matches/*.txt") # 匹配matches下后綴為txt的文件,帶全路徑
message("match *.txt result: ${result}")
file(GLOB result RELATIVE /XXX/YYY/ZZZ/matches "myfile*")
message("list file: ${result}") # 查找當(dāng)前目錄./下的myfile開頭的文件,返回相對(duì)于./matches路徑的結(jié)果
運(yùn)行結(jié)果:
*all files in ./matches: /XXX/YYY/ZZZ/matches/log1.txt;/XXX/YYY/ZZZ/matches/log2.txt;/XXX/YYY/ZZZ/matches/log3.txt;/XXX/YYY/ZZZ/matches/log4.txt;/XXX/YYY/ZZZ/matches/log5.txt;/XXX/YYY/ZZZ/matches/test1.dat;//XXX/YYY/ZZZ/matches/test2.dat;/XXX/YYY/ZZZ/matches/test3.dat;/XXX/YYY/ZZZ/matches/test4.dat
match .txt result: /XXX/YYY/ZZZ/matches/log1.txt;/XXX/YYY/ZZZ/matches/log2.txt;/XXX/YYY/ZZZ/matches/log3.txt;/XXX/YYY/ZZZ/matches/log4.txt;/XXX/YYY/ZZZ/matches/log5.txt
list file: ../myfile_download;../myfile_read;../myfile_wirte;../myfile_write
-
file(GLOB_RECURSE <variable> [FOLLOW_SYMLINKS] [LIST_DIRECTORIES true|false] [RELATIVE <path>] [CONFIGURE_DEPENDS] [<globbing-expressions>...])
說(shuō)明:
??與GLOB區(qū)別是,該子命令會(huì)遞歸的遍歷匹配目錄的所有子目錄,然后尋找匹配的文件。
-
file(MAKE_DIRECTORY [<directories>...])
說(shuō)明:創(chuàng)建指定目錄,如果指定的目錄的路徑中有不存在的目錄,也會(huì)一并創(chuàng)建。
file(MAKE_DIRECTORY ./dir1/dir2/dir3/mynewdir) # dir1、dir2、dir3、mynewdir目錄都會(huì)被創(chuàng)建
-
file(REMOVE|REMOVE_RECURSE [<files>...])
說(shuō)明:移除指定的文件,
REMOVE_RECURSE模式將會(huì)移除給定的文件和目錄(即使目錄是非空的)。如果給定的文件不存在,也不會(huì)有錯(cuò)誤的信息提示,如果文件是以相對(duì)路徑提供,那么會(huì)以當(dāng)前目錄作為參考。
3.15版本之前,如果是空的文件路徑輸入,會(huì)將空路徑當(dāng)成相對(duì)路徑,以當(dāng)前目錄作為參考,刪除當(dāng)前目錄的內(nèi)容;而3.15及之后的版本,空的文件輸入會(huì)被忽略,并給出一個(gè)提示信息。
# CMakeLists.txt
file(REMOVE "./dir1/dir2/dir3/mynewdir/testfile1") # 刪除指定文件testfile1
file(REMOVE_RECURSE "./dir1/dir2/dir3/mynewdir/testfile2") # 刪除指定文件testfile2
file(REMOVE_RECURSE "./dir1/dir2/dir3/mynewdir") # 刪除指定目錄mynewdir,會(huì)遞歸刪除mynewdir目錄下所有的文件和子目錄,也會(huì)刪除mynewdir目錄本身
file(REMOVE "") # 3.15及之后的版本會(huì)忽略該語(yǔ)句并給出提示,假設(shè)該語(yǔ)句位于CMakeLists.txt文件的第23行,提示信息見(jiàn)下
運(yùn)行結(jié)果:
CMake Warning (dev) at CMakeLists.txt:23 (file):
Ignoring empty file name in REMOVE.
This warning is for project developers. Use -Wno-dev to suppress it.
-
file(RENAME <oldname> <newname> [RESULT <result>] [NO_REPLACE])
說(shuō)明:將指定的文件或者目錄從舊路徑
<oldname>移動(dòng)到新路徑<newname>下,如果存在相同的名稱文件或者目錄會(huì)進(jìn)行自動(dòng)替換。
RESULT <result>:3.21版本引入。如果命令執(zhí)行成功,將<result>變量置為0,否則<result>變量存儲(chǔ)錯(cuò)誤信息(CMake不會(huì)產(chǎn)生錯(cuò)誤)。如果未指定該選項(xiàng),當(dāng)執(zhí)行不成功,CMake會(huì)產(chǎn)生一個(gè)錯(cuò)誤。NO_REPLACE:3.21版本引入。默認(rèn)情況下新路徑下已經(jīng)存在文件或目錄,會(huì)自動(dòng)進(jìn)行替換,指定該選項(xiàng)則不會(huì)對(duì)相同的文件或目錄進(jìn)行替換,而是會(huì)產(chǎn)生一個(gè)錯(cuò)誤(如果指定了RESULT選項(xiàng),NO_REPLACE會(huì)存儲(chǔ)到RESULT指定的變量中。)
# CMakeLists.txt
file(RENAME ./rename_test/old/oldfile6 ./rename_test/new/) # 會(huì)提示錯(cuò)誤:No such file or directory
file(RENAME ./rename_test/old/oldfile6 ./rename_test/new/ RESULT info) # 不會(huì)提示錯(cuò)誤,錯(cuò)誤信息No such file or directory會(huì)存儲(chǔ)到info中
message("operation result: ${info}")
file(RENAME ./rename_test/old/oldfile1 ./rename_test/new/newfile1 RESULT info) # 執(zhí)行成功,info結(jié)果為0
message("operation result: ${info}")
file(RENAME ./rename_test/old/olddir1/oldfile4 ./rename_test/new/olddir1/oldfile4 NO_REPLACE RESULT info) # 有NO_REPLACE選項(xiàng),因此無(wú)法進(jìn)行替換操作,info中存儲(chǔ)的是NO_REPLACE
message("operation result: ${info}")
file(RENAME ./rename_test/old/olddir1/oldfile4 ./rename_test/new/olddir1/oldfile4 RESULT info) # 執(zhí)行成功,info結(jié)果為0
message("operation result: ${info}")
上述命令操作的文件樹結(jié)構(gòu)為:
├── CMakeLists.txt
├── rename_test
│ ├── new
│ │ └── olddir1
│ │ └── oldfile4
│ └── old
│ │ └── olddir1
│ │ └── oldfile4
│ | ├── olddir1
│ | ├── oldfile2
│ | └── oldfile3
-
file(COPY_FILE <oldname> <newname> [RESULT <result>] [ONLY_IF_DIFFERENT])
說(shuō)明:
3.21版本引入。將文件從<oldname>復(fù)制到<newname>,不支持目錄的復(fù)制。如果<oldname>是一個(gè)符號(hào)鏈接,那么會(huì)讀取<oldname>實(shí)際鏈接的內(nèi)容,并將實(shí)際指向的內(nèi)容復(fù)制到<newname>中。該命令支持的幾個(gè)選項(xiàng)解析如下:
RESULT <result>:如果執(zhí)行成功,<result>變量?jī)?nèi)容為0,執(zhí)行出錯(cuò)該變量?jī)?nèi)容為具體的錯(cuò)誤信息。如果未指定該選項(xiàng)且命令執(zhí)行出錯(cuò),那么CMake會(huì)拋出錯(cuò)誤并停止構(gòu)建。ONLY_IF_DIFFERENT:如果目標(biāo)文件<newname>已經(jīng)存在,并且<newname>文件的內(nèi)容與<oldname>內(nèi)容一樣,那么不做替換操作,這樣就可以避免更新<newname>的時(shí)間戳。
# CMakeLists.txt
file(COPY_FILE mydir mydir_copy) # 不支持目錄,如果不指定RESULT,CMake構(gòu)建會(huì)提示錯(cuò)誤:file COPY_FILE cannot copy a directory
file(COPY_FILE mydir mydir_copy RESULT result)
message("Copy dir result: ${result}") # 復(fù)制不成功,CMake構(gòu)建不會(huì)提示錯(cuò)誤,錯(cuò)誤信息會(huì)存到result中
file(COPY_FILE myfile myfile_copy RESULT result) # myfile內(nèi)容為"This is a file for testing."
file(TIMESTAMP myfile_copy ts)
message("Copy file result: ${result}, timestamp: ${ts}") # 復(fù)制成功,結(jié)果為0
execute_process(COMMAND sleep 5)
file(COPY_FILE myfile myfile_copy RESULT result) # 復(fù)制相同的內(nèi)容,未指定ONLY_IF_DIFFERENT選項(xiàng),仍會(huì)執(zhí)行賦值操作,注意時(shí)間戳打印不一致
file(TIMESTAMP myfile_copy ts)
message("Copy file for same content result: ${result}, timestamp: ${ts}")
execute_process(COMMAND sleep 5)
file(COPY_FILE myfile myfile_copy RESULT result ONLY_IF_DIFFERENT) # 復(fù)制相同的內(nèi)容,指定ONLY_IF_DIFFERENT選項(xiàng),不會(huì)執(zhí)行復(fù)制動(dòng)作,因此時(shí)間戳沒(méi)有變化
file(TIMESTAMP myfile_copy ts)
message("Copy file for same content result: ${result}, timestamp: ${ts}")
file(WRITE myfile_copy "Rewrite file content.")
execute_process(COMMAND sleep 5)
file(COPY_FILE myfile myfile_copy RESULT result ONLY_IF_DIFFERENT) # 由于目標(biāo)文件內(nèi)容和源文件內(nèi)容不一致了,會(huì)執(zhí)行復(fù)制操作
file(TIMESTAMP myfile_copy ts)
message("Copy file for different content result: ${result}, timestamp: ${ts}")
執(zhí)行結(jié)果為:
CMake Error at CMakeLists.txt:4 (file): file COPY_FILE cannot copy a directory
/XXX/YYY/ZZZ/mydirCopy dir result: cannot copy a directory
Copy file result: 0, timestamp: 2022-05-15T08:07:51
Copy file for same content result: 0, timestamp: 2022-05-15T08:07:56
Copy file for same content(use ONLY_IF_DIFFEREBT)result: 0, timestamp: 2022-05-15T08:07:56
Copy file for different content result: 0, timestamp: 2022-05-15T08:08:06
-- Configuring incomplete, errors occurred!
-
file(<COPY|INSTALL> <files>... DESTINATION <dir> [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS] [FILE_PERMISSIONS <permissions>...] [DIRECTORY_PERMISSIONS <permissions>...] [FOLLOW_SYMLINK_CHAIN] [FILES_MATCHING] [[PATTERN <pattern> | REGEX <regex>] [EXCLUDE] [PERMISSIONS <permissions>...]] [...])
說(shuō)明:如果只是簡(jiǎn)單的文件復(fù)制,可以使用前面的
file(COPY_FILE)命令。相對(duì)于file(COPY_FILE),本命令是一個(gè)更復(fù)雜的命令,它可以復(fù)制文件、目錄、符號(hào)鏈接等。輸入文件的目錄是相對(duì)于當(dāng)前源文件路徑,目的文件路徑是相對(duì)于當(dāng)前構(gòu)建路徑。
COPY子命令會(huì)保存輸入文件的時(shí)間戳,如果目的文件存在,那么會(huì)將目的文件的時(shí)間戳修改成和輸入文件一致。默認(rèn)情況下(USE_SOURCE_PERMISSIONS選項(xiàng))也會(huì)將輸入文件的權(quán)限傳遞給目的文件,除非通過(guò)NO_SOURCE_PERMISSIONS選項(xiàng)顯示禁止。INSTALL子命令與COPY子命令稍微不一樣的地方是:INSTALL子命令會(huì)打印狀態(tài)信息,并且默認(rèn)情況下不會(huì)將輸入文件的權(quán)限傳遞給目的文件(也就是默認(rèn)為NO_SOURCE_PERMISSIONS選項(xiàng))。install()命令就是使用file(INSTALL)命令來(lái)產(chǎn)生安裝腳本文件的。在3.22版本以后,還可以給CMAKE_INSTALL_MODE環(huán)境變量賦值來(lái)改變file(INSTALL)的默認(rèn)復(fù)制行為。FOLLOW_SYMLINK_CHAIN:如果指定了該選項(xiàng),會(huì)遞歸的解析符號(hào)鏈接,直到找到最終的文件,并且每一個(gè)符號(hào)鏈接都會(huì)在指定的目的目錄創(chuàng)建出來(lái),并且都指向同個(gè)目錄下創(chuàng)建的最終文件。這個(gè)選項(xiàng)在類Unix系統(tǒng)下特別有用,在這些系統(tǒng)中,庫(kù)文件都是以版本號(hào)命名的符號(hào)鏈接形式安裝,由不具體的版本指向具體的版本。- 對(duì)于權(quán)限,
FILES_MACHING、PATTERN、REGEX和EXCLUDE請(qǐng)參考install(DIRECTORY)。
目錄結(jié)構(gòu)為:
copy_test
├── dest
└── source
├── dir_for_copy
│ └── file1
└── libs
├── mylib.so
├── mylib.so.1 -> mylib.so
├── mylib.so.1.2 -> mylib.so.1
└── mylib.so.1.2.3 -> mylib.so.1.2
# CMakeLists.txt
file(COPY copy_test/source/dir_for_copy/file1 DESTINATION copy_test/dest/) # 假定file1的權(quán)限是660,使用COPY,默認(rèn)拷貝后的文件權(quán)限也是660,查看 執(zhí)行結(jié)果1
file(INSTALL copy_test/source/dir_for_copy/file1 DESTINATION copy_test/dest/) # 假定file1的權(quán)限是660,使用INSTALL,默認(rèn)拷貝后的文件權(quán)限是644(系統(tǒng)默認(rèn)文件創(chuàng)建權(quán)限),查看 執(zhí)行結(jié)果2
file(COPY copy_test/source/dir_for_copy DESTINATION copy_test/dest/) # 拷貝dir_for_copy目錄
file(COPY copy_test/source/libs/mylib.so DESTINATION copy_test/dest/libs FOLLOW_SYMLINK_CHAIN) # 遞歸拷貝mylib.so的鏈接并創(chuàng)建,查看 執(zhí)行結(jié)果3
file(COPY copy_test/source/libs/mylib.so DESTINATION copy_test/dest/libs_nosymlink) # 只會(huì)拷貝單個(gè)mylib.so文件,查看 執(zhí)行結(jié)果4
- 執(zhí)行結(jié)果1:
復(fù)制前的file1權(quán)限:
-rw-rw----copy_test/source/dir_for_copy/file1
復(fù)制后的file1權(quán)限:
-rw-rw----copy_test/dest/file1- 執(zhí)行結(jié)果2:
復(fù)制前的file1權(quán)限:
-rw-rw----copy_test/source/dir_for_copy/file1
復(fù)制后的file1權(quán)限:
-rw-r--r--copy_test/dest/file1
并且使用INSTALL會(huì)打印處中間的執(zhí)行狀態(tài)信息:
-- Up-to-date: /XXX/YYY/ZZZ/copy_test/dest//file1- 執(zhí)行結(jié)果3:
有FOLLOW_SYMLINK_CHAIN選項(xiàng),復(fù)制后的目錄結(jié)構(gòu),會(huì)將整個(gè)鏈接遞歸創(chuàng)建出來(lái):
copy_test
├── dest
│ ├── libs
│ │ ├── mylib.so -> mylib.so.1
│ │ ├── mylib.so.1 -> mylib.so.1.2
│ │ ├── mylib.so.1.2 -> mylib.so.1.2.3
│ │ └── mylib.so.1.2.3
└── source
├── dir_for_copy
│ └── file1
└── libs
├── mylib.so -> mylib.so.1
├── mylib.so.1 -> mylib.so.1.2
├── mylib.so.1.2 -> mylib.so.1.2.3
└── mylib.so.1.2.3- 執(zhí)行結(jié)果4:
沒(méi)有FOLLOW_SYMLINK_CHAIN選項(xiàng),只會(huì)將鏈接文件當(dāng)成普通文件復(fù)制:
copy_test
├── dest
│ └── libs_nosymlink
│ └── mylib.so -> mylib.so.1
└── source
├── dir_for_copy
│ └── file1
└── libs
├── mylib.so -> mylib.so.1
├── mylib.so.1 -> mylib.so.1.2
├── mylib.so.1.2 -> mylib.so.1.2.3
└── mylib.so.1.2.3
-
file(SIZE <filename> <variable>)
說(shuō)明:
3.14版本引入,計(jì)算文件的大小,要求指向文件的路徑是合法的路徑,且文件本身是可讀的。
# CMakeLists.txt
set(filename "myfile_read")
file(SIZE ${filename} sz)
message("file ${filename} size is : ${sz} bytes")
執(zhí)行結(jié)果為:
file myfile_read size is : 50 bytes
-
file(READ_SYMLINK <linkname> <variable>)
說(shuō)明:
3.14版本引入。讀取鏈接文件并將該鏈接文件指向的文件路徑保存到變量<variable>中,如果鏈接文件不存在,CMake會(huì)拋出一個(gè)錯(cuò)誤。需要注意的是,該命令返回的時(shí)候鏈接文件原始指向的文件路徑,并且是相對(duì)路徑。
# CMakeLists.txt
set(linkname "/XXX/YYY/ZZZ/copy_test/source/libs/mylib.so")
file(READ_SYMLINK ${linkname} result) # 復(fù)制的是mylib.so執(zhí)行的mylib.so.1,且不會(huì)遞歸解析
message("Get link result: ${result}")
# 可以通過(guò)如下方法來(lái)獲取絕對(duì)路徑
if (NOT IS_ABSOLUTE "${result}")
get_filename_component(dir "${linkname}" DIRECTORY)
set(result "${dir}/${result}")
endif()
message("Get link result after add absolute path: ${result}")
執(zhí)行結(jié)果為:
Get link result: mylib.so.1
Get link result after add absolute path: /XXX/YYY/ZZZ/copy_test/source/libs/mylib.so.1
-
file(CREATE_LINK <original> <linkname> [RESULT <result>] [COPY_ON_ERROR] [SYMBOLIC])
說(shuō)明:
3.14版本引入,創(chuàng)建一個(gè)指向<original>的鏈接文件<linkname>,如果<linkname>已經(jīng)存在,則會(huì)被覆蓋。默認(rèn)創(chuàng)建的是硬鏈接(硬鏈接要求原始文件存在且不是目錄)。
RESULT <result>:如果執(zhí)行成功,<result>變量?jī)?nèi)容為0,執(zhí)行出錯(cuò)該變量?jī)?nèi)容為具體的錯(cuò)誤信息。如果未指定該選項(xiàng)且命令執(zhí)行出錯(cuò),那么CMake會(huì)拋出錯(cuò)誤并停止構(gòu)建。SYMBOLIC:創(chuàng)建軟連接。COPY_ON_ERROR:如果創(chuàng)建鏈接文件失敗,那么復(fù)制文件。主要用于<original>和<linkname>在不同的驅(qū)動(dòng)器或者掛在點(diǎn)的場(chǎng)景,此時(shí)創(chuàng)建硬鏈接會(huì)失敗,用此選項(xiàng)可以復(fù)制文件。
# CMakeLists.txt
set(original "myfile_read")
file(CREATE_LINK ${original} myfile_read_hardlink)
file(CREATE_LINK ${original} myfile_read_softlink SYMBOLIC)
執(zhí)行結(jié)果為,硬鏈接用
ls -l查詢,數(shù)字是2:
-rw-r--r--2myfile_read
-rw-r--r--2shengyi staff 50 5 12 22:18 myfile_read_hardlink
lrwxr-xr-x 1 shengyi staff 11 5 17 08:52myfile_read_softlink -> myfile_read
-
file(CHMOD <files>... <directories>... [PERMISSIONS <permissions>...] [FILE_PERMISSIONS <permissions>...] [DIRECTORY_PERMISSIONS <permissions>...])
說(shuō)明:
3.19版本引入,修改指定文件或目錄的權(quán)限,合法的權(quán)限設(shè)置選項(xiàng)有:OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ, GROUP_WRITE, GROUP_EXECUTE, WORLD_READ, WORLD_WRITE, WORLD_EXECUTE, SETUID, SETGID。此外,PERMISSIONS、FILE_PERMISSIONS、DIRECTORY_PERMISSIONS只能單獨(dú)使用或者按照如下方式組合使用:
PERMISSIONS:所有指定的文件或目錄的權(quán)限都會(huì)被修改。FILE_PERMISSIONS:只改變指定文件的權(quán)限。DIRECTORY_PERMISSIONS:只改變指定目錄的權(quán)限。- 同時(shí)指定
PERMISSIONS和FILE_PERMISSIONS:文件的權(quán)限會(huì)被FILE_PERMISSIONS指定的權(quán)限覆寫。- 同時(shí)指定
PERMISSIONS和DIRECTORY_PERMISSIONS:目錄的權(quán)限會(huì)被DIRECTORY_PERMISSIONS指定的權(quán)限覆寫。- 同時(shí)指定
FILE_PERMISSIONS和DIRECTORY_PERMISSIONS:FILE_PERMISSIONS指定的權(quán)限應(yīng)用于文件,DIRECTORY_PERMISSIONS指定的權(quán)限應(yīng)用于目錄。
# CMakeLists.txt
# 備注:原始權(quán)限 file_test 644; dir_test 755
file(CHMOD file_test PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ GROUP_WRITE WORLD_READ WORLD_WRITE) # 修改權(quán)限為666
#file(CHMOD dir_test PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_WRITE WORLD_EXECUTE) # 修改權(quán)限為777
file(CHMOD file_test PERMISSIONS OWNER_READ GROUP_READ WORLD_READ FILE_PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ GROUP_WRITE WORLD_READ) # FILE_PERMISSIONS指定權(quán)限起作用,修改為664
file(CHMOD dir_test PERMISSIONS OWNER_READ GROUP_READ WORLD_READ DIRECTORY_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) # DIRECTORY_PERMISSIONS指定的權(quán)限起作用,修改為755
-
file(CHMOD_RECURSE <files>... <directories>... [PERMISSIONS <permissions>...] [FILE_PERMISSIONS <permissions>...] [DIRECTORY_PERMISSIONS <permissions>...])
說(shuō)明:
3.19版本引入,與CHMOD的區(qū)別就是CHMOD_RECURSE會(huì)遞歸的修改指定目錄下的子目錄和文件權(quán)限,類似于Linux命令chmod -R。
3.4 子命令:路徑轉(zhuǎn)換
-
file(REAL_PATH <path> <out-var> [BASE_DIRECTORY <dir>] [EXPAND_TILDE])
說(shuō)明:
3.19版本中引入。計(jì)算指定路徑的絕對(duì)路徑。
BASE_DIRECTORY <dir>:如果指定了該選項(xiàng),且給定待轉(zhuǎn)換的路徑<path>是一個(gè)相對(duì)路徑,那么計(jì)算<path>相對(duì)于<dir>的路徑。如果未指定該選項(xiàng),那么計(jì)算<path>相對(duì)于CMAKE_CURRENT_SOURCE_DIR環(huán)境變量的路徑。EXPAND_TILDE:3.21版本新增。如果<path>是~或以~/開頭,那么~會(huì)被替換為用戶的home目錄。home目錄的值是從環(huán)境變量中得到,在Wndows下,首先會(huì)從USERPROFILE環(huán)境變量獲取,如果未指定該環(huán)境變量,則會(huì)從HOME環(huán)境變量中獲?。黄渌到y(tǒng)只會(huì)從HOME環(huán)境變量中獲取。
# CMakeLists.txt
file(REAL_PATH dir_test result BASE_DIRECTORY "/bin")
message("Conversion result: ${result}")
message("Home path is : $ENV{HOME}")
file(REAL_PATH "~/dir_test" result BASE_DIRECTORY "/bin" EXPAND_TILDE) # 此時(shí)會(huì)忽略掉BASE_DIRECTORY指定的值
message("Conversion result: ${result}")
運(yùn)行結(jié)果(
macOS系統(tǒng)):
Conversion result: /bin/dir_test
Home path is : /Users/user1
Conversion result: /Users/user1/dir_test
-
file(RELATIVE_PATH <variable> <directory> <file>)
說(shuō)明:計(jì)算
<directory>到<file>的相對(duì)路徑,實(shí)際上就是怎么從<directory>通過(guò).、..等切換到<file>。需要注意的是,<directory>和<file>都必須是絕對(duì)路徑。
# CMakeLists.txt
file(RELATIVE_PATH result /usr/local /etc/passwd)
message("Conversion result: ${result}")
運(yùn)行結(jié)果(
macOS系統(tǒng)):
Conversion result: ../../etc/passwd
-
file(TO_CMAKE_PATH|TO_NATIVE_PATH "<path>" <variable>)
說(shuō)明:
TO_CMAKE_PATH將系統(tǒng)原生路徑轉(zhuǎn)換為CMake風(fēng)格的路徑。TO_NATIVE_PATH則反過(guò)來(lái),將CMake風(fēng)格的路徑轉(zhuǎn)換為系統(tǒng)原生路徑。
CMake風(fēng)格的路徑:路徑以/作為目錄之間的分隔符,且多個(gè)目錄以;分割的序列。- 原生系統(tǒng)路徑:在
Windows下,以\作為目錄分隔符,多個(gè)路徑以;分隔;而在其他系統(tǒng),以/作為目錄分隔符,多個(gè)路徑以:分隔。例如在我的macOS下,PATH環(huán)境變量(對(duì)應(yīng)系統(tǒng)原生路徑)為:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin注意:子命令
RELATIVE_PATH,TO_CMAKE_PATH和TO_NATIVE_PATH已經(jīng)分別被cmake_path的子命令RELATIVE_PATH、CONVERT ... TO_CMAKE_PATH_LIST、CONVERT ... TO_NATIVE_PATH_LIST取代。因此直接參考cmake_path的相關(guān)命令。
3.5 子命令:傳輸
-
file(DOWNLOAD <url> [<file>] [<options>...]);file(UPLOAD <file> <url> [<options>...])
說(shuō)明:從
<url>指定的地址下載到本地<file>中。從3.19版本開始,如果沒(méi)有指定本地文件<file>,那么不會(huì)保存文件,這樣在檢測(cè)待下載文件是否存在的時(shí)候比較有用。該命令還有許多可選項(xiàng),解析如下:
INACTIVITY_TIMEOUT <seconds>:當(dāng)超過(guò)指定時(shí)間沒(méi)有活動(dòng)則終止操作(上傳/下載)。LOG <variable>:將可讀的日志存儲(chǔ)到變量中。SHOW_PROGRESS:打印進(jìn)度信息。STATUS <variable>:存儲(chǔ)命令的操作(上傳/下載)結(jié)果,由長(zhǎng)度為2,以;分隔的序列組成,序列的第一個(gè)元素是一個(gè)以數(shù)字表示的結(jié)果返回值,第二元素是一個(gè)字符串表示錯(cuò)誤的信息。如果沒(méi)有出錯(cuò),則只返回0。TIMEOUT <seconds>:超時(shí)后終止操作(上傳/下載)。USERPWD <username>:<password>:3.7新增,為操作(上傳/下載)指定用戶名和密碼。HTTPHEADER <HTTP-header>:3.7新增,為操作(上傳/下載)指定http協(xié)議的頭,該選項(xiàng)可以重復(fù)多次使用。NETRC <level>:3.11新增,指定操作(上傳/下載)是否使用.netrc文件,如果未指定該選項(xiàng),那么會(huì)從變量CMAKE_NETRC中獲取,有如下幾個(gè)級(jí)別:IGNORED表示忽略.netrc文件,也是選項(xiàng)的默認(rèn)值;OPTIONAL表示.netrc文件可選,會(huì)優(yōu)先從URL中獲取信息,如果未從URL獲取到信息則會(huì)從.netrc文件獲?。?code>REQUIRED表示使用.netrc文件,忽略URL中的信息。NETRC_FILE <file>:3.11新增,指定另一個(gè).netrc文件,來(lái)替換home目錄下的.netrc文件。如果未指定該選項(xiàng),則會(huì)從CMAKE_NETRC_FILE變量中獲取。TLS_VERIFY <ON|OFF>:指定是否校驗(yàn)https URL服務(wù)器證書,默認(rèn)是不驗(yàn)證。如果未指定該選項(xiàng),則會(huì)從CMAKE_TLS_VERIFY變量中獲取。3.18版本中增加了對(duì)file(UPLOAD)的支持。TLS_CAINFO <file>:為https URL指定一個(gè)定制的證書鑒權(quán)文件。未指定該選項(xiàng),則會(huì)從CMAKE_TLS_CAINFO變量中獲取。3.18版本中增加了對(duì)file(UPLOAD)的支持。如下選項(xiàng)只支持
DOWNLOAD:
EXPECTED_HASH ALGO=<value>:驗(yàn)證下載的內(nèi)容的哈希值是否匹配期望的哈希值。ALGO指定file(HASH)支持的HASH算法,如果不匹配下載會(huì)出錯(cuò)。注意,如果未指定本地<file>文件,該命令會(huì)執(zhí)行出錯(cuò)。EXPECTED_MD5 <value>:該選項(xiàng)是為了兼容歷史選項(xiàng),實(shí)際上可以用上面的命令替代。它校驗(yàn)下載內(nèi)容的MD5值和期望的是否匹配。如果不匹配下載會(huì)出錯(cuò)。注意,如果未指定本地<file>文件,該命令會(huì)執(zhí)行出錯(cuò)。
3.6 子命令:鎖
-
file(LOCK <path> [DIRECTORY] [RELEASE] [GUARD <FUNCTION|FILE|PROCESS>] [RESULT_VARIABLE <variable>] [TIMEOUT <seconds>])
說(shuō)明:
3.2版本新增。鎖定<path>指定的文件。
DIRECTORY:指定該選項(xiàng)會(huì)鎖定目錄,并會(huì)創(chuàng)建一個(gè)<path>/cmake.lock文件。GUARD:指定鎖定的范圍,默認(rèn)是PROCESS(進(jìn)程),可選的還有FUNCTION(函數(shù))和FILE(文件)。RELEASE:顯式的釋放鎖。指定該選項(xiàng)時(shí),GUARD和TIMEOUT會(huì)被忽略。TIMEOUT:指定等待鎖定的超時(shí)時(shí)間,如果值為0,表示只會(huì)嘗試去鎖定一次,其他非0值則是嘗試鎖定文件的超時(shí)時(shí)間。如果未指定該選項(xiàng),則會(huì)一直嘗試鎖定,直到鎖定成功或者出錯(cuò)。RESULT_VARIABLE:存儲(chǔ)命令執(zhí)行的結(jié)果,如果成功,結(jié)果是0,否則存儲(chǔ)具體的錯(cuò)誤。如果未指定該選項(xiàng),發(fā)生錯(cuò)誤時(shí)候CMake會(huì)終止構(gòu)建并拋出錯(cuò)誤。鎖只是一個(gè)建議項(xiàng),不能保證鎖定后進(jìn)程也會(huì)遵循。也不能對(duì)一個(gè)文件鎖定
2次。
為了驗(yàn)證,我們創(chuàng)建了兩個(gè)
CMakeLists.txt文件對(duì)同一個(gè)文件/目錄進(jìn)行鎖定,目錄樹如下:
├── CMakeLists.txt
├── file_lock_test
│ ├── CMakeLists.txt
├── myfile_read
├── myfile_read_dir
# 頂層的CMakeLists.txt:在鎖定文件myfile_read和文件夾myfile_read_dir后,睡眠50秒,目的是讓file_lock_test下的CMakeLists.txt指定
file(LOCK myfile_read_dir DIRECTORY RESULT_VARIABLE result)
message("lock myfile_read_dir result: ${result}")
file(LOCK myfile_read RESULT_VARIABLE result)
message("lock myfile_read result: ${result}")
execute_process(COMMAND sleep 50)
# file_lock_test下的CMakeLists.txt
file(LOCK ../myfile_read_dir DIRECTORY RESULT_VARIABLE result TIMEOUT 0)
message("lock dir myfile_read_dir result: ${result}")
file(LOCK ../myfile_read RESULT_VARIABLE result TIMEOUT 10)
message("lock myfile_read result: ${result}")
運(yùn)行結(jié)果:
首先執(zhí)行頂層的CMakeLists.txt,出現(xiàn)如下打印說(shuō)明鎖定成功:
lock myfile_read_dir result: 0
lock myfile_read result: 0
然后執(zhí)行file_lock_test下的CMakeLists.txt,出現(xiàn)如下打印說(shuō)明文件或者目錄已經(jīng)被鎖定,命令超時(shí)退出了:
lock dir myfile_read_dir result: Timeout reached
lock myfile_read result: Timeout reached
3.7 子命令:歸檔
-
file(ARCHIVE_CREATE OUTPUT <archive> PATHS <paths>... [FORMAT <format>] [COMPRESSION <compression> [COMPRESSION_LEVEL <compression-level>]] [MTIME <mtime>] [VERBOSE])
說(shuō)明:
3.18版本新增。將PATHS指定的文件和目錄進(jìn)行歸檔,不支持通配符。
FORMAT:指定歸檔的格式,支持7zip, gnutar, pax, paxr, raw, zip,如果未指定該選項(xiàng),默認(rèn)歸檔格式是paxr。COMPRESSION:指定壓縮方式,7zip和zip歸檔格式已經(jīng)使用壓縮,其他格式默認(rèn)不壓縮,因此需要指定壓縮方式,支持的壓縮方式有None, BZip2, GZip, XZ, Zstd。COMPRESSION_LEVEL:3.19版本新增。在指定壓縮方式的前提下,可以指定壓縮級(jí)別,范圍是0-9,默認(rèn)是0。VERBOSE:呈現(xiàn)歸檔命令的輸出。MTIME:如果要指定壓縮文件的修改時(shí)間,指定該選項(xiàng)。
待壓縮文件夾的結(jié)構(gòu)為:
archive_test
├── dir1
│ └── file4
├── file1
├── file2
└── file
# CMakeLists.txt
file(ARCHIVE_CREATE OUTPUT result.tar.gz PATHS archive_test FORMAT gnutar COMPRESSION GZip VERBOSE MTIME "2022/5/18 23:59:59")
運(yùn)行結(jié)果,并生成了一個(gè)
result.tar.gz的壓縮包:
archive_test
archive_test/file3
archive_test/file2
archive_test/file1
archive_test/dir1
archive_test/dir1/file4
-
file(ARCHIVE_EXTRACT INPUT <archive> [DESTINATION <dir>] [PATTERNS <patterns>...] [LIST_ONLY] [VERBOSE])
說(shuō)明:
3.18版本新增。提取或者顯示歸檔文件的內(nèi)容。
DESTINATION:將歸檔文件提取到指定路徑。PATTERNS:通過(guò)該選項(xiàng),可以從歸檔文件中提取或者顯示指定的文件/目錄,支持通配符。LIST_ONLY:顯示歸檔文件內(nèi)容,不提取。VERBOSE:呈現(xiàn)提取歸檔文件命令的輸出。以歸檔的
result.tar.gz為例:
# CMakeLists.txt
message("====list========")
file(ARCHIVE_EXTRACT INPUT result.tar.gz VERBOSE LIST_ONLY) # 顯示歸檔文件內(nèi)容,不提取
message("====extract dir1/file4========")
file(ARCHIVE_EXTRACT INPUT result.tar.gz DESTINATION extract_dir1 PATTERNS "*dir1/*" VERBOSE) # 提取dir1目錄下文件到extract_dir1目錄
message("====extract all========")
file(ARCHIVE_EXTRACT INPUT result.tar.gz DESTINATION extract_dir2 VERBOSE) # 提取全部?jī)?nèi)容到extract_dir2目錄
運(yùn)行結(jié)果:
====list========
drwxr-xr-x 0 shengyi staff 0 18 May 23:59 archive_test/
-rw-r--r-- 0 shengyi staff 8 18 May 23:59 archive_test/file3
-rw-r--r-- 0 shengyi staff 8 18 May 23:59 archive_test/file2
-rw-r--r-- 0 shengyi staff 6 18 May 23:59 archive_test/file1
drwxr-xr-x 0 shengyi staff 0 18 May 23:59 archive_test/dir1/
-rw-r--r-- 0 shengyi staff 8 18 May 23:59 archive_test/dir1/file4
====extract dir1/file4========
x archive_test/dir1/
x archive_test/dir1/file4
====extract all========
x archive_test/
x archive_test/file3
x archive_test/file2
x archive_test/file1
x archive_test/dir1/
x archive_test/dir1/file4
extract_dir1目錄內(nèi)容:
extract_dir1
└── archive_test
└── dir1
└── file4
extract_dir2目錄內(nèi)容:
extract_dir2
└── archive_test
├── dir1
│ └── file4
├── file1
├── file2
└── file3