summaryrefslogtreecommitdiff
path: root/mesonbuild/backend/backends.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/backend/backends.py')
-rw-r--r--mesonbuild/backend/backends.py107
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):