How to check whether a source file exists, even if generated?

Is there a way to check whether a file exists either on disk or as a GENERATED file? Calling get_source_file_properties on a non-existent file without a custom command defined for it results in a fatal error.

If you’re talking about the file(GENERATE) command, I don’t think there’s a way to tell what files will be generated.

For files generated during cmake configuration, you can use if (EXISTS) just like any other file, but you need to know its absolute path.

What are you trying to do here? There may be another way (I smell an XY problem here).

1 Like

@benthevining What are you saying here? I am unable to understand what you are talking about.

For normal files, you can just do:

if (EXISTS "${path_to_files}")
  ...
else()
  ...
endif()

However, there is also a file(GENERATE) command which creates files specific to each build configuration. These files are written at the end of CMake’s processing, when it actually outputs the buildsystem, so if you were to use the above method to check if they exist during the script processing phase, you would find that they do not exist yet.

1 Like

I’m writing a CMake helper function to distribute with my package that takes either (a) a CMake target name or (b) the name of a Python script file and runs it as a custom command (with some toolchain/environment dependent arguments).

I want to warn the user if they have a typo in the (b) case since it currently fails during the build, rather than at configure time.

1 Like

that’s a good idea for a helper function!

how exactly are you checking for the existence of the python script file when the function is called? It sounds like the regular if (EXISTS) should work, because I would expect the python script to have to exist at the time the function is called (otherwise there would be no possible way to check for typos in the passed script name).

You could do something like this:

function (add_python_command script)

    if (NOT IS_ABSOLUTE "${script}")
        set (script "${CMAKE_CURRENT_LIST_DIR}/${script}")
    endif()

    if(NOT EXISTS "${script}")
        message (FATAL_ERROR "Error: python script ${script} does not exist!")
    endif()

    ...

endfunction()
1 Like

I would do something like:

# Determine it isn't a target.
# Make absolute as in the previous comment.
if (NOT EXISTS "${script}")
  if (…) # Check if under `CMAKE_BINARY_DIR`
    # Assume it will be generated (`AUTHOR_WARNING` perhaps).
  else ()
    # Error
  endif ()
endif ()

If it is generated, your target needs to grow a dependency on a target or command that will make it available. You could accept this as an argument to your helper. If it isn’t set, then it can’t be generated (as there’s no way to guarantee its presence otherwise) and must exist. Otherwise assume it will (maybe with message(AUTHOR_WARNING) to at least make some noise about the missing dependency to ensure its existence).

1 Like