diff options
Diffstat (limited to 'ninjabackend.py')
-rw-r--r-- | ninjabackend.py | 129 |
1 files changed, 82 insertions, 47 deletions
diff --git a/ninjabackend.py b/ninjabackend.py index b2d5d00..01223ab 100644 --- a/ninjabackend.py +++ b/ninjabackend.py @@ -109,8 +109,8 @@ class NinjaBuildElement(): class NinjaBackend(backends.Backend): - def __init__(self, build, interp): - super().__init__(build, interp) + def __init__(self, build): + super().__init__(build) self.source_suffix_in_objs = True self.ninja_filename = 'build.ninja' self.fortran_deps = {} @@ -122,7 +122,8 @@ class NinjaBackend(backends.Backend): raise MesonException('Multiple producers for Ninja target "%s". Please rename your targets.' % n) self.all_outputs[n] = True - def generate(self): + def generate(self, interp): + self.interpreter = interp outfilename = os.path.join(self.environment.get_build_dir(), self.ninja_filename) tempfilename = outfilename + '~' outfile = open(tempfilename, 'w') @@ -205,7 +206,7 @@ class NinjaBackend(backends.Backend): for gensource in target.get_generated_sources(): if isinstance(gensource, build.CustomTarget): for src in gensource.output: - src = os.path.join(gensource.subdir, src) + src = os.path.join(self.get_target_dir(gensource), src) if self.environment.is_source(src) and not self.environment.is_header(src): if is_unity: unity_deps.append(os.path.join(self.environment.get_build_dir(), RawFilename(src))) @@ -222,13 +223,13 @@ class NinjaBackend(backends.Backend): else: for src in gensource.get_outfilelist(): if self.environment.is_object(src): - obj_list.append(os.path.join(self.get_target_private_dir(target), src)) + obj_list.append(os.path.join(self.get_target_private_dir_abs(target), src)) elif not self.environment.is_header(src): if is_unity: if '/' in src: rel_src = src else: - rel_src = os.path.join(self.get_target_private_dir(target), src) + rel_src = os.path.join(self.get_target_private_dir_abs(target), src) unity_deps.append(rel_src) abs_src = os.path.join(self.environment.get_build_dir(), rel_src) unity_src.append(abs_src) @@ -275,15 +276,14 @@ class NinjaBackend(backends.Backend): if not tname in self.processed_targets: self.generate_target(t, outfile) - def hackety_hack(self, hack): - if isinstance(hack, list): - return hack[0] - return hack - def generate_custom_target(self, target, outfile): - ofilenames = [os.path.join(target.subdir, i) for i in target.output] - # FIXME, should not grab element at zero but rather expand all. - deps = [os.path.join(i.get_subdir(), self.hackety_hack(i.get_filename())) for i in target.get_dependencies()] + ofilenames = [os.path.join(self.get_target_dir(target), i) for i in target.output] + deps = [] + for i in target.get_dependencies(): + # FIXME, should not grab element at zero but rather expand all. + if isinstance(i, list): + i = i[0] + deps.append(os.path.join(self.get_target_dir(i), i.get_filename()[0])) srcs = [] for i in target.sources: if isinstance(i, str): @@ -299,9 +299,14 @@ class NinjaBackend(backends.Backend): if not isinstance(tmp, list): tmp = [tmp] for fname in tmp: - elem.add_dep(os.path.join(d.get_subdir(), fname)) + elem.add_dep(os.path.join(self.get_target_dir(d), fname)) cmd = [] for i in target.command: + if isinstance(i, build.CustomTarget): + # GIR scanner will attempt to execute this binary but + # it assumes that it is in path, so always give it a full path. + tmp = i.get_filename()[0] + i = os.path.join(self.get_target_dir(i), tmp) for (j, src) in enumerate(srcs): i = i.replace('@INPUT%d@' % j, src) for (j, res) in enumerate(ofilenames): @@ -311,7 +316,21 @@ class NinjaBackend(backends.Backend): elif i == '@OUTPUT@': cmd += ofilenames else: + if '@OUTDIR@' in i: + i = i.replace('@OUTDIR@', self.get_target_dir(target)) + elif '@PRIVATE_OUTDIR_' in i: + match = re.search('@PRIVATE_OUTDIR_(ABS_)?([a-zA-Z@:]*)@', i) + source = match.group(0) + if match.group(1) is None: + lead_dir = '' + else: + lead_dir = self.environment.get_build_dir() + target_id = match.group(2) + i = i.replace(source, + os.path.join(lead_dir, + self.get_target_dir(self.build.targets[target_id]))) cmd.append(i) + elem.add_item('COMMAND', cmd) elem.add_item('description', 'Generating %s with a custom command.' % target.name) elem.write(outfile) @@ -505,7 +524,6 @@ class NinjaBackend(backends.Backend): d.man.append(i) def generate_data_install(self, d): - dataroot = self.environment.get_datadir() data = self.build.get_data() for de in data: subdir = de.get_install_dir() @@ -597,7 +615,7 @@ class NinjaBackend(backends.Backend): def generate_jar_target(self, target, outfile): fname = target.get_filename() subdir = target.get_subdir() - outname_rel = os.path.join(subdir, fname) + outname_rel = os.path.join(self.get_target_dir(target), fname) src_list = target.get_sources() class_list = [] compiler = self.get_compiler_for_source(src_list[0]) @@ -610,13 +628,13 @@ class NinjaBackend(backends.Backend): if main_class != '': e = 'e' for src in src_list: - class_list.append(self.generate_single_java_compile(subdir, src, target, compiler, outfile)) + class_list.append(self.generate_single_java_compile(src, target, compiler, outfile)) jar_rule = 'java_LINKER' commands = [c+m+e+f] if e != '': commands.append(main_class) commands.append(self.get_target_filename(target)) - commands += ['-C', self.get_target_private_dir(target)] + commands += ['-C', self.get_target_private_dir_abs(target)] commands += class_list elem = NinjaBuildElement(outname_rel, jar_rule, []) elem.add_dep([os.path.join(self.get_target_private_dir(target), i) for i in class_list]) @@ -649,8 +667,7 @@ class NinjaBackend(backends.Backend): def generate_cs_target(self, target, outfile): buildtype = self.environment.coredata.buildtype fname = target.get_filename() - subdir = target.get_subdir() - outname_rel = os.path.join(subdir, fname) + outname_rel = os.path.join(self.get_target_dir(target), fname) src_list = target.get_sources() compiler = self.get_compiler_for_source(src_list[0]) assert(compiler.get_language() == 'cs') @@ -669,8 +686,9 @@ class NinjaBackend(backends.Backend): deps += resource_deps commands += compiler.get_output_args(outname_rel) for l in target.link_targets: - commands += compiler.get_link_args(l.get_filename()) - deps.append(l.get_filename()) + lname = os.path.join(self.get_target_dir(l), l.get_filename()) + commands += compiler.get_link_args(lname) + deps.append(lname) if '-g' in commands: outputs = [outname_rel, outname_rel + '.mdb'] else: @@ -681,13 +699,13 @@ class NinjaBackend(backends.Backend): self.check_outputs(elem) elem.write(outfile) - def generate_single_java_compile(self, subdir, src, target, compiler, outfile): + def generate_single_java_compile(self, src, target, compiler, outfile): args = [] args += compiler.get_buildtype_args(self.environment.coredata.buildtype) args += compiler.get_output_args(self.get_target_private_dir(target)) rel_src = src.rel_to_builddir(self.build_to_src) plain_class_path = src.fname[:-4] + 'class' - rel_obj = os.path.join(self.get_target_private_dir(target), plain_class_path) + rel_obj = os.path.join(self.get_target_private_dir_abs(target), plain_class_path) element = NinjaBuildElement(rel_obj, compiler.get_language() + '_COMPILER', rel_src) element.add_item('ARGS', args) element.write(outfile) @@ -709,7 +727,7 @@ class NinjaBackend(backends.Backend): if not s.endswith('.vala'): continue vapibase = os.path.basename(s.fname)[:-4] + 'vapi' - rel_vapi = os.path.join(self.get_target_private_dir(target), vapibase) + rel_vapi = os.path.join(self.get_target_private_dir_abs(target), vapibase) args = ['--fast-vapi=' + rel_vapi] rel_s = s.rel_to_builddir(self.build_to_src) element = NinjaBuildElement(rel_vapi, valac.get_language() + '_COMPILER', rel_s) @@ -740,7 +758,7 @@ class NinjaBackend(backends.Backend): for s in src: if not s.endswith('.vala'): continue - args = ['-d', self.get_target_private_dir(target)] + args = ['-d', self.get_target_private_dir_abs(target)] sc = os.path.basename(s.fname)[:-4] + 'c' args += ['-C'] vapi_order_deps = [] @@ -750,7 +768,7 @@ class NinjaBackend(backends.Backend): (vapibase, rel_vapi) = vapi_info args += ['--use-fast-vapi=' + rel_vapi] vapi_order_deps.append(rel_vapi) - relsc = os.path.join(self.get_target_private_dir(target), sc) + relsc = os.path.join(self.get_target_private_dir_abs(target), sc) rel_s = s.rel_to_builddir(self.build_to_src) args += ['--deps', relsc + '.d'] if self.environment.coredata.werror: @@ -1114,17 +1132,17 @@ rule FORTRAN_DEP_HACK extra_dependencies = [os.path.join(self.build_to_src, i) for i in genlist.extra_depends] for i in range(len(infilelist)): if len(generator.outputs) == 1: - sole_output = os.path.join(self.get_target_private_dir(target), outfilelist[i]) + sole_output = os.path.join(self.get_target_private_dir_abs(target), outfilelist[i]) else: sole_output = '' curfile = infilelist[i] infilename = os.path.join(self.build_to_src, curfile) outfiles = genlist.get_outputs_for(curfile) - outfiles = [os.path.join(self.get_target_private_dir(target), of) for of in outfiles] + outfiles = [os.path.join(self.get_target_private_dir_abs(target), of) for of in outfiles] args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output)\ for x in base_args] - args = self.replace_outputs(args, self.get_target_private_dir(target), outfilelist) - relout = os.path.join(target.subdir, target.get_basename() + target.type_suffix()) + args = self.replace_outputs(args, self.get_target_private_dir_abs(target), outfilelist) + relout = self.get_target_private_dir(target) args = [x.replace("@SOURCE_DIR@", self.build_to_src).replace("@BUILD_DIR@", relout) for x in args] cmdlist = exe_arr + args @@ -1169,7 +1187,7 @@ rule FORTRAN_DEP_HACK def get_fortran_deps(self, compiler, src, target): mod_files = [] usere = re.compile(r"\s*use\s+(\w+)", re.IGNORECASE) - dirname = self.get_target_private_dir(target) + dirname = self.get_target_private_dir_abs(target) tdeps= self.fortran_deps[target.get_basename()] for line in open(src): usematch = usere.match(line) @@ -1219,7 +1237,7 @@ rule FORTRAN_DEP_HACK if '/' in src: rel_src = src else: - rel_src = os.path.join(self.get_target_private_dir(target), src) + rel_src = os.path.join(self.get_target_private_dir_abs(target), src) abs_src = os.path.join(self.environment.get_source_dir(), rel_src) else: if isinstance(src, File): @@ -1247,7 +1265,7 @@ rule FORTRAN_DEP_HACK pch_dep = [] else: arr = [] - i = os.path.join(self.get_target_private_dir(target), compiler.get_pch_name(pchlist[0])) + i = os.path.join(self.get_target_private_dir_abs(target), compiler.get_pch_name(pchlist[0])) arr.append(i) pch_dep = arr for i in target.get_include_dirs(): @@ -1259,6 +1277,14 @@ rule FORTRAN_DEP_HACK sargs = compiler.get_include_args(srctreedir) commands += bargs commands += sargs + custom_target_include_dirs = [] + for i in target.generated: + if isinstance(i, build.CustomTarget): + idir = self.get_target_dir(i) + if idir not in custom_target_include_dirs: + custom_target_include_dirs.append(idir) + for i in custom_target_include_dirs: + commands+= compiler.get_include_args(i) if self.environment.coredata.use_pch: commands += self.get_pch_include_args(compiler, target) crstr = '' @@ -1277,14 +1303,14 @@ rule FORTRAN_DEP_HACK depelem = NinjaBuildElement(modfile, 'FORTRAN_DEP_HACK', rel_obj) depelem.write(outfile) self.check_outputs(depelem) - commands += compiler.get_module_outdir_args(self.get_target_private_dir(target)) + commands += compiler.get_module_outdir_args(self.get_target_private_dir_abs(target)) element = NinjaBuildElement(rel_obj, compiler_name, rel_src) for d in header_deps: if isinstance(d, RawFilename): d = d.fname elif not '/' in d: - d = os.path.join(self.get_target_private_dir(target), d) + d = os.path.join(self.get_target_private_dir_abs(target), d) element.add_dep(d) for d in extra_deps: element.add_dep(d) @@ -1292,7 +1318,7 @@ rule FORTRAN_DEP_HACK if isinstance(d, RawFilename): d = d.fname elif not '/' in d : - d = os.path.join(self.get_target_private_dir(target), d) + d = os.path.join(self.get_target_private_dir_abs(target), d) element.add_orderdep(d) element.add_orderdep(pch_dep) element.add_orderdep(extra_orderdeps) @@ -1307,13 +1333,13 @@ rule FORTRAN_DEP_HACK # Fortran is a bit weird (again). When you link against a library, just compiling a source file # requires the mod files that are output when single files are built. To do this right we would need to # scan all inputs and write out explicit deps for each file. That is stoo slow and too much effort so - # instead just have an ordered dependendy on the library. This ensures all reqquired mod files are created. + # instead just have an ordered dependendy on the library. This ensures all required mod files are created. # The real deps are then detected via dep file generation from the compiler. This breaks on compilers that # produce incorrect dep files but such is life. def get_fortran_orderdeps(self, target, compiler): if compiler.language != 'fortran': return [] - return [os.path.join(lt.subdir, lt.filename) for lt in target.link_targets] + return [os.path.join(self.get_target_dir(lt), lt.filename) for lt in target.link_targets] def generate_msvc_pch_command(self, target, compiler, pch): if len(pch) != 2: @@ -1321,7 +1347,7 @@ rule FORTRAN_DEP_HACK header = pch[0] source = pch[1] pchname = compiler.get_pch_name(header) - dst = os.path.join(self.get_target_private_dir(target), pchname) + dst = os.path.join(self.get_target_private_dir_abs(target), pchname) commands = [] commands += self.generate_basic_compiler_args(target, compiler) @@ -1334,7 +1360,7 @@ rule FORTRAN_DEP_HACK def generate_gcc_pch_command(self, target, compiler, pch): commands = [] commands += self.generate_basic_compiler_args(target, compiler) - dst = os.path.join(self.get_target_private_dir(target), + dst = os.path.join(self.get_target_private_dir_abs(target), os.path.split(pch)[-1] + '.' + compiler.get_pch_suffix()) dep = dst + '.' + compiler.get_depfile_suffix() return (commands, dep, dst, []) # Gcc does not create an object file during pch generation. @@ -1372,7 +1398,7 @@ rule FORTRAN_DEP_HACK def generate_shsym(self, outfile, target): target_name = self.get_target_filename(target) - targetdir = self.get_target_private_dir(target) + targetdir = self.get_target_private_dir_abs(target) symname = os.path.join(targetdir, target_name + '.symbols') elem = NinjaBuildElement(symname, 'SHSYM', target_name) if self.environment.is_cross_build() and self.environment.cross_info.need_cross_compiler(): @@ -1432,7 +1458,7 @@ rule FORTRAN_DEP_HACK for dep in d.get_external_deps(): commands += dep.get_link_args() commands += linker.build_rpath_args(self.environment.get_build_dir(),\ - target.get_rpaths(), target.install_rpath) + self.determine_rpath_dirs(target), target.install_rpath) if self.environment.coredata.coverage: commands += linker.get_coverage_link_args() commands += extra_args @@ -1445,9 +1471,18 @@ rule FORTRAN_DEP_HACK self.check_outputs(elem) return elem + def determine_rpath_dirs(self, target): + link_deps = target.get_all_link_deps() + result = [] + for ld in link_deps: + prospective = self.get_target_dir(ld) + if not prospective in result: + result.append(prospective) + return result + def get_dependency_filename(self, t): if isinstance(t, build.SharedLibrary): - return os.path.join(self.get_target_private_dir(t), self.get_target_filename(t) + '.symbols') + return os.path.join(self.get_target_private_dir_abs(t), self.get_target_filename(t) + '.symbols') return self.get_target_filename(t) def generate_shlib_aliases(self, target, outdir): @@ -1471,7 +1506,7 @@ rule FORTRAN_DEP_HACK gcno_elem.add_item('COMMAND', [sys.executable, clean_script, '.', 'gcno']) gcno_elem.add_item('description', 'Deleting gcno files') gcno_elem.write(outfile) - self.check_outputs(elem, gcno_elem) + self.check_outputs(gcno_elem, gcno_elem) gcda_elem = NinjaBuildElement('clean-gcda', 'CUSTOM_COMMAND', 'PHONY') script_root = self.environment.get_script_dir() @@ -1501,7 +1536,7 @@ rule FORTRAN_DEP_HACK plainname = os.path.split(src)[1] basename = plainname.split('.')[0] outname = rule.name_templ.replace('@BASENAME@', basename).replace('@PLAINNAME@', plainname) - outfilename = os.path.join(self.get_target_private_dir(target), outname) + outfilename = os.path.join(self.get_target_private_dir_abs(target), outname) infilename = os.path.join(self.build_to_src, target.get_source_subdir(), src) elem = NinjaBuildElement(outfilename, rule.name, infilename) elem.write(outfile) |