aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
authorDaniel Mensinger <daniel@mensinger-ka.de>2018-12-11 17:50:38 +0100
committerDaniel Mensinger <daniel@mensinger-ka.de>2019-01-06 12:19:30 +0100
commit7691b0460c53478cfc2e11fca156557add6579bf (patch)
tree2831b2421bc8bd3e40fea62232a8a415a96f638e /mesonbuild
parentb9c4913cf032144eed0cb6308aaff4e77a825f08 (diff)
downloadmeson-7691b0460c53478cfc2e11fca156557add6579bf.zip
meson-7691b0460c53478cfc2e11fca156557add6579bf.tar.gz
meson-7691b0460c53478cfc2e11fca156557add6579bf.tar.bz2
Ninja backend target introspection
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/backend/backends.py14
-rw-r--r--mesonbuild/backend/ninjabackend.py127
-rw-r--r--mesonbuild/mintro.py2
3 files changed, 124 insertions, 19 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index b36b98c..b3b6df9 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -1158,7 +1158,8 @@ class Backend:
"language": "<LANG>",
"compiler": ["result", "of", "comp.get_exelist()"],
"parameters": ["list", "of", "compiler", "parameters],
- "source_files": ["list", "of", "all", "<LANG>", "source", "files"]
+ "sources": ["list", "of", "all", "<LANG>", "source", "files"],
+ "generated_sources": ["list", "of", "generated", "source", "files"]
}
]
@@ -1169,20 +1170,23 @@ class Backend:
source_list = []
for i in source_list_raw:
if isinstance(i, mesonlib.File):
- source_list += [os.path.join(i.subdir, i.fname)]
+ source_list += [i.absolute_path(self.environment.get_source_dir(), self.environment.get_build_dir())]
elif isinstance(i, str):
- source_list += [i]
+ source_list += [os.path.join(self.environment.get_source_dir(), i)]
+ source_list = list(map(lambda x: os.path.normpath(x), source_list))
return [{
'language': 'unknown',
'compiler': [],
'parameters': [],
- 'source_files': source_list
+ 'sources': source_list,
+ 'generated_sources': []
}]
return [{
'language': 'unknown',
'compiler': [],
'parameters': [],
- 'source_files': []
+ 'sources': [],
+ 'generated_sources': []
}]
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 44bdaab..06b4506 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -150,6 +150,8 @@ class NinjaBackend(backends.Backend):
self.ninja_filename = 'build.ninja'
self.fortran_deps = {}
self.all_outputs = {}
+ self.introspection_data = {}
+ self._intro_last_index = 0
def create_target_alias(self, to_target, outfile):
# We need to use aliases for targets that might be used as directory
@@ -321,6 +323,73 @@ int dummy;
return False
return True
+ def create_target_source_introspection(self, target, comp, parameters, sources, generated_sources):
+ '''
+ Adds the source file introspection information for a language of a target
+
+ Internal introspection storage formart:
+ self.introspection_data = {
+ '<target ID>': [
+ {
+ 'language: 'lang',
+ 'compiler': ['comp', 'exe', 'list'],
+ 'parameters': ['UNIQUE', 'parameter', 'list'],
+ 'sources': [],
+ 'generated_sources': [],
+ 'id_hash': 634523234445 # Internal unique hash to identify a compiler / language / paramerter combo
+ }
+ ]
+ }
+ '''
+ build_dir = self.environment.get_build_dir()
+ id = target.get_id()
+ lang = comp.get_language()
+ tgt = self.introspection_data[id]
+ id_hash = hash((lang, CompilerArgs))
+ src_block = None
+ # Find an existing entry or create a new one
+ # ... first check the last used index
+ if self._intro_last_index < len(tgt):
+ tmp = tgt[self._intro_last_index]
+ if tmp['id_hash'] == id_hash:
+ src_block = tmp
+ # ... check all entries
+ if src_block is None:
+ for idx, i in enumerate(tgt):
+ if i['id_hash'] == id_hash:
+ src_block = i
+ self._intro_last_index = idx
+ break
+ # ... create a new one
+ if src_block is None:
+ # Convert parameters
+ if isinstance(parameters, CompilerArgs):
+ parameters = parameters.to_native(copy=True)
+ for idx, i in enumerate(parameters):
+ if i[:2] == '-I' or i[:2] == '/I' or i[:2] == '-L':
+ parameters[idx] = i[:2] + os.path.normpath(os.path.join(build_dir, i[2:]))
+ if target.is_cross:
+ parameters += comp.get_cross_extra_flags(self.environment, False)
+ # The new entry
+ src_block = {
+ 'language': lang,
+ 'compiler': comp.get_exelist(),
+ 'parameters': parameters,
+ 'sources': [],
+ 'generated_sources': [],
+ 'id_hash': id_hash
+ }
+ self._intro_last_index = len(tgt)
+ tgt.append(src_block)
+ # Make source files absolute
+ sources = [x.rel_to_builddir(self.build_to_src) if isinstance(x, File) else x for x in sources]
+ sources = [os.path.normpath(os.path.join(build_dir, x)) for x in sources]
+ generated_sources = [x.rel_to_builddir(self.build_to_src) if isinstance(x, File) else x for x in generated_sources]
+ generated_sources = [os.path.normpath(os.path.join(build_dir, x)) for x in generated_sources]
+ # Add the source files
+ src_block['sources'] += sources
+ src_block['generated_sources'] += generated_sources
+
def generate_target(self, target, outfile):
if isinstance(target, build.CustomTarget):
self.generate_custom_target(target, outfile)
@@ -330,6 +399,8 @@ int dummy;
if name in self.processed_targets:
return
self.processed_targets[name] = True
+ # Initialize an empty introspection source list
+ self.introspection_data[name] = []
# Generate rules for all dependency targets
self.process_target_dependencies(target, outfile)
# If target uses a language that cannot link to C objects,
@@ -770,14 +841,16 @@ int dummy;
# Add possible java generated files to src list
generated_sources = self.get_target_generated_sources(target)
+ gen_src_list = []
for rel_src, gensrc in generated_sources.items():
dirpart, fnamepart = os.path.split(rel_src)
raw_src = File(True, dirpart, fnamepart)
if rel_src.endswith('.java'):
- src_list.append(raw_src)
+ gen_src_list.append(raw_src)
- for src in src_list:
- plain_class_path = self.generate_single_java_compile(src, target, compiler, outfile)
+ 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)
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')
@@ -803,6 +876,8 @@ int dummy;
elem.add_dep(class_dep_list)
elem.add_item('ARGS', commands)
elem.write(outfile)
+ # 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):
args = []
@@ -856,10 +931,11 @@ int dummy;
else:
outputs = [outname_rel]
generated_sources = self.get_target_generated_sources(target)
+ generated_rel_srcs = []
for rel_src in generated_sources.keys():
dirpart, fnamepart = os.path.split(rel_src)
if rel_src.lower().endswith('.cs'):
- rel_srcs.append(os.path.normpath(rel_src))
+ generated_rel_srcs.append(os.path.normpath(rel_src))
deps.append(os.path.normpath(rel_src))
for dep in target.get_external_deps():
@@ -867,19 +943,15 @@ int dummy;
commands += self.build.get_project_args(compiler, target.subproject, target.is_cross)
commands += self.build.get_global_args(compiler, target.is_cross)
- elem = NinjaBuildElement(self.all_outputs, outputs, 'cs_COMPILER', rel_srcs)
+ 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.generate_generator_list_rules(target, outfile)
+ self.create_target_source_introspection(target, compiler, commands, rel_srcs, generated_rel_srcs)
- def generate_single_java_compile(self, src, target, compiler, outfile):
- 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():
- if rel_src.endswith('.java'):
- deps.append(rel_src)
+ def determine_single_java_compile_args(self, target, compiler):
args = []
args += compiler.get_buildtype_args(self.get_option_for_target('buildtype', target))
args += self.build.get_global_args(compiler, target.is_cross)
@@ -894,6 +966,14 @@ int dummy;
for idir in i.get_incdirs():
sourcepath += os.path.join(self.build_to_src, i.curdir, idir) + os.pathsep
args += ['-sourcepath', sourcepath]
+ return args
+
+ def generate_single_java_compile(self, src, target, compiler, args, outfile):
+ 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():
+ if rel_src.endswith('.java'):
+ deps.append(rel_src)
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)
@@ -1102,6 +1182,7 @@ int dummy;
element.add_item('ARGS', args)
element.add_dep(extra_dep_files)
element.write(outfile)
+ 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):
@@ -1193,6 +1274,7 @@ int dummy;
element.write(outfile)
if isinstance(target, build.SharedLibrary):
self.generate_shsym(outfile, target)
+ self.create_target_source_introspection(target, rustc, args, [main_rust_file], [])
def swift_module_file_name(self, target):
return os.path.join(self.get_target_private_dir(target),
@@ -1241,12 +1323,14 @@ int dummy;
module_name = self.target_swift_modulename(target)
swiftc = target.compilers['swift']
abssrc = []
+ relsrc = []
abs_headers = []
header_imports = []
for i in target.get_sources():
if swiftc.can_compile(i):
- relsrc = i.rel_to_builddir(self.build_to_src)
- abss = os.path.normpath(os.path.join(self.environment.get_build_dir(), relsrc))
+ rels = i.rel_to_builddir(self.build_to_src)
+ abss = os.path.normpath(os.path.join(self.environment.get_build_dir(), rels))
+ relsrc.append(rels)
abssrc.append(abss)
elif self.environment.is_header(i):
relh = i.rel_to_builddir(self.build_to_src)
@@ -1330,6 +1414,8 @@ int dummy;
elem.write(outfile)
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):
num_pools = self.environment.coredata.backend_options['backend_max_links'].value
@@ -2049,6 +2135,12 @@ rule FORTRAN_DEP_HACK%s
commands = self._generate_single_compile(target, compiler, is_generated)
commands = CompilerArgs(commands.compiler, commands)
+ # Create introspection information
+ if is_generated is False:
+ self.create_target_source_introspection(target, compiler, commands, [src], [])
+ else:
+ self.create_target_source_introspection(target, compiler, commands, [], [src])
+
build_dir = self.environment.get_build_dir()
if isinstance(src, File):
rel_src = src.rel_to_builddir(self.build_to_src)
@@ -2663,6 +2755,15 @@ rule FORTRAN_DEP_HACK%s
elem = NinjaBuildElement(self.all_outputs, deps, 'phony', '')
elem.write(outfile)
+ def get_introspection_data(self, target_id, target):
+ if target_id not in self.introspection_data or len(self.introspection_data[target_id]) == 0:
+ return super().get_introspection_data(target_id, target)
+
+ result = self.introspection_data[target_id].copy()
+ for i in result:
+ i.pop('id_hash')
+ return result
+
def load(build_dir):
filename = os.path.join(build_dir, 'meson-private', 'install.dat')
with open(filename, 'rb') as f:
diff --git a/mesonbuild/mintro.py b/mesonbuild/mintro.py
index e10b95b..9372ed8 100644
--- a/mesonbuild/mintro.py
+++ b/mesonbuild/mintro.py
@@ -272,7 +272,7 @@ def list_target_files(target_name, targets):
raise RuntimeError('Target with the ID "{}" could not be found'.format(target_name))
for i in tgt['sources']:
- result += i['source_files']
+ result += i['sources'] + i['generated_sources']
return ('target_files', result)