meson-build

How to copy a file in Meson to a subdirectory


My application uses a Glade file and also cached data in a JSON file. When I do the following, everything works okay as long as the user installs the application with ninja install

    #Install cached JSON file
    install_data(
        join_paths('data', 'dataCache.json'),
        install_dir: join_paths('myapp', 'resources')
    )
    #Install the user interface glade file
    install_data(
        join_paths('src', 'MainWindow.glade'),
        install_dir: join_paths('myapp', 'resources')
    )

The downside is that the user needs to install the application. I want the user to be able to just build the application with ninja and run it without installing it if they don't want to install it on their system. The problem is that when I do

    #Copy the cached JSON file to the build output directory
    configure_file(input : join_paths('data', 'dataCache.json'),
        output : join_paths('myapp', 'resources', 'dataCache.json'),
        copy: true
    )

    #Copy the Glade file to the build output directory
    configure_file(input : join_paths('src', 'MainWindow.glade'),
        output : join_paths('myapp', 'resources', 'MainWindow.glade'),
        copy: true
    )

I get ERROR: Output file name must not contain a subdirectory.

Is there a way to run ninja and have it create the directories myapp/resources on the build folder and then copy the Glade and JSON file there to be used as resources? Such as to let the user run the application without having to do ninja install?


Solution

  • You can do it by making a script and call it from Meson.

    For example, in a file copy.py that takes the relative input and output paths as arguments:

    #!/usr/bin/env python3 
    
    import os, sys, shutil
    
    # get absolute input and output paths
    input_path = os.path.join(
        os.getenv('MESON_SOURCE_ROOT'), 
        os.getenv('MESON_SUBDIR'),
        sys.argv[1])
    
    output_path = os.path.join(
        os.getenv('MESON_BUILD_ROOT'), 
        os.getenv('MESON_SUBDIR'),
        sys.argv[2])
    
    # make sure destination directory exists
    os.makedirs(os.path.dirname(output_path), exist_ok=True)
    
    # and finally copy the file
    shutil.copyfile(input_path, output_path)
    

    and then in your meson.build file:

    copy = find_program('copy.py')
    
    run_command(
        copy,
        join_paths('src', 'dataCache.json'), 
        join_paths('myapp', 'resources', 'dataCache.json')
    )
    run_command(
        copy, 
        join_paths('src', 'MainWindow.glade'), 
        join_paths('myapp', 'resources', 'MainWindow.glade')
    )