• CMake中file的使用


          CMake中的file命令用于文件操作,其文件格式如下:此命令专用于需要访问文件系统的文件和路径操作

    1. Reading
    2. file(READ
    3. [OFFSET ] [LIMIT ] [HEX])
    4. file(STRINGS [...])
    5. file( )
    6. file(TIMESTAMP [] [UTC])
    7. file(GET_RUNTIME_DEPENDENCIES
    8. [RESOLVED_DEPENDENCIES_VAR ]
    9. [UNRESOLVED_DEPENDENCIES_VAR ]
    10. [CONFLICTING_DEPENDENCIES_PREFIX ]
    11. [EXECUTABLES [...]]
    12. [LIBRARIES [...]]
    13. [MODULES [...]]
    14. [DIRECTORIES [...]]
    15. [BUNDLE_EXECUTABLE ]
    16. [PRE_INCLUDE_REGEXES [...]]
    17. [PRE_EXCLUDE_REGEXES [...]]
    18. [POST_INCLUDE_REGEXES [...]]
    19. [POST_EXCLUDE_REGEXES [...]]
    20. [POST_INCLUDE_FILES [...]]
    21. [POST_EXCLUDE_FILES [...]])
    22. Writing
    23. file({WRITE | APPEND} ...)
    24. file({TOUCH | TOUCH_NOCREATE} [...])
    25. file(GENERATE OUTPUT output-file
    26. [CONDITION expression] [TARGET target]
    27. [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS |
    28. FILE_PERMISSIONS ...]
    29. [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
    30. file(CONFIGURE OUTPUT output-file
    31. CONTENT content
    32. [ESCAPE_QUOTES] [@ONLY]
    33. [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])
    34. Filesystem
    35. file(GLOB
    36. [LIST_DIRECTORIES true|false] [RELATIVE ] [CONFIGURE_DEPENDS]
    37. [...])
    38. file(GLOB_RECURSE [FOLLOW_SYMLINKS]
    39. [LIST_DIRECTORIES true|false] [RELATIVE ] [CONFIGURE_DEPENDS]
    40. [...])
    41. file(MAKE_DIRECTORY [<dir>...])
    42. file({REMOVE | REMOVE_RECURSE } [...])
    43. file(RENAME
    44. [RESULT ]
    45. [NO_REPLACE])
    46. file(COPY_FILE
    47. [RESULT ]
    48. [ONLY_IF_DIFFERENT])
    49. file( ... DESTINATION <dir>
    50. [NO_SOURCE_PERMISSIONS | USE_SOURCE_PERMISSIONS]
    51. [FILE_PERMISSIONS ...]
    52. [DIRECTORY_PERMISSIONS ...]
    53. [FOLLOW_SYMLINK_CHAIN]
    54. [FILES_MATCHING]
    55. [[PATTERN | REGEX ]
    56. [EXCLUDE] [PERMISSIONS ...]] [...])
    57. file(SIZE )
    58. file(READ_SYMLINK )
    59. file(CREATE_LINK
    60. [RESULT ] [COPY_ON_ERROR] [SYMBOLIC])
    61. file(CHMOD ... ...
    62. [PERMISSIONS ...]
    63. [FILE_PERMISSIONS ...]
    64. [DIRECTORY_PERMISSIONS ...])
    65. file(CHMOD_RECURSE ... ...
    66. [PERMISSIONS ...]
    67. [FILE_PERMISSIONS ...]
    68. [DIRECTORY_PERMISSIONS ...])
    69. Path Conversion
    70. file(REAL_PATH [BASE_DIRECTORY <dir>] [EXPAND_TILDE])
    71. file(RELATIVE_PATH )
    72. file({TO_CMAKE_PATH | TO_NATIVE_PATH} )
    73. Transfer
    74. file(DOWNLOAD [] [...])
    75. file(UPLOAD [...])
    76. Locking
    77. file(LOCK [DIRECTORY] [RELEASE]
    78. [GUARD ]
    79. [RESULT_VARIABLE ]
    80. [TIMEOUT ])
    81. Archiving
    82. file(ARCHIVE_CREATE OUTPUT
    83. PATHS ...
    84. [FORMAT ]
    85. [COMPRESSION [COMPRESSION_LEVEL ]]
    86. [MTIME ]
    87. [VERBOSE])
    88. file(ARCHIVE_EXTRACT INPUT
    89. [DESTINATION <dir>]
    90. [PATTERNS ...]
    91. [LIST_ONLY]
    92. [VERBOSE]
    93. [TOUCH])

          1.Reading:
          (1).READ:从名为的文件中读取内容,并将其存储在中。可选项,从给定的开始,最多读取个字节。HEX选项将数据转换为十六进制表示。如果指定了HEX,则输出(a到f)中的字母均为小写。
          (2).STRINGS:解析中的ASCII字符串列表并将其存储在中。文件中的二进制数据被忽略。回车符(\r, CR)被忽略。选项包括:LENGTH_MAXIMUM,仅考虑不超过指定长度的字符串;类似的还包括LENGTH_MINIMUM, LIMIT_COUNT, LIMIT_INPUT, LIMIT_OUTPUT, NEWLINE_CONSUME, NO_HEX_CONVERSION, REGEX, ENCODING.
          (3).:计算内容的加密hash,并将其存储在中。支持的hash算法是string()命令中列出的名称。
          (4).TIMESTAMP:计算修改时间的字符串表示时间并将其存储在中。如果命令无法获得时间戳变量,则将其设置为空字符串("").选项和UTC参考string(TIMESTAMP)命令。
          (5).GET_RUNTIME_DEPENDENCIES:递归地获取给定文件所依赖的库列表。注意:此子命令不适用于project mode,它旨在install时使用。

    1. file(READ CMakeLists.txt var OFFSET 0 LIMIT 36)
    2. # Note:var结果输出中会有个空行
    3. message("var: ${var}") # var: cmake_minimum_required(VERSION 3.22)
    4. file(STRINGS CMakeLists.txt var)
    5. # Note:单行输出,行与行之间使用";"分开
    6. 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 ====")
    7. file(STRINGS CMakeLists.txt var LENGTH_MAXIMUM 5)
    8. # Note:长度超过5的字符串会使用";"分开,但是内容并不会减少
    9. 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; ====;")
    10. file(MD5 ../CMakeLists.txt var)
    11. message("var: ${var}") # var: 078ae43310e4d60a20915d00c9953713
    12. file(TIMESTAMP ../CMakeLists.txt var)
    13. message("var: ${var}") # var: 2022-10-26T10:24:59
    14. file(TIMESTAMP ../CMakeLists.txt var %B:%U UTC)
    15. message("var: ${var}") # var: October:43

          2.Writing:
          (1).WRITE,APPEND:写入名为的文件。如果该文件不存在则会创建它。如果文件已经存在,WRITE模式将覆盖它,APPEND模式将追加到末尾。指定的路径中不存在的所有目录都将被创建。
          (2).TOUCH,TOUCH_NOCREATE:如果不存在,则创建一个不包含任何内容的。如果已经存在,那么它的访问和/或修改将更新到函数调用被执行的时间
          如果存在,则使用TOUCH_NOCREATE来touch它,但不创建它。如果不存在,它将被忽略。
          使用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。

    1. file(WRITE tmp.txt "csdn addr: https://blog.csdn.net/fengbingchun")
    2. file(APPEND tmp.txt "github addr: https://github.com/fengbingchun")
    3. file(READ tmp.txt var)
    4. message("var: ${var}") # var: csdn addr: https://blog.csdn.net/fengbingchungithub addr: https://github.com/fengbingchun
    5. file(TOUCH_NOCREATE CMakeLists.txt)
    6. file(TIMESTAMP ../CMakeLists.txt var)
    7. 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:
          如果指定了RESULT,成功时将设置为0,否则设置为错误消息。如果未指定RESULT且此操作失败,则会触发error.
          如果指定了NO_REPLACE,如果路径已经存在则不会替换它。如果指定了RESULT,则将设置为NO_REPLACE,否则将触发error.
          (5).COPY_FILE:将文件从拷贝到不支持目录拷贝。符号链接被忽略,的内容作为一个新文件被读取和写入到
          选项包括RESULT和ONLY_IF_DIFFERENT:
          如果指定了RESULT,成功时将设置为0,否则设置为错误消息。如果未指定RESULT且此操作失败,则会触发error.
          如果指定了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:查询符号链接并将其指向的路径存储在中。如果不存在或不是符号链接,CMake会触发fatal error.
          注意:该命令返回的是原始的符号链接路径,而不是相对路径。
          (9).CREATE_LINK:创建指向的链接。默认情况下,它将是硬链接(hard link),但是提供SYMBOLIC选项会导致符号链接。硬链接要求存在并且是文件而不是目录。如果已经存在,它将被覆盖。
          如果指定了RESULT,成功时将设置为0,否则设置为错误消息。如果未指定RESULT且此操作失败,则会触发error.
          (10).CHMOD:指定权限。有效权限有OWNER_READ,OWNER_WRITE, OWNER_EXECUTE, GROUP_READ, GROUP_WRITE, GROUP_EXECUTE, WORLD_READ, WORLD_WRITE, WORLD_EXECUTE, SETUID, SETGID.
          (11).CHMOD_RECURSE:与CHMOD相同,但是递归更改中存在的文件和目录的权限。

    1. file(GLOB var *.txt)
    2. 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
    3. file(GLOB var RELATIVE /home/spring/GitHub/ *.txt )
    4. message("var: ${var}") # var: Linux_Code_Test/Samples_CMake/messy_usage/CMakeLists.txt;Linux_Code_Test/Samples_CMake/messy_usage/tmp.txt
    5. # Note:LIST_DIRECTORIES的设置好像没有生效??
    6. file(GLOB var LIST_DIRECTORIES false *.txt )
    7. 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
    8. file(MAKE_DIRECTORY tmp1/tmp2)
    9. file(REMOVE_RECURSE tmp1/tmp2)
    10. file(REMOVE_RECURSE build/tmp2)
    11. file(RENAME tmp1 build/tmp2 RESULT result)
    12. message("result: ${result}") # result: 0
    13. file(COPY_FILE CMakeLists.txt build/tmp.txt RESULT result)
    14. message("result: ${result}") # result: 0
    15. file(COPY ../complex_usage ../special_usage DESTINATION .)
    16. file(INSTALL ../multi_executable_file DESTINATION .) # -- Installing: /home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage/build/./multi_executable_file
    17. file(SIZE ../CMakeLists.txt var)
    18. message("var: ${var}") # var: 250
    19. set(linkname "/usr/bin/gcc")
    20. file(READ_SYMLINK ${linkname} var)
    21. message("var: ${var}") # var: gcc-11
    22. if(NOT IS_ABSOLUTE "${ver}")
    23. get_filename_component(dir ${linkname} DIRECTORY)
    24. set(result ${dir}/${var})
    25. endif()
    26. message("result: ${result}") # result: /usr/bin/gcc-11
    27. file(CREATE_LINK build.sh tmp3 RESULT result SYMBOLIC)
    28. message("result: ${result}") # result: failed to create symbolic link 'tmp3': Operation not permitted ????
    29. file(CHMOD tmp.txt FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE) # build/tmp.txt

          4.Path Conversion:
          (1).REAL_PATH:计算现有文件或目录的绝对路径,并解析符号链接。
          如果指定了BASE_DIRECTORY,如果提供的是相对路径,则会相对于给定的基本目录

    进行评估。如果没有提供基本目录,则默认基本目录将为CMAKE_CURRENT_SOURCE_DIR。
          如果指定了EXPAND_TILDE,如果是~或以~/开头,~将替换为用户的主目录(home directory)。主目录的路径是从环境变量中获得的。
          (2).RELATIVE_PATH:计算从的相对路径,并将其存储在中。
          (3).TO_CMAKE_PATH:将native 转换为正斜杠(/)的cmake-style路径。
          TO_NATIVE_PATH:将cmake-style 转换为带有特定平台斜杠(在Windows上为\,其它平台为/)的native路径。
          始终在周围使用双引号,以确保它被视为该命令的单个参数

    1. file(REAL_PATH build.sh var)
    2. message("var: ${var}") # var: /home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage/build.sh
    3. file(REAL_PATH gcc var BASE_DIRECTORY /usr/bin)
    4. message("var: ${var}") # var: /usr/bin/x86_64-linux-gnu-gcc-11
    5. file(RELATIVE_PATH var ${CMAKE_CURRENT_SOURCE_DIR} /usr/bin/gcc)
    6. message("var: ${var}") # var: ../../../../../../usr/bin/gcc
    7. file(TO_CMAKE_PATH "/usr/bin/cmake" var)
    8. 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.

    1. file(DOWNLOAD https://github.com/fengbingchun/Linux_Code_Test/blob/master/Samples_CMake/messy_usage/CMakeLists.txt cmakelists.txt
    2. LOG var STATUS var2) # cmakelists.txt保存到build目录下
    3. message("var: ${var}") # var: Trying 20.205.243.166:443...
    4. # Connected to github.com (20.205.243.166) port 443 (#0)
    5. message("var2: ${var2}") # var2: 0;"No error"

          6.Locking:如果不存在DIRECTORY选项,则锁定由指定的文件,否则锁定/cmake.lock文件。
          注意:锁是建议性的,不能保证其它进程也会尊重此锁。不允许尝试两次锁定文件。

    1. file(LOCK build DIRECTORY RESULT_VARIABLE var) # build目录下会生成cmake.lock文件
    2. message("var: ${var}") # var: 0

          7.Archiving:
          (1).ARCHIVE_CREATE:中列出的文件和目录创建指定的文件。注意:必须列出实际文件或目录,不支持通配符(wildcards).
          FORMAT选项支持的格式有7zip, gnutar, pax, paxr, raw和zip。如果没有指定FORMAT,则默认格式为paxr。
          VERBOSE选项为存档操作启用详细输出。
          (2).ARCHIVE_EXTRACT:提取或列出指定的的内容。可以使用DESTINATION选项指定将存档(archive)内容提取到的目录。如果目录不存在,将创建该目录。如果未给出DESTINATION,将使用当前的二进制目录。
          如果需要,可以使用指定的选择要从存档中列出和提取的文件和目录。支持通配符。如果未给出PATTERNS,则将列出或提取整个存档。
          LIST_ONLY将列出存档中的文件,而不是提取它们。
          TOUCH选项为提取的文件提供当前本地时间戳,而不是从存档中提取文件时间戳。
          使用VERBOSE,该命令将产生详细输出。

    1. file(ARCHIVE_CREATE OUTPUT tmp.zip PATHS ../CMakeLists.txt FORMAT zip VERBOSE) # 在build目录下生成tmp.zip
    2. file(ARCHIVE_EXTRACT INPUT tmp.zip DESTINATION xxxx VERBOSE) # 在build目录下解析tmp.zip,但是在build/xxxx目录下并不存在CMakeLists.txt ????
    3. 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内容如下:

    1. #! /bin/bash
    2. # supported input parameters(cmake commands)
    3. params=(function macro cmake_parse_arguments \
    4. find_library find_path find_file find_program find_package \
    5. cmake_policy cmake_minimum_required project include \
    6. string list set foreach message option if while return \
    7. math file configure_file \
    8. include_directories)
    9. usage()
    10. {
    11. echo "Error: $0 needs to have an input parameter"
    12. echo "supported input parameters:"
    13. for param in ${params[@]}; do
    14. echo " $0 ${param}"
    15. done
    16. exit -1
    17. }
    18. if [ $# != 1 ]; then
    19. usage
    20. fi
    21. flag=0
    22. for param in ${params[@]}; do
    23. if [ $1 == ${param} ]; then
    24. flag=1
    25. break
    26. fi
    27. done
    28. if [ ${flag} == 0 ]; then
    29. echo "Error: parameter \"$1\" is not supported"
    30. usage
    31. exit -1
    32. fi
    33. if [[ ! -d "build" ]]; then
    34. mkdir build
    35. cd build
    36. else
    37. cd build
    38. fi
    39. echo "==== test $1 ===="
    40. # test_set.cmake: cmake -DTEST_CMAKE_FEATURE=$1 --log-level=verbose ..
    41. # test_option.cmake: cmake -DTEST_CMAKE_FEATURE=$1 -DBUILD_PYTORCH=ON ..
    42. cmake -DTEST_CMAKE_FEATURE=$1 ..
    43. # It can be executed directly on the terminal, no need to execute build.sh, for example: cmake -P test_set.cmake
    44. make

          CMakeLists.txt内容如下:

    1. cmake_minimum_required(VERSION 3.22)
    2. project(cmake_feature_usage)
    3. message("#### current cmake version: ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}")
    4. include(test_${TEST_CMAKE_FEATURE}.cmake)
    5. message("==== test finish ====")

          test_file.cmake:为上面的所有示例代码

          可能的执行结果如下图所示:

          GitHubhttps://github.com/fengbingchun/Linux_Code_Test

  • 相关阅读:
    [入门到吐槽系列] Webix 10分钟入门 二 表单Form的使用
    java毕业设计项目源代码CRM客户关系管理系统
    苹果召开WWDC:属于你的“定制”AI智能?
    GEE:提取一个小区域影像的所有波段像素值到csv
    【英语语法】 yet
    在Linux上安装redis7
    【贪心训练】挑剔的美食家
    K8S二进制安装与部署
    smqtt:高性能开源MQTT消息代理Broker
    jquery常用方法积累
  • 原文地址:https://blog.csdn.net/fengbingchun/article/details/128051242