From 42e9028868bdbf0c9e007bf446608c6eba4077bc Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Tue, 9 Apr 2019 18:05:00 +0100 Subject: ninja: Remove use of unset ninja variable 'aliasing' Setting this variable to contain additional commands to symlink shlib aliases was removed in commit c0bf3e8d, so it's always unset now, and thus does nothing. --- mesonbuild/backend/ninjabackend.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 8edaeec..89fa543 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1473,10 +1473,10 @@ int dummy; if compiler.can_linker_accept_rsp(): command_template = ''' command = {executable} @$out.rsp rspfile = $out.rsp - rspfile_content = $ARGS {output_args} $in $LINK_ARGS $aliasing + rspfile_content = $ARGS {output_args} $in $LINK_ARGS ''' else: - command_template = ' command = {executable} $ARGS {output_args} $in $LINK_ARGS $aliasing\n' + command_template = ' command = {executable} $ARGS {output_args} $in $LINK_ARGS\n' command = command_template.format( executable=' '.join(compiler.get_linker_exelist()), output_args=' '.join(compiler.get_linker_output_args('$out')) -- cgit v1.1 From 7bc1db2d7b05836545ef5a9452383a9940c0348c Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Wed, 10 Apr 2019 15:45:14 +0100 Subject: ninja: Move things which aren't rules or build statements up to generate() --- mesonbuild/backend/ninjabackend.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 89fa543..f1527da 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -220,6 +220,14 @@ int dummy; outfile.write('# It is autogenerated by the Meson build system.\n') outfile.write('# Do not edit by hand.\n\n') outfile.write('ninja_required_version = 1.5.1\n\n') + + num_pools = self.environment.coredata.backend_options['backend_max_links'].value + if num_pools > 0: + outfile.write('''pool link_pool + depth = %d + +''' % num_pools) + with self.detect_vs_dep_prefix(tempfilename) as outfile: self.generate_rules(outfile) self.generate_phony(outfile) @@ -238,6 +246,8 @@ int dummy; outfile.write('# Suffix\n\n') self.generate_utils(outfile) self.generate_ending(outfile) + default = 'default all\n\n' + outfile.write(default) # Only overwrite the old build file after the new one has been # fully created. os.replace(tempfilename, outfilename) @@ -774,12 +784,6 @@ int dummy; outfile.write('# Rules for compiling.\n\n') self.generate_compile_rules(outfile) outfile.write('# Rules for linking.\n\n') - num_pools = self.environment.coredata.backend_options['backend_max_links'].value - if num_pools > 0: - outfile.write('''pool link_pool - depth = %d - -''' % num_pools) if self.environment.is_cross_build(): self.generate_static_link_rules(True, outfile) self.generate_static_link_rules(False, outfile) @@ -2706,9 +2710,6 @@ rule FORTRAN_DEP_HACK%s elem = NinjaBuildElement(self.all_outputs, 'all', 'phony', targetlist) elem.write(outfile) - default = 'default all\n\n' - outfile.write(default) - elem = NinjaBuildElement(self.all_outputs, 'meson-clean', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', [self.ninja_command, '-t', 'clean']) elem.add_item('description', 'Cleaning.') -- cgit v1.1 From 1303389700e91057316560ab1a4f3071ca2959a8 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Mon, 19 Nov 2018 13:59:04 +0000 Subject: ninja: Store rules Store the rules and then write them all out, rather than writing them out as we go. Store the rule broken down into parts which do and don't go into rspfile, so we can construct either a rsp or non-rsp version of the rule. --- mesonbuild/backend/ninjabackend.py | 361 +++++++++++++++++++------------------ 1 file changed, 181 insertions(+), 180 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index f1527da..8c856b2 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -63,6 +63,48 @@ Please report this error with a test case to the Meson bug tracker.''' % text raise MesonException(errmsg) return text +class NinjaComment: + def __init__(self, comment): + self.comment = comment + + def write(self, outfile): + for l in self.comment.split('\n'): + outfile.write('# ') + outfile.write(l) + outfile.write('\n') + outfile.write('\n') + +class NinjaRule: + def __init__(self, rule, command, args, description, + rspable = False, deps = None, depfile = None, extra = None): + self.name = rule + self.command = command # includes args which never go into a rspfile + self.args = args # args which will go into a rspfile, if used + self.description = description + self.deps = deps # depstyle 'gcc' or 'msvc' + self.depfile = depfile + self.extra = extra + self.rspable = rspable # if a rspfile can be used + + def write(self, outfile): + outfile.write('rule %s\n' % self.name) + if self.rspable: + outfile.write(' command = %s @$out.rsp\n' % self.command) + outfile.write(' rspfile = $out.rsp\n') + outfile.write(' rspfile_content = %s\n' % self.args) + else: + outfile.write(' command = %s %s\n' % (self.command, self.args)) + if self.deps: + outfile.write(' deps = %s\n' % self.deps) + if self.depfile: + outfile.write(' depfile = %s\n' % self.depfile) + outfile.write(' description = %s\n' % self.description) + if self.extra: + for l in self.extra.split('\n'): + outfile.write(' ') + outfile.write(l) + outfile.write('\n') + outfile.write('\n') class NinjaBuildElement: def __init__(self, all_outputs, outfilenames, rule, infilenames): @@ -230,6 +272,7 @@ int dummy; with self.detect_vs_dep_prefix(tempfilename) as outfile: self.generate_rules(outfile) + self.write_rules(outfile) self.generate_phony(outfile) outfile.write('# Build rules for targets\n\n') for t in self.build.get_targets().values(): @@ -781,36 +824,43 @@ int dummy; self.create_target_alias('meson-benchmark', outfile) def generate_rules(self, outfile): - outfile.write('# Rules for compiling.\n\n') + self.rules = [] + + self.add_rule_comment(NinjaComment('Rules for compiling.')) self.generate_compile_rules(outfile) - outfile.write('# Rules for linking.\n\n') + self.add_rule_comment(NinjaComment('Rules for linking.')) if self.environment.is_cross_build(): self.generate_static_link_rules(True, outfile) self.generate_static_link_rules(False, outfile) self.generate_dynamic_link_rules(outfile) - outfile.write('# Other rules\n\n') - outfile.write('rule CUSTOM_COMMAND\n') - outfile.write(' command = $COMMAND\n') - outfile.write(' description = $DESC\n') - outfile.write(' restat = 1\n\n') + self.add_rule_comment(NinjaComment('Other rules')) # Ninja errors out if you have deps = gcc but no depfile, so we must # have two rules for custom commands. - outfile.write('rule CUSTOM_COMMAND_DEP\n') - outfile.write(' command = $COMMAND\n') - outfile.write(' description = $DESC\n') - outfile.write(' deps = gcc\n') - outfile.write(' depfile = $DEPFILE\n') - outfile.write(' restat = 1\n\n') - outfile.write('rule REGENERATE_BUILD\n') + self.add_rule(NinjaRule('CUSTOM_COMMAND', '$COMMAND', '', '$DESC', + extra='restat = 1')) + self.add_rule(NinjaRule('CUSTOM_COMMAND_DEP', '$COMMAND', '', '$DESC', + deps='gcc', depfile='$DEPFILE', + extra='restat = 1')) + c = [ninja_quote(quote_func(x)) for x in self.environment.get_build_command()] + \ ['--internal', 'regenerate', ninja_quote(quote_func(self.environment.get_source_dir())), ninja_quote(quote_func(self.environment.get_build_dir()))] - outfile.write(" command = " + ' '.join(c) + ' --backend ninja\n') - outfile.write(' description = Regenerating build files.\n') - outfile.write(' generator = 1\n\n') - outfile.write('\n') + self.add_rule(NinjaRule('REGENERATE_BUILD', + ' '.join(c) + ' --backend ninja', '', + 'Regenerating build files.', + extra='generator = 1')) + + def add_rule_comment(self, comment): + self.rules.append(comment) + + def add_rule(self, rule): + self.rules.append(rule) + + def write_rules(self, outfile): + for r in self.rules: + r.write(outfile) def generate_phony(self, outfile): outfile.write('# Phony build target, always out of date\n') @@ -976,13 +1026,10 @@ int dummy; return plain_class_path def generate_java_link(self, outfile): - rule = 'rule java_LINKER\n' - command = ' command = jar $ARGS\n' - description = ' description = Creating JAR $out.\n' - outfile.write(rule) - outfile.write(command) - outfile.write(description) - outfile.write('\n') + rule = 'java_LINKER' + command = 'jar $ARGS' + description = 'Creating JAR $out.' + self.add_rule(NinjaRule(rule, command, '', description)) def determine_dep_vapis(self, target): """ @@ -1427,14 +1474,10 @@ int dummy; crstr = '' if static_linker is None: return - rule = 'rule STATIC%s_LINKER\n' % crstr - if static_linker.can_linker_accept_rsp(): - command_template = ''' command = {executable} $LINK_ARGS {output_args} @$out.rsp - rspfile = $out.rsp - rspfile_content = $in -''' - else: - command_template = ' command = {executable} $LINK_ARGS {output_args} $in\n' + rule = 'STATIC%s_LINKER' % crstr + command_template = '{executable} $LINK_ARGS {output_args}' + args = '$in' + cmdlist = [] # FIXME: Must normalize file names with pathlib.Path before writing # them out to fix this properly on Windows. See: @@ -1446,15 +1489,19 @@ int dummy; # it exists. https://github.com/mesonbuild/meson/issues/1355 cmdlist = [execute_wrapper, rmfile_prefix.format('$out')] cmdlist += static_linker.get_exelist() - command = command_template.format( - executable=' '.join(cmdlist), - output_args=' '.join(static_linker.get_output_args('$out'))) - description = ' description = Linking static target $out.\n\n' - outfile.write(rule) - outfile.write(command) + subst = { + 'executable': ' '.join(cmdlist), + 'output_args': ' '.join(static_linker.get_output_args('$out')) + } + command = command_template.format(**subst) + description = 'Linking static target $out.' if num_pools > 0: - outfile.write(' pool = link_pool\n') - outfile.write(description) + pool = 'pool = link_pool' + else: + pool = None + self.add_rule(NinjaRule(rule, command, args, description, + rspable=static_linker.can_linker_accept_rsp(), + extra=pool)) def generate_dynamic_link_rules(self, outfile): num_pools = self.environment.coredata.backend_options['backend_max_links'].value @@ -1473,101 +1520,73 @@ int dummy; crstr = '' if is_cross: crstr = '_CROSS' - rule = 'rule %s%s_LINKER\n' % (langname, crstr) - if compiler.can_linker_accept_rsp(): - command_template = ''' command = {executable} @$out.rsp - rspfile = $out.rsp - rspfile_content = $ARGS {output_args} $in $LINK_ARGS -''' - else: - command_template = ' command = {executable} $ARGS {output_args} $in $LINK_ARGS\n' - command = command_template.format( - executable=' '.join(compiler.get_linker_exelist()), - output_args=' '.join(compiler.get_linker_output_args('$out')) - ) - description = ' description = Linking target $out.\n' - outfile.write(rule) - outfile.write(command) + rule = '%s%s_LINKER' % (langname, crstr) + command_template = '{executable}' + args_template = '$ARGS {output_args} $in $LINK_ARGS' + subst = { + 'executable': ' '.join(compiler.get_linker_exelist()), + 'output_args': ' '.join(compiler.get_linker_output_args('$out')), + } + command = command_template.format(**subst) + args = args_template.format(**subst) + description = 'Linking target $out.' if num_pools > 0: - outfile.write(' pool = link_pool\n') - outfile.write(description) - outfile.write('\n') - outfile.write('\n') + pool = 'pool = link_pool' + else: + pool = None + self.add_rule(NinjaRule(rule, command, args, description, + rspable=compiler.can_linker_accept_rsp(), + extra=pool)) + args = [ninja_quote(quote_func(x)) for x in self.environment.get_build_command()] + \ ['--internal', 'symbolextractor', '$in', '$out'] - symrule = 'rule SHSYM\n' - symcmd = ' command = ' + ' '.join(args) + ' $CROSS\n' - synstat = ' restat = 1\n' - syndesc = ' description = Generating symbol file $out.\n' - outfile.write(symrule) - outfile.write(symcmd) - outfile.write(synstat) - outfile.write(syndesc) - outfile.write('\n') + symrule = 'SHSYM' + symcmd = ' '.join(args) + ' $CROSS' + syndesc = 'Generating symbol file $out.' + synstat = 'restat = 1' + self.add_rule(NinjaRule(symrule, symcmd, '', syndesc, extra=synstat)) def generate_java_compile_rule(self, compiler, outfile): - rule = 'rule %s_COMPILER\n' % compiler.get_language() + rule = '%s_COMPILER' % compiler.get_language() invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) - command = ' command = %s $ARGS $in\n' % invoc - description = ' description = Compiling Java object $in.\n' - outfile.write(rule) - outfile.write(command) - outfile.write(description) - outfile.write('\n') + command = '%s $ARGS $in' % invoc + description = 'Compiling Java object $in.' + self.add_rule(NinjaRule(rule, command, '', description)) def generate_cs_compile_rule(self, compiler, outfile): - rule = 'rule %s_COMPILER\n' % compiler.get_language() + rule = '%s_COMPILER' % compiler.get_language() invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) - - if mesonlib.is_windows(): - command = ''' command = {executable} @$out.rsp - rspfile = $out.rsp - rspfile_content = $ARGS $in -'''.format(executable=invoc) - else: - command = ' command = %s $ARGS $in\n' % invoc - - description = ' description = Compiling C Sharp target $out.\n' - outfile.write(rule) - outfile.write(command) - outfile.write(description) - outfile.write('\n') + command = '%s' % invoc + args = '$ARGS $in' + description = 'Compiling C Sharp target $out.' + self.add_rule(NinjaRule(rule, command, args, description, + rspable=mesonlib.is_windows())) def generate_vala_compile_rules(self, compiler, outfile): - rule = 'rule %s_COMPILER\n' % compiler.get_language() + rule = '%s_COMPILER' % compiler.get_language() invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) - command = ' command = %s $ARGS $in\n' % invoc - description = ' description = Compiling Vala source $in.\n' - restat = ' restat = 1\n' # ValaC does this always to take advantage of it. - outfile.write(rule) - outfile.write(command) - outfile.write(description) - outfile.write(restat) - outfile.write('\n') + command = '%s $ARGS $in' % invoc + description = 'Compiling Vala source $in.' + self.add_rule(NinjaRule(rule, command, '', description, extra='restat = 1')) def generate_rust_compile_rules(self, compiler, outfile, is_cross): crstr = '' if is_cross: crstr = '_CROSS' - rule = 'rule %s%s_COMPILER\n' % (compiler.get_language(), crstr) + rule = '%s%s_COMPILER' % (compiler.get_language(), crstr) invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) - command = ' command = %s $ARGS $in\n' % invoc - description = ' description = Compiling Rust source $in.\n' - depfile = ' depfile = $targetdep\n' - - depstyle = ' deps = gcc\n' - outfile.write(rule) - outfile.write(command) - outfile.write(description) - outfile.write(depfile) - outfile.write(depstyle) - outfile.write('\n') + command = '%s $ARGS $in' % invoc + description = 'Compiling Rust source $in.' + depfile = '$targetdep' + depstyle = 'gcc' + self.add_rule(NinjaRule(rule, command, '', description, deps=depstyle, + depfile=depfile)) def generate_swift_compile_rules(self, compiler, outfile): - rule = 'rule %s_COMPILER\n' % compiler.get_language() + rule = '%s_COMPILER' % compiler.get_language() full_exe = [ninja_quote(x) for x in self.environment.get_build_command()] + [ '--internal', 'dirchanger', @@ -1575,49 +1594,37 @@ int dummy; ] invoc = (' '.join(full_exe) + ' ' + ' '.join(ninja_quote(i) for i in compiler.get_exelist())) - command = ' command = %s $ARGS $in\n' % invoc - description = ' description = Compiling Swift source $in.\n' - outfile.write(rule) - outfile.write(command) - outfile.write(description) - outfile.write('\n') + command = '%s $ARGS $in' % invoc + description = 'Compiling Swift source $in.' + self.add_rule(NinjaRule(rule, command, '', description)) def generate_fortran_dep_hack(self, outfile, crstr): + rule = 'FORTRAN_DEP_HACK%s' % (crstr) if mesonlib.is_windows(): cmd = 'cmd /C ""' else: cmd = 'true' - template = '''# Workaround for these issues: -# https://groups.google.com/forum/#!topic/ninja-build/j-2RfBIOd_8 -# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485 -rule FORTRAN_DEP_HACK%s - command = %s - description = Dep hack - restat = 1 - -''' - outfile.write(template % (crstr, cmd)) + self.add_rule_comment(NinjaComment('''Workaround for these issues: +https://groups.google.com/forum/#!topic/ninja-build/j-2RfBIOd_8 +https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) + self.add_rule(NinjaRule(rule, cmd, '', 'Dep hack', extra='restat = 1')) def generate_llvm_ir_compile_rule(self, compiler, is_cross, outfile): if getattr(self, 'created_llvm_ir_rule', False): return - rule = 'rule llvm_ir{}_COMPILER\n'.format('_CROSS' if is_cross else '') - if compiler.can_linker_accept_rsp(): - command_template = ' command = {executable} @$out.rsp\n' \ - ' rspfile = $out.rsp\n' \ - ' rspfile_content = $ARGS {output_args} {compile_only_args} $in\n' - else: - command_template = ' command = {executable} $ARGS {output_args} {compile_only_args} $in\n' - command = command_template.format( - executable=' '.join([ninja_quote(i) for i in compiler.get_exelist()]), - output_args=' '.join(compiler.get_output_args('$out')), - compile_only_args=' '.join(compiler.get_compile_only_args()) - ) - description = ' description = Compiling LLVM IR object $in.\n' - outfile.write(rule) - outfile.write(command) - outfile.write(description) - outfile.write('\n') + rule = 'llvm_ir{}_COMPILER'.format('_CROSS' if is_cross else '') + command_template = '{executable}' + args_template = '$ARGS {output_args} {compile_only_args} $in' + subst = { + 'executable': ' '.join([ninja_quote(i) for i in compiler.get_exelist()]), + 'output_args': ' '.join(compiler.get_output_args('$out')), + 'compile_only_args': ' '.join(compiler.get_compile_only_args()), + } + command = command_template.format(**subst) + args = args_template.format(**subst) + description = 'Compiling LLVM IR object $in.' + self.add_rule(NinjaRule(rule, command, args, description, + rspable=compiler.can_linker_accept_rsp())) self.created_llvm_ir_rule = True def generate_compile_rule_for(self, langname, compiler, is_cross, outfile): @@ -1646,7 +1653,7 @@ rule FORTRAN_DEP_HACK%s crstr = '' if langname == 'fortran': self.generate_fortran_dep_hack(outfile, crstr) - rule = 'rule %s%s_COMPILER\n' % (langname, crstr) + rule = '%s%s_COMPILER' % (langname, crstr) depargs = compiler.get_dependency_gen_args('$out', '$DEPFILE') quoted_depargs = [] for d in depargs: @@ -1654,30 +1661,26 @@ rule FORTRAN_DEP_HACK%s d = quote_func(d) quoted_depargs.append(d) - if compiler.can_linker_accept_rsp(): - command_template = ''' command = {executable} @$out.rsp - rspfile = $out.rsp - rspfile_content = $ARGS {dep_args} {output_args} {compile_only_args} $in -''' - else: - command_template = ' command = {executable} $ARGS {dep_args} {output_args} {compile_only_args} $in\n' - command = command_template.format( - executable=' '.join([ninja_quote(i) for i in compiler.get_exelist()]), - dep_args=' '.join(quoted_depargs), - output_args=' '.join(compiler.get_output_args('$out')), - compile_only_args=' '.join(compiler.get_compile_only_args()) - ) - description = ' description = Compiling %s object $out.\n' % compiler.get_display_language() + command_template = '{executable}' + args_template = '$ARGS {dep_args} {output_args} {compile_only_args} $in' + subst = { + 'executable': ' '.join([ninja_quote(i) for i in compiler.get_exelist()]), + 'dep_args': ' '.join(quoted_depargs), + 'output_args': ' '.join(compiler.get_output_args('$out')), + 'compile_only_args': ' '.join(compiler.get_compile_only_args()), + } + command = command_template.format(**subst) + args = args_template.format(**subst) + description = 'Compiling %s object $out.' % compiler.get_display_language() if isinstance(compiler, VisualStudioCCompiler): - deps = ' deps = msvc\n' + deps = 'msvc' + depfile = None else: - deps = ' deps = gcc\n' - deps += ' depfile = $DEPFILE\n' - outfile.write(rule) - outfile.write(command) - outfile.write(deps) - outfile.write(description) - outfile.write('\n') + deps = 'gcc' + depfile = '$DEPFILE' + self.add_rule(NinjaRule(rule, command, args, description, + rspable=compiler.can_linker_accept_rsp(), + deps=deps, depfile=depfile)) def generate_pch_rule_for(self, langname, compiler, is_cross, outfile): if langname != 'c' and langname != 'cpp': @@ -1686,7 +1689,7 @@ rule FORTRAN_DEP_HACK%s crstr = '_CROSS' else: crstr = '' - rule = 'rule %s%s_PCH\n' % (langname, crstr) + rule = '%s%s_PCH' % (langname, crstr) depargs = compiler.get_dependency_gen_args('$out', '$DEPFILE') quoted_depargs = [] @@ -1698,23 +1701,21 @@ rule FORTRAN_DEP_HACK%s output = '' else: output = ' '.join(compiler.get_output_args('$out')) - command = " command = {executable} $ARGS {dep_args} {output_args} {compile_only_args} $in\n".format( + command = "{executable} $ARGS {dep_args} {output_args} {compile_only_args} $in".format( executable=' '.join(compiler.get_exelist()), dep_args=' '.join(quoted_depargs), output_args=output, compile_only_args=' '.join(compiler.get_compile_only_args()) ) - description = ' description = Precompiling header %s.\n' % '$in' + description = 'Precompiling header $in.' if isinstance(compiler, VisualStudioCCompiler): - deps = ' deps = msvc\n' + deps = 'msvc' + depfile = None else: - deps = ' deps = gcc\n' - deps += ' depfile = $DEPFILE\n' - outfile.write(rule) - outfile.write(command) - outfile.write(deps) - outfile.write(description) - outfile.write('\n') + deps = 'gcc' + depfile = '$DEPFILE' + self.add_rule(NinjaRule(rule, command, '', description, deps=deps, + depfile=depfile)) def generate_compile_rules(self, outfile): for langname, compiler in self.build.compilers.items(): -- cgit v1.1 From 45d1dff592765a8a225599eec58ef5a75cd521c2 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Wed, 5 Dec 2018 13:41:56 +0000 Subject: ninja: Remove unneeded outfile args (rules) After the previous commit, outfile is now passed down to lots of things which don't use it, as they only create rules, rather than writing them out. Remove these unnecessary args. --- mesonbuild/backend/ninjabackend.py | 65 +++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 8c856b2..2ed2a78 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -271,7 +271,7 @@ int dummy; ''' % num_pools) with self.detect_vs_dep_prefix(tempfilename) as outfile: - self.generate_rules(outfile) + self.generate_rules() self.write_rules(outfile) self.generate_phony(outfile) outfile.write('# Build rules for targets\n\n') @@ -823,16 +823,16 @@ int dummy; # Alias that runs the above-defined meson-benchmark target self.create_target_alias('meson-benchmark', outfile) - def generate_rules(self, outfile): + def generate_rules(self): self.rules = [] self.add_rule_comment(NinjaComment('Rules for compiling.')) - self.generate_compile_rules(outfile) + self.generate_compile_rules() self.add_rule_comment(NinjaComment('Rules for linking.')) if self.environment.is_cross_build(): - self.generate_static_link_rules(True, outfile) - self.generate_static_link_rules(False, outfile) - self.generate_dynamic_link_rules(outfile) + self.generate_static_link_rules(True) + self.generate_static_link_rules(False) + self.generate_dynamic_link_rules() self.add_rule_comment(NinjaComment('Other rules')) # Ninja errors out if you have deps = gcc but no depfile, so we must # have two rules for custom commands. @@ -1025,7 +1025,7 @@ int dummy; element.write(outfile) return plain_class_path - def generate_java_link(self, outfile): + def generate_java_link(self): rule = 'java_LINKER' command = 'jar $ARGS' description = 'Creating JAR $out.' @@ -1458,11 +1458,11 @@ int dummy; # Introspection information self.create_target_source_introspection(target, swiftc, compile_args + header_imports + module_includes, relsrc, rel_generated) - def generate_static_link_rules(self, is_cross, outfile): + def generate_static_link_rules(self, is_cross): num_pools = self.environment.coredata.backend_options['backend_max_links'].value if 'java' in self.build.compilers: if not is_cross: - self.generate_java_link(outfile) + self.generate_java_link() if is_cross: if self.environment.is_cross_build(): static_linker = self.build.static_cross_linker @@ -1503,7 +1503,7 @@ int dummy; rspable=static_linker.can_linker_accept_rsp(), extra=pool)) - def generate_dynamic_link_rules(self, outfile): + def generate_dynamic_link_rules(self): num_pools = self.environment.coredata.backend_options['backend_max_links'].value ctypes = [(self.build.compilers, False)] if self.environment.is_cross_build(): @@ -1549,14 +1549,14 @@ int dummy; synstat = 'restat = 1' self.add_rule(NinjaRule(symrule, symcmd, '', syndesc, extra=synstat)) - def generate_java_compile_rule(self, compiler, outfile): + def generate_java_compile_rule(self, compiler): rule = '%s_COMPILER' % compiler.get_language() invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) command = '%s $ARGS $in' % invoc description = 'Compiling Java object $in.' self.add_rule(NinjaRule(rule, command, '', description)) - def generate_cs_compile_rule(self, compiler, outfile): + def generate_cs_compile_rule(self, compiler): rule = '%s_COMPILER' % compiler.get_language() invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) command = '%s' % invoc @@ -1565,14 +1565,14 @@ int dummy; self.add_rule(NinjaRule(rule, command, args, description, rspable=mesonlib.is_windows())) - def generate_vala_compile_rules(self, compiler, outfile): + def generate_vala_compile_rules(self, compiler): rule = '%s_COMPILER' % compiler.get_language() invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) command = '%s $ARGS $in' % invoc description = 'Compiling Vala source $in.' self.add_rule(NinjaRule(rule, command, '', description, extra='restat = 1')) - def generate_rust_compile_rules(self, compiler, outfile, is_cross): + def generate_rust_compile_rules(self, compiler, is_cross): crstr = '' if is_cross: crstr = '_CROSS' @@ -1585,7 +1585,7 @@ int dummy; self.add_rule(NinjaRule(rule, command, '', description, deps=depstyle, depfile=depfile)) - def generate_swift_compile_rules(self, compiler, outfile): + def generate_swift_compile_rules(self, compiler): rule = '%s_COMPILER' % compiler.get_language() full_exe = [ninja_quote(x) for x in self.environment.get_build_command()] + [ '--internal', @@ -1598,7 +1598,7 @@ int dummy; description = 'Compiling Swift source $in.' self.add_rule(NinjaRule(rule, command, '', description)) - def generate_fortran_dep_hack(self, outfile, crstr): + def generate_fortran_dep_hack(self, crstr): rule = 'FORTRAN_DEP_HACK%s' % (crstr) if mesonlib.is_windows(): cmd = 'cmd /C ""' @@ -1609,7 +1609,7 @@ https://groups.google.com/forum/#!topic/ninja-build/j-2RfBIOd_8 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) self.add_rule(NinjaRule(rule, cmd, '', 'Dep hack', extra='restat = 1')) - def generate_llvm_ir_compile_rule(self, compiler, is_cross, outfile): + def generate_llvm_ir_compile_rule(self, compiler, is_cross): if getattr(self, 'created_llvm_ir_rule', False): return rule = 'llvm_ir{}_COMPILER'.format('_CROSS' if is_cross else '') @@ -1627,32 +1627,32 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) rspable=compiler.can_linker_accept_rsp())) self.created_llvm_ir_rule = True - def generate_compile_rule_for(self, langname, compiler, is_cross, outfile): + def generate_compile_rule_for(self, langname, compiler, is_cross): if langname == 'java': if not is_cross: - self.generate_java_compile_rule(compiler, outfile) + self.generate_java_compile_rule(compiler) return if langname == 'cs': if not is_cross: - self.generate_cs_compile_rule(compiler, outfile) + self.generate_cs_compile_rule(compiler) return if langname == 'vala': if not is_cross: - self.generate_vala_compile_rules(compiler, outfile) + self.generate_vala_compile_rules(compiler) return if langname == 'rust': - self.generate_rust_compile_rules(compiler, outfile, is_cross) + self.generate_rust_compile_rules(compiler, is_cross) return if langname == 'swift': if not is_cross: - self.generate_swift_compile_rules(compiler, outfile) + self.generate_swift_compile_rules(compiler) return if is_cross: crstr = '_CROSS' else: crstr = '' if langname == 'fortran': - self.generate_fortran_dep_hack(outfile, crstr) + self.generate_fortran_dep_hack(crstr) rule = '%s%s_COMPILER' % (langname, crstr) depargs = compiler.get_dependency_gen_args('$out', '$DEPFILE') quoted_depargs = [] @@ -1682,7 +1682,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) rspable=compiler.can_linker_accept_rsp(), deps=deps, depfile=depfile)) - def generate_pch_rule_for(self, langname, compiler, is_cross, outfile): + def generate_pch_rule_for(self, langname, compiler, is_cross): if langname != 'c' and langname != 'cpp': return if is_cross: @@ -1717,20 +1717,19 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) self.add_rule(NinjaRule(rule, command, '', description, deps=deps, depfile=depfile)) - def generate_compile_rules(self, outfile): + def generate_compile_rules(self): for langname, compiler in self.build.compilers.items(): if compiler.get_id() == 'clang': - self.generate_llvm_ir_compile_rule(compiler, False, outfile) - self.generate_compile_rule_for(langname, compiler, False, outfile) - self.generate_pch_rule_for(langname, compiler, False, outfile) + self.generate_llvm_ir_compile_rule(compiler, False) + self.generate_compile_rule_for(langname, compiler, False) + self.generate_pch_rule_for(langname, compiler, False) if self.environment.is_cross_build(): cclist = self.build.cross_compilers for langname, compiler in cclist.items(): if compiler.get_id() == 'clang': - self.generate_llvm_ir_compile_rule(compiler, True, outfile) - self.generate_compile_rule_for(langname, compiler, True, outfile) - self.generate_pch_rule_for(langname, compiler, True, outfile) - outfile.write('\n') + self.generate_llvm_ir_compile_rule(compiler, True) + self.generate_compile_rule_for(langname, compiler, True) + self.generate_pch_rule_for(langname, compiler, True) def generate_generator_list_rules(self, target, outfile): # CustomTargets have already written their rules and -- cgit v1.1 From c4304d25f9df2e37afa76acddc2dd41bdc4e38a5 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Wed, 10 Apr 2019 14:49:29 +0100 Subject: ninja: Store build statements Store the build statements and then write them all out, rather than writing them out as we go. Construct a NinjaBuildElement for the 'PHONY' target, rather than writing it literally to the build.ninja file. --- mesonbuild/backend/ninjabackend.py | 106 +++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 47 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 2ed2a78..bb51559 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -207,7 +207,7 @@ class NinjaBackend(backends.Backend): raise AssertionError(m.format(to_target)) from_target = to_target[len('meson-'):] elem = NinjaBuildElement(self.all_outputs, from_target, 'phony', to_target) - elem.write(outfile) + self.add_build(elem) def detect_vs_dep_prefix(self, tempfilename): '''VS writes its dependency in a locale dependent format. @@ -273,22 +273,24 @@ int dummy; with self.detect_vs_dep_prefix(tempfilename) as outfile: self.generate_rules() self.write_rules(outfile) + self.build_elements = [] self.generate_phony(outfile) - outfile.write('# Build rules for targets\n\n') + self.add_build_comment(NinjaComment('Build rules for targets')) for t in self.build.get_targets().values(): self.generate_target(t, outfile) - outfile.write('# Test rules\n\n') + self.add_build_comment(NinjaComment('Test rules')) self.generate_tests(outfile) - outfile.write('# Install rules\n\n') + self.add_build_comment(NinjaComment('Install rules')) self.generate_install(outfile) self.generate_dist(outfile) if 'b_coverage' in self.environment.coredata.base_options and \ self.environment.coredata.base_options['b_coverage'].value: - outfile.write('# Coverage rules\n\n') + self.add_build_comment(NinjaComment('Coverage rules')) self.generate_coverage_rules(outfile) - outfile.write('# Suffix\n\n') + self.add_build_comment(NinjaComment('Suffix')) self.generate_utils(outfile) self.generate_ending(outfile) + self.write_builds(outfile) default = 'default all\n\n' outfile.write(default) # Only overwrite the old build file after the new one has been @@ -590,7 +592,7 @@ int dummy; linker, stdlib_args = self.determine_linker_and_stdlib_args(target) elem = self.generate_link(target, outfile, outname, obj_list, linker, pch_objects, stdlib_args=stdlib_args) self.generate_shlib_aliases(target, self.get_target_dir(target)) - elem.write(outfile) + self.add_build(elem) def process_target_dependencies(self, target, outfile): for t in target.get_dependencies(): @@ -677,7 +679,7 @@ int dummy; cmd = self.replace_paths(target, cmd) elem.add_item('COMMAND', cmd) elem.add_item('description', desc.format(target.name, cmd_type)) - elem.write(outfile) + self.add_build(elem) self.processed_targets[target.get_id()] = True def generate_run_target(self, target, outfile): @@ -739,7 +741,7 @@ int dummy; elem.add_item('COMMAND', cmd) elem.add_item('description', 'Running external command %s.' % target.name) elem.add_item('pool', 'console') - elem.write(outfile) + self.add_build(elem) # Alias that runs the target defined above with the name the user specified self.create_target_alias(target_name, outfile) self.processed_targets[target.get_id()] = True @@ -758,7 +760,7 @@ int dummy; e = NinjaBuildElement(self.all_outputs, 'meson-coverage', 'CUSTOM_COMMAND', 'PHONY') self.generate_coverage_command(e, []) e.add_item('description', 'Generates coverage reports.') - e.write(outfile) + self.add_build(e) # Alias that runs the target defined above self.create_target_alias('meson-coverage', outfile) self.generate_coverage_legacy_rules(outfile) @@ -767,21 +769,21 @@ int dummy; e = NinjaBuildElement(self.all_outputs, 'meson-coverage-xml', 'CUSTOM_COMMAND', 'PHONY') self.generate_coverage_command(e, ['--xml']) e.add_item('description', 'Generates XML coverage report.') - e.write(outfile) + self.add_build(e) # Alias that runs the target defined above self.create_target_alias('meson-coverage-xml', outfile) e = NinjaBuildElement(self.all_outputs, 'meson-coverage-text', 'CUSTOM_COMMAND', 'PHONY') self.generate_coverage_command(e, ['--text']) e.add_item('description', 'Generates text coverage report.') - e.write(outfile) + self.add_build(e) # Alias that runs the target defined above self.create_target_alias('meson-coverage-text', outfile) e = NinjaBuildElement(self.all_outputs, 'meson-coverage-html', 'CUSTOM_COMMAND', 'PHONY') self.generate_coverage_command(e, ['--html']) e.add_item('description', 'Generates HTML coverage report.') - e.write(outfile) + self.add_build(e) # Alias that runs the target defined above self.create_target_alias('meson-coverage-html', outfile) @@ -792,7 +794,7 @@ int dummy; elem.add_item('DESC', 'Installing files.') elem.add_item('COMMAND', self.environment.get_build_command() + ['install', '--no-rebuild']) elem.add_item('pool', 'console') - elem.write(outfile) + self.add_build(elem) # Alias that runs the target defined above self.create_target_alias('meson-install', outfile) @@ -807,7 +809,7 @@ int dummy; elem.add_item('COMMAND', cmd) elem.add_item('DESC', 'Running all tests.') elem.add_item('pool', 'console') - elem.write(outfile) + self.add_build(elem) # Alias that runs the above-defined meson-test target self.create_target_alias('meson-test', outfile) @@ -819,7 +821,7 @@ int dummy; elem.add_item('COMMAND', cmd) elem.add_item('DESC', 'Running benchmark suite.') elem.add_item('pool', 'console') - elem.write(outfile) + self.add_build(elem) # Alias that runs the above-defined meson-benchmark target self.create_target_alias('meson-benchmark', outfile) @@ -855,17 +857,27 @@ int dummy; def add_rule_comment(self, comment): self.rules.append(comment) + def add_build_comment(self, comment): + self.build_elements.append(comment) + def add_rule(self, rule): self.rules.append(rule) + def add_build(self, build): + self.build_elements.append(build) + def write_rules(self, outfile): for r in self.rules: r.write(outfile) + def write_builds(self, outfile): + for b in self.build_elements: + b.write(outfile) + def generate_phony(self, outfile): - outfile.write('# Phony build target, always out of date\n') - outfile.write('build PHONY: phony\n') - outfile.write('\n') + self.add_build_comment(NinjaComment('Phony build target, always out of date')) + elem = NinjaBuildElement(self.all_outputs, 'PHONY', 'phony', '') + self.add_build(elem) def generate_jar_target(self, target, outfile): fname = target.get_filename() @@ -917,7 +929,7 @@ int dummy; elem = NinjaBuildElement(self.all_outputs, outname_rel, jar_rule, []) elem.add_dep(class_dep_list) elem.add_item('ARGS', commands) - elem.write(outfile) + self.add_build(elem) # Create introspection information self.create_target_source_introspection(target, compiler, compile_args, src_list, gen_src_list) @@ -934,7 +946,7 @@ int dummy; elem = NinjaBuildElement(self.all_outputs, ofilename, "CUSTOM_COMMAND", rel_sourcefile) elem.add_item('COMMAND', ['resgen', rel_sourcefile, ofilename]) elem.add_item('DESC', 'Compiling resource %s.' % rel_sourcefile) - elem.write(outfile) + self.add_build(elem) deps.append(ofilename) a = '-resource:' + ofilename else: @@ -988,7 +1000,7 @@ int dummy; elem = NinjaBuildElement(self.all_outputs, outputs, 'cs_COMPILER', rel_srcs + generated_rel_srcs) elem.add_dep(deps) elem.add_item('ARGS', commands) - elem.write(outfile) + self.add_build(elem) self.generate_generator_list_rules(target, outfile) self.create_target_source_introspection(target, compiler, commands, rel_srcs, generated_rel_srcs) @@ -1022,7 +1034,7 @@ int dummy; element = NinjaBuildElement(self.all_outputs, rel_obj, compiler.get_language() + '_COMPILER', rel_src) element.add_dep(deps) element.add_item('ARGS', args) - element.write(outfile) + self.add_build(element) return plain_class_path def generate_java_link(self): @@ -1220,7 +1232,7 @@ int dummy; all_files + dependency_vapis) element.add_item('ARGS', args) element.add_dep(extra_dep_files) - element.write(outfile) + self.add_build(element) self.create_target_source_introspection(target, valac, args, all_files, []) return other_src[0], other_src[1], vala_c_src @@ -1312,7 +1324,7 @@ int dummy; element.add_item('ARGS', args) element.add_item('targetdep', depfile) element.add_item('cratetype', cratetype) - element.write(outfile) + self.add_build(element) if isinstance(target, build.SharedLibrary): self.generate_shsym(outfile, target) self.create_target_source_introspection(target, rustc, args, [main_rust_file], []) @@ -1434,25 +1446,25 @@ int dummy; elem.add_dep(abs_headers) elem.add_item('ARGS', compile_args + header_imports + abs_generated + module_includes) elem.add_item('RUNDIR', rundir) - elem.write(outfile) + self.add_build(elem) elem = NinjaBuildElement(self.all_outputs, out_module_name, 'swift_COMPILER', abssrc) elem.add_dep(in_module_files + rel_generated) elem.add_item('ARGS', compile_args + abs_generated + module_includes + swiftc.get_mod_gen_args()) elem.add_item('RUNDIR', rundir) - elem.write(outfile) + self.add_build(elem) if isinstance(target, build.StaticLibrary): elem = self.generate_link(target, outfile, self.get_target_filename(target), rel_objects, self.build.static_linker) - elem.write(outfile) + self.add_build(elem) elif isinstance(target, build.Executable): elem = NinjaBuildElement(self.all_outputs, self.get_target_filename(target), 'swift_COMPILER', []) elem.add_dep(rel_objects) elem.add_dep(link_deps) elem.add_item('ARGS', link_args + swiftc.get_std_exe_link_args() + objects + abs_link_deps) elem.add_item('RUNDIR', rundir) - elem.write(outfile) + self.add_build(elem) else: raise MesonException('Swift supports only executable and static library targets.') # Introspection information @@ -1815,7 +1827,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) if isinstance(exe, build.BuildTarget): elem.add_dep(self.get_target_filename(exe)) elem.add_item('COMMAND', cmd) - elem.write(outfile) + self.add_build(elem) def scan_fortran_module_outputs(self, target): """ @@ -1981,7 +1993,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) # current compiler. commands = commands.to_native() element.add_item('ARGS', commands) - element.write(outfile) + self.add_build(element) return rel_obj def get_source_dir_include_args(self, target, compiler): @@ -2179,7 +2191,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) if srcfile == src: depelem = NinjaBuildElement(self.all_outputs, modfile, 'FORTRAN_DEP_HACK' + crstr, rel_obj) - depelem.write(outfile) + self.add_build(depelem) commands += compiler.get_module_outdir_args(self.get_target_private_dir(target)) element = NinjaBuildElement(self.all_outputs, rel_obj, compiler_name, rel_src) @@ -2200,7 +2212,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) element.add_orderdep(i) element.add_item('DEPFILE', dep_file) element.add_item('ARGS', commands) - element.write(outfile) + self.add_build(element) return rel_obj def add_header_deps(self, target, ninja_element, header_deps): @@ -2297,7 +2309,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) self.add_header_deps(target, elem, header_deps) elem.add_item('ARGS', commands) elem.add_item('DEPFILE', dep) - elem.write(outfile) + self.add_build(elem) return pch_objects def generate_shsym(self, outfile, target): @@ -2308,7 +2320,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) elem = NinjaBuildElement(self.all_outputs, symname, 'SHSYM', target_file) if self.environment.is_cross_build(): elem.add_item('CROSS', '--cross-host=' + self.environment.machines.host.system) - elem.write(outfile) + self.add_build(elem) def get_cross_stdlib_link_args(self, target, linker): if isinstance(target, build.StaticLibrary) or not target.is_cross: @@ -2610,7 +2622,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) 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.') - e.write(outfile) + self.add_build(e) # Alias that runs the target defined above self.create_target_alias('meson-clean-ctlist', outfile) # Write out the data file passed to the script @@ -2624,7 +2636,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) clean_script = os.path.join(script_root, 'delwithsuffix.py') gcno_elem.add_item('COMMAND', mesonlib.python_command + [clean_script, '.', 'gcno']) gcno_elem.add_item('description', 'Deleting gcno files.') - gcno_elem.write(outfile) + self.add_build(gcno_elem) # Alias that runs the target defined above self.create_target_alias('meson-clean-gcno', outfile) @@ -2633,7 +2645,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) clean_script = os.path.join(script_root, 'delwithsuffix.py') gcda_elem.add_item('COMMAND', mesonlib.python_command + [clean_script, '.', 'gcda']) gcda_elem.add_item('description', 'Deleting gcda files.') - gcda_elem.write(outfile) + self.add_build(gcda_elem) # Alias that runs the target defined above self.create_target_alias('meson-clean-gcda', outfile) @@ -2655,7 +2667,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) self.environment.build_dir, ] + self.environment.get_build_command()) elem.add_item('pool', 'console') - elem.write(outfile) + self.add_build(elem) # Alias that runs the target defined above self.create_target_alias('meson-dist', outfile) @@ -2666,7 +2678,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) elem = NinjaBuildElement(self.all_outputs, 'meson-scan-build', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', cmd) elem.add_item('pool', 'console') - elem.write(outfile) + self.add_build(elem) # Alias that runs the target defined above self.create_target_alias('meson-scan-build', outfile) @@ -2685,7 +2697,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) elem = NinjaBuildElement(self.all_outputs, 'meson-' + target_name, 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', cmd) elem.add_item('pool', 'console') - elem.write(outfile) + self.add_build(elem) self.create_target_alias('meson-' + target_name, outfile) # For things like scan-build and other helper tools we might have. @@ -2696,7 +2708,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) elem = NinjaBuildElement(self.all_outputs, 'meson-uninstall', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', cmd) elem.add_item('pool', 'console') - elem.write(outfile) + self.add_build(elem) # Alias that runs the target defined above self.create_target_alias('meson-uninstall', outfile) @@ -2708,7 +2720,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) targetlist.append(os.path.join(self.get_target_dir(t), t.get_outputs()[0])) elem = NinjaBuildElement(self.all_outputs, 'all', 'phony', targetlist) - elem.write(outfile) + self.add_build(elem) elem = NinjaBuildElement(self.all_outputs, 'meson-clean', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('COMMAND', [self.ninja_command, '-t', 'clean']) @@ -2736,19 +2748,19 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) self.generate_gcov_clean(outfile) elem.add_dep('clean-gcda') elem.add_dep('clean-gcno') - elem.write(outfile) + self.add_build(elem) deps = self.get_regen_filelist() elem = NinjaBuildElement(self.all_outputs, 'build.ninja', 'REGENERATE_BUILD', deps) elem.add_item('pool', 'console') - elem.write(outfile) + self.add_build(elem) elem = NinjaBuildElement(self.all_outputs, 'reconfigure', 'REGENERATE_BUILD', 'PHONY') elem.add_item('pool', 'console') - elem.write(outfile) + self.add_build(elem) elem = NinjaBuildElement(self.all_outputs, deps, 'phony', '') - elem.write(outfile) + self.add_build(elem) def get_introspection_data(self, target_id, target): if target_id not in self.introspection_data or len(self.introspection_data[target_id]) == 0: -- cgit v1.1 From 798cacd30a3f174b2d4c6373e6415ab52b1970e9 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Wed, 10 Apr 2019 15:54:02 +0100 Subject: ninja: Remove unneeded outfile args (build statements) After the previous commit, outfile is now passed down to lots of things which don't use it, as they only create built statements, rather than writing them out. Remove these unnecessary args. --- mesonbuild/backend/ninjabackend.py | 176 ++++++++++++++++++------------------- 1 file changed, 88 insertions(+), 88 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index bb51559..1cab434 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -196,7 +196,7 @@ class NinjaBackend(backends.Backend): self.all_outputs = {} self.introspection_data = {} - def create_target_alias(self, to_target, outfile): + 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', @@ -274,22 +274,22 @@ int dummy; self.generate_rules() self.write_rules(outfile) self.build_elements = [] - self.generate_phony(outfile) + self.generate_phony() self.add_build_comment(NinjaComment('Build rules for targets')) for t in self.build.get_targets().values(): - self.generate_target(t, outfile) + self.generate_target(t) self.add_build_comment(NinjaComment('Test rules')) - self.generate_tests(outfile) + self.generate_tests() self.add_build_comment(NinjaComment('Install rules')) - self.generate_install(outfile) - self.generate_dist(outfile) + self.generate_install() + self.generate_dist() if 'b_coverage' in self.environment.coredata.base_options and \ self.environment.coredata.base_options['b_coverage'].value: self.add_build_comment(NinjaComment('Coverage rules')) - self.generate_coverage_rules(outfile) + self.generate_coverage_rules() self.add_build_comment(NinjaComment('Suffix')) - self.generate_utils(outfile) - self.generate_ending(outfile) + self.generate_utils() + self.generate_ending() self.write_builds(outfile) default = 'default all\n\n' outfile.write(default) @@ -432,11 +432,11 @@ int dummy; return True return False - def generate_target(self, target, outfile): + def generate_target(self, target): if isinstance(target, build.CustomTarget): - self.generate_custom_target(target, outfile) + self.generate_custom_target(target) if isinstance(target, build.RunTarget): - self.generate_run_target(target, outfile) + self.generate_run_target(target) name = target.get_id() if name in self.processed_targets: return @@ -444,20 +444,20 @@ int dummy; # Initialize an empty introspection source list self.introspection_data[name] = {} # Generate rules for all dependency targets - self.process_target_dependencies(target, outfile) + self.process_target_dependencies(target) # If target uses a language that cannot link to C objects, # just generate for that language and return. if isinstance(target, build.Jar): - self.generate_jar_target(target, outfile) + self.generate_jar_target(target) return if self.is_rust_target(target): - self.generate_rust_target(target, outfile) + self.generate_rust_target(target) return if 'cs' in target.compilers: - self.generate_cs_target(target, outfile) + self.generate_cs_target(target) return if 'swift' in target.compilers: - self.generate_swift_target(target, outfile) + self.generate_swift_target(target) return # Now we handle the following languages: @@ -475,14 +475,14 @@ int dummy; # Sources consumed by valac are filtered out. These only contain # C/C++ sources, objects, generated libs, and unknown sources now. target_sources, generated_sources, \ - vala_generated_sources = self.generate_vala_compile(target, outfile) + vala_generated_sources = self.generate_vala_compile(target) else: target_sources = self.get_target_sources(target) generated_sources = self.get_target_generated_sources(target) vala_generated_sources = [] self.scan_fortran_module_outputs(target) # Generate rules for GeneratedLists - self.generate_generator_list_rules(target, outfile) + self.generate_generator_list_rules(target) # Generate rules for building the remaining source files in this target outname = self.get_target_filename(target) @@ -534,15 +534,15 @@ int dummy; # because we need `header_deps` to be fully generated in the above loop. for src in generated_source_files: if self.environment.is_llvm_ir(src): - o = self.generate_llvm_ir_compile(target, outfile, src) + o = self.generate_llvm_ir_compile(target, src) else: - o = self.generate_single_compile(target, outfile, src, True, + o = self.generate_single_compile(target, src, True, header_deps=header_deps) obj_list.append(o) use_pch = self.environment.coredata.base_options.get('b_pch', False) if use_pch and target.has_pch(): - pch_objects = self.generate_pch(target, outfile, header_deps=header_deps) + pch_objects = self.generate_pch(target, header_deps=header_deps) else: pch_objects = [] @@ -572,39 +572,39 @@ int dummy; # Passing 'vala' here signifies that we want the compile # arguments to be specialized for C code generated by # valac. For instance, no warnings should be emitted. - obj_list.append(self.generate_single_compile(target, outfile, src, 'vala', [], header_deps)) + obj_list.append(self.generate_single_compile(target, src, 'vala', [], header_deps)) # Generate compile targets for all the pre-existing sources for this target for f, src in target_sources.items(): if not self.environment.is_header(src): if self.environment.is_llvm_ir(src): - obj_list.append(self.generate_llvm_ir_compile(target, outfile, src)) + obj_list.append(self.generate_llvm_ir_compile(target, src)) elif is_unity and self.get_target_source_can_unity(target, src): abs_src = os.path.join(self.environment.get_build_dir(), src.rel_to_builddir(self.build_to_src)) unity_src.append(abs_src) else: - obj_list.append(self.generate_single_compile(target, outfile, src, False, [], header_deps)) + obj_list.append(self.generate_single_compile(target, src, False, [], header_deps)) obj_list += self.flatten_object_list(target) if is_unity: for src in self.generate_unity_files(target, unity_src): - obj_list.append(self.generate_single_compile(target, outfile, src, True, unity_deps + header_deps)) + obj_list.append(self.generate_single_compile(target, src, True, unity_deps + header_deps)) linker, stdlib_args = self.determine_linker_and_stdlib_args(target) - elem = self.generate_link(target, outfile, outname, obj_list, linker, pch_objects, stdlib_args=stdlib_args) + elem = self.generate_link(target, outname, obj_list, linker, pch_objects, stdlib_args=stdlib_args) self.generate_shlib_aliases(target, self.get_target_dir(target)) self.add_build(elem) - def process_target_dependencies(self, target, outfile): + def process_target_dependencies(self, target): for t in target.get_dependencies(): if t.get_id() not in self.processed_targets: - self.generate_target(t, outfile) + self.generate_target(t) - def custom_target_generator_inputs(self, target, outfile): + def custom_target_generator_inputs(self, target): for s in target.sources: if hasattr(s, 'held_object'): s = s.held_object if isinstance(s, build.GeneratedList): - self.generate_genlist_for_target(s, target, outfile) + self.generate_genlist_for_target(s, target) def unwrap_dep_list(self, target): deps = [] @@ -617,8 +617,8 @@ int dummy; deps.append(os.path.join(self.get_target_dir(i), output)) return deps - def generate_custom_target(self, target, outfile): - self.custom_target_generator_inputs(target, outfile) + def generate_custom_target(self, target): + self.custom_target_generator_inputs(target) (srcs, ofilenames, cmd) = self.eval_custom_target_command(target) deps = self.unwrap_dep_list(target) deps += self.get_custom_target_depend_files(target) @@ -682,7 +682,7 @@ int dummy; self.add_build(elem) self.processed_targets[target.get_id()] = True - def generate_run_target(self, target, outfile): + def generate_run_target(self, target): cmd = self.environment.get_build_command() + ['--internal', 'commandrunner'] deps = self.unwrap_dep_list(target) arg_strings = [] @@ -743,7 +743,7 @@ int dummy; elem.add_item('pool', 'console') self.add_build(elem) # Alias that runs the target defined above with the name the user specified - self.create_target_alias(target_name, outfile) + self.create_target_alias(target_name) self.processed_targets[target.get_id()] = True def generate_coverage_command(self, elem, outputs): @@ -756,38 +756,38 @@ int dummy; self.environment.get_build_dir(), self.environment.get_log_dir()]) - def generate_coverage_rules(self, outfile): + def generate_coverage_rules(self): e = NinjaBuildElement(self.all_outputs, 'meson-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', outfile) - self.generate_coverage_legacy_rules(outfile) + self.create_target_alias('meson-coverage') + self.generate_coverage_legacy_rules() - def generate_coverage_legacy_rules(self, outfile): + def generate_coverage_legacy_rules(self): e = NinjaBuildElement(self.all_outputs, 'meson-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', outfile) + self.create_target_alias('meson-coverage-xml') e = NinjaBuildElement(self.all_outputs, 'meson-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', outfile) + self.create_target_alias('meson-coverage-text') e = NinjaBuildElement(self.all_outputs, 'meson-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', outfile) + self.create_target_alias('meson-coverage-html') - def generate_install(self, outfile): + def generate_install(self): self.create_install_data_files() elem = NinjaBuildElement(self.all_outputs, 'meson-install', 'CUSTOM_COMMAND', 'PHONY') elem.add_dep('all') @@ -796,9 +796,9 @@ int dummy; elem.add_item('pool', 'console') self.add_build(elem) # Alias that runs the target defined above - self.create_target_alias('meson-install', outfile) + self.create_target_alias('meson-install') - def generate_tests(self, outfile): + def generate_tests(self): self.serialize_tests() cmd = self.environment.get_build_command(True) + ['test', '--no-rebuild'] if not self.environment.coredata.get_builtin_option('stdsplit'): @@ -811,7 +811,7 @@ int dummy; elem.add_item('pool', 'console') self.add_build(elem) # Alias that runs the above-defined meson-test target - self.create_target_alias('meson-test', outfile) + self.create_target_alias('meson-test') # And then benchmarks. cmd = self.environment.get_build_command(True) + [ @@ -823,7 +823,7 @@ int dummy; elem.add_item('pool', 'console') self.add_build(elem) # Alias that runs the above-defined meson-benchmark target - self.create_target_alias('meson-benchmark', outfile) + self.create_target_alias('meson-benchmark') def generate_rules(self): self.rules = [] @@ -874,12 +874,12 @@ int dummy; for b in self.build_elements: b.write(outfile) - def generate_phony(self, outfile): + def generate_phony(self): self.add_build_comment(NinjaComment('Phony build target, always out of date')) elem = NinjaBuildElement(self.all_outputs, 'PHONY', 'phony', '') self.add_build(elem) - def generate_jar_target(self, target, outfile): + def generate_jar_target(self, target): fname = target.get_filename() outname_rel = os.path.join(self.get_target_dir(target), fname) src_list = target.get_sources() @@ -904,7 +904,7 @@ int dummy; compile_args = self.determine_single_java_compile_args(target, compiler) for src in src_list + gen_src_list: - plain_class_path = self.generate_single_java_compile(src, target, compiler, compile_args, outfile) + plain_class_path = self.generate_single_java_compile(src, target, compiler, compile_args) class_list.append(plain_class_path) class_dep_list = [os.path.join(self.get_target_private_dir(target), i) for i in class_list] manifest_path = os.path.join(self.get_target_private_dir(target), 'META-INF', 'MANIFEST.MF') @@ -933,7 +933,7 @@ int dummy; # Create introspection information self.create_target_source_introspection(target, compiler, compile_args, src_list, gen_src_list) - def generate_cs_resource_tasks(self, target, outfile): + def generate_cs_resource_tasks(self, target): args = [] deps = [] for r in target.resources: @@ -954,7 +954,7 @@ int dummy; args.append(a) return args, deps - def generate_cs_target(self, target, outfile): + def generate_cs_target(self, target): buildtype = self.get_option_for_target('buildtype', target) fname = target.get_filename() outname_rel = os.path.join(self.get_target_dir(target), fname) @@ -972,7 +972,7 @@ int dummy; commands.append('-target:library') else: raise MesonException('Unknown C# target type.') - (resource_args, resource_deps) = self.generate_cs_resource_tasks(target, outfile) + (resource_args, resource_deps) = self.generate_cs_resource_tasks(target) commands += resource_args deps += resource_deps commands += compiler.get_output_args(outname_rel) @@ -1002,7 +1002,7 @@ int dummy; elem.add_item('ARGS', commands) self.add_build(elem) - self.generate_generator_list_rules(target, outfile) + self.generate_generator_list_rules(target) self.create_target_source_introspection(target, compiler, commands, rel_srcs, generated_rel_srcs) def determine_single_java_compile_args(self, target, compiler): @@ -1022,7 +1022,7 @@ int dummy; args += ['-sourcepath', sourcepath] return args - def generate_single_java_compile(self, src, target, compiler, args, outfile): + def generate_single_java_compile(self, src, target, compiler, args): deps = [os.path.join(self.get_target_dir(l), l.get_filename()) for l in target.link_targets] generated_sources = self.get_target_generated_sources(target) for rel_src, gensrc in generated_sources.items(): @@ -1117,7 +1117,7 @@ int dummy; srctype[f] = gensrc return vala, vapi, (others, othersgen) - def generate_vala_compile(self, target, outfile): + def generate_vala_compile(self, target): """Vala is compiled into C. Set up all necessary build steps here.""" (vala_src, vapi_src, other_src) = self.split_vala_sources(target) extra_dep_files = [] @@ -1236,7 +1236,7 @@ int dummy; self.create_target_source_introspection(target, valac, args, all_files, []) return other_src[0], other_src[1], vala_c_src - def generate_rust_target(self, target, outfile): + def generate_rust_target(self, target): rustc = target.compilers['rust'] # Rust compiler takes only the main file as input and # figures out what other files are needed via import @@ -1326,7 +1326,7 @@ int dummy; element.add_item('cratetype', cratetype) self.add_build(element) if isinstance(target, build.SharedLibrary): - self.generate_shsym(outfile, target) + self.generate_shsym(target) self.create_target_source_introspection(target, rustc, args, [main_rust_file], []) def swift_module_file_name(self, target): @@ -1372,7 +1372,7 @@ int dummy; others.append(i) return srcs, others - def generate_swift_target(self, target, outfile): + def generate_swift_target(self, target): module_name = self.target_swift_modulename(target) swiftc = target.compilers['swift'] abssrc = [] @@ -1455,7 +1455,7 @@ int dummy; elem.add_item('RUNDIR', rundir) self.add_build(elem) if isinstance(target, build.StaticLibrary): - elem = self.generate_link(target, outfile, self.get_target_filename(target), + elem = self.generate_link(target, self.get_target_filename(target), rel_objects, self.build.static_linker) self.add_build(elem) elif isinstance(target, build.Executable): @@ -1743,14 +1743,14 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) self.generate_compile_rule_for(langname, compiler, True) self.generate_pch_rule_for(langname, compiler, True) - def generate_generator_list_rules(self, target, outfile): + def generate_generator_list_rules(self, target): # CustomTargets have already written their rules and # CustomTargetIndexes don't actually get generated, so write rules for # GeneratedLists here for genlist in target.get_generated_sources(): if isinstance(genlist, (build.CustomTarget, build.CustomTargetIndex)): continue - self.generate_genlist_for_target(genlist, target, outfile) + self.generate_genlist_for_target(genlist, target) def replace_paths(self, target, args, override_subdir=None): if override_subdir: @@ -1766,7 +1766,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) args = [x.replace('\\', '/') for x in args] return args - def generate_genlist_for_target(self, genlist, target, outfile): + def generate_genlist_for_target(self, genlist, target): generator = genlist.get_generator() subdir = genlist.subdir exe = generator.get_exe() @@ -1961,7 +1961,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) def get_link_debugfile_args(self, linker, target, outname): return linker.get_link_debugfile_args(outname) - def generate_llvm_ir_compile(self, target, outfile, src): + def generate_llvm_ir_compile(self, target, src): compiler = get_compiler_for_source(target.compilers.values(), src) commands = CompilerArgs(compiler) # Compiler args for compiling this target @@ -2114,7 +2114,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) commands += compiler.get_include_args(self.get_target_private_dir(target), False) return commands - def generate_single_compile(self, target, outfile, src, is_generated=False, header_deps=None, order_deps=None): + def generate_single_compile(self, target, src, is_generated=False, header_deps=None, order_deps=None): """ Compiles C/C++, ObjC/ObjC++, Fortran, and D sources """ @@ -2275,7 +2275,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) dep = dst + '.' + compiler.get_depfile_suffix() return commands, dep, dst, [] # Gcc does not create an object file during pch generation. - def generate_pch(self, target, outfile, header_deps=None): + def generate_pch(self, target, header_deps=None): header_deps = header_deps if header_deps is not None else [] cstr = '' pch_objects = [] @@ -2312,7 +2312,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) self.add_build(elem) return pch_objects - def generate_shsym(self, outfile, target): + def generate_shsym(self, target): target_name = target.get_filename() target_file = self.get_target_filename(target) targetdir = self.get_target_private_dir(target) @@ -2455,7 +2455,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) return guessed_dependencies + absolute_libs - def generate_link(self, target, outfile, outname, obj_list, linker, extra_args=None, stdlib_args=None): + def generate_link(self, target, outname, obj_list, linker, extra_args=None, stdlib_args=None): extra_args = extra_args if extra_args is not None else [] stdlib_args = stdlib_args if stdlib_args is not None else [] if isinstance(target, build.StaticLibrary): @@ -2463,7 +2463,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) else: linker_base = linker.get_language() # Fixme. if isinstance(target, build.SharedLibrary): - self.generate_shsym(outfile, target) + self.generate_shsym(target) crstr = '' if target.is_cross: crstr = '_CROSS' @@ -2616,7 +2616,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) except OSError: mlog.debug("Library versioning disabled because we do not have symlink creation privileges.") - def generate_custom_target_clean(self, outfile, trees): + def generate_custom_target_clean(self, trees): e = NinjaBuildElement(self.all_outputs, 'meson-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') @@ -2624,13 +2624,13 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) 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', outfile) + 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, outfile): + def generate_gcov_clean(self): gcno_elem = NinjaBuildElement(self.all_outputs, 'meson-clean-gcno', 'CUSTOM_COMMAND', 'PHONY') script_root = self.environment.get_script_dir() clean_script = os.path.join(script_root, 'delwithsuffix.py') @@ -2638,7 +2638,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) 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', outfile) + self.create_target_alias('meson-clean-gcno') gcda_elem = NinjaBuildElement(self.all_outputs, 'meson-clean-gcda', 'CUSTOM_COMMAND', 'PHONY') script_root = self.environment.get_script_dir() @@ -2647,7 +2647,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) 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', outfile) + self.create_target_alias('meson-clean-gcda') def get_user_option_args(self): cmds = [] @@ -2658,7 +2658,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) # affect behavior in any other way. return sorted(cmds) - def generate_dist(self, outfile): + def generate_dist(self): elem = NinjaBuildElement(self.all_outputs, 'meson-dist', 'CUSTOM_COMMAND', 'PHONY') elem.add_item('DESC', 'Creating source packages') elem.add_item('COMMAND', self.environment.get_build_command() + [ @@ -2669,9 +2669,9 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) elem.add_item('pool', 'console') self.add_build(elem) # Alias that runs the target defined above - self.create_target_alias('meson-dist', outfile) + self.create_target_alias('meson-dist') - def generate_scanbuild(self, outfile): + def generate_scanbuild(self): 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() @@ -2680,9 +2680,9 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) elem.add_item('pool', 'console') self.add_build(elem) # Alias that runs the target defined above - self.create_target_alias('meson-scan-build', outfile) + self.create_target_alias('meson-scan-build') - def generate_clangformat(self, outfile): + def generate_clangformat(self): import shutil target_name = 'clang-format' if shutil.which('clang-format') is None: @@ -2698,21 +2698,21 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) elem.add_item('COMMAND', cmd) elem.add_item('pool', 'console') self.add_build(elem) - self.create_target_alias('meson-' + target_name, outfile) + self.create_target_alias('meson-' + target_name) # For things like scan-build and other helper tools we might have. - def generate_utils(self, outfile): - self.generate_scanbuild(outfile) - self.generate_clangformat(outfile) + def generate_utils(self): + self.generate_scanbuild() + self.generate_clangformat() cmd = self.environment.get_build_command() + ['--internal', 'uninstall'] elem = NinjaBuildElement(self.all_outputs, 'meson-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', outfile) + self.create_target_alias('meson-uninstall') - def generate_ending(self, outfile): + def generate_ending(self): targetlist = [] for t in self.get_build_by_default_targets().values(): # Add the first output of each target to the 'all' target so that @@ -2726,7 +2726,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) 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', outfile) + 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 @@ -2741,11 +2741,11 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) for o in t.get_outputs(): ctlist.append(os.path.join(self.get_target_dir(t), o)) if ctlist: - elem.add_dep(self.generate_custom_target_clean(outfile, ctlist)) + elem.add_dep(self.generate_custom_target_clean(ctlist)) if 'b_coverage' in self.environment.coredata.base_options and \ self.environment.coredata.base_options['b_coverage'].value: - self.generate_gcov_clean(outfile) + self.generate_gcov_clean() elem.add_dep('clean-gcda') elem.add_dep('clean-gcno') self.add_build(elem) -- cgit v1.1 From e4d4ac773adcae257c9dd17753a6f3f132356759 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Fri, 12 Apr 2019 15:42:27 +0100 Subject: ninja: Push concatenation of command down into NinjaRule Pass the command line to NinjaRule() as a list of strings, not already concatenated as a string. --- mesonbuild/backend/ninjabackend.py | 126 ++++++++++++++----------------------- 1 file changed, 47 insertions(+), 79 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 1cab434..977bcdd 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -40,12 +40,12 @@ FORTRAN_SUBMOD_PAT = r"\s*submodule\s*\((\w+:?\w+)\)\s*(\w+)\s*$" if mesonlib.is_windows(): quote_func = lambda s: '"{}"'.format(s) - execute_wrapper = 'cmd /c' - rmfile_prefix = 'del /f /s /q {} &&' + execute_wrapper = ['cmd', '/c'] + rmfile_prefix = ['del', '/f', '/s', '/q', '{}', '&&'] else: quote_func = shlex.quote - execute_wrapper = '' - rmfile_prefix = 'rm -f {} &&' + execute_wrapper = [] + rmfile_prefix = ['rm', '-f', '{}', '&&'] def ninja_quote(text, is_build_line=False): if is_build_line: @@ -89,11 +89,11 @@ class NinjaRule: def write(self, outfile): outfile.write('rule %s\n' % self.name) if self.rspable: - outfile.write(' command = %s @$out.rsp\n' % self.command) + outfile.write(' command = %s @$out.rsp\n' % ' '.join(self.command)) outfile.write(' rspfile = $out.rsp\n') - outfile.write(' rspfile_content = %s\n' % self.args) + outfile.write(' rspfile_content = %s\n' % ' '.join(self.args)) else: - outfile.write(' command = %s %s\n' % (self.command, self.args)) + outfile.write(' command = %s\n' % ' '.join(self.command + self.args)) if self.deps: outfile.write(' deps = %s\n' % self.deps) if self.depfile: @@ -838,9 +838,9 @@ int dummy; self.add_rule_comment(NinjaComment('Other rules')) # Ninja errors out if you have deps = gcc but no depfile, so we must # have two rules for custom commands. - self.add_rule(NinjaRule('CUSTOM_COMMAND', '$COMMAND', '', '$DESC', + self.add_rule(NinjaRule('CUSTOM_COMMAND', ['$COMMAND'], [], '$DESC', extra='restat = 1')) - self.add_rule(NinjaRule('CUSTOM_COMMAND_DEP', '$COMMAND', '', '$DESC', + self.add_rule(NinjaRule('CUSTOM_COMMAND_DEP', ['$COMMAND'], [], '$DESC', deps='gcc', depfile='$DEPFILE', extra='restat = 1')) @@ -850,7 +850,7 @@ int dummy; ninja_quote(quote_func(self.environment.get_source_dir())), ninja_quote(quote_func(self.environment.get_build_dir()))] self.add_rule(NinjaRule('REGENERATE_BUILD', - ' '.join(c) + ' --backend ninja', '', + c + ['--backend', 'ninja'], [], 'Regenerating build files.', extra='generator = 1')) @@ -1039,9 +1039,9 @@ int dummy; def generate_java_link(self): rule = 'java_LINKER' - command = 'jar $ARGS' + command = ['jar', '$ARGS'] description = 'Creating JAR $out.' - self.add_rule(NinjaRule(rule, command, '', description)) + self.add_rule(NinjaRule(rule, command, [], description)) def determine_dep_vapis(self, target): """ @@ -1487,10 +1487,8 @@ int dummy; if static_linker is None: return rule = 'STATIC%s_LINKER' % crstr - command_template = '{executable} $LINK_ARGS {output_args}' - args = '$in' - cmdlist = [] + args = ['$in'] # FIXME: Must normalize file names with pathlib.Path before writing # them out to fix this properly on Windows. See: # https://github.com/mesonbuild/meson/issues/1517 @@ -1499,19 +1497,16 @@ int dummy; # `ar` has no options to overwrite archives. It always appends, # which is never what we want. Delete an existing library first if # it exists. https://github.com/mesonbuild/meson/issues/1355 - cmdlist = [execute_wrapper, rmfile_prefix.format('$out')] + cmdlist = execute_wrapper + [c.format('$out') for c in rmfile_prefix] cmdlist += static_linker.get_exelist() - subst = { - 'executable': ' '.join(cmdlist), - 'output_args': ' '.join(static_linker.get_output_args('$out')) - } - command = command_template.format(**subst) + cmdlist += ['$LINK_ARGS'] + cmdlist += static_linker.get_output_args('$out') description = 'Linking static target $out.' if num_pools > 0: pool = 'pool = link_pool' else: pool = None - self.add_rule(NinjaRule(rule, command, args, description, + self.add_rule(NinjaRule(rule, cmdlist, args, description, rspable=static_linker.can_linker_accept_rsp(), extra=pool)) @@ -1533,14 +1528,8 @@ int dummy; if is_cross: crstr = '_CROSS' rule = '%s%s_LINKER' % (langname, crstr) - command_template = '{executable}' - args_template = '$ARGS {output_args} $in $LINK_ARGS' - subst = { - 'executable': ' '.join(compiler.get_linker_exelist()), - 'output_args': ' '.join(compiler.get_linker_output_args('$out')), - } - command = command_template.format(**subst) - args = args_template.format(**subst) + command = compiler.get_linker_exelist() + args = ['$ARGS'] + compiler.get_linker_output_args('$out') + ['$in', '$LINK_ARGS'] description = 'Linking target $out.' if num_pools > 0: pool = 'pool = link_pool' @@ -1556,45 +1545,45 @@ int dummy; '$in', '$out'] symrule = 'SHSYM' - symcmd = ' '.join(args) + ' $CROSS' + symcmd = args + ['$CROSS'] syndesc = 'Generating symbol file $out.' synstat = 'restat = 1' - self.add_rule(NinjaRule(symrule, symcmd, '', syndesc, extra=synstat)) + self.add_rule(NinjaRule(symrule, symcmd, [], syndesc, extra=synstat)) def generate_java_compile_rule(self, compiler): rule = '%s_COMPILER' % compiler.get_language() - invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) - command = '%s $ARGS $in' % invoc + invoc = [ninja_quote(i) for i in compiler.get_exelist()] + command = invoc + ['$ARGS', '$in'] description = 'Compiling Java object $in.' - self.add_rule(NinjaRule(rule, command, '', description)) + self.add_rule(NinjaRule(rule, command, [], description)) def generate_cs_compile_rule(self, compiler): rule = '%s_COMPILER' % compiler.get_language() - invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) - command = '%s' % invoc - args = '$ARGS $in' + invoc = [ninja_quote(i) for i in compiler.get_exelist()] + command = invoc + args = ['$ARGS', '$in'] description = 'Compiling C Sharp target $out.' self.add_rule(NinjaRule(rule, command, args, description, rspable=mesonlib.is_windows())) def generate_vala_compile_rules(self, compiler): rule = '%s_COMPILER' % compiler.get_language() - invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) - command = '%s $ARGS $in' % invoc + invoc = [ninja_quote(i) for i in compiler.get_exelist()] + command = invoc + ['$ARGS', '$in'] description = 'Compiling Vala source $in.' - self.add_rule(NinjaRule(rule, command, '', description, extra='restat = 1')) + self.add_rule(NinjaRule(rule, command, [], description, extra='restat = 1')) def generate_rust_compile_rules(self, compiler, is_cross): crstr = '' if is_cross: crstr = '_CROSS' rule = '%s%s_COMPILER' % (compiler.get_language(), crstr) - invoc = ' '.join([ninja_quote(i) for i in compiler.get_exelist()]) - command = '%s $ARGS $in' % invoc + invoc = [ninja_quote(i) for i in compiler.get_exelist()] + command = invoc + ['$ARGS', '$in'] description = 'Compiling Rust source $in.' depfile = '$targetdep' depstyle = 'gcc' - self.add_rule(NinjaRule(rule, command, '', description, deps=depstyle, + self.add_rule(NinjaRule(rule, command, [], description, deps=depstyle, depfile=depfile)) def generate_swift_compile_rules(self, compiler): @@ -1604,36 +1593,28 @@ int dummy; 'dirchanger', '$RUNDIR', ] - invoc = (' '.join(full_exe) + ' ' + - ' '.join(ninja_quote(i) for i in compiler.get_exelist())) - command = '%s $ARGS $in' % invoc + invoc = full_exe + [ninja_quote(i) for i in compiler.get_exelist()] + command = invoc + ['$ARGS', '$in'] description = 'Compiling Swift source $in.' - self.add_rule(NinjaRule(rule, command, '', description)) + self.add_rule(NinjaRule(rule, command, [], description)) def generate_fortran_dep_hack(self, crstr): rule = 'FORTRAN_DEP_HACK%s' % (crstr) if mesonlib.is_windows(): - cmd = 'cmd /C ""' + cmd = ['cmd', '/C'] else: - cmd = 'true' + cmd = ['true'] self.add_rule_comment(NinjaComment('''Workaround for these issues: https://groups.google.com/forum/#!topic/ninja-build/j-2RfBIOd_8 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) - self.add_rule(NinjaRule(rule, cmd, '', 'Dep hack', extra='restat = 1')) + self.add_rule(NinjaRule(rule, cmd, [], 'Dep hack', extra='restat = 1')) def generate_llvm_ir_compile_rule(self, compiler, is_cross): if getattr(self, 'created_llvm_ir_rule', False): return rule = 'llvm_ir{}_COMPILER'.format('_CROSS' if is_cross else '') - command_template = '{executable}' - args_template = '$ARGS {output_args} {compile_only_args} $in' - subst = { - 'executable': ' '.join([ninja_quote(i) for i in compiler.get_exelist()]), - 'output_args': ' '.join(compiler.get_output_args('$out')), - 'compile_only_args': ' '.join(compiler.get_compile_only_args()), - } - command = command_template.format(**subst) - args = args_template.format(**subst) + command = [ninja_quote(i) for i in compiler.get_exelist()] + args = ['$ARGS'] + compiler.get_output_args('$out') + compiler.get_compile_only_args() + ['$in'] description = 'Compiling LLVM IR object $in.' self.add_rule(NinjaRule(rule, command, args, description, rspable=compiler.can_linker_accept_rsp())) @@ -1673,16 +1654,8 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) d = quote_func(d) quoted_depargs.append(d) - command_template = '{executable}' - args_template = '$ARGS {dep_args} {output_args} {compile_only_args} $in' - subst = { - 'executable': ' '.join([ninja_quote(i) for i in compiler.get_exelist()]), - 'dep_args': ' '.join(quoted_depargs), - 'output_args': ' '.join(compiler.get_output_args('$out')), - 'compile_only_args': ' '.join(compiler.get_compile_only_args()), - } - command = command_template.format(**subst) - args = args_template.format(**subst) + command = [ninja_quote(i) for i in compiler.get_exelist()] + args = ['$ARGS'] + quoted_depargs + compiler.get_output_args('$out') + compiler.get_compile_only_args() + ['$in'] description = 'Compiling %s object $out.' % compiler.get_display_language() if isinstance(compiler, VisualStudioCCompiler): deps = 'msvc' @@ -1710,15 +1683,10 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) d = quote_func(d) quoted_depargs.append(d) if isinstance(compiler, VisualStudioCCompiler): - output = '' + output = [] else: - output = ' '.join(compiler.get_output_args('$out')) - command = "{executable} $ARGS {dep_args} {output_args} {compile_only_args} $in".format( - executable=' '.join(compiler.get_exelist()), - dep_args=' '.join(quoted_depargs), - output_args=output, - compile_only_args=' '.join(compiler.get_compile_only_args()) - ) + output = compiler.get_output_args('$out') + command = compiler.get_exelist() + ['$ARGS'] + quoted_depargs + output + compiler.get_compile_only_args() + ['$in'] description = 'Precompiling header $in.' if isinstance(compiler, VisualStudioCCompiler): deps = 'msvc' @@ -1726,7 +1694,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) else: deps = 'gcc' depfile = '$DEPFILE' - self.add_rule(NinjaRule(rule, command, '', description, deps=deps, + self.add_rule(NinjaRule(rule, command, [], description, deps=deps, depfile=depfile)) def generate_compile_rules(self): -- cgit v1.1 From 091459cbdf6261f677b29eb27e04666a331ad996 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Mon, 22 Apr 2019 17:11:17 +0100 Subject: ninja: Expand comment on shell-unquoted ninja variables --- mesonbuild/backend/ninjabackend.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 977bcdd..968fcf9 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -158,7 +158,10 @@ class NinjaBuildElement: line = line.replace('\\', '/') outfile.write(line) - # All the entries that should remain unquoted + # ninja variables whose value should remain unquoted. The value of these + # ninja variables (or variables we use them in) is interpreted directly + # by ninja (e.g. the value of the depfile variable is a pathname that + # ninja will read from, etc.), so it must not be shell quoted. raw_names = {'DEPFILE', 'DESC', 'pool', 'description'} for e in self.elems: -- cgit v1.1 From 0debaab8d1547570e321ea11ea4fc8307ae55874 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Wed, 10 Apr 2019 14:49:29 +0100 Subject: ninja: Suppress unused rules in output Don't bother outputting any rules which aren't referenced by any build statement. --- mesonbuild/backend/ninjabackend.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 968fcf9..9a6fdad 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -85,8 +85,12 @@ class NinjaRule: self.depfile = depfile self.extra = extra self.rspable = rspable # if a rspfile can be used + self.refcount = 0 def write(self, outfile): + if not self.refcount: + return + outfile.write('rule %s\n' % self.name) if self.rspable: outfile.write(' command = %s @$out.rsp\n' % ' '.join(self.command)) @@ -275,7 +279,7 @@ int dummy; with self.detect_vs_dep_prefix(tempfilename) as outfile: self.generate_rules() - self.write_rules(outfile) + self.build_elements = [] self.generate_phony() self.add_build_comment(NinjaComment('Build rules for targets')) @@ -293,7 +297,10 @@ int dummy; self.add_build_comment(NinjaComment('Suffix')) self.generate_utils() self.generate_ending() + + self.write_rules(outfile) self.write_builds(outfile) + default = 'default all\n\n' outfile.write(default) # Only overwrite the old build file after the new one has been @@ -830,6 +837,7 @@ int dummy; def generate_rules(self): self.rules = [] + self.ruledict = {} self.add_rule_comment(NinjaComment('Rules for compiling.')) self.generate_compile_rules() @@ -865,10 +873,15 @@ int dummy; def add_rule(self, rule): self.rules.append(rule) + self.ruledict[rule.name] = rule def add_build(self, build): self.build_elements.append(build) + # increment rule refcount + if build.rule != 'phony': + self.ruledict[build.rule].refcount += 1 + def write_rules(self, outfile): for r in self.rules: r.write(outfile) -- cgit v1.1