diff options
-rw-r--r-- | backends.py | 32 | ||||
-rw-r--r-- | build.py | 20 | ||||
-rw-r--r-- | compilers.py | 2 | ||||
-rw-r--r-- | coredata.py | 6 | ||||
-rw-r--r-- | interpreter.py | 37 | ||||
-rwxr-xr-x | meson.py | 17 | ||||
-rwxr-xr-x | mesonconf.py | 6 | ||||
-rw-r--r-- | modules/gnome.py | 14 | ||||
-rw-r--r-- | ninjabackend.py | 129 | ||||
-rwxr-xr-x | run_tests.py | 12 | ||||
-rw-r--r-- | test cases/common/57 custom target chain/meson.build | 14 | ||||
-rw-r--r-- | test cases/common/61 custom target source output/meson.build | 2 | ||||
-rw-r--r-- | test cases/common/65 multiple generators/meson.build | 10 | ||||
-rw-r--r-- | test cases/common/65 multiple generators/subdir/meson.build | 2 | ||||
-rwxr-xr-x | test cases/common/78 ctarget dependency/gen2.py | 6 | ||||
-rw-r--r-- | test cases/common/78 ctarget dependency/meson.build | 2 | ||||
-rw-r--r-- | test cases/frameworks/7 gnome/gir/meson.build | 4 | ||||
-rw-r--r-- | vs2010backend.py | 15 | ||||
-rw-r--r-- | xcodebackend.py | 7 |
19 files changed, 202 insertions, 135 deletions
diff --git a/backends.py b/backends.py index 8d71314..0fc8646 100644 --- a/backends.py +++ b/backends.py @@ -37,10 +37,9 @@ class TestSerialisation: # This class contains the basic functionality that is needed by all backends. # Feel free to move stuff in and out of it as you see fit. class Backend(): - def __init__(self, build, interp): + def __init__(self, build): self.build = build self.environment = build.environment - self.interpreter = interp self.processed_targets = {} self.dep_rules = {} self.build_to_src = os.path.relpath(self.environment.get_source_dir(), @@ -69,12 +68,18 @@ class Backend(): return filename def get_target_dir(self, target): - dirname = target.get_subdir() + if self.environment.coredata.layout == 'mirror': + dirname = target.get_subdir() + else: + dirname = 'meson-out' os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True) return dirname def get_target_private_dir(self, target): - dirname = os.path.join(self.get_target_dir(target), target.get_basename() + target.type_suffix()) + return os.path.join(self.get_target_dir(target), target.get_basename() + target.type_suffix()) + + def get_target_private_dir_abs(self, target): + dirname = self.get_target_private_dir(target) os.makedirs(os.path.join(self.environment.get_build_dir(), dirname), exist_ok=True) return dirname @@ -87,7 +92,7 @@ class Backend(): language = comp.get_language() suffix = '.' + comp.get_default_suffix() if language not in langlist: - outfilename = os.path.join(self.get_target_private_dir(target), target.name + '-unity' + suffix) + outfilename = os.path.join(self.get_target_private_dir_abs(target), target.name + '-unity' + suffix) outfileabs = os.path.join(self.environment.get_build_dir(), outfilename) outfileabs_tmp = outfileabs + '.tmp' abs_files.append(outfileabs) @@ -167,7 +172,7 @@ class Backend(): def determine_ext_objs(self, extobj, proj_dir_to_build_root=''): result = [] - targetdir = self.get_target_private_dir(extobj.target) + targetdir = self.get_target_private_dir_abs(extobj.target) suffix = '.' + self.environment.get_object_suffix() for osrc in extobj.srclist: osrc_base = osrc.fname @@ -187,7 +192,7 @@ class Backend(): def get_pch_include_args(self, compiler, target): args = [] - pchpath = self.get_target_private_dir(target) + pchpath = self.get_target_private_dir_abs(target) includeargs = compiler.get_include_args(pchpath) for lang in ['c', 'cpp']: p = target.get_pch(lang) @@ -223,7 +228,7 @@ class Backend(): # Fortran rquires extra include directives. if compiler.language == 'fortran': for lt in target.link_targets: - priv_dir = os.path.join(lt.subdir, lt.get_basename() + lt.type_suffix()) + priv_dir = os.path.join(self.get_target_dir(lt), lt.get_basename() + lt.type_suffix()) incflag = compiler.get_include_args(priv_dir) commands += incflag return commands @@ -254,8 +259,15 @@ class Backend(): if not isinstance(target, build.Executable): print(target) return [] - prospectives = target.get_transitive_rpaths() - return [os.path.join(self.environment.get_build_dir(), i) for i in prospectives if len(i) > 0] + prospectives = target.get_transitive_link_deps() + result = [] + for ld in prospectives: + if ld == '' or ld == '.': + continue + dirseg = os.path.join(self.environment.get_build_dir(), self.get_target_dir()) + if dirseg not in result: + result.append(dirseg) + return result def write_test_file(self, datafile): arr = [] @@ -267,13 +267,13 @@ class BuildTarget(): def extract_all_objects(self): return ExtractedObjects(self, self.sources) - def get_rpaths(self): - return self.get_transitive_rpaths() + def get_all_link_deps(self): + return self.get_transitive_link_deps() - def get_transitive_rpaths(self): + def get_transitive_link_deps(self): result = [] for i in self.link_targets: - result += i.get_rpaths() + result += i.get_all_link_deps() return result def get_custom_install_dir(self): @@ -648,8 +648,8 @@ class SharedLibrary(BuildTarget): def get_import_filename(self): return self.prefix + self.name + '.' + self.importsuffix - def get_rpaths(self): - return [self.subdir] + self.get_transitive_rpaths() + def get_all_link_deps(self): + return [self] + self.get_transitive_link_deps() def get_filename(self): '''Works on all platforms except OSX, which does its own thing.''' @@ -744,13 +744,7 @@ class CustomTarget: final_cmd += c.get_command() elif isinstance(c, BuildTarget) or isinstance(c, CustomTarget): self.dependencies.append(c) - # GIR scanner will attempt to execute this binary but - # it assumes that it is in path, so always give it a full path. - tmp = c.get_filename() - if isinstance(tmp, str): - tmp =[tmp] - totarget = [os.path.join('.', c.get_subdir(), i) for i in tmp] - final_cmd += totarget + final_cmd.append(c) elif isinstance(c, list): # Hackety hack, only supports one level of flattening. Should really # work to arbtrary depth. diff --git a/compilers.py b/compilers.py index 24853e1..df8fc2f 100644 --- a/compilers.py +++ b/compilers.py @@ -202,6 +202,8 @@ class CCompiler(): return [] def get_include_args(self, path): + if path == '': + path = '.' return ['-I' + path] def get_std_shared_lib_link_args(self): diff --git a/coredata.py b/coredata.py index 2a7b2ce..793cd47 100644 --- a/coredata.py +++ b/coredata.py @@ -30,7 +30,8 @@ builtin_options = {'buildtype': True, 'localedir' : True, 'werror' : True, 'warning_level': True, - } + 'layout' : True, + } # This class contains all data that must persist over multiple # invocations of Meson. It is roughly the same thing as @@ -58,6 +59,7 @@ class CoreData(): self.coverage = options.coverage self.warning_level = options.warning_level self.werror = options.werror + self.layout = options.layout self.user_options = {} self.external_args = {} # These are set from "the outside" with e.g. mesonconf self.external_link_args = {} @@ -98,6 +100,8 @@ class CoreData(): return self.mandir if optname == 'localedir': return self.localedir + if optname == 'layout': + return self.layout raise RuntimeError('Tried to get unknown builtin option %s' % optname) def load(filename): diff --git a/interpreter.py b/interpreter.py index 2d86454..5da6d8b 100644 --- a/interpreter.py +++ b/interpreter.py @@ -449,15 +449,22 @@ class GeneratedObjectsHolder(InterpreterObject): self.held_object = held_object class BuildTargetHolder(InterpreterObject): - def __init__(self, target): + def __init__(self, target, interp): super().__init__() self.held_object = target + self.interpreter = interp self.methods.update({'extract_objects' : self.extract_objects_method, - 'extract_all_objects' : self.extract_all_objects_method}) + 'extract_all_objects' : self.extract_all_objects_method, + 'get_id': self.get_id_method, + 'outdir' : self.outdir_method, + }) def is_cross(self): return self.held_object.is_cross() + def outdir_method(self, args, kwargs): + return self.interpreter.backend.get_target_dir(self.held_object) + def extract_objects_method(self, args, kwargs): gobjs = self.held_object.extract_objects(args) return GeneratedObjectsHolder(gobjs) @@ -466,21 +473,24 @@ class BuildTargetHolder(InterpreterObject): gobjs = self.held_object.extract_all_objects() return GeneratedObjectsHolder(gobjs) + def get_id_method(self, args, kwargs): + return self.held_object.get_id() + class ExecutableHolder(BuildTargetHolder): - def __init__(self, target): - super().__init__(target) + def __init__(self, target, interp): + super().__init__(target, interp) class StaticLibraryHolder(BuildTargetHolder): - def __init__(self, target): - super().__init__(target) + def __init__(self, target, interp): + super().__init__(target, interp) class SharedLibraryHolder(BuildTargetHolder): - def __init__(self, target): - super().__init__(target) + def __init__(self, target, interp): + super().__init__(target, interp) class JarHolder(BuildTargetHolder): - def __init__(self, target): - super().__init__(target) + def __init__(self, target, interp): + super().__init__(target, interp) class CustomTargetHolder(InterpreterObject): def __init__(self, object_to_hold): @@ -806,8 +816,9 @@ class MesonMain(InterpreterObject): class Interpreter(): - def __init__(self, build, subproject='', subdir='', subproject_dir='subprojects'): + def __init__(self, build, backend, subproject='', subdir='', subproject_dir='subprojects'): self.build = build + self.backend = backend self.subproject = subproject self.subdir = subdir self.source_root = build.environment.get_source_dir() @@ -1176,7 +1187,7 @@ class Interpreter(): os.makedirs(os.path.join(self.build.environment.get_build_dir(), subdir), exist_ok=True) self.global_args_frozen = True mlog.log('\nExecuting subproject ', mlog.bold(dirname), '.\n', sep='') - subi = Interpreter(self.build, dirname, subdir, self.subproject_dir) + subi = Interpreter(self.build, self.backend, dirname, subdir, self.subproject_dir) subi.subprojects = self.subprojects subi.subproject_stack = self.subproject_stack + [dirname] @@ -1727,7 +1738,7 @@ class Interpreter(): mlog.debug('Unknown target type:', str(targetholder)) raise RuntimeError('Unreachable code') target = targetclass(name, self.subdir, self.subproject, is_cross, sources, objs, self.environment, kwargs) - l = targetholder(target) + l = targetholder(target, self) self.add_target(name, l.held_object) self.global_args_frozen = True return l @@ -28,6 +28,7 @@ parser = argparse.ArgumentParser() backendlist = ['ninja', 'vs2010', 'xcode'] build_types = ['plain', 'debug', 'debugoptimized', 'release'] +layouts = ['mirror', 'flat'] warning_levels = ['1', '2', '3'] default_warning = '1' @@ -71,6 +72,8 @@ parser.add_argument('--unity', action='store_true', dest='unity', default=False, help='unity build') parser.add_argument('--werror', action='store_true', dest='werror', default=False,\ help='Treat warnings as errors') +parser.add_argument('--layout', choices=layouts, dest='layout', default='mirror',\ + help='Build directory layout.') parser.add_argument('--warnlevel', default=default_warning, dest='warning_level', choices=warning_levels,\ help='Level of compiler warnings to use (larger is more, default is %(default)s)') parser.add_argument('--cross-file', default=None, dest='cross_file', @@ -141,24 +144,24 @@ itself as required.''' else: mlog.log('Build type:', mlog.bold('native build')) b = build.Build(env) - intr = interpreter.Interpreter(b) - mlog.log('Build machine cpu:', mlog.bold(intr.builtin['build_machine'].cpu_method([], {}))) if env.is_cross_build(): mlog.log('Host machine cpu:', mlog.bold(intr.builtin['host_machine'].cpu_method([], {}))) mlog.log('Target machine cpu:', mlog.bold(intr.builtin['target_machine'].cpu_method([], {}))) - intr.run() if self.options.backend == 'ninja': import ninjabackend - g = ninjabackend.NinjaBackend(b, intr) + g = ninjabackend.NinjaBackend(b) elif self.options.backend == 'vs2010': import vs2010backend - g = vs2010backend.Vs2010Backend(b, intr) + g = vs2010backend.Vs2010Backend(b) elif self.options.backend == 'xcode': import xcodebackend - g = xcodebackend.XCodeBackend(b, intr) + g = xcodebackend.XCodeBackend(b) else: raise RuntimeError('Unknown backend "%s".' % self.options.backend) - g.generate() + intr = interpreter.Interpreter(b, g) + mlog.log('Build machine cpu:', mlog.bold(intr.builtin['build_machine'].cpu_method([], {}))) + intr.run() + g.generate(intr) env.generating_finished() dumpfile = os.path.join(env.get_scratch_dir(), 'build.dat') pickle.dump(b, open(dumpfile, 'wb')) diff --git a/mesonconf.py b/mesonconf.py index 608661e..db526b0 100755 --- a/mesonconf.py +++ b/mesonconf.py @@ -18,7 +18,7 @@ import sys, os import pickle import argparse import coredata, optinterpreter -from meson import build_types, warning_levels +from meson import build_types, layouts, warning_levels parser = argparse.ArgumentParser() @@ -80,6 +80,10 @@ class Conf: if v not in build_types: raise ConfException('Invalid build type %s.' % v) self.coredata.buildtype = v + elif k == 'layout': + if v not in layouts: + raise ConfException('Invalid layout type %s.' % v) + self.coredata.layout = v elif k == 'warnlevel': if not v in warning_levels: raise ConfException('Invalid warning level %s.' % v) diff --git a/modules/gnome.py b/modules/gnome.py index ac68515..231cbd4 100644 --- a/modules/gnome.py +++ b/modules/gnome.py @@ -139,15 +139,15 @@ class GnomeModule: inc_dirs = kwargs.pop('include_directories') if not isinstance(inc_dirs, list): inc_dirs = [inc_dirs] - for id in inc_dirs: - if isinstance(id.held_object, build.IncludeDirs): - scan_command += ['--add-include-path=%s' % inc for inc in id.held_object.get_incdirs()] + for ind in inc_dirs: + if isinstance(ind.held_object, build.IncludeDirs): + scan_command += ['--add-include-path=%s' % inc for inc in ind.held_object.get_incdirs()] else: raise MesonException('Gir include dirs should be include_directories()') if isinstance(girtarget, build.Executable): scan_command += ['--program', girtarget] elif isinstance(girtarget, build.SharedLibrary): - scan_command += ["-L", os.path.join (state.environment.get_build_dir(), girtarget.subdir)] + scan_command += ["-L@PRIVATE_OUTDIR_ABS_%s@" % girtarget.get_id()] libname = girtarget.get_basename() scan_command += ['--library', libname] scankwargs = {'output' : girfile, @@ -163,9 +163,9 @@ class GnomeModule: typelib_output = '%s-%s.typelib' % (ns, nsversion) typelib_cmd = ['g-ir-compiler', scan_target, '--output', '@OUTPUT@'] if inc_dirs: - for id in inc_dirs: + for incd in inc_dirs: typelib_cmd += ['--includedir=%s' % inc for inc in - id.held_object.get_incdirs()] + incd.held_object.get_incdirs()] if deps: for dep in deps: girdir = dep.held_object.get_variable ("girdir") @@ -248,7 +248,7 @@ class GnomeModule: cmd += ['--interface-prefix', kwargs.pop('interface_prefix')] if 'namespace' in kwargs: cmd += ['--c-namespace', kwargs.pop('namespace')] - cmd += ['--generate-c-code', os.path.join(state.subdir, namebase), '@INPUT@'] + cmd += ['--generate-c-code', '@OUTDIR@/' + namebase, '@INPUT@'] outputs = [namebase + '.c', namebase + '.h'] custom_kwargs = {'input' : xml_file, 'output' : outputs, 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) diff --git a/run_tests.py b/run_tests.py index 7d5f92f..f6a6a81 100755 --- a/run_tests.py +++ b/run_tests.py @@ -172,7 +172,7 @@ def run_test_inprocess(testdir): return (returncode, mystdout.getvalue(), mystderr.getvalue()) -def run_test(testdir, should_succeed): +def run_test(testdir, extra_args, should_succeed): global compile_commands mlog.shutdown() # Close the log file because otherwise Windows wets itself. shutil.rmtree(test_build_dir) @@ -182,7 +182,7 @@ def run_test(testdir, should_succeed): print('Running test: ' + testdir) gen_start = time.time() gen_command = [meson_command, '--prefix', '/usr', '--libdir', 'lib', testdir, test_build_dir]\ - + unity_flags + backend_flags + + unity_flags + backend_flags + extra_args (returncode, stdo, stde) = run_configure_inprocess(gen_command) gen_time = time.time() - gen_start if not should_succeed: @@ -255,7 +255,7 @@ def detect_tests_to_run(): all_tests.append(('fortran', gather_tests('test cases/fortran'), False if shutil.which('gfortran') else True)) return all_tests -def run_tests(): +def run_tests(extra_args): all_tests = detect_tests_to_run() logfile = open('meson-test-run.txt', 'w', encoding="utf_8") junit_root = ET.Element('testsuites') @@ -290,7 +290,7 @@ def run_tests(): skipped_tests += 1 else: ts = time.time() - result = run_test(t, name != 'failing') + result = run_test(t, extra_args, name != 'failing') te = time.time() conf_time += result.conftime build_time += result.buildtime @@ -351,6 +351,8 @@ def generate_prebuilt_object(): if __name__ == '__main__': parser = argparse.ArgumentParser(description="Run the test suite of Meson.") + parser.add_argument('extra_args', nargs='*', + help='arguments that are passed directly to Meson (remember to have -- before these).') parser.add_argument('--backend', default=None, dest='backend', choices = backendlist) options = parser.parse_args() @@ -362,7 +364,7 @@ if __name__ == '__main__': check_format() pbfile = generate_prebuilt_object() try: - run_tests() + run_tests(options.extra_args) except StopException: pass os.unlink(pbfile) diff --git a/test cases/common/57 custom target chain/meson.build b/test cases/common/57 custom target chain/meson.build index 7bfcddb..f53206e 100644 --- a/test cases/common/57 custom target chain/meson.build +++ b/test cases/common/57 custom target chain/meson.build @@ -5,17 +5,15 @@ python = find_program('python3') comp = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler.py') comp2 = '@0@/@1@'.format(meson.current_source_dir(), 'my_compiler2.py') infile = '@0@/@1@'.format(meson.current_source_dir(), 'data_source.txt') -outfile = '@0@/@1@'.format(meson.current_build_dir(), 'data.dat') -outfile2 = '@0@/@1@'.format(meson.current_build_dir(), 'data2.dat') mytarget = custom_target('bindat', -output : 'data.dat', -command : [python, comp, infile, outfile], + output : 'data.dat', + command : [python, comp, infile, '@OUTPUT@'], ) mytarget2 = custom_target('bindat2', -output : 'data2.dat', -command : [python, comp2, mytarget, outfile2], -install : true, -install_dir : 'subdir' + output : 'data2.dat', + command : [python, comp2, mytarget, '@OUTPUT@'], + install : true, + install_dir : 'subdir' ) diff --git a/test cases/common/61 custom target source output/meson.build b/test cases/common/61 custom target source output/meson.build index ae65055..f9d039d 100644 --- a/test cases/common/61 custom target source output/meson.build +++ b/test cases/common/61 custom target source output/meson.build @@ -2,7 +2,7 @@ project('source generation', 'c') ct = custom_target('gen', output : ['mylib.h', 'mylib.c'], -command : [find_program('generator.py'), meson.current_build_dir()], +command : [find_program('generator.py'), '@OUTDIR@'], ) e = executable('prog', 'main.c', ct) diff --git a/test cases/common/65 multiple generators/meson.build b/test cases/common/65 multiple generators/meson.build index b6fd038..66f7fa9 100644 --- a/test cases/common/65 multiple generators/meson.build +++ b/test cases/common/65 multiple generators/meson.build @@ -4,10 +4,10 @@ comp = find_program('mygen.py') subdir('subdir') generated2 = custom_target('generated2', -output : ['source2.h', 'source2.cpp'], -input : 'data2.dat', -command : [comp, '@INPUT0@', meson.current_build_dir()]) + output : ['source2.h', 'source2.cpp'], + input : 'data2.dat', + command : [comp, '@INPUT0@', '@OUTDIR@']) exe = executable('prog', 'main.cpp', generated, generated2, -include_directories : include_directories('subdir')) -test('generated test', exe) + include_directories : include_directories('subdir')) + test('generated test', exe) diff --git a/test cases/common/65 multiple generators/subdir/meson.build b/test cases/common/65 multiple generators/subdir/meson.build index 49c6248..2456ecb 100644 --- a/test cases/common/65 multiple generators/subdir/meson.build +++ b/test cases/common/65 multiple generators/subdir/meson.build @@ -1,4 +1,4 @@ generated = custom_target('generated', output : ['source1.h', 'source1.cpp'], input : 'data.dat', -command : [comp, '@INPUT0@', meson.current_build_dir()]) +command : [comp, '@INPUT0@', '@OUTDIR@']) diff --git a/test cases/common/78 ctarget dependency/gen2.py b/test cases/common/78 ctarget dependency/gen2.py index 3f3595b..3a8be7d 100755 --- a/test cases/common/78 ctarget dependency/gen2.py +++ b/test cases/common/78 ctarget dependency/gen2.py @@ -1,9 +1,9 @@ #!/usr/bin/env python3 -import sys +import sys, os from glob import glob -files = glob('*.tmp') +files = glob(os.path.join(sys.argv[1], '*.tmp')) assert(len(files) == 1) -open(sys.argv[1], 'w').write(open(files[0], 'r').read()) +open(sys.argv[2], 'w').write(open(files[0], 'r').read()) diff --git a/test cases/common/78 ctarget dependency/meson.build b/test cases/common/78 ctarget dependency/meson.build index baed2da..cd11951 100644 --- a/test cases/common/78 ctarget dependency/meson.build +++ b/test cases/common/78 ctarget dependency/meson.build @@ -16,5 +16,5 @@ command : [g1, '@INPUT@', '@OUTPUT@']) custom_target('output', output : 'output.dat', -command : [g2, '@OUTPUT@'], +command : [g2, '@OUTDIR@', '@OUTPUT@'], depends : c1) diff --git a/test cases/frameworks/7 gnome/gir/meson.build b/test cases/frameworks/7 gnome/gir/meson.build index 32884db..287c0d7 100644 --- a/test cases/frameworks/7 gnome/gir/meson.build +++ b/test cases/frameworks/7 gnome/gir/meson.build @@ -27,6 +27,6 @@ gnome.generate_gir( test('gobject introspection/c', girexe) test('gobject introspection/py', find_program('prog.py'), - env : ['GI_TYPELIB_PATH=@0@'.format(meson.current_build_dir()), - 'LD_LIBRARY_PATH=@0@'.format(meson.current_build_dir()), + env : ['GI_TYPELIB_PATH=' + girlib.outdir(), + 'LD_LIBRARY_PATH=' + girlib.outdir(), ]) diff --git a/vs2010backend.py b/vs2010backend.py index 268615b..e834584 100644 --- a/vs2010backend.py +++ b/vs2010backend.py @@ -19,8 +19,8 @@ import xml.dom.minidom from coredata import MesonException class Vs2010Backend(backends.Backend): - def __init__(self, build, interp): - super().__init__(build, interp) + def __init__(self, build): + super().__init__(build) self.project_file_version = '10.0.30319.1' # foo.c compiles to foo.obj, not foo.c.obj self.source_suffix_in_obj = False @@ -40,17 +40,17 @@ class Vs2010Backend(backends.Backend): base_args = generator.get_arglist() for i in range(len(infilelist)): if len(infilelist) == len(outfilelist): - 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.environment.get_source_dir(), 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] all_output_files += outfiles args = [x.replace("@INPUT@", infilename).replace('@OUTPUT@', sole_output)\ for x in base_args] - args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir()).replace("@BUILD_DIR@", self.get_target_private_dir(target)) + args = [x.replace("@SOURCE_DIR@", self.environment.get_source_dir()).replace("@BUILD_DIR@", self.get_target_private_dir_abs(target)) for x in args] fullcmd = [exe_file] + args cbs = ET.SubElement(idgroup, 'CustomBuildStep') @@ -62,7 +62,8 @@ class Vs2010Backend(backends.Backend): ET.SubElement(pg, 'CustomBuildBeforeTargets').text = 'ClCompile' return all_output_files - def generate(self): + def generate(self, interp): + self.interpreter = interp self.generate_pkgconfig_files() sln_filename = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.sln') projlist = self.generate_projects() @@ -221,7 +222,7 @@ class Vs2010Backend(backends.Backend): clconf = ET.SubElement(compiles, 'ClCompile') opt = ET.SubElement(clconf, 'Optimization') opt.text = 'disabled' - inc_dirs = [proj_to_src_dir, self.get_target_private_dir(target)] + inc_dirs = [proj_to_src_dir, self.get_target_private_dir_abs(target)] cur_dir = target.subdir if cur_dir == '': cur_dir= '.' diff --git a/xcodebackend.py b/xcodebackend.py index a5df6a5..847b5af 100644 --- a/xcodebackend.py +++ b/xcodebackend.py @@ -19,8 +19,8 @@ import uuid, os, sys from coredata import MesonException class XCodeBackend(backends.Backend): - def __init__(self, build, interp): - super().__init__(build, interp) + def __init__(self, build): + super().__init__(build) self.project_uid = self.environment.coredata.guid.replace('-', '')[:24] self.project_conflist = self.gen_id() self.indent = ' ' @@ -61,7 +61,8 @@ class XCodeBackend(backends.Backend): if not text.endswith('\n'): self.ofile.write('\n') - def generate(self): + def generate(self, interp): + self.interpreter = interp self.serialise_tests() self.generate_filemap() self.generate_buildmap() |