aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/backend/backends.py43
-rw-r--r--mesonbuild/backend/ninjabackend.py365
-rw-r--r--mesonbuild/backend/vs2010backend.py6
-rw-r--r--mesonbuild/build.py22
-rw-r--r--test cases/vala/11 mixed sources/c/foo.c5
-rw-r--r--test cases/vala/11 mixed sources/c/meson.build5
-rw-r--r--test cases/vala/11 mixed sources/c/writec.py12
-rw-r--r--test cases/vala/11 mixed sources/foo.c3
-rw-r--r--test cases/vala/11 mixed sources/meson.build4
-rw-r--r--test cases/vala/11 mixed sources/vala/bar.vala (renamed from test cases/vala/11 mixed sources/bar.vala)0
-rw-r--r--test cases/vala/8 generated source/src/meson.build5
-rw-r--r--test cases/vala/8 generated source/src/test.vala3
-rw-r--r--test cases/vala/8 generated sources/installed_files.txt (renamed from test cases/vala/8 generated source/installed_files.txt)0
-rw-r--r--test cases/vala/8 generated sources/meson.build (renamed from test cases/vala/8 generated source/meson.build)0
-rw-r--r--test cases/vala/8 generated sources/src/config.vala.in (renamed from test cases/vala/8 generated source/src/config.vala.in)0
-rw-r--r--test cases/vala/8 generated sources/src/copy_file.py7
-rw-r--r--test cases/vala/8 generated sources/src/meson.build17
-rw-r--r--test cases/vala/8 generated sources/src/returncode.in3
-rw-r--r--test cases/vala/8 generated sources/src/test.vala4
-rw-r--r--test cases/vala/8 generated sources/src/write_wrapper.py12
-rw-r--r--test cases/vala/8 generated sources/tools/meson.build (renamed from test cases/vala/8 generated source/tools/meson.build)2
21 files changed, 340 insertions, 178 deletions
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 1d3fddd..0eb4c6e 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -93,16 +93,16 @@ class Backend():
src = src.fname
raise RuntimeError('No specified compiler can handle file ' + src)
- def get_target_filename(self, target):
- assert(isinstance(target, (build.BuildTarget, build.CustomTarget)))
- targetdir = self.get_target_dir(target)
- fname = target.get_filename()
- if isinstance(fname, list):
- # FIXME FIXME FIXME: build.CustomTarget has multiple output files
- # and get_filename() returns them all
- fname = fname[0]
- filename = os.path.join(targetdir, fname)
- return filename
+ def get_target_filename(self, t):
+ if isinstance(t, build.CustomTarget):
+ if len(t.get_outputs()) != 1:
+ mlog.log(mlog.red('WARNING'), 'custom_target {!r} has more ' \
+ 'than one output! Using the first one.'.format(t.name))
+ filename = t.get_outputs()[0]
+ else:
+ assert(isinstance(t, build.BuildTarget))
+ filename = t.get_filename()
+ return os.path.join(self.get_target_dir(t), filename)
def get_target_filename_abs(self, target):
return os.path.join(self.environment.get_build_dir(), self.get_target_filename(target))
@@ -140,6 +140,19 @@ class Backend():
dirname = os.path.join(self.environment.get_build_dir(), self.get_target_private_dir(target))
return dirname
+ def get_target_generated_dir(self, target, gensrc, src):
+ """
+ Takes a BuildTarget, a generator source (CustomTarget or GeneratedList),
+ and a generated source filename.
+ Returns the full path of the generated source relative to the build root
+ """
+ # CustomTarget generators output to the build dir of the CustomTarget
+ if isinstance(gensrc, build.CustomTarget):
+ return os.path.join(self.get_target_dir(gensrc), src)
+ # GeneratedList generators output to the private build directory of the
+ # target that the GeneratedList is used in
+ return os.path.join(self.get_target_private_dir(target), src)
+
def generate_unity_files(self, target, unity_src):
langlist = {}
abs_files = []
@@ -520,15 +533,17 @@ class Backend():
outdir = '.'
if absolute_paths:
outdir = os.path.join(self.environment.get_build_dir(), outdir)
- for i in target.sources:
+ for i in target.get_sources():
if hasattr(i, 'held_object'):
i = i.held_object
if isinstance(i, str):
fname = [os.path.join(self.build_to_src, target.subdir, i)]
- elif isinstance(i, (build.BuildTarget, build.CustomTarget)):
+ elif isinstance(i, build.BuildTarget):
fname = [self.get_target_filename(i)]
+ elif isinstance(i, build.CustomTarget):
+ fname = [os.path.join(self.get_target_dir(i), p) for p in i.get_outputs()]
elif isinstance(i, build.GeneratedList):
- fname = [os.path.join(self.get_target_private_dir(target), p) for p in i.get_outfilelist()]
+ fname = [os.path.join(self.get_target_private_dir(target), p) for p in i.get_outputs()]
else:
fname = [i.rel_to_builddir(self.build_to_src)]
if absolute_paths:
@@ -542,7 +557,7 @@ class Backend():
elif 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]
+ tmp = i.get_outputs()[0]
i = os.path.join(self.get_target_dir(i), tmp)
elif isinstance(i, mesonlib.File):
i = i.rel_to_builddir(self.build_to_src)
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index f8c8109..fa537ad 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -35,6 +35,10 @@ def ninja_quote(text):
return text.replace(' ', '$ ').replace(':', '$:')
class RawFilename():
+ """
+ Used when a filename is already relative to the root build directory, so
+ that we know not to add the target's private build directory to it.
+ """
def __init__(self, fname):
self.fname = fname
@@ -216,26 +220,57 @@ int dummy;
# we need to add an order dependency to them.
def get_generated_headers(self, target):
header_deps = []
- for gensource in target.get_generated_sources():
- if isinstance(gensource, build.CustomTarget):
+ # XXX: Why don't we add deps to CustomTarget headers here?
+ for genlist in target.get_generated_sources():
+ if isinstance(genlist, build.CustomTarget):
continue
- for src in gensource.get_outfilelist():
+ for src in genlist.get_outputs():
if self.environment.is_header(src):
- header_deps.append(os.path.join(self.get_target_private_dir(target), src))
+ header_deps.append(self.get_target_generated_dir(target, genlist, src))
+ # Recurse and find generated headers
for dep in target.link_targets:
if isinstance(dep, (build.StaticLibrary, build.SharedLibrary)):
header_deps += self.get_generated_headers(dep)
return header_deps
+ def get_target_generated_sources(self, target):
+ """
+ Returns a dictionary with the keys being the path to the file
+ (relative to the build directory) of that type and the value
+ being the GeneratorList or CustomTarget that generated it.
+ """
+ srcs = {}
+ for gensrc in target.get_generated_sources():
+ for s in gensrc.get_outputs():
+ f = self.get_target_generated_dir(target, gensrc, s)
+ srcs[f] = s
+ return srcs
+
+ def get_target_sources(self, target):
+ srcs = {}
+ for s in target.get_sources():
+ # BuildTarget sources are always mesonlib.File files which are
+ # either in the source root, or generated with configure_file and
+ # in the build root
+ if not isinstance(s, File):
+ raise InvalidArguments('All sources in target {!r} must be of type mesonlib.File'.format(t))
+ f = s.rel_to_builddir(self.build_to_src)
+ srcs[f] = s
+ return srcs
+
def generate_target(self, target, outfile):
if isinstance(target, build.CustomTarget):
self.generate_custom_target(target, outfile)
if isinstance(target, build.RunTarget):
self.generate_run_target(target, outfile)
name = target.get_id()
- vala_gen_sources = []
if name in self.processed_targets:
return
+ self.processed_targets[name] = True
+ # Generate rules for all dependency targets
+ self.process_target_dependencies(target, outfile)
+ # If target uses a language that cannot link to C objects,
+ # just generate for that language and return.
if isinstance(target, build.Jar):
self.generate_jar_target(target, outfile)
return
@@ -248,11 +283,28 @@ int dummy;
if 'swift' in target.compilers:
self.generate_swift_target(target, outfile)
return
+
+ # Pre-existing target C/C++ sources to be built; dict of full path to
+ # source relative to build root and the original File object.
+ target_sources = {}
+ # GeneratedList and CustomTarget sources to be built; dict of the full
+ # path to source relative to build root and the generating target/list
+ generated_sources = {}
+ # Array of sources generated by valac that have to be compiled
+ vala_generated_sources = []
if 'vala' in target.compilers:
- vala_gen_sources = self.generate_vala_compile(target, outfile)
+ # Sources consumed by valac are filtered out. These only contain
+ # C/C++ sources, objects, generated libs, and unknown sources now.
+ target_sources, generated_sources, \
+ vala_generated_sources = self.generate_vala_compile(target, outfile)
+ else:
+ target_sources = self.get_target_sources(target)
+ generated_sources = self.get_target_generated_sources(target)
self.scan_fortran_module_outputs(target)
- self.process_target_dependencies(target, outfile)
- self.generate_custom_generator_rules(target, outfile)
+ # Generate rules for GeneratedLists
+ self.generate_generator_list_rules(target, outfile)
+
+ # Generate rules for building the remaining source files in this target
outname = self.get_target_filename(target)
obj_list = []
use_pch = self.environment.coredata.base_options.get('b_pch', False)
@@ -275,41 +327,24 @@ int dummy;
# This will be set as dependencies of all the target's sources. At the
# same time, also deal with generated sources that need to be compiled.
generated_source_files = []
- for gensource in target.get_generated_sources():
- if isinstance(gensource, build.CustomTarget):
- for src in gensource.output:
- src = os.path.join(self.get_target_dir(gensource), src)
- generated_output_sources.append(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)))
- else:
- generated_source_files.append(RawFilename(src))
- elif self.environment.is_object(src):
- obj_list.append(src)
- elif self.environment.is_library(src):
- pass
- else:
- # Assume anything not specifically a source file is a header. This is because
- # people generate files with weird suffixes (.inc, .fh) that they then include
- # in their source files.
- header_deps.append(RawFilename(src))
+ for rel_src, gensrc in generated_sources.items():
+ generated_output_sources.append(rel_src)
+ if self.environment.is_source(rel_src) and not self.environment.is_header(rel_src):
+ if is_unity:
+ unity_deps.append(rel_src)
+ abs_src = os.path.join(self.environment.get_build_dir(), rel_src)
+ unity_src.append(abs_src)
+ else:
+ generated_source_files.append(RawFilename(rel_src))
+ elif self.environment.is_object(rel_src):
+ obj_list.append(rel_src)
+ elif self.environment.is_library(rel_src):
+ pass
else:
- for src in gensource.get_outfilelist():
- generated_output_sources.append(src)
- if self.environment.is_object(src):
- obj_list.append(os.path.join(self.get_target_private_dir(target), src))
- elif not self.environment.is_header(src):
- if is_unity:
- if self.has_dir_part(src):
- rel_src = src
- else:
- rel_src = os.path.join(self.get_target_private_dir(target), src)
- unity_deps.append(rel_src)
- abs_src = os.path.join(self.environment.get_build_dir(), rel_src)
- unity_src.append(abs_src)
- else:
- generated_source_files.append(src)
+ # Assume anything not specifically a source file is a header. This is because
+ # people generate files with weird suffixes (.inc, .fh) that they then include
+ # in their source files.
+ header_deps.append(RawFilename(rel_src))
# These are the generated source files that need to be built for use by
# this target. We create the Ninja build file elements for this here
# because we need `header_deps` to be fully generated in the above loop.
@@ -319,8 +354,8 @@ int dummy;
header_deps=header_deps))
# Generate compilation targets for C sources generated from Vala
# sources. This can be extended to other $LANG->C compilers later if
- # necessary.
- for src in vala_gen_sources:
+ # necessary. This needs to be separate for at least Vala
+ for src in vala_generated_sources:
src_list.append(src)
if is_unity:
unity_src.append(os.path.join(self.environment.get_build_dir(), src))
@@ -334,11 +369,12 @@ int dummy;
if self.environment.is_header(src):
header_deps.append(src)
else:
+ # Passing 'vala' here signifies that we want the compile
+ # arguments to be specialized for C code generated by
+ # valac. For instance, no warnings should be emitted.
obj_list.append(self.generate_single_compile(target, outfile, src, 'vala', [], header_deps))
# Generate compile targets for all the pre-existing sources for this target
- for src in target.get_sources():
- if src.endswith('.vala'):
- continue
+ for f, src in target_sources.items():
if not self.environment.is_header(src):
src_list.append(src)
if is_unity:
@@ -355,7 +391,6 @@ int dummy;
elem = self.generate_link(target, outfile, outname, obj_list, linker, pch_objects)
self.generate_shlib_aliases(target, self.get_target_dir(target))
elem.write(outfile)
- self.processed_targets[name] = True
def process_target_dependencies(self, target, outfile):
for t in target.get_dependencies():
@@ -376,10 +411,9 @@ int dummy;
# FIXME, should not grab element at zero but rather expand all.
if isinstance(i, list):
i = i[0]
- fname = i.get_filename()
- if isinstance(fname, list):
- fname = fname[0]
- deps.append(os.path.join(self.get_target_dir(i), fname))
+ # Add a dependency on all the outputs of this target
+ for output in i.get_outputs():
+ deps.append(os.path.join(self.get_target_dir(i), output))
return deps
def generate_custom_target(self, target, outfile):
@@ -401,11 +435,9 @@ int dummy;
deps.append(os.path.join(self.build_to_src, i))
elem.add_dep(deps)
for d in target.extra_depends:
- tmp = d.get_filename()
- if not isinstance(tmp, list):
- tmp = [tmp]
- for fname in tmp:
- elem.add_dep(os.path.join(self.get_target_dir(d), fname))
+ # Add a dependency on all the outputs of this target
+ for output in d.get_outputs():
+ elem.add_dep(os.path.join(self.get_target_dir(d), output))
# If the target requires capturing stdout, then use the serialized
# executable wrapper to capture that output and save it to a file.
#
@@ -541,7 +573,8 @@ int dummy;
should_strip = self.environment.coredata.get_builtin_option('strip')
for t in self.build.get_targets().values():
if t.should_install():
- # Find the installation directory
+ # Find the installation directory. FIXME: Currently only one
+ # installation directory is supported for each target
outdir = t.get_custom_install_dir()
if outdir is not None:
pass
@@ -572,9 +605,14 @@ int dummy;
# stripped, and doesn't have an install_rpath
i = [self.get_target_debug_filename(t), outdir, [], False, '']
d.targets.append(i)
- i = [self.get_target_filename(t), outdir, t.get_aliaslist(),\
- should_strip, t.install_rpath]
- d.targets.append(i)
+ if isinstance(t, build.BuildTarget):
+ i = [self.get_target_filename(t), outdir, t.get_aliaslist(),\
+ should_strip, t.install_rpath]
+ d.targets.append(i)
+ elif isinstance(t, build.CustomTarget):
+ for output in t.get_outputs():
+ f = os.path.join(self.get_target_dir(t), output)
+ d.targets.append([f, outdir, [], False, None])
def generate_custom_install_script(self, d):
d.install_scripts = self.build.install_scripts
@@ -838,17 +876,13 @@ int dummy;
outfile.write(description)
outfile.write('\n')
- def split_vala_sources(self, sources):
- other_src = []
- vapi_src = []
- for s in sources:
- if s.endswith('.vapi'):
- vapi_src.append(s)
- else:
- other_src.append(s)
- return (other_src, vapi_src)
-
def determine_dep_vapis(self, target):
+ """
+ Peek into the sources of BuildTargets we're linking with, and if any of
+ them was built with Vala, assume that it also generated a .vapi file of
+ the same name as the BuildTarget and return the path to it relative to
+ the build directory.
+ """
result = []
for dep in target.link_targets:
for i in dep.sources:
@@ -861,57 +895,119 @@ int dummy;
break
return result
+ def split_vala_sources(self, t):
+ """
+ Splits the target's sources into .vala, .vapi, and other sources.
+ Handles both pre-existing and generated sources.
+
+ Returns a tuple (vala, vapi, others) each of which is a dictionary with
+ the keys being the path to the file (relative to the build directory)
+ and the value being the object that generated or represents the file.
+ """
+ vala = {}
+ vapi = {}
+ others = {}
+ othersgen = {}
+ # Split pre-existing sources
+ for s in t.get_sources():
+ # BuildTarget sources are always mesonlib.File files which are
+ # either in the source root, or generated with configure_file and
+ # in the build root
+ if not isinstance(s, File):
+ msg = 'All sources in target {!r} must be of type ' \
+ 'mesonlib.File, not {!r}'.format(t, s)
+ raise InvalidArguments(msg)
+ f = s.rel_to_builddir(self.build_to_src)
+ if s.endswith('.vala'):
+ srctype = vala
+ elif s.endswith('.vapi'):
+ srctype = vapi
+ else:
+ srctype = others
+ srctype[f] = s
+ # Split generated sources
+ for gensrc in t.get_generated_sources():
+ for s in gensrc.get_outputs():
+ f = self.get_target_generated_dir(t, gensrc, s)
+ if s.endswith('.vala'):
+ srctype = vala
+ elif s.endswith('.vapi'):
+ srctype = vapi
+ # Generated non-Vala (C/C++) sources. Won't be used for
+ # generating the Vala compile rule below.
+ else:
+ srctype = othersgen
+ # Duplicate outputs are disastrous
+ if f in srctype:
+ msg = 'Duplicate output {0!r} from {1!r} {2!r}; ' \
+ 'conflicts with {0!r} from {4!r} {3!r}' \
+ ''.format(f, type(gensrc).__name__, gensrc.name,
+ srctype[f].name, type(srctype[f]).__name__)
+ raise InvalidArguments(msg)
+ # Store 'somefile.vala': GeneratedList (or CustomTarget)
+ srctype[f] = gensrc
+ return (vala, vapi, (others, othersgen))
+
def generate_vala_compile(self, target, outfile):
"""Vala is compiled into C. Set up all necessary build steps here."""
- valac = target.compilers['vala']
- (other_src, vapi_src) = self.split_vala_sources(target.get_sources())
- vapi_src = [x.rel_to_builddir(self.build_to_src) for x in vapi_src]
+ (vala_src, vapi_src, other_src) = self.split_vala_sources(target)
extra_dep_files = []
- if len(other_src) == 0:
+ if len(vala_src) == 0:
raise InvalidArguments('Vala library has no Vala source files.')
- namebase = target.name
- base_h = namebase + '.h'
- base_vapi = namebase + '.vapi'
- hname = os.path.normpath(os.path.join(self.get_target_dir(target), base_h))
- vapiname = os.path.normpath(os.path.join(self.get_target_dir(target), base_vapi))
-
- generated_c_files = []
- outputs = [vapiname]
- args = []
- args += self.build.get_global_args(valac)
- args += valac.get_buildtype_args(self.environment.coredata.get_builtin_option('buildtype'))
- args += ['-d', self.get_target_private_dir(target)]
- args += ['-C']#, '-o', cname]
- if not isinstance(target, build.Executable):
- outputs.append(hname)
- args += ['-H', hname]
- args += ['--library=' + target.name]
- args += ['--vapi=' + os.path.join('..', base_vapi)]
- vala_src = []
- for s in other_src:
- if not s.endswith('.vala'):
- continue
- vala_file = s.rel_to_builddir(self.build_to_src)
- vala_src.append(vala_file)
+
+ valac = target.compilers['vala']
+ c_out_dir = self.get_target_private_dir(target)
+ # C files generated by valac
+ vala_c_src = []
+ # Files generated by valac
+ valac_outputs = []
+ # All sources that are passed to valac on the commandline
+ all_files = list(vapi_src.keys())
+ for (vala_file, gensrc) in vala_src.items():
+ all_files.append(vala_file)
# Figure out where the Vala compiler will write the compiled C file
- dirname, basename = os.path.split(vala_file)
# If the Vala file is in a subdir of the build dir (in our case
# because it was generated/built by something else), the subdir path
# components will be preserved in the output path. But if the Vala
# file is outside the build directory, the path components will be
# stripped and just the basename will be used.
- c_file = os.path.splitext(basename)[0] + '.c'
- if s.is_built:
- c_file = os.path.join(dirname, c_file)
- full_c = os.path.join(self.get_target_private_dir(target), c_file)
- generated_c_files.append(full_c)
- outputs.append(full_c)
+ if isinstance(gensrc, (build.CustomTarget, build.GeneratedList)) or gensrc.is_built:
+ vala_c_file = os.path.splitext(vala_file)[0] + '.c'
+ else:
+ vala_c_file = os.path.splitext(os.path.basename(vala_file))[0] + '.c'
+ # All this will be placed inside the c_out_dir
+ vala_c_file = os.path.join(c_out_dir, vala_c_file)
+ vala_c_src.append(vala_c_file)
+ valac_outputs.append(vala_c_file)
+
+ args = []
+ args += self.build.get_global_args(valac)
+ args += valac.get_buildtype_args(self.environment.coredata.get_builtin_option('buildtype'))
+ # Tell Valac to output everything in our private directory. Sadly this
+ # means it will also preserve the directory components of Vala sources
+ # found inside the build tree (generated sources).
+ args += ['-d', c_out_dir]
+ args += ['-C']
+ if not isinstance(target, build.Executable):
+ # Library name
+ args += ['--library=' + target.name]
+ # Outputted header
+ hname = os.path.join(self.get_target_dir(target), target.name + '.h')
+ args += ['-H', hname]
+ valac_outputs.append(hname)
+ # Outputted vapi file
+ base_vapi = target.name + '.vapi'
+ vapiname = os.path.join(self.get_target_dir(target), base_vapi)
+ # Force valac to write the vapi file in the target build dir.
+ # Without this, it will write it inside c_out_dir
+ args += ['--vapi=../' + base_vapi]
+ valac_outputs.append(vapiname)
if self.environment.coredata.get_builtin_option('werror'):
args += valac.get_werror_args()
- for d in target.external_deps:
+ for d in target.get_external_deps():
if isinstance(d, dependencies.PkgConfigDependency):
if d.name == 'glib-2.0' and d.version_requirement is not None \
- and d.version_requirement.startswith(('>=', '==')):
+ and d.version_requirement.startswith(('>=', '==')):
args += ['--target-glib', d.version_requirement[2:]]
args += ['--pkg', d.name]
extra_args = []
@@ -926,14 +1022,13 @@ int dummy;
dependency_vapis = self.determine_dep_vapis(target)
extra_dep_files += dependency_vapis
args += extra_args
- args += dependency_vapis
- element = NinjaBuildElement(self.all_outputs, outputs,
+ element = NinjaBuildElement(self.all_outputs, valac_outputs,
valac.get_language() + '_COMPILER',
- vala_src + vapi_src)
+ all_files + dependency_vapis)
element.add_item('ARGS', args)
element.add_dep(extra_dep_files)
element.write(outfile)
- return generated_c_files
+ return other_src[0], other_src[1], vala_c_src
def generate_rust_target(self, target, outfile):
rustc = target.compilers['rust']
@@ -1006,16 +1101,7 @@ int dummy;
return result
def split_swift_generated_sources(self, target):
- all_srcs = []
- for genlist in target.get_generated_sources():
- if isinstance(genlist, build.CustomTarget):
- for ifile in genlist.get_filename():
- rel = os.path.join(self.get_target_dir(genlist), ifile)
- all_srcs.append(rel)
- else:
- for ifile in genlist.get_outfilelist():
- rel = os.path.join(self.get_target_private_dir(target), ifile)
- all_srcs.append(rel)
+ all_srcs = self.get_target_generated_sources(target)
srcs = []
others = []
for i in all_srcs:
@@ -1392,18 +1478,20 @@ rule FORTRAN_DEP_HACK
self.generate_pch_rule_for(langname, compiler, qstr, True, outfile)
outfile.write('\n')
- def generate_custom_generator_rules(self, target, outfile):
+ def generate_generator_list_rules(self, target, outfile):
+ # CustomTargets have already written their rules,
+ # so write rules for GeneratedLists here
for genlist in target.get_generated_sources():
if isinstance(genlist, build.CustomTarget):
- continue # Customtarget has already written its output rules
+ continue
self.generate_genlist_for_target(genlist, target, outfile)
def generate_genlist_for_target(self, genlist, target, outfile):
generator = genlist.get_generator()
exe = generator.get_exe()
exe_arr = self.exe_object_to_cmd_array(exe)
- infilelist = genlist.get_infilelist()
- outfilelist = genlist.get_outfilelist()
+ infilelist = genlist.get_inputs()
+ outfilelist = genlist.get_outputs()
base_args = generator.get_arglist()
extra_dependencies = [os.path.join(self.build_to_src, i) for i in genlist.extra_depends]
for i in range(len(infilelist)):
@@ -1579,6 +1667,9 @@ rule FORTRAN_DEP_HACK
return linker.get_link_debugfile_args(outname)
def generate_single_compile(self, target, outfile, src, is_generated=False, header_deps=[], order_deps=[]):
+ """
+ Compiles only C/C++ and ObjC/ObjC++ sources
+ """
if(isinstance(src, str) and src.endswith('.h')):
raise RuntimeError('Fug')
if isinstance(src, RawFilename) and src.fname.endswith('.h'):
@@ -1635,7 +1726,7 @@ rule FORTRAN_DEP_HACK
if isinstance(src, File):
rel_src = src.rel_to_builddir(self.build_to_src)
else:
- raise build.InvalidArguments('Invalid source type.')
+ raise InvalidArguments('Invalid source type: {!r}'.format(src))
abs_src = os.path.join(self.environment.get_build_dir(), rel_src)
if isinstance(src, (RawFilename, File)):
src_filename = src.fname
@@ -1659,11 +1750,12 @@ rule FORTRAN_DEP_HACK
arr.append(i)
pch_dep = arr
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 target.get_generated_sources():
+ if not isinstance(i, build.CustomTarget):
+ continue
+ 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, False)
if self.environment.coredata.base_options.get('b_pch', False):
@@ -1761,7 +1853,10 @@ rule FORTRAN_DEP_HACK
if len(pch) == 0:
continue
if '/' not in pch[0] or '/' not in pch[-1]:
- raise build.InvalidArguments('Precompiled header of "%s" must not be in the same directory as source, please put it in a subdirectory.' % target.get_basename())
+ msg = 'Precompiled header of {!r} must not be in the same ' \
+ 'directory as source, please put it in a subdirectory.' \
+ ''.format(target.get_basename())
+ raise InvalidArguments(msg)
compiler = self.get_compiler_for_lang(lang)
if compiler.id == 'msvc':
src = os.path.join(self.build_to_src, target.get_source_subdir(), pch[-1])
@@ -1941,7 +2036,9 @@ rule FORTRAN_DEP_HACK
# are used by something else or are meant to be always built
if isinstance(t, build.CustomTarget) and not (t.install or t.build_always):
continue
- targetlist.append(self.get_target_filename(t))
+ # Add the first output of each target to the 'all' target so that
+ # they are all built
+ targetlist.append(os.path.join(self.get_target_dir(t), t.get_outputs()[0]))
elem = NinjaBuildElement(self.all_outputs, 'all', 'phony', targetlist)
elem.write(outfile)
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py
index eca7473..f1d949a 100644
--- a/mesonbuild/backend/vs2010backend.py
+++ b/mesonbuild/backend/vs2010backend.py
@@ -102,7 +102,7 @@ class Vs2010Backend(backends.Backend):
down = self.target_to_build_root(target)
for genlist in target.get_generated_sources():
if isinstance(genlist, build.CustomTarget):
- for i in genlist.output:
+ for i in genlist.get_outputs():
# Path to the generated source from the current vcxproj dir via the build root
ipath = os.path.join(down, self.get_target_dir(genlist), i)
custom_target_output_files.append(ipath)
@@ -112,8 +112,8 @@ class Vs2010Backend(backends.Backend):
else:
generator = genlist.get_generator()
exe = generator.get_exe()
- infilelist = genlist.get_infilelist()
- outfilelist = genlist.get_outfilelist()
+ infilelist = genlist.get_inputs()
+ outfilelist = genlist.get_outputs()
exe_arr = self.exe_object_to_cmd_array(exe)
base_args = generator.get_arglist()
for i in range(len(infilelist)):
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 17cc89e..e16f118 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -547,6 +547,9 @@ class BuildTarget():
def get_filename(self):
return self.filename
+ def get_outputs(self):
+ return [self.filename]
+
def get_debug_filename(self):
"""
The name of the file that contains debugging symbols for this target
@@ -650,12 +653,6 @@ by calling get_variable() on the subproject object.''')
raise InvalidArguments('Tried to mix cross built and native libraries in target {!r}'.format(self.name))
self.link_targets.append(t)
- def set_generated(self, genlist):
- for g in genlist:
- if not(isinstance(g, GeneratedList)):
- raise InvalidArguments('Generated source argument is not the output of a generator.')
- self.generated.append(g)
-
def add_pch(self, language, pchlist):
if len(pchlist) == 0:
return
@@ -705,7 +702,7 @@ class Generator():
def __init__(self, args, kwargs):
if len(args) != 1:
raise InvalidArguments('Generator requires one and only one positional argument')
-
+
exe = args[0]
if hasattr(exe, 'held_object'):
exe = exe.held_object
@@ -779,6 +776,7 @@ class GeneratedList():
if hasattr(generator, 'held_object'):
generator = generator.held_object
self.generator = generator
+ self.name = self.generator.exe
self.infilelist = []
self.outfilelist = []
self.outmap = {}
@@ -791,10 +789,10 @@ class GeneratedList():
self.outfilelist += outfiles
self.outmap[newfile] = outfiles
- def get_infilelist(self):
+ def get_inputs(self):
return self.infilelist
- def get_outfilelist(self):
+ def get_outputs(self):
return self.outfilelist
def get_outputs_for(self, filename):
@@ -1085,7 +1083,6 @@ class CustomTarget:
self.depfile = None
self.process_kwargs(kwargs)
self.extra_files = []
- self.install_rpath = ''
unknowns = []
for k in kwargs:
if k not in CustomTarget.known_kwargs:
@@ -1217,12 +1214,9 @@ class CustomTarget:
def get_subdir(self):
return self.subdir
- def get_filename(self):
+ def get_outputs(self):
return self.output
- def get_aliaslist(self):
- return []
-
def get_sources(self):
return self.sources
diff --git a/test cases/vala/11 mixed sources/c/foo.c b/test cases/vala/11 mixed sources/c/foo.c
new file mode 100644
index 0000000..f3c6fb8
--- /dev/null
+++ b/test cases/vala/11 mixed sources/c/foo.c
@@ -0,0 +1,5 @@
+int retval (void);
+
+int test (void) {
+ return retval ();
+}
diff --git a/test cases/vala/11 mixed sources/c/meson.build b/test cases/vala/11 mixed sources/c/meson.build
new file mode 100644
index 0000000..ead0575
--- /dev/null
+++ b/test cases/vala/11 mixed sources/c/meson.build
@@ -0,0 +1,5 @@
+writec = find_program('writec.py')
+
+retval = custom_target('writec',
+ output : 'retval.c',
+ command : [writec, '@OUTPUT@'])
diff --git a/test cases/vala/11 mixed sources/c/writec.py b/test cases/vala/11 mixed sources/c/writec.py
new file mode 100644
index 0000000..2cc822b
--- /dev/null
+++ b/test cases/vala/11 mixed sources/c/writec.py
@@ -0,0 +1,12 @@
+#!/usr/bin/env python3
+
+import sys
+
+c = '''int
+retval(void) {
+ return 0;
+}
+'''
+
+with open(sys.argv[1], 'w') as f:
+ f.write(c)
diff --git a/test cases/vala/11 mixed sources/foo.c b/test cases/vala/11 mixed sources/foo.c
deleted file mode 100644
index 05910a6..0000000
--- a/test cases/vala/11 mixed sources/foo.c
+++ /dev/null
@@ -1,3 +0,0 @@
-int test () {
- return 0;
-}
diff --git a/test cases/vala/11 mixed sources/meson.build b/test cases/vala/11 mixed sources/meson.build
index c84c8cd..75b8ecd 100644
--- a/test cases/vala/11 mixed sources/meson.build
+++ b/test cases/vala/11 mixed sources/meson.build
@@ -2,4 +2,6 @@ project('foo', 'c', 'vala')
glib = dependency('glib-2.0')
-executable('foo', 'foo.c', 'bar.vala', dependencies: [glib])
+subdir('c')
+e = executable('foo', 'c/foo.c', retval, 'vala/bar.vala', dependencies: [glib])
+test('test foo', e)
diff --git a/test cases/vala/11 mixed sources/bar.vala b/test cases/vala/11 mixed sources/vala/bar.vala
index 10dce1e..10dce1e 100644
--- a/test cases/vala/11 mixed sources/bar.vala
+++ b/test cases/vala/11 mixed sources/vala/bar.vala
diff --git a/test cases/vala/8 generated source/src/meson.build b/test cases/vala/8 generated source/src/meson.build
deleted file mode 100644
index 9096c67..0000000
--- a/test cases/vala/8 generated source/src/meson.build
+++ /dev/null
@@ -1,5 +0,0 @@
-config = configure_file(input: 'config.vala.in',
- output: 'config.vala',
- configuration: cd)
-
-src = files('test.vala')
diff --git a/test cases/vala/8 generated source/src/test.vala b/test cases/vala/8 generated source/src/test.vala
deleted file mode 100644
index 98d6821..0000000
--- a/test cases/vala/8 generated source/src/test.vala
+++ /dev/null
@@ -1,3 +0,0 @@
-void main() {
- print (Config.x);
-}
diff --git a/test cases/vala/8 generated source/installed_files.txt b/test cases/vala/8 generated sources/installed_files.txt
index a4c37f6..a4c37f6 100644
--- a/test cases/vala/8 generated source/installed_files.txt
+++ b/test cases/vala/8 generated sources/installed_files.txt
diff --git a/test cases/vala/8 generated source/meson.build b/test cases/vala/8 generated sources/meson.build
index 7271821..7271821 100644
--- a/test cases/vala/8 generated source/meson.build
+++ b/test cases/vala/8 generated sources/meson.build
diff --git a/test cases/vala/8 generated source/src/config.vala.in b/test cases/vala/8 generated sources/src/config.vala.in
index a5196fd..a5196fd 100644
--- a/test cases/vala/8 generated source/src/config.vala.in
+++ b/test cases/vala/8 generated sources/src/config.vala.in
diff --git a/test cases/vala/8 generated sources/src/copy_file.py b/test cases/vala/8 generated sources/src/copy_file.py
new file mode 100644
index 0000000..b90d91f
--- /dev/null
+++ b/test cases/vala/8 generated sources/src/copy_file.py
@@ -0,0 +1,7 @@
+#!/usr/bin/env python3
+
+import os
+import sys
+import shutil
+
+shutil.copyfile(sys.argv[1], sys.argv[2])
diff --git a/test cases/vala/8 generated sources/src/meson.build b/test cases/vala/8 generated sources/src/meson.build
new file mode 100644
index 0000000..06515c1
--- /dev/null
+++ b/test cases/vala/8 generated sources/src/meson.build
@@ -0,0 +1,17 @@
+config = configure_file(input: 'config.vala.in',
+ output: 'config.vala',
+ configuration: cd)
+
+print = find_program('write_wrapper.py')
+wrapper = custom_target('wrapper',
+ output : 'print_wrapper.vala',
+ command : [print, '@OUTPUT@'])
+
+copy = find_program('copy_file.py')
+gen = generator(copy,
+ output : '@BASENAME@.vala',
+ arguments : ['@INPUT@', '@OUTPUT@'])
+
+returncode = gen.process('returncode.in')
+
+src = files('test.vala')
diff --git a/test cases/vala/8 generated sources/src/returncode.in b/test cases/vala/8 generated sources/src/returncode.in
new file mode 100644
index 0000000..e3d3ea6
--- /dev/null
+++ b/test cases/vala/8 generated sources/src/returncode.in
@@ -0,0 +1,3 @@
+int return_code() {
+ return 0;
+}
diff --git a/test cases/vala/8 generated sources/src/test.vala b/test cases/vala/8 generated sources/src/test.vala
new file mode 100644
index 0000000..ca27676
--- /dev/null
+++ b/test cases/vala/8 generated sources/src/test.vala
@@ -0,0 +1,4 @@
+int main() {
+ print_wrapper (Config.x);
+ return return_code ();
+}
diff --git a/test cases/vala/8 generated sources/src/write_wrapper.py b/test cases/vala/8 generated sources/src/write_wrapper.py
new file mode 100644
index 0000000..b5608f7
--- /dev/null
+++ b/test cases/vala/8 generated sources/src/write_wrapper.py
@@ -0,0 +1,12 @@
+#!/usr/bin/env python3
+
+import sys
+
+contents = '''
+void print_wrapper(string arg) {
+ print (arg);
+}
+'''
+
+with open(sys.argv[1], 'w') as f:
+ f.write(contents)
diff --git a/test cases/vala/8 generated source/tools/meson.build b/test cases/vala/8 generated sources/tools/meson.build
index 834ec1a..303468e 100644
--- a/test cases/vala/8 generated source/tools/meson.build
+++ b/test cases/vala/8 generated sources/tools/meson.build
@@ -1,3 +1,3 @@
-executable('generatedtest', [src, config],
+executable('generatedtest', [src, config, returncode, wrapper],
install : true,
dependencies: [dependency('glib-2.0'), dependency('gobject-2.0')])