diff options
Diffstat (limited to 'mesonbuild/backend/backends.py')
| -rw-r--r-- | mesonbuild/backend/backends.py | 107 |
1 files changed, 68 insertions, 39 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 81283dc80..6f4501cb2 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -16,6 +16,7 @@ import os, pickle, re from .. import build from .. import dependencies from .. import mesonlib +from .. import compilers import json import subprocess from ..mesonlib import MesonException @@ -36,7 +37,7 @@ class InstallData(): class ExecutableSerialisation(): def __init__(self, name, fname, cmd_args, env, is_cross, exe_wrapper, - workdir, extra_paths): + workdir, extra_paths, capture): self.name = name self.fname = fname self.cmd_args = cmd_args @@ -45,6 +46,7 @@ class ExecutableSerialisation(): self.exe_runner = exe_wrapper self.workdir = workdir self.extra_paths = extra_paths + self.capture = capture class TestSerialisation: def __init__(self, name, suite, fname, is_cross, exe_wrapper, is_parallel, cmd_args, env, @@ -143,24 +145,34 @@ class Backend(): langlist = {} abs_files = [] result = [] - for src in unity_src: - comp = self.get_compiler_for_source(src, target.is_cross) - language = comp.get_language() - suffix = '.' + comp.get_default_suffix() - if language not in langlist: - 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) - outfileabs_tmp_dir = os.path.dirname(outfileabs_tmp) - if not os.path.exists(outfileabs_tmp_dir): - os.makedirs(outfileabs_tmp_dir) - outfile = open(outfileabs_tmp, 'w') - langlist[language] = outfile - result.append(outfilename) - ofile = langlist[language] - ofile.write('#include<%s>\n' % src) - [x.close() for x in langlist.values()] + + def init_language_file(language, 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) + outfileabs_tmp_dir = os.path.dirname(outfileabs_tmp) + if not os.path.exists(outfileabs_tmp_dir): + os.makedirs(outfileabs_tmp_dir) + result.append(outfilename) + return open(outfileabs_tmp, 'w') + + try: + for src in unity_src: + comp = self.get_compiler_for_source(src, target.is_cross) + language = comp.get_language() + try: + ofile = langlist[language] + except KeyError: + suffix = '.' + comp.get_default_suffix() + ofile = langlist[language] = init_language_file(language, + suffix) + ofile.write('#include<%s>\n' % src) + finally: + for x in langlist.values(): + x.close() [mesonlib.replace_if_different(x, x + '.tmp') for x in abs_files] return result @@ -181,18 +193,25 @@ class Backend(): raise MesonException('Unknown data type in object list.') return obj_list - def serialise_executable(self, exe, cmd_args, workdir, env={}): + def serialise_executable(self, exe, cmd_args, workdir, env={}, + capture=None): import uuid # Can't just use exe.name here; it will likely be run more than once - scratch_file = 'meson_exe_{0}_{1}.dat'.format(exe.name, + if isinstance(exe, (dependencies.ExternalProgram, + build.BuildTarget, build.CustomTarget)): + basename = exe.name + else: + basename = os.path.basename(exe) + scratch_file = 'meson_exe_{0}_{1}.dat'.format(basename, str(uuid.uuid4())[:8]) exe_data = os.path.join(self.environment.get_scratch_dir(), scratch_file) with open(exe_data, 'wb') as f: if isinstance(exe, dependencies.ExternalProgram): exe_fullpath = exe.fullpath + elif isinstance(exe, (build.BuildTarget, build.CustomTarget)): + exe_fullpath = [self.get_target_filename_abs(exe)] else: - exe_fullpath = [os.path.join(self.environment.get_build_dir(), - self.get_target_filename(exe))] + exe_fullpath = [exe] is_cross = self.environment.is_cross_build() and \ self.environment.cross_info.need_cross_compiler() and \ self.environment.cross_info.need_exe_wrapper() @@ -204,21 +223,19 @@ class Backend(): extra_paths = self.determine_windows_extra_paths(exe) else: extra_paths = [] - es = ExecutableSerialisation(exe.name, exe_fullpath, cmd_args, env, + es = ExecutableSerialisation(basename, exe_fullpath, cmd_args, env, is_cross, exe_wrapper, workdir, - extra_paths) + extra_paths, capture) pickle.dump(es, f) return exe_data def serialise_tests(self): test_data = os.path.join(self.environment.get_scratch_dir(), 'meson_test_setup.dat') - datafile = open(test_data, 'wb') - self.write_test_file(datafile) - datafile.close() + with open(test_data, 'wb') as datafile: + self.write_test_file(datafile) benchmark_data = os.path.join(self.environment.get_scratch_dir(), 'meson_benchmark_setup.dat') - datafile = open(benchmark_data, 'wb') - self.write_benchmark_file(datafile) - datafile.close() + with open(benchmark_data, 'wb') as datafile: + self.write_benchmark_file(datafile) return (test_data, benchmark_data) def has_source_suffix(self, target, suffix): @@ -239,6 +256,9 @@ class Backend(): def has_swift(self, target): return self.has_source_suffix(target, '.swift') + def has_d(self, target): + return self.has_source_suffix(target, '.d') + def determine_linker(self, target, src): if isinstance(target, build.StaticLibrary): if self.build.static_cross_linker is not None: @@ -361,10 +381,12 @@ class Backend(): def build_target_link_arguments(self, compiler, deps): args = [] for d in deps: - if not isinstance(d, build.StaticLibrary) and\ - not isinstance(d, build.SharedLibrary): + if not isinstance(d, (build.StaticLibrary, build.SharedLibrary)): raise RuntimeError('Tried to link with a non-library target "%s".' % d.get_basename()) - args.append(self.get_target_filename_for_linking(d)) + if isinstance(compiler, compilers.LLVMDCompiler): + args.extend(['-L', self.get_target_filename_for_linking(d)]) + else: + args.append(self.get_target_filename_for_linking(d)) # If you have executable e that links to shared lib s1 that links to shared library s2 # you have to specify s2 as well as s1 when linking e even if e does not directly use # s2. Gcc handles this case fine but Clang does not for some reason. Thus we need to @@ -434,7 +456,8 @@ class Backend(): mfobj = {'type': 'dependency manifest', 'version': '1.0'} mfobj['projects'] = self.build.dep_manifest - open(ifilename, 'w').write(json.dumps(mfobj)) + with open(ifilename, 'w') as f: + f.write(json.dumps(mfobj)) d.data.append([ifilename, ofilename]) def get_regen_filelist(self): @@ -519,7 +542,7 @@ class Backend(): i = i.held_object if isinstance(i, str): fname = [os.path.join(self.build_to_src, target.subdir, i)] - elif isinstance(i, build.BuildTarget): + elif isinstance(i, (build.BuildTarget, build.CustomTarget)): fname = [self.get_target_filename(i)] elif isinstance(i, build.GeneratedList): fname = [os.path.join(self.get_target_private_dir(target), p) for p in i.get_outfilelist()] @@ -539,7 +562,7 @@ class Backend(): tmp = i.get_filename()[0] i = os.path.join(self.get_target_dir(i), tmp) elif isinstance(i, mesonlib.File): - i = os.path.join(i.subdir, i.fname) + i = i.rel_to_builddir(self.build_to_src) if absolute_paths: i = os.path.join(self.environment.get_build_dir(), i) # FIXME: str types are blindly added and ignore the 'absolute_paths' argument @@ -557,6 +580,14 @@ class Backend(): else: if '@OUTDIR@' in i: i = i.replace('@OUTDIR@', outdir) + elif '@DEPFILE@' in i: + if target.depfile is None: + raise MesonException('Custom target %s has @DEPFILE@ but no depfile keyword argument.' % target.name) + if absolute_paths: + dfilename = os.path.join(self.get_target_private_dir_abs(target), target.depfile) + else: + dfilename = os.path.join(self.get_target_private_dir(target), target.depfile) + i = i.replace('@DEPFILE@', dfilename) elif '@PRIVATE_OUTDIR_' in i: match = re.search('@PRIVATE_OUTDIR_(ABS_)?([-a-zA-Z0-9.@:]*)@', i) source = match.group(0) @@ -564,12 +595,10 @@ class Backend(): lead_dir = '' else: lead_dir = self.environment.get_build_dir() - target_id = match.group(2) i = i.replace(source, os.path.join(lead_dir, outdir)) cmd.append(i) - cmd = [i.replace('\\', '/') for i in cmd] return (srcs, ofilenames, cmd) def run_postconf_scripts(self): |
