CMake中的file命令用于文件操作,其文件格式如下:此命令专用于需要访问文件系统的文件和路径操作
- Reading
- file(READ
- [OFFSET
] [LIMIT ] [HEX]) - file(STRINGS
[...]) - file(
) - file(TIMESTAMP
[] [UTC]) - file(GET_RUNTIME_DEPENDENCIES
- [RESOLVED_DEPENDENCIES_VAR
] - [UNRESOLVED_DEPENDENCIES_VAR
] - [CONFLICTING_DEPENDENCIES_PREFIX
] - [EXECUTABLES [
...]] - [LIBRARIES [
...]] - [MODULES [
...]] - [DIRECTORIES [
...]] - [BUNDLE_EXECUTABLE
] - [PRE_INCLUDE_REGEXES [
...]] - [PRE_EXCLUDE_REGEXES [
...]] - [POST_INCLUDE_REGEXES [
...]] - [POST_EXCLUDE_REGEXES [
...]] - [POST_INCLUDE_FILES [
...]] - [POST_EXCLUDE_FILES [
...]]) -
- Writing
- file({WRITE | APPEND}
...) - file({TOUCH | TOUCH_NOCREATE} [
...]) - file(GENERATE OUTPUT output-file
-
- [CONDITION expression] [TARGET target]
- [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS |
- FILE_PERMISSIONS
...] - [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
- file(CONFIGURE OUTPUT output-file
- CONTENT content
- [ESCAPE_QUOTES] [@ONLY]
- [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
-
- Filesystem
- file(GLOB
- [LIST_DIRECTORIES true|false] [RELATIVE
] [CONFIGURE_DEPENDS] - [
...]) - file(GLOB_RECURSE
[FOLLOW_SYMLINKS] - [LIST_DIRECTORIES true|false] [RELATIVE
] [CONFIGURE_DEPENDS] - [
...]) - file(MAKE_DIRECTORY [<dir>...])
- file({REMOVE | REMOVE_RECURSE } [
...]) - file(RENAME
- [RESULT
] - [NO_REPLACE])
- file(COPY_FILE
- [RESULT
] - [ONLY_IF_DIFFERENT])
- file(
... DESTINATION <dir> - [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS]
- [FILE_PERMISSIONS
...] - [DIRECTORY_PERMISSIONS
...] - [FOLLOW_SYMLINK_CHAIN]
- [FILES_MATCHING]
- [[PATTERN
| REGEX ] - [EXCLUDE] [PERMISSIONS
...]] [...]) - file(SIZE
) - file(READ_SYMLINK
) - file(CREATE_LINK
- [RESULT
] [COPY_ON_ERROR] [SYMBOLIC]) - file(CHMOD
... ... - [PERMISSIONS
...] - [FILE_PERMISSIONS
...] - [DIRECTORY_PERMISSIONS
...]) - file(CHMOD_RECURSE
... ... - [PERMISSIONS
...] - [FILE_PERMISSIONS
...] - [DIRECTORY_PERMISSIONS
...]) -
- Path Conversion
- file(REAL_PATH
[BASE_DIRECTORY <dir>] [EXPAND_TILDE]) - file(RELATIVE_PATH
) - file({TO_CMAKE_PATH | TO_NATIVE_PATH}
) -
- Transfer
- file(DOWNLOAD
[] [...]) - file(UPLOAD
[...]) -
- Locking
- file(LOCK
[DIRECTORY] [RELEASE] - [GUARD
] - [RESULT_VARIABLE
] - [TIMEOUT
]) -
- Archiving
- file(ARCHIVE_CREATE OUTPUT
- PATHS
... - [FORMAT
] - [COMPRESSION
[COMPRESSION_LEVEL ]] - [MTIME
] - [VERBOSE])
- file(ARCHIVE_EXTRACT INPUT
- [DESTINATION <dir>]
- [PATTERNS
...] - [LIST_ONLY]
- [VERBOSE]
- [TOUCH])
1.Reading:
(1).READ:从名为
(2).STRINGS:解析
(3).
(4).TIMESTAMP:计算
(5).GET_RUNTIME_DEPENDENCIES:递归地获取给定文件所依赖的库列表。注意:此子命令不适用于project mode,它旨在install时使用。
- file(READ CMakeLists.txt var OFFSET 0 LIMIT 36)
- # Note:var结果输出中会有个空行
- message("var: ${var}") # var: cmake_minimum_required(VERSION 3.22)
-
- file(STRINGS CMakeLists.txt var)
- # Note:单行输出,行与行之间使用";"分开
- message("var: ${var}") # var: cmake_minimum_required(VERSION 3.22);project(cmake_feature_usage);;message("#### current cmake version: ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}");include(test_${TEST_CMAKE_FEATURE}.cmake);message("==== test finish ====")
- file(STRINGS CMakeLists.txt var LENGTH_MAXIMUM 5)
- # Note:长度超过5的字符串会使用";"分开,但是内容并不会减少
- message("var: ${var}") # var: cmake;_mini;mum_r;equir;ed(VE;RSION; 3.22;);proje;ct(cm;ake_f;eatur;e_usa;ge);;messa;ge("#;### c;urren;t cma;ke ve;rsion;: ${C;MAKE_;MAJOR;_VERS;ION}.;${CMA;KE_MI;NOR_V;ERSIO;N}.${;CMAKE;_PATC;H_VER;SION};");inclu;de(te;st_${;TEST_;CMAKE;_FEAT;URE}.;cmake;);messa;ge("=;=== t;est f;inish; ====;")
-
- file(MD5 ../CMakeLists.txt var)
- message("var: ${var}") # var: 078ae43310e4d60a20915d00c9953713
-
- file(TIMESTAMP ../CMakeLists.txt var)
- message("var: ${var}") # var: 2022-10-26T10:24:59
- file(TIMESTAMP ../CMakeLists.txt var %B:%U UTC)
- message("var: ${var}") # var: October:43
2.Writing:
(1).WRITE,APPEND:将
(2).TOUCH,TOUCH_NOCREATE:如果
如果存在
使用TOUCH和TOUCH_NOCREATE将不会修改现有文件的内容。
(3).GENERATE:为当前CMake Generator支持的每个构建配置(build configuration)生成一个输出文件。根据输入内容评估generator expressions,以生成输出内容。
注意:file(GENERATE)直到生成阶段(generation phase)才创建输出文件。当file(GENERATE)命令返回时,尚未写入输出文件,仅在处理了project的所有CMakeLists.txt文件后才写入输入文件。
(4).CONFIGURE:使用CONTENT给出的输入生成一个输出文件,并替换其中包含的@VAR@或${VAR}变量值。替换规则的行为与configure_file命令相同。为了匹配configure_file的行为,OUTPUT和CONTENT都不支持generator expressions。
- file(WRITE tmp.txt "csdn addr: https://blog.csdn.net/fengbingchun")
- file(APPEND tmp.txt "github addr: https://github.com/fengbingchun")
- file(READ tmp.txt var)
- message("var: ${var}") # var: csdn addr: https://blog.csdn.net/fengbingchungithub addr: https://github.com/fengbingchun
-
- file(TOUCH_NOCREATE CMakeLists.txt)
- file(TIMESTAMP ../CMakeLists.txt var)
- message("var: ${var}") # var: 2022-11-21T14:42:05
3.Filesystem:
(1).GLOB,GLOB_RECURSE:生成与
如果指定了RELATIVE标志,则结果将作为给定路径的相对路径返回。
默认情况下,GLOB列出目录(lists directories),如果LIST_DIRECTORIES设置为false,则目录将被省略。
注意:不建议使用GLOB从源树(source tree)中收集源文件列表。如果在添加或删除源时没有CMakeLists.txt文件更改,则生成的构建系统将不知道何时要求CMake重新生成。
GLOB_RECURSE模式将遍历匹配目录下的所有子目录和匹配的文件。只有在给出FOLLOW_SYMLINKS或策略CMP0009没有设置为NEW时,才会遍历符号链接(symlink)的子目录。
(2).MAKE_DIRECTORY:根据需要创建给定的目录及其父目录。
(3).REMOVE,REMOVE_RECURSE:删除给定的文件。REMOVE_RECURSE模式将删除给定的文件和目录,以及非空目录。如果给定的文件不存在,不会触发error。相对输入路径是相对于当前源目录进行评估的(evaluated)。
(4).RENAME:将文件系统中的文件或目录从
如果指定了RESULT,成功时将
如果指定了NO_REPLACE,如果
(5).COPY_FILE:将文件从
选项包括RESULT和ONLY_IF_DIFFERENT:
如果指定了RESULT,成功时将
如果指定了ONLY_IF_DIFFERENT,如果
此子命令与带有COPYONLY选项的configure_file命令有一些相似之处。一个重要的区别是configure_file创建了对源文件的依赖,因此如果CMake发生更改,它将重新运行。file(COPY_FILE)子命令不会创建这样的依赖。
(6).COPY,INSTALL:COPY签名将文件、目录和符号链接拷贝到目标文件夹。相对输入路径是相对于当前源目录进行评估的(evaluated),相对目标路径是相对于当前构建目录进行评估的。拷贝保留输入文件的时间戳,如果文件存在于具有相同时间戳的目标位置,则优化该文件。拷贝保留输入权限,除非给出明确的权限或NO_SOURCE_PERMISSIONS(默认为USE_SOURCE_PERMISSIONS)。
如果指定了FOLLOW_SYMLINK_CHAIN,COPY将在给定的路径上递归解析符号链接,直到找到真正的文件,并在目标位置为遇到的每个符号链接安装相应的符号链接。此功能在某些Unix系统上非常有用。
有关权限、FILES_MATCHING, PATTERN, REGEX和EXCLUDE选项,可参考install(DIRECTORY)命令。
INSTALL签名与COPY签名稍有不同:它打印状态信息,并且NO_SOURCE_PERMISSIONS是默认值。
环境变量CMAKE_INSTALL_MODE可以覆盖file(INSTALL)的默认拷贝行为。
(7).SIZE:确定
(8).READ_SYMLINK:查询符号链接
注意:该命令返回的是原始的符号链接路径,而不是相对路径。
(9).CREATE_LINK:创建指向
如果指定了RESULT,成功时将
(10).CHMOD:为
(11).CHMOD_RECURSE:与CHMOD相同,但是递归更改
- file(GLOB var *.txt)
- message("var: ${var}") # var: /home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage/CMakeLists.txt;/home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage/tmp.txt
-
- file(GLOB var RELATIVE /home/spring/GitHub/ *.txt )
- message("var: ${var}") # var: Linux_Code_Test/Samples_CMake/messy_usage/CMakeLists.txt;Linux_Code_Test/Samples_CMake/messy_usage/tmp.txt
-
- # Note:LIST_DIRECTORIES的设置好像没有生效??
- file(GLOB var LIST_DIRECTORIES false *.txt )
- message("var: ${var}") # var: /home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage/CMakeLists.txt;/home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage/tmp.txt
-
- file(MAKE_DIRECTORY tmp1/tmp2)
- file(REMOVE_RECURSE tmp1/tmp2)
-
- file(REMOVE_RECURSE build/tmp2)
- file(RENAME tmp1 build/tmp2 RESULT result)
- message("result: ${result}") # result: 0
-
- file(COPY_FILE CMakeLists.txt build/tmp.txt RESULT result)
- message("result: ${result}") # result: 0
-
- file(COPY ../complex_usage ../special_usage DESTINATION .)
- file(INSTALL ../multi_executable_file DESTINATION .) # -- Installing: /home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage/build/./multi_executable_file
-
- file(SIZE ../CMakeLists.txt var)
- message("var: ${var}") # var: 250
-
- set(linkname "/usr/bin/gcc")
- file(READ_SYMLINK ${linkname} var)
- message("var: ${var}") # var: gcc-11
- if(NOT IS_ABSOLUTE "${ver}")
- get_filename_component(dir ${linkname} DIRECTORY)
- set(result ${dir}/${var})
- endif()
- message("result: ${result}") # result: /usr/bin/gcc-11
-
- file(CREATE_LINK build.sh tmp3 RESULT result SYMBOLIC)
- message("result: ${result}") # result: failed to create symbolic link 'tmp3': Operation not permitted ????
-
- file(CHMOD tmp.txt FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE) # build/tmp.txt
4.Path Conversion:
(1).REAL_PATH:计算现有文件或目录的绝对路径,并解析符号链接。
如果指定了BASE_DIRECTORY,如果提供的
如果指定了EXPAND_TILDE,如果
(2).RELATIVE_PATH:计算从
(3).TO_CMAKE_PATH:将native
TO_NATIVE_PATH:将cmake-style
始终在
- file(REAL_PATH build.sh var)
- message("var: ${var}") # var: /home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage/build.sh
- file(REAL_PATH gcc var BASE_DIRECTORY /usr/bin)
- message("var: ${var}") # var: /usr/bin/x86_64-linux-gnu-gcc-11
-
- file(RELATIVE_PATH var ${CMAKE_CURRENT_SOURCE_DIR} /usr/bin/gcc)
- message("var: ${var}") # var: ../../../../../../usr/bin/gcc
-
- file(TO_CMAKE_PATH "/usr/bin/cmake" var)
- message("var: ${var}") # var: /usr/bin/cmake
5.Transfer:
(1).DOWNLOAD:下载指定的
(2).UPLOAD:上传本地的
如果未为file(DOWNLOAD)指定
DOWNLOAD和UPLOAD选项有:INACTIVITY_TIMEOUT, LOG, SHOW_PROGRESS, STATUS, TIMEOUT, USERPWD, HTTPHEADER, NETRC, NETRC_FILE, TLS_VERIFY, TLS_CAINFO.
DOWNLOAD的其它选项还包括:EXPECTED_HASH, EXPECTED_MD5, RANGE_START, RANGE_END.
- file(DOWNLOAD https://github.com/fengbingchun/Linux_Code_Test/blob/master/Samples_CMake/messy_usage/CMakeLists.txt cmakelists.txt
- LOG var STATUS var2) # cmakelists.txt保存到build目录下
- message("var: ${var}") # var: Trying 20.205.243.166:443...
- # Connected to github.com (20.205.243.166) port 443 (#0)
- message("var2: ${var2}") # var2: 0;"No error"
6.Locking:如果不存在DIRECTORY选项,则锁定由
注意:锁是建议性的,不能保证其它进程也会尊重此锁。不允许尝试两次锁定文件。
- file(LOCK build DIRECTORY RESULT_VARIABLE var) # build目录下会生成cmake.lock文件
- message("var: ${var}") # var: 0
7.Archiving:
(1).ARCHIVE_CREATE:用
FORMAT选项支持的格式有7zip, gnutar, pax, paxr, raw和zip。如果没有指定FORMAT,则默认格式为paxr。
VERBOSE选项为存档操作启用详细输出。
(2).ARCHIVE_EXTRACT:提取或列出指定的
如果需要,可以使用指定的
LIST_ONLY将列出存档中的文件,而不是提取它们。
TOUCH选项为提取的文件提供当前本地时间戳,而不是从存档中提取文件时间戳。
使用VERBOSE,该命令将产生详细输出。
- file(ARCHIVE_CREATE OUTPUT tmp.zip PATHS ../CMakeLists.txt FORMAT zip VERBOSE) # 在build目录下生成tmp.zip
- file(ARCHIVE_EXTRACT INPUT tmp.zip DESTINATION xxxx VERBOSE) # 在build目录下解析tmp.zip,但是在build/xxxx目录下并不存在CMakeLists.txt ????
- file(ARCHIVE_EXTRACT INPUT tmp.zip LIST_ONLY VERBOSE) # -rw-r--r-- 0 0 0 250 21 Nov 14:42 ../CMakeLists.txt
执行上述测试代码需要3个文件:build.sh, CMakeLists.txt, test_file.cmake
build.sh内容如下:
- #! /bin/bash
-
- # supported input parameters(cmake commands)
- params=(function macro cmake_parse_arguments \
- find_library find_path find_file find_program find_package \
- cmake_policy cmake_minimum_required project include \
- string list set foreach message option if while return \
- math file configure_file \
- include_directories)
-
- usage()
- {
- echo "Error: $0 needs to have an input parameter"
-
- echo "supported input parameters:"
- for param in ${params[@]}; do
- echo " $0 ${param}"
- done
-
- exit -1
- }
-
- if [ $# != 1 ]; then
- usage
- fi
-
- flag=0
- for param in ${params[@]}; do
- if [ $1 == ${param} ]; then
- flag=1
- break
- fi
- done
-
- if [ ${flag} == 0 ]; then
- echo "Error: parameter \"$1\" is not supported"
- usage
- exit -1
- fi
-
- if [[ ! -d "build" ]]; then
- mkdir build
- cd build
- else
- cd build
- fi
-
- echo "==== test $1 ===="
-
- # test_set.cmake: cmake -DTEST_CMAKE_FEATURE=$1 --log-level=verbose ..
- # test_option.cmake: cmake -DTEST_CMAKE_FEATURE=$1 -DBUILD_PYTORCH=ON ..
- cmake -DTEST_CMAKE_FEATURE=$1 ..
- # It can be executed directly on the terminal, no need to execute build.sh, for example: cmake -P test_set.cmake
- make
CMakeLists.txt内容如下:
- cmake_minimum_required(VERSION 3.22)
- project(cmake_feature_usage)
-
- message("#### current cmake version: ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}")
- include(test_${TEST_CMAKE_FEATURE}.cmake)
- message("==== test finish ====")
test_file.cmake:为上面的所有示例代码
可能的执行结果如下图所示:
