CMake check that a local file exists

FileCmakeFile Exists

File Problem Overview


In my CMake script I want to see if I have a file on my system, and if it is there do something with it, otherwise do something with a default file. Here is the code:

find_file(
          ${project_name}_${customer}_config 
          ${ROOT}/configuration/${customer}/configuration.${project_name}.xml
)

if(NOT ${${project_name}_${customer}_config} STREQUAL
   ${project_name}_${customer}_config-NOTFOUND )
        configure_file(${ROOT}/configuration/${customer}/configuration.${project_name}.xml
                       ${CMAKE_CURRENT_BINARY_DIR}/conf/configuration.xml)
else()
    configure_file(${FAPP_ROOT}/configuration/Default/configuration.${project_name}.xml
                   ${CMAKE_CURRENT_BINARY_DIR}/conf/configuration.xml)
endif()

But it seems, this is not working.

What is the proper way of checking if a file exists in CMake?

File Solutions


Solution 1 - File

The proper way to check if a file exists, if you already know the full path name to the file is simply:

if(EXISTS "${ROOT}/configuration/${customer}/configuration.${project_name}.xml")
   ...
else()
   ...
endif()

Solution 2 - File

You should be able to just use

if(NOT ${project_name}_${customer}_config)

From the docs:

> if(<constant>) > True if the constant is 1, ON, YES, TRUE, Y, or a non-zero number. False if the constant is 0, OFF, NO, FALSE, N, IGNORE, "", or ends in the suffix '-NOTFOUND'.

However, if the file is found using find_file, the value is cached, and subsequent runs of CMake will not try to find it again. To force a recheck on every run, before the find_file call do:

unset(${project_name}_${customer}_config CACHE)

Solution 3 - File

I believe the if (EXISTS <path>) is a good solution. I'd like to share a scenario I recently encountered, though you probably won't care about this scenario in most cases.

Please note, this solution will not return true if the file is not accessible by the effective user. The file does exist, but it's just not readable.

A workaround for this scenario if you do care about whether the file really exists or not, is to call execute_process(COMMAND ls /dev/fb0 RESULT_VARIABLE result OUTPUT_QUIET ERROR_QUIET) and then check the result like this:

if (result)
    message("/dev/fb0 doesn't exist.")
endif()

edit: add ERROR_QUIET in execute_process or you will get error messages from ls when the file does not exist.

Solution 4 - File

From Condition Syntax docs:

> if(EXISTS path-to-file-or-directory) > >True if the named file or directory exists. Behavior is well-defined only for full paths. Resolves symbolic links, i.e. if the named file or directory is a symbolic link, returns true if the target of the symbolic link exists.

If the file you are looking for is located within the current cmakelist-file, then one solution could be:

if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE_WORKING_ON}) ...

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFerenc DeakView Question on Stackoverflow
Solution 1 - FileDLRdaveView Answer on Stackoverflow
Solution 2 - FileFraserView Answer on Stackoverflow
Solution 3 - FileZHANG ZikaiView Answer on Stackoverflow
Solution 4 - FileMujtaba AldebesView Answer on Stackoverflow