Svalorzen
Svalorzen

Reputation: 5608

CMake globbing generated files

I'm using asn1c in order to produce from one or more .asn1 files a series of .h and .c files into a given folder.

These C files have no correspondence in names with the original asn1 files.

These files must be linked together with mine in order to obtain a working executable. I'd love to be able to:

Since the generated files are not known in advance it's ok to just glob whatever the contents of the output directory of the asn1c command - as long as the directory is not empty I'm happy.

Upvotes: 7

Views: 4157

Answers (1)

Tsyvarev
Tsyvarev

Reputation: 65870

CMake expects complete list of sources to be passed to add_executable(). That is, you cannot glob files generated at build stage - it would be too late.

You have several ways for handle generating source files without knowing their names in advance:

  1. Generate files at configuration stage with execute_process. After that you may use file(GLOB) for collect source names and pass them to add_executable():

    execute_process(COMMAND asn1c <list of .asn1 files>)
    file(GLOB generated_sources "${CMAKE_CURRENT_BINARY_DIR}/*.c")
    add_executable(my_exe <list of normal sources> ${generated_sources})
    

    If input files for generation (.asn1 in your case) are not intended to be changed in the future, this is the most simple approach which just works.

    If you intend to change input files and expect CMake to detect these changings and regenerate source, some more action should be taken. E.g., you may first copy input files into build directory with configure_file(COPY_ONLY). In that case input files will be tracked, and CMake will rerun if they are changed:

    set(build_input_files) # Will be list of files copied into build tree
    foreach(input_file <list of .asn1 files>)
        # Extract name of the file for generate path of the file in the build tree
        get_filename_component(input_file_name ${input_file} NAME)
        # Path to the file created by copy
        set(build_input_file ${CMAKE_CURRENT_BINARY_DIR}/${input_file_name})
        # Copy file
        configure_file(${input_file} ${build_input_file} COPY_ONLY)
        # Add name of created file into the list
        list(APPEND build_input_files ${build_input_file})
    endforeach()
    
    execute_process(COMMAND asn1c ${build_input_files})
    file(GLOB generated_sources "${CMAKE_CURRENT_BINARY_DIR}/*.c")
    add_executable(my_exe <list of normal sources> ${generated_sources})
    
  2. Parse input files for determine, which files would be created from them. Not sure whether it works with .asn1, but for some formats this works:

    set(input_files <list of .asn1 files>)
    execute_process(COMMAND <determine_output_files> ${input_files}
        OUTPUT_VARIABLE generated_sources)
    add_executable(my_exe <list of normal sources> ${generated_sources})
    add_custom_command(OUTPUT ${generated_sources}
        COMMAND asn1c ${input_files}
        DEPENDS ${input_files})
    

    In that case CMake will detect changes in input files (but in case of modification of list of generated source files you need to rerun cmake manually).

Upvotes: 7

Related Questions