aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Schwartz <eschwartz@archlinux.org>2022-05-26 22:33:52 -0400
committerEli Schwartz <eschwartz@archlinux.org>2022-05-31 17:49:29 -0400
commitdd2f1c4c57874a0efcd9f6d331985c408101c30d (patch)
tree0af74e8a9eb283c2f457ba730716afa51a5a3e6e
parent40c69630df1057401a9ae3ec5584a9ff8d1bef46 (diff)
downloadmeson-dd2f1c4c57874a0efcd9f6d331985c408101c30d.zip
meson-dd2f1c4c57874a0efcd9f6d331985c408101c30d.tar.gz
meson-dd2f1c4c57874a0efcd9f6d331985c408101c30d.tar.bz2
ninja backend: simplify generation of phony targets
Every phony target has a special indirection rule created because ninja is bad at deleting generated outputs and tries to delete phony outputs too. Instead of invoking this as a separate helper post-creation function to create the alias, wrap NinjaBuildElement and create it behind the scenes. This simplifies target naming and means one less line at every single use site.
-rw-r--r--mesonbuild/backend/ninjabackend.py97
1 files changed, 33 insertions, 64 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 35c14ee..c6f82e3 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -434,18 +434,23 @@ class NinjaBackend(backends.Backend):
self.introspection_data = {}
self.created_llvm_ir_rule = PerMachine(False, False)
- def create_target_alias(self, to_target):
- # We need to use aliases for targets that might be used as directory
- # names to workaround a Ninja bug that breaks `ninja -t clean`.
- # This is used for 'reserved' targets such as 'test', 'install',
- # 'benchmark', etc, and also for RunTargets.
- # https://github.com/mesonbuild/meson/issues/1644
- if not to_target.startswith('meson-'):
- raise AssertionError(f'Invalid usage of create_target_alias with {to_target!r}')
- from_target = to_target[len('meson-'):]
- elem = NinjaBuildElement(self.all_outputs, from_target, 'phony', to_target)
+ def create_phony_target(self, all_outputs, dummy_outfile, rulename, phony_infilename, implicit_outs=None):
+ '''
+ We need to use aliases for targets that might be used as directory
+ names to workaround a Ninja bug that breaks `ninja -t clean`.
+ This is used for 'reserved' targets such as 'test', 'install',
+ 'benchmark', etc, and also for RunTargets.
+ https://github.com/mesonbuild/meson/issues/1644
+ '''
+ if dummy_outfile.startswith('meson-'):
+ raise AssertionError(f'Invalid usage of create_phony_target with {dummy_outfile!r}')
+
+ to_name = f'meson-{dummy_outfile}'
+ elem = NinjaBuildElement(all_outputs, dummy_outfile, 'phony', to_name)
self.add_build(elem)
+ return NinjaBuildElement(all_outputs, to_name, rulename, phony_infilename, implicit_outs)
+
def detect_vs_dep_prefix(self, tempfilename):
'''VS writes its dependency in a locale dependent format.
Detect the search prefix to use.'''
@@ -1050,13 +1055,10 @@ class NinjaBackend(backends.Backend):
env=target_env,
verbose=True)
cmd_type = f' (wrapped by meson {reason})' if reason else ''
- internal_target_name = f'meson-{target_name}'
- elem = NinjaBuildElement(self.all_outputs, internal_target_name, 'CUSTOM_COMMAND', [])
+ elem = self.create_phony_target(self.all_outputs, target_name, 'CUSTOM_COMMAND', [])
elem.add_item('COMMAND', meson_exe_cmd)
elem.add_item('description', f'Running external command {target.name}{cmd_type}')
elem.add_item('pool', 'console')
- # Alias that runs the target defined above with the name the user specified
- self.create_target_alias(internal_target_name)
deps = self.unwrap_dep_list(target)
deps += self.get_custom_target_depend_files(target)
elem.add_dep(deps)
@@ -1084,55 +1086,43 @@ class NinjaBackend(backends.Backend):
(['--use_llvm_cov'] if use_llvm_cov else []))
def generate_coverage_rules(self, gcovr_exe: T.Optional[str], gcovr_version: T.Optional[str]):
- e = NinjaBuildElement(self.all_outputs, 'meson-coverage', 'CUSTOM_COMMAND', 'PHONY')
+ e = self.create_phony_target(self.all_outputs, 'coverage', 'CUSTOM_COMMAND', 'PHONY')
self.generate_coverage_command(e, [])
e.add_item('description', 'Generates coverage reports')
self.add_build(e)
- # Alias that runs the target defined above
- self.create_target_alias('meson-coverage')
self.generate_coverage_legacy_rules(gcovr_exe, gcovr_version)
def generate_coverage_legacy_rules(self, gcovr_exe: T.Optional[str], gcovr_version: T.Optional[str]):
- e = NinjaBuildElement(self.all_outputs, 'meson-coverage-html', 'CUSTOM_COMMAND', 'PHONY')
+ e = self.create_phony_target(self.all_outputs, 'coverage-html', 'CUSTOM_COMMAND', 'PHONY')
self.generate_coverage_command(e, ['--html'])
e.add_item('description', 'Generates HTML coverage report')
self.add_build(e)
- # Alias that runs the target defined above
- self.create_target_alias('meson-coverage-html')
if gcovr_exe:
- e = NinjaBuildElement(self.all_outputs, 'meson-coverage-xml', 'CUSTOM_COMMAND', 'PHONY')
+ e = self.create_phony_target(self.all_outputs, 'coverage-xml', 'CUSTOM_COMMAND', 'PHONY')
self.generate_coverage_command(e, ['--xml'])
e.add_item('description', 'Generates XML coverage report')
self.add_build(e)
- # Alias that runs the target defined above
- self.create_target_alias('meson-coverage-xml')
- e = NinjaBuildElement(self.all_outputs, 'meson-coverage-text', 'CUSTOM_COMMAND', 'PHONY')
+ e = self.create_phony_target(self.all_outputs, 'coverage-text', 'CUSTOM_COMMAND', 'PHONY')
self.generate_coverage_command(e, ['--text'])
e.add_item('description', 'Generates text coverage report')
self.add_build(e)
- # Alias that runs the target defined above
- self.create_target_alias('meson-coverage-text')
if mesonlib.version_compare(gcovr_version, '>=4.2'):
- e = NinjaBuildElement(self.all_outputs, 'meson-coverage-sonarqube', 'CUSTOM_COMMAND', 'PHONY')
+ e = self.create_phony_target(self.all_outputs, 'coverage-sonarqube', 'CUSTOM_COMMAND', 'PHONY')
self.generate_coverage_command(e, ['--sonarqube'])
e.add_item('description', 'Generates Sonarqube XML coverage report')
self.add_build(e)
- # Alias that runs the target defined above
- self.create_target_alias('meson-coverage-sonarqube')
def generate_install(self):
self.create_install_data_files()
- elem = NinjaBuildElement(self.all_outputs, 'meson-install', 'CUSTOM_COMMAND', 'PHONY')
+ elem = self.create_phony_target(self.all_outputs, 'install', 'CUSTOM_COMMAND', 'PHONY')
elem.add_dep('all')
elem.add_item('DESC', 'Installing files.')
elem.add_item('COMMAND', self.environment.get_build_command() + ['install', '--no-rebuild'])
elem.add_item('pool', 'console')
self.add_build(elem)
- # Alias that runs the target defined above
- self.create_target_alias('meson-install')
def generate_tests(self):
self.serialize_tests()
@@ -1141,25 +1131,21 @@ class NinjaBackend(backends.Backend):
cmd += ['--no-stdsplit']
if self.environment.coredata.get_option(OptionKey('errorlogs')):
cmd += ['--print-errorlogs']
- elem = NinjaBuildElement(self.all_outputs, 'meson-test', 'CUSTOM_COMMAND', ['all', 'PHONY'])
+ elem = self.create_phony_target(self.all_outputs, 'test', 'CUSTOM_COMMAND', ['all', 'PHONY'])
elem.add_item('COMMAND', cmd)
elem.add_item('DESC', 'Running all tests.')
elem.add_item('pool', 'console')
self.add_build(elem)
- # Alias that runs the above-defined meson-test target
- self.create_target_alias('meson-test')
# And then benchmarks.
cmd = self.environment.get_build_command(True) + [
'test', '--benchmark', '--logbase',
'benchmarklog', '--num-processes=1', '--no-rebuild']
- elem = NinjaBuildElement(self.all_outputs, 'meson-benchmark', 'CUSTOM_COMMAND', ['all', 'PHONY'])
+ elem = self.create_phony_target(self.all_outputs, 'benchmark', 'CUSTOM_COMMAND', ['all', 'PHONY'])
elem.add_item('COMMAND', cmd)
elem.add_item('DESC', 'Running benchmark suite.')
elem.add_item('pool', 'console')
self.add_build(elem)
- # Alias that runs the above-defined meson-benchmark target
- self.create_target_alias('meson-benchmark')
def generate_rules(self):
self.rules = []
@@ -3170,33 +3156,27 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
mlog.debug("Library versioning disabled because we do not have symlink creation privileges.")
def generate_custom_target_clean(self, trees: T.List[str]) -> str:
- e = NinjaBuildElement(self.all_outputs, 'meson-clean-ctlist', 'CUSTOM_COMMAND', 'PHONY')
+ e = self.create_phony_target(self.all_outputs, 'clean-ctlist', 'CUSTOM_COMMAND', 'PHONY')
d = CleanTrees(self.environment.get_build_dir(), trees)
d_file = os.path.join(self.environment.get_scratch_dir(), 'cleantrees.dat')
e.add_item('COMMAND', self.environment.get_build_command() + ['--internal', 'cleantrees', d_file])
e.add_item('description', 'Cleaning custom target directories')
self.add_build(e)
- # Alias that runs the target defined above
- self.create_target_alias('meson-clean-ctlist')
# Write out the data file passed to the script
with open(d_file, 'wb') as ofile:
pickle.dump(d, ofile)
return 'clean-ctlist'
def generate_gcov_clean(self):
- gcno_elem = NinjaBuildElement(self.all_outputs, 'meson-clean-gcno', 'CUSTOM_COMMAND', 'PHONY')
+ gcno_elem = self.create_phony_target(self.all_outputs, 'clean-gcno', 'CUSTOM_COMMAND', 'PHONY')
gcno_elem.add_item('COMMAND', mesonlib.get_meson_command() + ['--internal', 'delwithsuffix', '.', 'gcno'])
gcno_elem.add_item('description', 'Deleting gcno files')
self.add_build(gcno_elem)
- # Alias that runs the target defined above
- self.create_target_alias('meson-clean-gcno')
- gcda_elem = NinjaBuildElement(self.all_outputs, 'meson-clean-gcda', 'CUSTOM_COMMAND', 'PHONY')
+ gcda_elem = self.create_phony_target(self.all_outputs, 'clean-gcda', 'CUSTOM_COMMAND', 'PHONY')
gcda_elem.add_item('COMMAND', mesonlib.get_meson_command() + ['--internal', 'delwithsuffix', '.', 'gcda'])
gcda_elem.add_item('description', 'Deleting gcda files')
self.add_build(gcda_elem)
- # Alias that runs the target defined above
- self.create_target_alias('meson-clean-gcda')
def get_user_option_args(self):
cmds = []
@@ -3209,13 +3189,11 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
return sorted(cmds)
def generate_dist(self):
- elem = NinjaBuildElement(self.all_outputs, 'meson-dist', 'CUSTOM_COMMAND', 'PHONY')
+ elem = self.create_phony_target(self.all_outputs, 'dist', 'CUSTOM_COMMAND', 'PHONY')
elem.add_item('DESC', 'Creating source packages')
elem.add_item('COMMAND', self.environment.get_build_command() + ['dist'])
elem.add_item('pool', 'console')
self.add_build(elem)
- # Alias that runs the target defined above
- self.create_target_alias('meson-dist')
def generate_scanbuild(self):
if not environment.detect_scanbuild():
@@ -3225,12 +3203,10 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
cmd = self.environment.get_build_command() + \
['--internal', 'scanbuild', self.environment.source_dir, self.environment.build_dir] + \
self.environment.get_build_command() + self.get_user_option_args()
- elem = NinjaBuildElement(self.all_outputs, 'meson-scan-build', 'CUSTOM_COMMAND', 'PHONY')
+ elem = self.create_phony_target(self.all_outputs, 'scan-build', 'CUSTOM_COMMAND', 'PHONY')
elem.add_item('COMMAND', cmd)
elem.add_item('pool', 'console')
self.add_build(elem)
- # Alias that runs the target defined above
- self.create_target_alias('meson-scan-build')
def generate_clangtool(self, name, extra_arg=None):
target_name = 'clang-' + name
@@ -3248,11 +3224,10 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
cmd = self.environment.get_build_command() + \
['--internal', 'clang' + name, self.environment.source_dir, self.environment.build_dir] + \
extra_args
- elem = NinjaBuildElement(self.all_outputs, 'meson-' + target_name, 'CUSTOM_COMMAND', 'PHONY')
+ elem = self.create_phony_target(self.all_outputs, target_name, 'CUSTOM_COMMAND', 'PHONY')
elem.add_item('COMMAND', cmd)
elem.add_item('pool', 'console')
self.add_build(elem)
- self.create_target_alias('meson-' + target_name)
def generate_clangformat(self):
if not environment.detect_clangformat():
@@ -3276,12 +3251,10 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
return
cmd = self.environment.get_build_command() + \
['--internal', 'tags', tool, self.environment.source_dir]
- elem = NinjaBuildElement(self.all_outputs, 'meson-' + target_name, 'CUSTOM_COMMAND', 'PHONY')
+ elem = self.create_phony_target(self.all_outputs, target_name, 'CUSTOM_COMMAND', 'PHONY')
elem.add_item('COMMAND', cmd)
elem.add_item('pool', 'console')
self.add_build(elem)
- # Alias that runs the target defined above
- self.create_target_alias('meson-' + target_name)
# For things like scan-build and other helper tools we might have.
def generate_utils(self):
@@ -3292,12 +3265,10 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
self.generate_tags('ctags', 'ctags')
self.generate_tags('cscope', 'cscope')
cmd = self.environment.get_build_command() + ['--internal', 'uninstall']
- elem = NinjaBuildElement(self.all_outputs, 'meson-uninstall', 'CUSTOM_COMMAND', 'PHONY')
+ elem = self.create_phony_target(self.all_outputs, 'uninstall', 'CUSTOM_COMMAND', 'PHONY')
elem.add_item('COMMAND', cmd)
elem.add_item('pool', 'console')
self.add_build(elem)
- # Alias that runs the target defined above
- self.create_target_alias('meson-uninstall')
def generate_ending(self):
targetlist = []
@@ -3309,11 +3280,9 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485'''))
elem = NinjaBuildElement(self.all_outputs, 'all', 'phony', targetlist)
self.add_build(elem)
- elem = NinjaBuildElement(self.all_outputs, 'meson-clean', 'CUSTOM_COMMAND', 'PHONY')
+ elem = self.create_phony_target(self.all_outputs, 'clean', 'CUSTOM_COMMAND', 'PHONY')
elem.add_item('COMMAND', self.ninja_command + ['-t', 'clean'])
elem.add_item('description', 'Cleaning')
- # Alias that runs the above-defined meson-clean target
- self.create_target_alias('meson-clean')
# If we have custom targets in this project, add all their outputs to
# the list that is passed to the `cleantrees.py` script. The script