rbaleksandar
rbaleksandar

Reputation: 9701

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

I am gathering all license files for the git submodules of my project that are inside a child directory to my project's root directory. From my experience a license file is normally called LICENSE or COPYRIGHT but ultimately I will just add a list of file names to look for.

I am facing a problem with one of the libraries, which has a different name for its license file namely COPYING and not LICENSE (which will be handled eventually with the list I have mentioned above) but what's more important is that it has a directory called RELICENSES, which has nothing to do with license files. Needless to say for this dependency my function fails with and error that it's unable to read it (permission denied) as a text file.

Here is my CMake function:

# 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()

I know the function is not perfect but I am looking into solving the particular problem mentioned in the question - how do I check if a string is a path to a file (not directory!). If I can do that, I can skip a lot of the processing by just dismissing an entry from my list of items found inside the directory if it's not an file (I will not handle the case where a file LICENSE is weird such as an executable).

Upvotes: 1

Views: 1148

Answers (1)

petwu
petwu

Reputation: 281

You could call file(GLOB) with the optional LIST_DIRECTORIES false parameter:

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

Or use if(IS_DIRECTORY):

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

Upvotes: 2

Related Questions