meson-build

Meson build: Python script to autogenerate code not getting executed


I have python script that generates source and header file based on a configuration file. I want to run the python script on every build to ensure the generated "test.cpp" and "test.h" are up to date.

Both "build_always_stale" and "build_by_default" are set to true, but the script is not getting executed.

python_file = files('script/autogenerate.py')
config_file = files('config/configuration.yaml')
custom_target(
    command: ['python3', python_file, meson.current_source_dir()],
    output: ['test.h', 'test.cpp'],
    input: config_file,
    build_always_stale: true,
    build_by_default: true
)

Since "test.cpp" and "test.h" should be created and filled by the script, I do not have these files created manually when i start the build. When I create the file manually before starting the build, the script runs only first time to autogenerate the code inside. But the script does not get executed the second time.

How can I get the autogenerating script to run every time even if no change is made to the python file and configuration file?


Solution

  • I would need to see more of your meson.build file to say for certain, but my assumption is you have something like this...

    project(...)
    
    # Note the result of `custom_target` is not used
    custom_target(output: ['test.h', 'test.cpp'], ...)
    
    executable('main', ...sources) 
    

    The problem you have here is that a custom_target() is just like an executable() or library(); meson needs to be told that the custom_target() is 'used by' another build target to ensure there is a correct sequencing events, e.g. your file generation runs, then then executable gets recompiled. The way to do this is to take the result of your custom_target() and include it in the sources list for any library() or executable() that needs said files to exist. Alternatively, you could use configure_file() to have the files be generated at configure-time, although there is no way to make this happen every single time (although I would not recommend doing that anyway).

    The following build file correctly regenerates the file each time:

    project('testing', 'c')
    
    header = custom_target(output: 'header.h', command: ['touch', '@OUTPUT@'], build_always_stale: true)
    executable('main', 'main.c', header)
    
    # where main.c is basically...
    # #include <header.h>
    # int main(void) { return 0; }