aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.appveyor.yml2
-rw-r--r--README.md11
-rw-r--r--authors.txt1
-rwxr-xr-xmeson.py6
-rw-r--r--mesonbuild/backend/backends.py21
-rw-r--r--mesonbuild/backend/ninjabackend.py3
-rw-r--r--mesonbuild/compilers.py77
-rw-r--r--mesonbuild/interpreter.py50
-rw-r--r--mesonbuild/modules/gnome.py275
-rw-r--r--mesonbuild/scripts/gtkdochelper.py88
-rw-r--r--test cases/common/94 default options/meson.build10
-rw-r--r--test cases/frameworks/12 multiple gir/gir/meson-subsample.c124
-rw-r--r--test cases/frameworks/12 multiple gir/gir/meson-subsample.h17
-rw-r--r--test cases/frameworks/12 multiple gir/gir/meson.build30
-rw-r--r--test cases/frameworks/12 multiple gir/gir/prog.c12
-rw-r--r--test cases/frameworks/12 multiple gir/installed_files.txt6
-rw-r--r--test cases/frameworks/12 multiple gir/meson.build7
-rw-r--r--test cases/frameworks/12 multiple gir/mesongir/meson-sample.c126
-rw-r--r--test cases/frameworks/12 multiple gir/mesongir/meson-sample.h.in22
-rw-r--r--test cases/frameworks/12 multiple gir/mesongir/meson.build37
-rw-r--r--test cases/linuxlike/9 compiler checks with dependencies/meson.build31
21 files changed, 796 insertions, 160 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
index d5e0fbf..09f67e4 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -10,8 +10,6 @@ branches:
- master
install:
- - ps: (new-object net.webclient).DownloadFile('https://www.python.org/ftp/python/3.4.4/python-3.4.4.msi', 'python-3.4.4.msi')
- - ps: msiexec /i python-3.4.4.msi /quiet /qn /norestart
- ps: (new-object net.webclient).DownloadFile('https://dl.dropboxusercontent.com/u/37517477/ninja.exe', 'c:\python34\ninja.exe')
- cmd: copy c:\python34\python.exe c:\python34\python3.exe
- '"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" /x86'
diff --git a/README.md b/README.md
index 95915b0..273398f 100644
--- a/README.md
+++ b/README.md
@@ -27,6 +27,17 @@ pip will download the package automatically). The exact command to
type to install with pip can very between systems, be sure to use the
Python 3 version of pip.
+#### Creating a standalone script
+
+Meson can be run as a [Python zip
+app](https://docs.python.org/3/library/zipapp.html). To generate the
+executable run the following command:
+
+ python3 -m zipapp -p '/usr/bin/env python3' -m meson:main -o meson <source checkout>
+
+Note that the source checkout may not be `meson` because it would
+clash with the generated binary name.
+
####Running
Meson requires that you have a source directory and a build directory
diff --git a/authors.txt b/authors.txt
index fbac571..f0c2006 100644
--- a/authors.txt
+++ b/authors.txt
@@ -45,3 +45,4 @@ Elliott Sales de Andrade
Patrick Griffis
Iain Lane
Daniel Brendle
+Franz Zapata
diff --git a/meson.py b/meson.py
index b977368..7f2c49d 100755
--- a/meson.py
+++ b/meson.py
@@ -17,8 +17,4 @@
from mesonbuild import mesonmain
import sys, os
-thisfile = __file__
-if not os.path.isabs(thisfile):
- thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile))
-
-sys.exit(mesonmain.run(thisfile, sys.argv[1:]))
+sys.exit(mesonmain.run(sys.argv[0], sys.argv[1:]))
diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py
index 8c0e7a8..bdbfee1 100644
--- a/mesonbuild/backend/backends.py
+++ b/mesonbuild/backend/backends.py
@@ -609,3 +609,24 @@ class Backend():
for s in self.build.postconf_scripts:
cmd = s['exe'].get_command() + s['args']
subprocess.check_call(cmd, env=child_env)
+
+ # Subprojects of subprojects may cause the same dep args to be used
+ # multiple times. Remove duplicates here. Note that we can't dedup
+ # libraries based on name alone, because "-lfoo -lbar -lfoo" is
+ # a completely valid (though pathological) sequence and removing the
+ # latter may fail. Usually only applies to static libs, though.
+ def dedup_arguments(self, commands):
+ includes = {}
+ final_commands = []
+ previous = '-fsuch_arguments=woof'
+ for c in commands:
+ if c.startswith(('-I' '-L', '/LIBPATH')):
+ if c in includes:
+ continue
+ includes[c] = True
+ if previous == c:
+ continue
+ previous = c
+ final_commands.append(c)
+ return final_commands
+
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index dd6ead2..a84de0e 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1671,6 +1671,7 @@ rule FORTRAN_DEP_HACK
element.add_orderdep(d)
element.add_orderdep(pch_dep)
element.add_orderdep(extra_orderdeps)
+ commands = self.dedup_arguments(commands)
for i in self.get_fortran_orderdeps(target, compiler):
element.add_orderdep(i)
element.add_item('DEPFILE', dep_file)
@@ -1833,7 +1834,7 @@ rule FORTRAN_DEP_HACK
custom_target_libraries = self.get_custom_target_provided_libraries(target)
commands += extra_args
commands += custom_target_libraries
- commands = linker.unix_link_flags_to_native(commands)
+ commands = linker.unix_link_flags_to_native(self.dedup_arguments(commands))
dep_targets = [self.get_dependency_filename(t) for t in dependencies]
dep_targets += [os.path.join(self.environment.source_dir,
target.subdir, t) for t in target.link_depends]
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py
index 08bb7f8..0310e01 100644
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -622,15 +622,15 @@ class CCompiler(Compiler):
code = 'int main(int argc, char **argv) { int class=0; return class; }\n'
return self.sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code)
- def has_header(self, hname, env, extra_args=None):
+ def has_header(self, hname, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
templ = '''#include<%s>
int someSymbolHereJustForFun;
'''
- return self.compiles(templ % hname, env, extra_args)
+ return self.compiles(templ % hname, env, extra_args, dependencies)
- def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None):
+ def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
templ = '''{2}
@@ -638,7 +638,7 @@ int someSymbolHereJustForFun;
int main () {{ {1}; }}'''
# Pass -O0 to ensure that the symbol isn't optimized away
args = extra_args + self.get_no_optimization_args()
- return self.compiles(templ.format(hname, symbol, prefix), env, args)
+ return self.compiles(templ.format(hname, symbol, prefix), env, args, dependencies)
def compile(self, code, srcname, extra_args=None):
if extra_args is None:
@@ -658,18 +658,23 @@ int main () {{ {1}; }}'''
os.remove(srcname)
return p
- def compiles(self, code, env, extra_args=None):
+ def compiles(self, code, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
if isinstance(extra_args, str):
extra_args = [extra_args]
+ if dependencies is None:
+ dependencies = []
+ elif not isinstance(dependencies, list):
+ dependencies = [dependencies]
suflen = len(self.default_suffix)
(fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix)
os.close(fd)
with open(srcname, 'w') as ofile:
ofile.write(code)
+ cargs = [a for d in dependencies for a in d.get_compile_args()]
# Convert flags to the native type of the selected compiler
- args = self.unix_link_flags_to_native(extra_args)
+ args = self.unix_link_flags_to_native(cargs + extra_args)
# Read c_args/cpp_args/etc from the cross-info file (if needed)
args += self.get_cross_extra_flags(env, compile=True, link=False)
# We only want to compile; not link
@@ -686,19 +691,25 @@ int main () {{ {1}; }}'''
pass
return p.returncode == 0
- def links(self, code, env, extra_args=None):
+ def links(self, code, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
elif isinstance(extra_args, str):
extra_args = [extra_args]
+ if dependencies is None:
+ dependencies = []
+ elif not isinstance(dependencies, list):
+ dependencies = [dependencies]
(fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix)
os.close(fd)
(fd, dstname) = tempfile.mkstemp()
os.close(fd)
with open(srcname, 'w') as ofile:
ofile.write(code)
+ cargs = [a for d in dependencies for a in d.get_compile_args()]
+ link_args = [a for d in dependencies for a in d.get_link_args()]
# Convert flags to the native type of the selected compiler
- args = self.unix_link_flags_to_native(extra_args)
+ args = self.unix_link_flags_to_native(cargs + link_args + extra_args)
# Select a CRT if needed since we're linking
args += self.get_linker_debug_crt_args()
# Read c_args/c_link_args/cpp_args/cpp_link_args/etc from the cross-info file (if needed)
@@ -712,17 +723,23 @@ int main () {{ {1}; }}'''
pass
return p.returncode == 0
- def run(self, code, env, extra_args=None):
+ def run(self, code, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
+ if dependencies is None:
+ dependencies = []
+ elif not isinstance(dependencies, list):
+ dependencies = [dependencies]
if self.is_cross and self.exe_wrapper is None:
raise CrossNoRunException('Can not run test applications in this cross environment.')
(fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix)
os.close(fd)
with open(srcname, 'w') as ofile:
ofile.write(code)
+ cargs = [a for d in dependencies for a in d.get_compile_args()]
+ link_args = [a for d in dependencies for a in d.get_link_args()]
# Convert flags to the native type of the selected compiler
- args = self.unix_link_flags_to_native(extra_args)
+ args = self.unix_link_flags_to_native(cargs + link_args + extra_args)
# Select a CRT if needed since we're linking
args += self.get_linker_debug_crt_args()
# Read c_link_args/cpp_link_args/etc from the cross-info file
@@ -771,7 +788,7 @@ int main () {{ {1}; }}'''
pass
return RunResult(True, pe.returncode, so, se)
- def cross_sizeof(self, element, prefix, env, extra_args=None):
+ def cross_sizeof(self, element, prefix, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
element_exists_templ = '''#include <stdio.h>
@@ -785,11 +802,11 @@ int main(int argc, char **argv) {{
int temparray[%d-sizeof(%s)];
'''
args = extra_args + self.get_no_optimization_args()
- if not self.compiles(element_exists_templ.format(prefix, element), env, args):
+ if not self.compiles(element_exists_templ.format(prefix, element), env, args, dependencies):
return -1
for i in range(1, 1024):
code = templ % (prefix, i, element)
- if self.compiles(code, env, args):
+ if self.compiles(code, env, args, dependencies):
if self.id == 'msvc':
# MSVC refuses to construct an array of zero size, so
# the test only succeeds when i is sizeof(element) + 1
@@ -797,11 +814,11 @@ int temparray[%d-sizeof(%s)];
return i
raise EnvironmentException('Cross checking sizeof overflowed.')
- def sizeof(self, element, prefix, env, extra_args=None):
+ def sizeof(self, element, prefix, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
if self.is_cross:
- return self.cross_sizeof(element, prefix, env, extra_args)
+ return self.cross_sizeof(element, prefix, env, extra_args, dependencies)
templ = '''#include<stdio.h>
%s
@@ -810,14 +827,14 @@ int main(int argc, char **argv) {
return 0;
};
'''
- res = self.run(templ % (prefix, element), env, extra_args)
+ res = self.run(templ % (prefix, element), env, extra_args, dependencies)
if not res.compiled:
return -1
if res.returncode != 0:
raise EnvironmentException('Could not run sizeof test binary.')
return int(res.stdout)
- def cross_alignment(self, typename, env, extra_args=None):
+ def cross_alignment(self, typename, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
type_exists_templ = '''#include <stdio.h>
@@ -834,11 +851,11 @@ struct tmp {
int testarray[%d-offsetof(struct tmp, target)];
'''
args = extra_args + self.get_no_optimization_args()
- if not self.compiles(type_exists_templ.format(typename), env, args):
+ if not self.compiles(type_exists_templ.format(typename), env, args, dependencies):
return -1
for i in range(1, 1024):
code = templ % (typename, i)
- if self.compiles(code, env, args):
+ if self.compiles(code, env, args, dependencies):
if self.id == 'msvc':
# MSVC refuses to construct an array of zero size, so
# the test only succeeds when i is sizeof(element) + 1
@@ -846,11 +863,11 @@ int testarray[%d-offsetof(struct tmp, target)];
return i
raise EnvironmentException('Cross checking offsetof overflowed.')
- def alignment(self, typename, env, extra_args=None):
+ def alignment(self, typename, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
if self.is_cross:
- return self.cross_alignment(typename, env, extra_args)
+ return self.cross_alignment(typename, env, extra_args, dependencies)
templ = '''#include<stdio.h>
#include<stddef.h>
@@ -864,7 +881,7 @@ int main(int argc, char **argv) {
return 0;
}
'''
- res = self.run(templ % typename, env, extra_args)
+ res = self.run(templ % typename, env, extra_args, dependencies)
if not res.compiled:
raise EnvironmentException('Could not compile alignment test.')
if res.returncode != 0:
@@ -874,7 +891,7 @@ int main(int argc, char **argv) {
raise EnvironmentException('Could not determine alignment of %s. Sorry. You might want to file a bug.' % typename)
return align
- def has_function(self, funcname, prefix, env, extra_args=None):
+ def has_function(self, funcname, prefix, env, extra_args=None, dependencies=None):
"""
First, this function looks for the symbol in the default libraries
provided by the compiler (stdlib + a few others usually). If that
@@ -931,7 +948,7 @@ int main(int argc, char **argv) {
if isinstance(val, bool):
return val
raise EnvironmentException('Cross variable {0} is not a boolean.'.format(varname))
- if self.links(templ.format(prefix, funcname), env, extra_args):
+ if self.links(templ.format(prefix, funcname), env, extra_args, dependencies):
return True
# Add -O0 to ensure that the symbol isn't optimized away by the compiler
args = extra_args + self.get_no_optimization_args()
@@ -940,15 +957,15 @@ int main(int argc, char **argv) {
# still detect the function. We still want to fail if __stub_foo or
# _stub_foo are defined, of course.
header_templ = '#include <limits.h>\n{0}\n' + stubs_fail + '\nint main() {{ {1}; }}'
- if self.links(header_templ.format(prefix, funcname), env, args):
+ if self.links(header_templ.format(prefix, funcname), env, args, dependencies):
return True
# Some functions like alloca() are defined as compiler built-ins which
# are inlined by the compiler, so test for that instead. Built-ins are
# special functions that ignore all includes and defines, so we just
# directly try to link via main().
- return self.links('int main() {{ {0}; }}'.format('__builtin_' + funcname), env, args)
+ return self.links('int main() {{ {0}; }}'.format('__builtin_' + funcname), env, args, dependencies)
- def has_members(self, typename, membernames, prefix, env, extra_args=None):
+ def has_members(self, typename, membernames, prefix, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
templ = '''{0}
@@ -962,15 +979,15 @@ void bar() {{
for m in membernames:
members += 'foo.{};\n'.format(m)
code = templ.format(prefix, typename, 'foo', members)
- return self.compiles(code, env, extra_args)
+ return self.compiles(code, env, extra_args, dependencies)
- def has_type(self, typename, prefix, env, extra_args):
+ def has_type(self, typename, prefix, env, extra_args, dependencies=None):
templ = '''%s
void bar() {
sizeof(%s);
};
'''
- return self.compiles(templ % (prefix, typename), env, extra_args)
+ return self.compiles(templ % (prefix, typename), env, extra_args, dependencies)
def find_library(self, libname, env, extra_dirs):
# First try if we can just add the library as -l.
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 4412ffe..cc85e77 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -667,6 +667,25 @@ class CompilerHolder(InterpreterObject):
args += mesonlib.stringlistify(kwargs.get('args', []))
return args
+ def determine_dependencies(self, kwargs, allowed_dep_types=None):
+ deps = kwargs.get('dependencies', None)
+ if allowed_dep_types is None:
+ allowed_dep_types = (dependencies.Dependency, dependencies.ExternalLibrary)
+ if deps is not None:
+ if not isinstance(deps, list):
+ deps = [deps]
+ final_deps = []
+ for d in deps:
+ try:
+ d = d.held_object
+ except Exception:
+ pass
+ if not isinstance(d, allowed_dep_types):
+ raise InterpreterException('Dependencies must be external deps')
+ final_deps.append(d)
+ deps = final_deps
+ return deps
+
def alignment_method(self, args, kwargs):
if len(args) != 1:
raise InterpreterException('Alignment method takes exactly one positional argument.')
@@ -686,7 +705,8 @@ class CompilerHolder(InterpreterObject):
if not isinstance(testname, str):
raise InterpreterException('Testname argument must be a string.')
extra_args = self.determine_args(kwargs)
- result = self.compiler.run(code, self.environment, extra_args)
+ deps = self.determine_dependencies(kwargs)
+ result = self.compiler.run(code, self.environment, extra_args, deps)
if len(testname) > 0:
if not result.compiled:
h = mlog.red('DID NOT COMPILE')
@@ -716,8 +736,9 @@ class CompilerHolder(InterpreterObject):
if not isinstance(prefix, str):
raise InterpreterException('Prefix argument of has_member must be a string.')
extra_args = self.determine_args(kwargs)
+ deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,))
had = self.compiler.has_members(typename, [membername], prefix,
- self.environment, extra_args)
+ self.environment, extra_args, deps)
if had:
hadtxt = mlog.green('YES')
else:
@@ -734,8 +755,9 @@ class CompilerHolder(InterpreterObject):
if not isinstance(prefix, str):
raise InterpreterException('Prefix argument of has_members must be a string.')
extra_args = self.determine_args(kwargs)
+ deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,))
had = self.compiler.has_members(typename, membernames, prefix,
- self.environment, extra_args)
+ self.environment, extra_args, deps)
if had:
hadtxt = mlog.green('YES')
else:
@@ -754,7 +776,8 @@ class CompilerHolder(InterpreterObject):
if not isinstance(prefix, str):
raise InterpreterException('Prefix argument of has_function must be a string.')
extra_args = self.determine_args(kwargs)
- had = self.compiler.has_function(funcname, prefix, self.environment, extra_args)
+ deps = self.determine_dependencies(kwargs)
+ had = self.compiler.has_function(funcname, prefix, self.environment, extra_args, deps)
if had:
hadtxt = mlog.green('YES')
else:
@@ -771,7 +794,8 @@ class CompilerHolder(InterpreterObject):
if not isinstance(prefix, str):
raise InterpreterException('Prefix argument of has_type must be a string.')
extra_args = self.determine_args(kwargs)
- had = self.compiler.has_type(typename, prefix, self.environment, extra_args)
+ deps = self.determine_dependencies(kwargs)
+ had = self.compiler.has_type(typename, prefix, self.environment, extra_args, deps)
if had:
hadtxt = mlog.green('YES')
else:
@@ -788,7 +812,8 @@ class CompilerHolder(InterpreterObject):
if not isinstance(prefix, str):
raise InterpreterException('Prefix argument of sizeof must be a string.')
extra_args = self.determine_args(kwargs)
- esize = self.compiler.sizeof(element, prefix, self.environment, extra_args)
+ deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,))
+ esize = self.compiler.sizeof(element, prefix, self.environment, extra_args, deps)
mlog.log('Checking for size of "%s": %d' % (element, esize))
return esize
@@ -801,7 +826,8 @@ class CompilerHolder(InterpreterObject):
if not isinstance(testname, str):
raise InterpreterException('Testname argument must be a string.')
extra_args = self.determine_args(kwargs)
- result = self.compiler.compiles(code, self.environment, extra_args)
+ deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,))
+ result = self.compiler.compiles(code, self.environment, extra_args, deps)
if len(testname) > 0:
if result:
h = mlog.green('YES')
@@ -819,7 +845,8 @@ class CompilerHolder(InterpreterObject):
if not isinstance(testname, str):
raise InterpreterException('Testname argument must be a string.')
extra_args = self.determine_args(kwargs)
- result = self.compiler.links(code, self.environment, extra_args)
+ deps = self.determine_dependencies(kwargs)
+ result = self.compiler.links(code, self.environment, extra_args, deps)
if len(testname) > 0:
if result:
h = mlog.green('YES')
@@ -834,7 +861,8 @@ class CompilerHolder(InterpreterObject):
check_stringlist(args)
string = args[0]
extra_args = self.determine_args(kwargs)
- haz = self.compiler.has_header(string, self.environment, extra_args)
+ deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,))
+ haz = self.compiler.has_header(string, self.environment, extra_args, deps)
if haz:
h = mlog.green('YES')
else:
@@ -852,7 +880,8 @@ class CompilerHolder(InterpreterObject):
if not isinstance(prefix, str):
raise InterpreterException('Prefix argument of has_function must be a string.')
extra_args = self.determine_args(kwargs)
- haz = self.compiler.has_header_symbol(hname, symbol, prefix, self.environment, extra_args)
+ deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,))
+ haz = self.compiler.has_header_symbol(hname, symbol, prefix, self.environment, extra_args, deps)
if haz:
h = mlog.green('YES')
else:
@@ -861,6 +890,7 @@ class CompilerHolder(InterpreterObject):
return haz
def find_library_method(self, args, kwargs):
+ # TODO add dependencies support?
if len(args) != 1:
raise InterpreterException('find_library method takes one argument.')
libname = args[0]
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index d8c8f10..11abf88 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -16,7 +16,7 @@
functionality such as gobject-introspection and gresources.'''
from .. import build
-import os, sys
+import os
import subprocess
from ..mesonlib import MesonException
from .. import dependencies
@@ -94,16 +94,17 @@ class GnomeModule:
return stdout.split('\n')[:-1]
- def get_link_args(self, state, lib, depends):
+ def get_link_args(self, state, lib, depends=None):
link_command = ['-l%s' % lib.name]
if isinstance(lib, build.SharedLibrary):
link_command += ['-L%s' %
os.path.join(state.environment.get_build_dir(),
lib.subdir)]
- depends.append(lib)
+ if depends:
+ depends.append(lib)
return link_command
- def get_include_args(self, state, include_dirs):
+ def get_include_args(self, state, include_dirs, prefix='-I'):
if not include_dirs:
return []
@@ -113,14 +114,81 @@ class GnomeModule:
dirs = incdirs.held_object
else:
dirs = incdirs
- for incdir in dirs.get_incdirs():
- if os.path.isabs(incdir):
- dirs_str += ['-I%s' % os.path.join(incdir)]
- else:
- dirs_str += ['-I%s' % os.path.join(state.environment.get_source_dir(),
- dirs.curdir, incdir)]
+
+ if isinstance(dirs, str):
+ dirs_str += ['%s%s' % (prefix, dirs)]
+ continue
+
+ # Should be build.IncludeDirs object.
+ basedir = dirs.get_curdir()
+ for d in dirs.get_incdirs():
+ expdir = os.path.join(basedir, d)
+ srctreedir = os.path.join(state.environment.get_source_dir(), expdir)
+ buildtreedir = os.path.join(state.environment.get_build_dir(), expdir)
+ dirs_str += ['%s%s' % (prefix, buildtreedir),
+ '%s%s' % (prefix, srctreedir)]
+ for d in dirs.get_extra_build_dirs():
+ dirs_str += ['%s%s' % (prefix, d)]
+
return dirs_str
+ def get_dependencies_flags(self, deps, state, depends=None):
+ cflags = set()
+ ldflags = set()
+ gi_includes = set()
+ if not isinstance(deps, list):
+ deps = [deps]
+
+ for dep in deps:
+ if hasattr(dep, 'held_object'):
+ dep = dep.held_object
+ if isinstance(dep, dependencies.InternalDependency):
+ cflags.update(self.get_include_args( state, dep.include_directories))
+ for lib in dep.libraries:
+ ldflags.update(self.get_link_args(state, lib.held_object, depends))
+ libdepflags = self.get_dependencies_flags(lib.held_object.get_external_deps(), state, depends)
+ cflags.update(libdepflags[0])
+ ldflags.update(libdepflags[1])
+ gi_includes.update(libdepflags[2])
+ extdepflags = self.get_dependencies_flags(dep.ext_deps, state, depends)
+ cflags.update(extdepflags[0])
+ ldflags.update(extdepflags[1])
+ gi_includes.update(extdepflags[2])
+ for source in dep.sources:
+ if isinstance(source.held_object, GirTarget):
+ gi_includes.update([os.path.join(state.environment.get_build_dir(),
+ source.held_object.get_subdir())])
+ # This should be any dependency other than an internal one.
+ elif isinstance(dep, dependencies.Dependency):
+ cflags.update(dep.get_compile_args())
+ for lib in dep.get_link_args():
+ if (os.path.isabs(lib) and
+ # For PkgConfigDependency only:
+ getattr(dep, 'is_libtool', False)):
+ ldflags.update(["-L%s" % os.path.dirname(lib)])
+ libname = os.path.basename(lib)
+ if libname.startswith("lib"):
+ libname = libname[3:]
+ libname = libname.split(".so")[0]
+ lib = "-l%s" % libname
+ # Hack to avoid passing some compiler options in
+ if lib.startswith("-W"):
+ continue
+ ldflags.update([lib])
+
+ if isinstance(dep, dependencies.PkgConfigDependency):
+ girdir = dep.get_variable("girdir")
+ if girdir:
+ gi_includes.update([girdir])
+ elif isinstance(dep, (build.StaticLibrary, build.SharedLibrary)):
+ for incd in dep.get_include_dirs():
+ cflags.update(incd.get_incdirs())
+ else:
+ mlog.log('dependency %s not handled to build gir files' % dep)
+ continue
+
+ return cflags, ldflags, gi_includes
+
def generate_gir(self, state, args, kwargs):
if len(args) != 1:
raise MesonException('Gir takes one argument')
@@ -143,6 +211,7 @@ class GnomeModule:
libsources = kwargs.pop('sources')
girfile = '%s-%s.gir' % (ns, nsversion)
depends = [girtarget]
+ gir_inc_dirs = []
scan_command = ['g-ir-scanner', '@INPUT@']
scan_command += pkgargs
@@ -151,7 +220,7 @@ class GnomeModule:
extra_args = mesonlib.stringlistify(kwargs.pop('extra_args', []))
scan_command += extra_args
- scan_command += self.get_include_args(state, girtarget.include_dirs)
+ scan_command += self.get_include_args(state, girtarget.get_include_dirs())
if 'link_with' in kwargs:
link_with = kwargs.pop('link_with')
@@ -162,12 +231,25 @@ class GnomeModule:
if 'includes' in kwargs:
includes = kwargs.pop('includes')
- if isinstance(includes, str):
- scan_command += ['--include=%s' % includes]
- elif isinstance(includes, list):
- scan_command += ['--include=%s' % inc for inc in includes]
- else:
- raise MesonException('Gir includes must be str or list')
+ if not isinstance(includes, list):
+ includes = [includes]
+ for inc in includes:
+ if hasattr(inc, 'held_object'):
+ inc = inc.held_object
+ if isinstance(inc, str):
+ scan_command += ['--include=%s' % (inc, )]
+ elif isinstance(inc, GirTarget):
+ gir_inc_dirs += [
+ os.path.join(state.environment.get_build_dir(),
+ inc.get_subdir()),
+ ]
+ scan_command += [
+ "--include=%s" % (inc.get_basename()[:-4], ),
+ ]
+ depends += [inc]
+ else:
+ raise MesonException(
+ 'Gir includes must be str, GirTarget, or list of them')
if state.global_args.get('c'):
scan_command += ['--cflags-begin']
scan_command += state.global_args['c']
@@ -191,54 +273,27 @@ class GnomeModule:
else:
raise MesonException('Gir export packages must be str or list')
- deps = None
- if 'dependencies' in kwargs:
- deps = kwargs.pop('dependencies')
- if not isinstance (deps, list):
- deps = [deps]
- for dep in deps:
- if isinstance(dep.held_object, dependencies.InternalDependency):
- scan_command += self.get_include_args(state, dep.held_object.include_directories)
- for lib in dep.held_object.libraries:
- scan_command += self.get_link_args(state, lib.held_object, depends)
- for source in dep.held_object.sources:
- if isinstance(source.held_object, GirTarget):
- scan_command += ["--add-include-path=%s" %
- os.path.join(state.environment.get_build_dir(),
- source.held_object.get_subdir())]
- elif isinstance(dep.held_object, dependencies.PkgConfigDependency):
- for lib in dep.held_object.libs:
- if os.path.isabs(lib) and dep.held_object.is_libtool:
- scan_command += ["-L%s" % os.path.dirname(lib)]
- libname = os.path.basename(lib)
- if libname.startswith("lib"):
- libname = libname[3:]
- libname = libname.split(".so")[0]
- lib = "-l%s" % libname
- # Hack to avoid passing some compiler options in
- if lib.startswith("-W"):
- continue
- scan_command += [lib]
-
- girdir = dep.held_object.get_variable ("girdir")
- if girdir:
- scan_command += ["--add-include-path=%s" % girdir]
- else:
- mlog.log('dependency %s not handled to build gir files' % dep)
- continue
+ deps = kwargs.pop('dependencies', [])
+ if not isinstance(deps, list):
+ deps = [deps]
+ deps = (girtarget.get_all_link_deps() + girtarget.get_external_deps() +
+ deps)
+ cflags, ldflags, gi_includes = self.get_dependencies_flags(deps, state, depends)
+ scan_command += list(cflags) + list(ldflags)
+ for i in gi_includes:
+ scan_command += ['--add-include-path=%s' % i]
+
+ inc_dirs = kwargs.pop('include_directories', [])
+ if not isinstance(inc_dirs, list):
+ inc_dirs = [inc_dirs]
+ for incd in inc_dirs:
+ if not isinstance(incd.held_object, (str, build.IncludeDirs)):
+ raise MesonException(
+ 'Gir include dirs should be include_directories().')
+ scan_command += self.get_include_args(state, inc_dirs)
+ scan_command += self.get_include_args(state, gir_inc_dirs + inc_dirs,
+ prefix='--add-include-path=')
- inc_dirs = None
- if kwargs.get('include_directories'):
- inc_dirs = kwargs.pop('include_directories')
-
- if not isinstance(inc_dirs, list):
- inc_dirs = [inc_dirs]
-
- for ind in inc_dirs:
- if isinstance(ind.held_object, build.IncludeDirs):
- scan_command += ['--add-include-path=%s' % inc for inc in ind.held_object.get_incdirs()]
- else:
- raise MesonException('Gir include dirs should be include_directories()')
if isinstance(girtarget, build.Executable):
scan_command += ['--program', girtarget]
elif isinstance(girtarget, build.SharedLibrary):
@@ -257,22 +312,24 @@ class GnomeModule:
typelib_output = '%s-%s.typelib' % (ns, nsversion)
typelib_cmd = ['g-ir-compiler', scan_target, '--output', '@OUTPUT@']
- if inc_dirs:
- for incd in inc_dirs:
- typelib_cmd += ['--includedir=%s' % inc for inc in
- incd.held_object.get_incdirs()]
- if deps:
- for dep in deps:
- if isinstance(dep.held_object, dependencies.InternalDependency):
- for source in dep.held_object.sources:
- if isinstance(source.held_object, GirTarget):
- typelib_cmd += ["--includedir=%s" %
- os.path.join(state.environment.get_build_dir(),
- source.held_object.get_subdir())]
- elif isinstance(dep.held_object, dependencies.PkgConfigDependency):
- girdir = dep.held_object.get_variable ("girdir")
- if girdir:
- typelib_cmd += ["--includedir=%s" % girdir]
+ typelib_cmd += self.get_include_args(state, gir_inc_dirs,
+ prefix='--includedir=')
+ for dep in deps:
+ if hasattr(dep, 'held_object'):
+ dep = dep.held_object
+ if isinstance(dep, dependencies.InternalDependency):
+ for source in dep.sources:
+ if isinstance(source.held_object, GirTarget):
+ typelib_cmd += [
+ "--includedir=%s" % (
+ os.path.join(state.environment.get_build_dir(),
+ source.held_object.get_subdir()),
+ )
+ ]
+ elif isinstance(dep, dependencies.PkgConfigDependency):
+ girdir = dep.get_variable("girdir")
+ if girdir:
+ typelib_cmd += ["--includedir=%s" % (girdir, )]
kwargs['output'] = typelib_output
kwargs['command'] = typelib_cmd
@@ -335,12 +392,40 @@ class GnomeModule:
'--modulename=' + modulename]
args += self.unpack_args('--htmlargs=', 'html_args', kwargs)
args += self.unpack_args('--scanargs=', 'scan_args', kwargs)
+ args += self.unpack_args('--scanobjsargs=', 'scanobjs_args', kwargs)
+ args += self.unpack_args('--gobjects-types-file=', 'gobject_typesfile', kwargs, state)
args += self.unpack_args('--fixxrefargs=', 'fixxref_args', kwargs)
+ args += self.unpack_args('--html-assets=', 'html_assets', kwargs, state)
+ args += self.unpack_args('--content-files=', 'content_files', kwargs, state)
+ args += self.unpack_args('--installdir=', 'install_dir', kwargs, state)
+ args += self.get_build_args(kwargs, state)
res = [build.RunTarget(targetname, command[0], command[1:] + args, [], state.subdir)]
if kwargs.get('install', True):
res.append(build.InstallScript(command + args))
return res
+ def get_build_args(self, kwargs, state):
+ args = []
+ cflags, ldflags, gi_includes = self.get_dependencies_flags(kwargs.get('dependencies', []), state)
+ inc_dirs = kwargs.get('include_directories', [])
+ if not isinstance(inc_dirs, list):
+ inc_dirs = [inc_dirs]
+ for incd in inc_dirs:
+ if not isinstance(incd.held_object, (str, build.IncludeDirs)):
+ raise MesonException(
+ 'Gir include dirs should be include_directories().')
+ cflags.update(self.get_include_args(state, inc_dirs))
+ if cflags:
+ args += ['--cflags=%s' % ' '.join(cflags)]
+ if ldflags:
+ args += ['--ldflags=%s' % ' '.join(ldflags)]
+ compiler = state.environment.coredata.compilers.get('c')
+ if compiler:
+ args += ['--cc=%s' % ' '.join(compiler.get_exelist())]
+ args += ['--ld=%s' % ' '.join(compiler.get_linker_exelist())]
+
+ return args
+
def gtkdoc_html_dir(self, state, args, kwarga):
if len(args) != 1:
raise MesonException('Must have exactly one argument.')
@@ -350,18 +435,24 @@ class GnomeModule:
return os.path.join('share/gtkdoc/html', modulename)
- def unpack_args(self, arg, kwarg_name, kwargs):
- try:
- new_args = kwargs[kwarg_name]
- if not isinstance(new_args, list):
- new_args = [new_args]
- for i in new_args:
- if not isinstance(i, str):
- raise MesonException('html_args values must be strings.')
- except KeyError:
- return[]
- if len(new_args) > 0:
- return [arg + '@@'.join(new_args)]
+ def unpack_args(self, arg, kwarg_name, kwargs, expend_file_state=None):
+ if kwarg_name not in kwargs:
+ return []
+
+ new_args = kwargs[kwarg_name]
+ if not isinstance(new_args, list):
+ new_args = [new_args]
+ args = []
+ for i in new_args:
+ if expend_file_state and isinstance(i, mesonlib.File):
+ i = os.path.join(expend_file_state.environment.get_build_dir(), i.subdir, i.fname)
+ elif not isinstance(i, str):
+ raise MesonException(kwarg_name + ' values must be strings.')
+ args.append(i)
+
+ if args:
+ return [arg + '@@'.join(args)]
+
return []
def gdbus_codegen(self, state, args, kwargs):
diff --git a/mesonbuild/scripts/gtkdochelper.py b/mesonbuild/scripts/gtkdochelper.py
index 0c87717..e87a379 100644
--- a/mesonbuild/scripts/gtkdochelper.py
+++ b/mesonbuild/scripts/gtkdochelper.py
@@ -30,7 +30,16 @@ parser.add_argument('--mainfile', dest='mainfile')
parser.add_argument('--modulename', dest='modulename')
parser.add_argument('--htmlargs', dest='htmlargs', default='')
parser.add_argument('--scanargs', dest='scanargs', default='')
+parser.add_argument('--scanobjsargs', dest='scanobjsargs', default='')
+parser.add_argument('--gobjects-types-file', dest='gobject_typesfile', default='')
parser.add_argument('--fixxrefargs', dest='fixxrefargs', default='')
+parser.add_argument('--ld', dest='ld', default='')
+parser.add_argument('--cc', dest='cc', default='')
+parser.add_argument('--ldflags', dest='ldflags', default='')
+parser.add_argument('--cflags', dest='cflags', default='')
+parser.add_argument('--content-files', dest='content_files', default='')
+parser.add_argument('--html-assets', dest='html_assets', default='')
+parser.add_argument('--installdir', dest='install_dir')
def gtkdoc_run_check(cmd, cwd):
p = subprocess.Popen(cmd, cwd=cwd,
@@ -45,15 +54,49 @@ def gtkdoc_run_check(cmd, cwd):
raise MesonException('\n'.join(err_msg))
def build_gtkdoc(source_root, build_root, doc_subdir, src_subdir,
- main_file, module, html_args, scan_args, fixxref_args):
+ main_file, module, html_args, scan_args, fixxref_args,
+ gobject_typesfile, scanobjs_args, ld, cc, ldflags, cflags,
+ html_assets, content_files):
+ print("Building documentation for %s" % module)
+
abs_src = os.path.join(source_root, src_subdir)
+ doc_src = os.path.join(source_root, doc_subdir)
abs_out = os.path.join(build_root, doc_subdir)
htmldir = os.path.join(abs_out, 'html')
+
+ content_files += [main_file]
+ sections = os.path.join(doc_src, module + "-sections.txt")
+ if os.path.exists(sections):
+ content_files.append(sections)
+
+ # Copy files to build directory
+ for f in content_files:
+ f_abs = os.path.join(doc_src, f)
+ shutil.copyfile(f_abs, os.path.join(
+ abs_out, os.path.basename(f_abs)))
+
+ shutil.rmtree(htmldir, ignore_errors=True)
+ try:
+ os.mkdir(htmldir)
+ except Exception:
+ pass
+
+ for f in html_assets:
+ f_abs = os.path.join(doc_src, f)
+ shutil.copyfile(f_abs, os.path.join(htmldir, os.path.basename(f_abs)))
+
scan_cmd = ['gtkdoc-scan',
'--module=' + module,
'--source-dir=' + abs_src] + scan_args
gtkdoc_run_check(scan_cmd, abs_out)
+ if gobject_typesfile:
+ scanobjs_cmd = ['gtkdoc-scangobj'] + scanobjs_args + [gobject_typesfile,
+ '--module=' + module, '--cflags=' + cflags, '--ldflags=' + ldflags]
+
+ gtkdoc_run_check(scanobjs_cmd, abs_out)
+
+
# Make docbook files
if main_file.endswith('sgml'):
modeflag = '--sgml-mode'
@@ -62,21 +105,16 @@ def build_gtkdoc(source_root, build_root, doc_subdir, src_subdir,
mkdb_cmd = ['gtkdoc-mkdb',
'--module=' + module,
'--output-format=xml',
+ '--expand-content-files=',
modeflag,
'--source-dir=' + abs_src]
- main_abs = os.path.join(source_root, doc_subdir, main_file)
if len(main_file) > 0:
# Yes, this is the flag even if the file is in xml.
mkdb_cmd.append('--main-sgml-file=' + main_file)
gtkdoc_run_check(mkdb_cmd, abs_out)
# Make HTML documentation
- shutil.rmtree(htmldir, ignore_errors=True)
- try:
- os.mkdir(htmldir)
- except Exception:
- pass
- mkhtml_cmd = ['gtkdoc-mkhtml',
+ mkhtml_cmd = ['gtkdoc-mkhtml',
'--path=' + abs_src,
module,
] + html_args
@@ -109,28 +147,42 @@ def run(args):
scanargs = options.scanargs.split('@@')
else:
scanargs = []
+ if len(options.scanobjsargs) > 0:
+ scanobjsargs = options.scanobjsargs.split('@@')
+ else:
+ scanobjsargs = []
if len(options.fixxrefargs) > 0:
fixxrefargs = options.fixxrefargs.split('@@')
else:
fixxrefargs = []
- build_gtkdoc(options.sourcedir,
- options.builddir,
- options.subdir,
- options.headerdir,
- options.mainfile,
- options.modulename,
- htmlargs,
- scanargs,
- fixxrefargs)
+ build_gtkdoc(
+ options.sourcedir,
+ options.builddir,
+ options.subdir,
+ options.headerdir,
+ options.mainfile,
+ options.modulename,
+ htmlargs,
+ scanargs,
+ fixxrefargs,
+ options.gobject_typesfile,
+ scanobjsargs,
+ options.ld,
+ options.cc,
+ options.ldflags,
+ options.cflags,
+ options.html_assets.split('@@') if options.html_assets else [],
+ options.content_files.split('@@') if options.content_files else [])
if 'MESON_INSTALL_PREFIX' in os.environ:
+ install_dir = options.install_dir if options.install_dir else options.modulename
destdir = os.environ.get('DESTDIR', '')
installdir = destdir_join(destdir, os.environ['MESON_INSTALL_PREFIX'])
install_gtkdoc(options.builddir,
options.subdir,
installdir,
'share/gtk-doc/html',
- options.modulename)
+ install_dir)
return 0
if __name__ == '__main__':
diff --git a/test cases/common/94 default options/meson.build b/test cases/common/94 default options/meson.build
index 6299106..a718bcc 100644
--- a/test cases/common/94 default options/meson.build
+++ b/test cases/common/94 default options/meson.build
@@ -2,6 +2,7 @@ project('default options', 'cpp', 'c', default_options : [
'buildtype=debugoptimized',
'cpp_std=c++03',
'cpp_eh=none',
+ 'warning_level=3',
])
cpp = meson.get_compiler('cpp')
@@ -9,11 +10,16 @@ cpp = meson.get_compiler('cpp')
assert(get_option('buildtype') == 'debugoptimized', 'Build type default value wrong.')
if cpp.get_id() == 'msvc'
- assert(get_option('cpp_eh') == 'none', 'MSVC eh value wrong.')
+ cpp_eh = get_option('cpp_eh')
+ assert(cpp_eh == 'none', 'MSVC eh value is "' + cpp_eh + '" instead of "none"')
else
- assert(get_option('cpp_std') == 'c++03', 'C++ std value wrong.')
+ cpp_std = get_option('cpp_std')
+ assert(cpp_std == 'c++03', 'C++ std value is "' + cpp_std + '" instead of c++03.')
endif
+w_level = get_option('warning_level')
+assert(w_level == '3', 'warning level "' + w_level + '" instead of "3"')
+
# FIXME. Since we no longer accept invalid options to c_std etc,
# there is no simple way to test this. Gcc does not seem to expose
# the C std used in a preprocessor token so we can't check for it.
diff --git a/test cases/frameworks/12 multiple gir/gir/meson-subsample.c b/test cases/frameworks/12 multiple gir/gir/meson-subsample.c
new file mode 100644
index 0000000..2d58a10
--- /dev/null
+++ b/test cases/frameworks/12 multiple gir/gir/meson-subsample.c
@@ -0,0 +1,124 @@
+#include "meson-subsample.h"
+
+struct _MesonSubSample
+{
+ MesonSample parent_instance;
+
+ gchar *msg;
+};
+
+G_DEFINE_TYPE (MesonSubSample, meson_sub_sample, MESON_TYPE_SAMPLE)
+
+enum {
+ PROP_0,
+ PROP_MSG,
+ LAST_PROP
+};
+
+static GParamSpec *gParamSpecs [LAST_PROP];
+
+/**
+ * meson_sub_sample_new:
+ * @msg: The message to set.
+ *
+ * Allocates a new #MesonSubSample.
+ *
+ * Returns: (transfer full): a #MesonSubSample.
+ */
+MesonSubSample *
+meson_sub_sample_new (const gchar *msg)
+{
+ g_return_val_if_fail (msg != NULL, NULL);
+
+ return g_object_new (MESON_TYPE_SUB_SAMPLE,
+ "message", msg,
+ NULL);
+}
+
+static void
+meson_sub_sample_finalize (GObject *object)
+{
+ MesonSubSample *self = (MesonSubSample *)object;
+
+ g_clear_pointer (&self->msg, g_free);
+
+ G_OBJECT_CLASS (meson_sub_sample_parent_class)->finalize (object);
+}
+
+static void
+meson_sub_sample_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MesonSubSample *self = MESON_SUB_SAMPLE (object);
+
+ switch (prop_id)
+ {
+ case PROP_MSG:
+ g_value_set_string (value, self->msg);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+meson_sub_sample_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MesonSubSample *self = MESON_SUB_SAMPLE (object);
+
+ switch (prop_id)
+ {
+ case PROP_MSG:
+ self->msg = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+meson_sub_sample_class_init (MesonSubSampleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = meson_sub_sample_finalize;
+ object_class->get_property = meson_sub_sample_get_property;
+ object_class->set_property = meson_sub_sample_set_property;
+
+ gParamSpecs [PROP_MSG] =
+ g_param_spec_string ("message",
+ "Message",
+ "The message to print.",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs);
+}
+
+static void
+meson_sub_sample_init (MesonSubSample *self)
+{
+}
+
+/**
+ * meson_sub_sample_print_message:
+ * @self: a #MesonSubSample.
+ *
+ * Prints the message.
+ *
+ * Returns: Nothing.
+ */
+void
+meson_sub_sample_print_message (MesonSubSample *self)
+{
+ g_return_if_fail (MESON_IS_SUB_SAMPLE (self));
+
+ g_print ("Message: %s\n", self->msg);
+}
diff --git a/test cases/frameworks/12 multiple gir/gir/meson-subsample.h b/test cases/frameworks/12 multiple gir/gir/meson-subsample.h
new file mode 100644
index 0000000..9d34a08
--- /dev/null
+++ b/test cases/frameworks/12 multiple gir/gir/meson-subsample.h
@@ -0,0 +1,17 @@
+#ifndef MESON_SUB_SAMPLE_H
+#define MESON_SUB_SAMPLE_H
+
+#include <glib-object.h>
+#include <meson-sample.h>
+
+G_BEGIN_DECLS
+
+#define MESON_TYPE_SUB_SAMPLE (meson_sub_sample_get_type())
+
+G_DECLARE_FINAL_TYPE (MesonSubSample, meson_sub_sample, MESON, SUB_SAMPLE, MesonSample)
+
+MesonSubSample *meson_sub_sample_new (const gchar *msg);
+
+G_END_DECLS
+
+#endif /* MESON_SUB_SAMPLE_H */
diff --git a/test cases/frameworks/12 multiple gir/gir/meson.build b/test cases/frameworks/12 multiple gir/gir/meson.build
new file mode 100644
index 0000000..6001a09
--- /dev/null
+++ b/test cases/frameworks/12 multiple gir/gir/meson.build
@@ -0,0 +1,30 @@
+libsources = ['meson-subsample.c', 'meson-subsample.h']
+
+girsubproject = shared_library(
+ 'girsubproject',
+ sources : libsources,
+ dependencies : [gobj, girlib_dep],
+ install : true
+)
+
+girexe = executable(
+ 'girprog',
+ sources : 'prog.c',
+ dependencies : [gobj, girlib_dep],
+ link_with : girsubproject
+)
+
+gnome.generate_gir(
+ girsubproject,
+ sources : libsources,
+ nsversion : '1.0',
+ namespace : 'MesonSub',
+ symbol_prefix : 'meson_sub_',
+ identifier_prefix : 'MesonSub',
+ includes : ['GObject-2.0', meson_gir],
+ install : true
+)
+
+message('TEST: ' + girsubproject.outdir())
+
+test('gobject introspection/subproject/c', girexe)
diff --git a/test cases/frameworks/12 multiple gir/gir/prog.c b/test cases/frameworks/12 multiple gir/gir/prog.c
new file mode 100644
index 0000000..f25c9d8
--- /dev/null
+++ b/test cases/frameworks/12 multiple gir/gir/prog.c
@@ -0,0 +1,12 @@
+#include "meson-subsample.h"
+
+gint
+main (gint argc,
+ gchar *argv[])
+{
+ MesonSample * i = (MesonSample*) meson_sub_sample_new ("Hello, sub/meson/c!");
+ meson_sample_print_message (i);
+ g_object_unref (i);
+
+ return 0;
+}
diff --git a/test cases/frameworks/12 multiple gir/installed_files.txt b/test cases/frameworks/12 multiple gir/installed_files.txt
new file mode 100644
index 0000000..9fb51bf
--- /dev/null
+++ b/test cases/frameworks/12 multiple gir/installed_files.txt
@@ -0,0 +1,6 @@
+usr/lib/girepository-1.0/Meson-1.0.typelib
+usr/lib/girepository-1.0/MesonSub-1.0.typelib
+usr/lib/libgirlib.so
+usr/lib/libgirsubproject.so
+usr/share/gir-1.0/Meson-1.0.gir
+usr/share/gir-1.0/MesonSub-1.0.gir
diff --git a/test cases/frameworks/12 multiple gir/meson.build b/test cases/frameworks/12 multiple gir/meson.build
new file mode 100644
index 0000000..794abc5
--- /dev/null
+++ b/test cases/frameworks/12 multiple gir/meson.build
@@ -0,0 +1,7 @@
+project('multiple-gobject-introspection', 'c')
+
+gnome = import('gnome')
+gobj = dependency('gobject-2.0')
+
+subdir('mesongir')
+subdir('gir')
diff --git a/test cases/frameworks/12 multiple gir/mesongir/meson-sample.c b/test cases/frameworks/12 multiple gir/mesongir/meson-sample.c
new file mode 100644
index 0000000..2ed9cdf
--- /dev/null
+++ b/test cases/frameworks/12 multiple gir/mesongir/meson-sample.c
@@ -0,0 +1,126 @@
+#include "meson-sample.h"
+
+typedef struct _MesonSamplePrivate
+{
+ gchar *msg;
+} MesonSamplePrivate;
+
+
+G_DEFINE_TYPE_WITH_PRIVATE (MesonSample, meson_sample, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_MSG,
+ LAST_PROP
+};
+
+static GParamSpec *gParamSpecs [LAST_PROP];
+
+/**
+ * meson_sample_new:
+ * @msg: The message to set.
+ *
+ * Allocates a new #MesonSample.
+ *
+ * Returns: (transfer full): a #MesonSample.
+ */
+MesonSample *
+meson_sample_new (const gchar *msg)
+{
+ g_return_val_if_fail (msg != NULL, NULL);
+
+ return g_object_new (MESON_TYPE_SAMPLE,
+ "message", msg,
+ NULL);
+}
+
+static void
+meson_sample_finalize (GObject *object)
+{
+ MesonSamplePrivate *priv = meson_sample_get_instance_private ((MesonSample *) object);
+
+ g_clear_pointer (&priv->msg, g_free);
+
+ G_OBJECT_CLASS (meson_sample_parent_class)->finalize (object);
+}
+
+static void
+meson_sample_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ MesonSamplePrivate *priv = meson_sample_get_instance_private ((MesonSample *) object);
+
+ switch (prop_id)
+ {
+ case PROP_MSG:
+ g_value_set_string (value, priv->msg);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+meson_sample_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ MesonSamplePrivate *priv = meson_sample_get_instance_private ((MesonSample *) object);
+
+ switch (prop_id)
+ {
+ case PROP_MSG:
+ priv->msg = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+meson_sample_class_init (MesonSampleClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = meson_sample_finalize;
+ object_class->get_property = meson_sample_get_property;
+ object_class->set_property = meson_sample_set_property;
+
+ gParamSpecs [PROP_MSG] =
+ g_param_spec_string ("message",
+ "Message",
+ "The message to print.",
+ NULL,
+ (G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs);
+}
+
+static void
+meson_sample_init (MesonSample *self)
+{
+}
+
+/**
+ * meson_sample_print_message:
+ * @self: a #MesonSample.
+ *
+ * Prints the message.
+ *
+ */
+void
+meson_sample_print_message (MesonSample *self)
+{
+ MesonSamplePrivate *priv;
+
+ g_return_if_fail (MESON_IS_SAMPLE (self));
+
+ priv = meson_sample_get_instance_private (self);
+
+ g_print ("Message: %s\n", priv->msg);
+}
diff --git a/test cases/frameworks/12 multiple gir/mesongir/meson-sample.h.in b/test cases/frameworks/12 multiple gir/mesongir/meson-sample.h.in
new file mode 100644
index 0000000..d0ab29e
--- /dev/null
+++ b/test cases/frameworks/12 multiple gir/mesongir/meson-sample.h.in
@@ -0,0 +1,22 @@
+#ifndef MESON_SAMPLE_H
+#define MESON_SAMPLE_H
+
+#include <@HEADER@>
+
+G_BEGIN_DECLS
+
+#define MESON_TYPE_SAMPLE (meson_sample_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (MesonSample, meson_sample, MESON, SAMPLE, GObject)
+
+struct _MesonSampleClass {
+ GObjectClass parent_class;
+};
+
+
+MesonSample *meson_sample_new (const gchar *msg);
+void meson_sample_print_message (MesonSample *self);
+
+G_END_DECLS
+
+#endif /* MESON_SAMPLE_H */
diff --git a/test cases/frameworks/12 multiple gir/mesongir/meson.build b/test cases/frameworks/12 multiple gir/mesongir/meson.build
new file mode 100644
index 0000000..4775fea
--- /dev/null
+++ b/test cases/frameworks/12 multiple gir/mesongir/meson.build
@@ -0,0 +1,37 @@
+conf = configuration_data()
+conf.set('HEADER', 'glib-object.h')
+
+meson_sample_header = configure_file(
+ input : 'meson-sample.h.in',
+ output : 'meson-sample.h',
+ configuration : conf)
+
+libsources = ['meson-sample.c', meson_sample_header]
+
+girlib = shared_library(
+ 'girlib',
+ sources : libsources,
+ dependencies : gobj,
+ install : true
+)
+
+girtarget = gnome.generate_gir(
+ girlib,
+ sources : libsources,
+ nsversion : '1.0',
+ namespace : 'Meson',
+ symbol_prefix : 'meson_',
+ identifier_prefix : 'Meson',
+ includes : ['GObject-2.0'],
+ install : true
+)
+meson_gir = girtarget[0]
+meson_typelib = girtarget[1]
+
+girlib_inc = include_directories('.')
+girlib_dep = declare_dependency(link_with : girlib,
+ include_directories : [girlib_inc],
+ dependencies : [gobj],
+ # Everything that uses libgst needs this built to compile
+ sources : girtarget,
+)
diff --git a/test cases/linuxlike/9 compiler checks with dependencies/meson.build b/test cases/linuxlike/9 compiler checks with dependencies/meson.build
new file mode 100644
index 0000000..2aa9015
--- /dev/null
+++ b/test cases/linuxlike/9 compiler checks with dependencies/meson.build
@@ -0,0 +1,31 @@
+project('compiler checks with dependencies', 'c')
+
+cc = meson.get_compiler('c')
+
+glib = dependency ('glib-2.0')
+if glib.found()
+ assert (cc.has_header('glib.h', dependencies : glib), 'glib.h not found')
+ assert (cc.has_type('gint32', prefix : '#include <glib.h>', dependencies : glib), 'gint32 not found')
+ assert (cc.has_function('g_print', dependencies : glib), 'g_print not found')
+ assert (cc.has_member('GError', 'message', prefix : '#include <glib.h>', dependencies : glib), 'GError::message not found')
+ assert (cc.has_header_symbol('glib.h', 'gint32', dependencies : glib), 'gint32 symbol not found')
+ linkcode = '''#include <glib.h>
+int main (int argc, char *argv[]) {
+ GError *error = g_error_new_literal (0, 0, NULL);
+ return error == NULL;
+}
+ '''
+ assert (cc.links(linkcode, dependencies : glib, name : 'Test link against glib'), 'Linking test against glib failed')
+endif
+
+zlib = cc.find_library ('z')
+if zlib.found()
+ linkcode = '''#include<zlib.h>
+int main(int argc, char *argv[]) {
+ void *ptr = (void*)(deflate);
+ return ptr == 0;
+}
+'''
+ assert (cc.has_function('deflate', prefix : '#include<zlib.h>', dependencies : zlib, name : 'Test for function in zlib'), 'has_function test failed.')
+ assert (cc.links(linkcode, dependencies : zlib, name : 'Test link against zlib'), 'Linking test failed against zlib.')
+endif