Browse Source

build: Fix possible race condition when compiling blueprint files

Due to an incompatibility between meson and our setup.
merge-requests/2136/head
Kévin Commaille 4 months ago
parent
commit
cf88df7e78
No known key found for this signature in database
GPG Key ID: F26F4BE20A08255B
  1. 68
      build-aux/compile-blueprints.sh
  2. 55
      src/meson.build

68
build-aux/compile-blueprints.sh

@ -0,0 +1,68 @@
#!/usr/bin/env bash
#
# Compile blueprint files to UI files all in the same directory.
#
# Usage: ./compile-blueprints.sh PATH_TO_BLUEPRINT_COMPILER OUTPUT_DIR BASE_INPUT_DIR [INPUT_FILE…]
#
# This should be a temporary solution to fix an incompatibility between our
# setup, blueprint-compiler and meson.
#
# The problem is that blueprint advises to use `custom_target()` with `output`
# set to `.`: https://gitlab.gnome.org/GNOME/blueprint-compiler/-/blob/70f32dc069c3ff13a54f24f24c0e720b938f587d/docs/setup.rst#L55
# This doesn't work well with ninja's caching, as it doesn't know which files
# are actually generated, so it might consider that the output is generated too
# soon, and proceed to compiling the gresource before all blueprint files are
# actually compiled.
#
# The fix for this is to actually set the proper list of generated files for the
# output. This doesn't work with our setup because we generate files in
# subdirectories and `custom_target`'s `output` only accepts a list of files in
# the current directory.
#
# So we have 2 options to fix this:
#
# 1. Use a `meson.build` file per subdirectory to compile the blueprints
# separately which is tedious and results in a lot of duplication.
# 2. Keep our current setup and find a way to generate a list of outputs that is
# accepted by meson.
#
# For simplicity, we want to use the second option and it would be easy if we
# could use `generator()` to compile the blueprints. It requires
# `gnome.compile_resources()` to accept a `generated_list` in `dependencies`,
# but it doesn't: https://github.com/mesonbuild/meson/issues/12336.
#
# So this implements another solution: compile all the UI files in the same
# directory by using a name scheme that avoids collisions. Then we can overwrite
# the path where the resource will be available in the gresource file
# definition by setting an `alias`.
#
# The output files will be located in `OUTPUT_DIR` and their names are the
# path of `INPUT_FILE` relative to the `BASE_INPUT_DIR` with the slashes
# replaced by `-`, and the extension changed.
set -e
compiler="$1"
shift
output_dir="$1"
shift
base_input_dir="$1"
shift
# For debugging.
# echo "Compiling files in $input_dir to $output_dir with $compiler"
for input_file in "$@"
do
# Change extension.
output_file="${input_file%.blp}.ui"
# Remove base input dir to get relative path.
output_file="${output_file#$base_input_dir\/}"
# Replace slashes with dashes.
output_file="$output_dir/${output_file//\//-}"
# For debugging
# echo "Compiling $input_file to $output_file"
"$compiler" compile --output "$output_file" "$input_file"
done

55
src/meson.build

@ -1,43 +1,48 @@
if not build_env_only if not build_env_only
# Compile Blueprint resources # Compile Blueprint resources
blp_files = [] blp_files = []
foreach line : fs.read('ui-blueprint-resources.in').splitlines() ui_files = []
if not line.startswith('#') and line.strip() != '' ui_files_xml = ''
blp_files += line
# These files are already added manually in the resources file because they
# need custom handling.
blp_gresource_exceptions = [
'shortcuts-dialog.blp', # Must use the root prefix for auto-detection, it must not be under `/ui`.
]
foreach file : fs.read('ui-blueprint-resources.in').splitlines()
file = file.strip()
if file.startswith('#') or file == ''
continue
endif
blp_files += file
# We need to put all output files in the same directory
ui_alias = file.replace('.blp', '.ui')
ui_file = ui_alias.replace('/', '-')
ui_files += ui_file
if not blp_gresource_exceptions.contains(file)
ui_files_xml += '\n <file compressed="true" preprocess="xml-stripblanks" alias="' + ui_alias + '">' + ui_file + '</file>'
endif endif
endforeach endforeach
blueprints = custom_target( blueprints = custom_target(
'blueprints', 'blueprints',
input: blp_files, input: blp_files,
output: '.', output: ui_files,
command: [ command: [
blueprint_compiler, '../build-aux/compile-blueprints.sh',
'batch-compile', blueprint_compiler.full_path(),
'@OUTPUT@', '@OUTDIR@',
'@CURRENT_SOURCE_DIR@', '@CURRENT_SOURCE_DIR@',
'@INPUT@', '@INPUT@',
], ],
) )
# Populate the GResource file for the compiled Blueprint files dynamically, # Populate the GResource file for the compiled Blueprint files dynamically.
# using the same file list.
# These files are already added manually in the resources file because they
# need custom handling.
blp_exceptions = [
'shortcuts-dialog.blp', # Must use the root prefix for auto-detection, it must not be under `/ui`.
]
ui_files_xml = ''
foreach file : blp_files
if not blp_exceptions.contains(file)
ui_files_xml += '\n <file compressed="true" preprocess="xml-stripblanks">' + file.replace(
'.blp',
'.ui',
) + '</file>'
endif
endforeach
ui_resources_xml = configure_file( ui_resources_xml = configure_file(
input: 'ui-resources.gresource.xml.in', input: 'ui-resources.gresource.xml.in',
output: 'ui-resources.gresource.xml', output: 'ui-resources.gresource.xml',

Loading…
Cancel
Save