aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/backend
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2019-04-28 21:51:06 +0300
committerGitHub <noreply@github.com>2019-04-28 21:51:06 +0300
commit03d34a79f8632bd8d84d06e1f76b2fdba00a9be0 (patch)
tree00576213c4e0e9e8dad62ba31ae9a9072a32f0d2 /mesonbuild/backend
parent65091b7677973b783cdb2ebb5b9be9b0b97db975 (diff)
parent0debaab8d1547570e321ea11ea4fc8307ae55874 (diff)
downloadmeson-03d34a79f8632bd8d84d06e1f76b2fdba00a9be0.zip
meson-03d34a79f8632bd8d84d06e1f76b2fdba00a9be0.tar.gz
meson-03d34a79f8632bd8d84d06e1f76b2fdba00a9be0.tar.bz2
Merge pull request #5309 from jon-turney/ninja-backend-refactoring
Ninja backend refactoring
Diffstat (limited to 'mesonbuild/backend')
-rw-r--r--mesonbuild/backend/ninjabackend.py763
1 files changed, 380 insertions, 383 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 8edaeec..9a6fdad 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:
@@ -63,6 +63,52 @@ 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
+ 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))
+ outfile.write(' rspfile = $out.rsp\n')
+ outfile.write(' rspfile_content = %s\n' % ' '.join(self.args))
+ else:
+ outfile.write(' command = %s\n' % ' '.join(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):
@@ -116,7 +162,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:
@@ -154,7 +203,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',
@@ -165,7 +214,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.
@@ -220,24 +269,40 @@ 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)
- outfile.write('# Build rules for targets\n\n')
+ self.generate_rules()
+
+ self.build_elements = []
+ 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)
- outfile.write('# Test rules\n\n')
- self.generate_tests(outfile)
- outfile.write('# Install rules\n\n')
- self.generate_install(outfile)
- self.generate_dist(outfile)
+ self.generate_target(t)
+ self.add_build_comment(NinjaComment('Test rules'))
+ self.generate_tests()
+ self.add_build_comment(NinjaComment('Install rules'))
+ self.generate_install()
+ self.generate_dist()
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.generate_coverage_rules(outfile)
- outfile.write('# Suffix\n\n')
- self.generate_utils(outfile)
- self.generate_ending(outfile)
+ self.add_build_comment(NinjaComment('Coverage rules'))
+ self.generate_coverage_rules()
+ 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
# fully created.
os.replace(tempfilename, outfilename)
@@ -377,11 +442,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
@@ -389,20 +454,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:
@@ -420,14 +485,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)
@@ -479,15 +544,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 = []
@@ -517,39 +582,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))
- elem.write(outfile)
+ 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 = []
@@ -562,8 +627,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)
@@ -624,10 +689,10 @@ 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):
+ def generate_run_target(self, target):
cmd = self.environment.get_build_command() + ['--internal', 'commandrunner']
deps = self.unwrap_dep_list(target)
arg_strings = []
@@ -686,9 +751,9 @@ 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.create_target_alias(target_name)
self.processed_targets[target.get_id()] = True
def generate_coverage_command(self, elem, outputs):
@@ -701,49 +766,49 @@ 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.')
- 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)
+ 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.')
- e.write(outfile)
+ 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.')
- e.write(outfile)
+ 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.')
- e.write(outfile)
+ 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')
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)
+ 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'):
@@ -754,9 +819,9 @@ 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)
+ self.create_target_alias('meson-test')
# And then benchmarks.
cmd = self.environment.get_build_command(True) + [
@@ -766,54 +831,71 @@ 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)
+ self.create_target_alias('meson-benchmark')
- def generate_rules(self, outfile):
- 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
+ def generate_rules(self):
+ self.rules = []
+ self.ruledict = {}
-''' % num_pools)
+ self.add_rule_comment(NinjaComment('Rules for compiling.'))
+ 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)
- 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.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.
- 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',
+ c + ['--backend', 'ninja'], [],
+ 'Regenerating build files.',
+ extra='generator = 1'))
- def generate_phony(self, outfile):
- outfile.write('# Phony build target, always out of date\n')
- outfile.write('build PHONY: phony\n')
- outfile.write('\n')
+ 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)
+ 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)
+
+ def write_builds(self, outfile):
+ for b in self.build_elements:
+ b.write(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()
@@ -838,7 +920,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')
@@ -863,11 +945,11 @@ 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)
- def generate_cs_resource_tasks(self, target, outfile):
+ def generate_cs_resource_tasks(self, target):
args = []
deps = []
for r in target.resources:
@@ -880,7 +962,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:
@@ -888,7 +970,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)
@@ -906,7 +988,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)
@@ -934,9 +1016,9 @@ 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.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):
@@ -956,7 +1038,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():
@@ -968,17 +1050,14 @@ 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, 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')
+ def generate_java_link(self):
+ rule = 'java_LINKER'
+ command = ['jar', '$ARGS']
+ description = 'Creating JAR $out.'
+ self.add_rule(NinjaRule(rule, command, [], description))
def determine_dep_vapis(self, target):
"""
@@ -1054,7 +1133,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 = []
@@ -1169,11 +1248,11 @@ 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
- 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
@@ -1261,9 +1340,9 @@ 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.generate_shsym(target)
self.create_target_source_introspection(target, rustc, args, [main_rust_file], [])
def swift_module_file_name(self, target):
@@ -1309,7 +1388,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 = []
@@ -1383,35 +1462,35 @@ 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),
+ elem = self.generate_link(target, 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
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
@@ -1423,15 +1502,9 @@ 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
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
@@ -1440,19 +1513,20 @@ 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()
- 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)
+ cmdlist += ['$LINK_ARGS']
+ cmdlist += static_linker.get_output_args('$out')
+ 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, cmdlist, args, description,
+ 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():
@@ -1469,180 +1543,126 @@ 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 $aliasing
-'''
- else:
- command_template = ' command = {executable} $ARGS {output_args} $in $LINK_ARGS $aliasing\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 = compiler.get_linker_exelist()
+ args = ['$ARGS'] + compiler.get_linker_output_args('$out') + ['$in', '$LINK_ARGS']
+ 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')
-
- def generate_java_compile_rule(self, compiler, outfile):
- rule = 'rule %s_COMPILER\n' % 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')
-
- def generate_cs_compile_rule(self, compiler, outfile):
- rule = 'rule %s_COMPILER\n' % 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')
-
- def generate_vala_compile_rules(self, compiler, outfile):
- rule = 'rule %s_COMPILER\n' % 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')
-
- def generate_rust_compile_rules(self, compiler, outfile, is_cross):
+ symrule = 'SHSYM'
+ symcmd = 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):
+ rule = '%s_COMPILER' % compiler.get_language()
+ 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))
+
+ def generate_cs_compile_rule(self, compiler):
+ rule = '%s_COMPILER' % compiler.get_language()
+ 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 = [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'))
+
+ def generate_rust_compile_rules(self, compiler, is_cross):
crstr = ''
if is_cross:
crstr = '_CROSS'
- rule = 'rule %s%s_COMPILER\n' % (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')
-
- def generate_swift_compile_rules(self, compiler, outfile):
- rule = 'rule %s_COMPILER\n' % compiler.get_language()
+ rule = '%s%s_COMPILER' % (compiler.get_language(), crstr)
+ 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,
+ depfile=depfile))
+
+ 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',
'dirchanger',
'$RUNDIR',
]
- 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')
+ 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))
- 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 ""'
+ 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))
-
- def generate_llvm_ir_compile_rule(self, compiler, is_cross, outfile):
+ 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'))
+
+ def generate_llvm_ir_compile_rule(self, compiler, is_cross):
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 = [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()))
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)
- rule = 'rule %s%s_COMPILER\n' % (langname, crstr)
+ self.generate_fortran_dep_hack(crstr)
+ rule = '%s%s_COMPILER' % (langname, crstr)
depargs = compiler.get_dependency_gen_args('$out', '$DEPFILE')
quoted_depargs = []
for d in depargs:
@@ -1650,39 +1670,27 @@ 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 = [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 = ' 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):
+ def generate_pch_rule_for(self, langname, compiler, is_cross):
if langname != 'c' and langname != 'cpp':
return
if is_cross:
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 = []
@@ -1691,50 +1699,42 @@ rule FORTRAN_DEP_HACK%s
d = quote_func(d)
quoted_depargs.append(d)
if isinstance(compiler, VisualStudioCCompiler):
- output = ''
+ output = []
else:
- output = ' '.join(compiler.get_output_args('$out'))
- command = " command = {executable} $ARGS {dep_args} {output_args} {compile_only_args} $in\n".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'
+ 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 = ' 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):
+ 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):
+ 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:
@@ -1750,7 +1750,7 @@ rule FORTRAN_DEP_HACK%s
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()
@@ -1811,7 +1811,7 @@ rule FORTRAN_DEP_HACK%s
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):
"""
@@ -1945,7 +1945,7 @@ rule FORTRAN_DEP_HACK%s
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
@@ -1977,7 +1977,7 @@ rule FORTRAN_DEP_HACK%s
# 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):
@@ -2098,7 +2098,7 @@ rule FORTRAN_DEP_HACK%s
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
"""
@@ -2175,7 +2175,7 @@ rule FORTRAN_DEP_HACK%s
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)
@@ -2196,7 +2196,7 @@ rule FORTRAN_DEP_HACK%s
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):
@@ -2259,7 +2259,7 @@ rule FORTRAN_DEP_HACK%s
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 = []
@@ -2293,10 +2293,10 @@ rule FORTRAN_DEP_HACK%s
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):
+ def generate_shsym(self, target):
target_name = target.get_filename()
target_file = self.get_target_filename(target)
targetdir = self.get_target_private_dir(target)
@@ -2304,7 +2304,7 @@ rule FORTRAN_DEP_HACK%s
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:
@@ -2439,7 +2439,7 @@ rule FORTRAN_DEP_HACK%s
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):
@@ -2447,7 +2447,7 @@ rule FORTRAN_DEP_HACK%s
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'
@@ -2600,38 +2600,38 @@ rule FORTRAN_DEP_HACK%s
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')
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)
+ 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')
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)
+ 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()
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)
+ self.create_target_alias('meson-clean-gcda')
def get_user_option_args(self):
cmds = []
@@ -2642,7 +2642,7 @@ rule FORTRAN_DEP_HACK%s
# 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() + [
@@ -2651,22 +2651,22 @@ rule FORTRAN_DEP_HACK%s
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)
+ 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()
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)
+ 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:
@@ -2681,22 +2681,22 @@ rule FORTRAN_DEP_HACK%s
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.create_target_alias('meson-' + target_name, outfile)
+ self.add_build(elem)
+ 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')
- elem.write(outfile)
+ 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
@@ -2704,16 +2704,13 @@ rule FORTRAN_DEP_HACK%s
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)
-
- default = 'default all\n\n'
- outfile.write(default)
+ self.add_build(elem)
elem = NinjaBuildElement(self.all_outputs, 'meson-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', 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
@@ -2728,26 +2725,26 @@ rule FORTRAN_DEP_HACK%s
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')
- 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: