CMake - 如何检查字符串是否为文件路径?

CMake - How to check if string is a file path?

我正在为项目的 git 子模块收集所有许可文件,这些文件位于项目根目录的子目录中。根据我的经验,许可证文件通常称为 LICENSE 或 COPYRIGHT,但最终我只会添加要查找的文件名列表。

我遇到了其中一个库的问题,它的许可文件名称不同,即 COPYING 而不是 LICENSE (最终将用我上面提到的列表处理)但更重要的是它有一个名为 RELICENSESdirectory,它什么都没有与许可证文件有关。不用说,对于这种依赖性,我的函数失败并出现无法将其作为文本文件读取(权限被拒绝)的错误。

这是我的 CMake 函数:

# extract_deps_licenses
# For a given directory (root directory for all dependencies) the function will look
# into ONLY the first level of each subdirectory (meaning non-recursive behaviour) and
# look for a license text file. If it finds one, its contents will be read and copyied
# into the provided target license file thus generatng a single license file for all 
# dependencies
# Currently looks for a license file containing the word "LICENSE" (not case-sensitive!)
# Special cases such as a license file not being a text file (e.g. executable) will lead 
# to exiting with error
#
# @param root_dir Root directory for all dependencies
# @param dest_license Path to license file that will be populated
#
# TODO For the future a third argument of type list will be provided. The list will contain
# possible names  for license files incl. COPYING, COPYRIGHT etc.
function(extract_deps_licenses root_dir dest_license)
    message("Retrieving git submodule status for dependencies")
    execute_process(
        COMMAND ${GIT_EXECUTABLE} submodule status
        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
        RESULT_VARIABLE deps_git_exit_code
        OUTPUT_VARIABLE deps_git_status
    )

    file(APPEND
        "${dest_license}"
        "\nGit information:\n"
        "\n${deps_git_status}\n"
    )

    # Get all directories under root_dir without recursion (subdirectories will not be traversed)
    file(GLOB dep_dirs "${root_dir}/*" DIRECTORY)
    foreach(dep_dir ${dep_dirs})
        # Get all but the last directory
        string(REGEX MATCH ".*\/" dep_parent_dirs ${dep_dir})
        # Get the last directory by excluding everything else
        # This leaves the dependency directory name, which will be used later
        string(REGEX REPLACE ${dep_parent_dirs} "" dep_name ${dep_dir})
        string(TOUPPER ${dep_name} dep_name)
        message("Found dependency ${dep_name} in \"${dep_dir}\"")

        # Get all items inside 
        file(GLOB paths "${dep_dir}/*")
        message("Looking for license file (non-recursive)")
        foreach(path_license ${paths})
            #get_filename_component(fname ${item} NAME_WE)
            string(TOUPPER "${path_license}" path_up)
            
            # Check if full path contains LICENSE
            # Will not work if LICENSE is a directory!
            string(REGEX MATCH "LICENSE" match ${path_up})

            # Exclude prefixes and suffixes for name of license file
            # directory that has nothing to do with license file)
            # Skip if path does not include LICENSE
            # FIXME Check if match is a file and not directory
            if((NOT match))# OR (NOT path_license FILE)) # <-------------------- CHECK IF A FILE HERE!!!
                continue()
            endif()

            set(license_path ${path_license})
            message("Found license \"${license_path}\"")

            # Read license text and append to full license text
            message("Copying license text to final license file at '${license_path}'")
            file(READ ${license_path} license_content)
            file(APPEND
                "${dest_license}"
                "\n${dep_name}\n\n"
                "${license_content}"
                "\n-----------------------------------------------------------------------------------------------------------\n"
            )
        endforeach()
    endforeach()

我知道该功能并不完美,但我正在研究解决问题中提到的特定问题 - 如何检查字符串是否是文件(而非目录!)的路径。如果我能做到这一点,如果它不是文件,我可以通过从我在目录中找到的项目列表中删除一个条目来跳过很多处理(我不会处理文件 LICENSE 很奇怪的情况,例如可执行文件).

您可以使用可选的 LIST_DIRECTORIES false 参数调用 file(GLOB)

file(GLOB paths LIST_DIRECTORIES false "${dep_dir}/*")

或使用if(IS_DIRECTORY):

if((NOT match) OR IS_DIRECTORY "${path_license}")
  continue()
endif()