aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2016-10-15 05:27:35 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2016-10-19 20:46:04 +0530
commit65e9761cb1c8c5d7f75c65f8b35af4ce9bb124d5 (patch)
treea4131a81ad8f3b60eba33b60b3ec4a21e8400f83
parent23b060f0aa64d59ab6636964f9c308d6c0d2bebc (diff)
downloadmeson-65e9761cb1c8c5d7f75c65f8b35af4ce9bb124d5.zip
meson-65e9761cb1c8c5d7f75c65f8b35af4ce9bb124d5.tar.gz
meson-65e9761cb1c8c5d7f75c65f8b35af4ce9bb124d5.tar.bz2
Support all kinds of generated vala and vapi sources
This is the first step in making Vala support have feature-parity with C/C++ support. Vala and Vapi sources generated with Generators and CustomTargets are no longer ignored. Dependencies are setup properly and they are added to the commandline.
-rw-r--r--mesonbuild/backend/ninjabackend.py195
-rw-r--r--mesonbuild/build.py1
-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
13 files changed, 175 insertions, 74 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index a3c36c2..fa537ad 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -264,7 +264,6 @@ int dummy;
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
@@ -285,14 +284,22 @@ int dummy;
self.generate_swift_target(target, outfile)
return
- # Pre-existing target C/C++ sources to be built
- target_sources = []
- # GeneratedList and CustomTarget sources to be built
- generated_sources = []
+ # 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)
- target_sources = self.get_target_sources(target)
- generated_sources = self.get_target_generated_sources(target)
+ # 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)
# Generate rules for GeneratedLists
self.generate_generator_list_rules(target, outfile)
@@ -347,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))
@@ -368,8 +375,6 @@ int dummy;
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 f, src in target_sources.items():
- if src.endswith('.vala'):
- continue
if not self.environment.is_header(src):
src_list.append(src)
if is_unity:
@@ -871,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:
@@ -894,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 = []
@@ -959,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']
@@ -1664,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
@@ -1791,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])
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index e500410..e16f118 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -776,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 = {}
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')])