Repository: mesonbuild/meson

Issue:
gnome.generate_gir() should accept multiple libraries
From `g-ir-scanner --help`:

```
  -l LIBRARIES, --library=LIBRARIES
                        libraries of this unit
```

Harfbuzz relies on this feature:

https://github.com/harfbuzz/harfbuzz/blob/master/src/Makefile.am#L434-L437




Discussion:
generate_gir() already support multiple libraries. GDA requires them, just add your dependency objects to your library, then they are added by generate_gir() automatically to g-ir-scanner using -l switch.

Result of command: https://gitlab.gnome.org/GNOME/libgda/blob/master/libgda/meson.build#L293
is:

/usr/bin/g-ir-scanner -pthread -I/usr/include/gobject-introspection-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include --no-libtool --namespace=Gda --nsversion=6.0 --warn-all --output libgda/Gda-6.0.gir --c-include=libgda/libgda.h -I/home/despinosa/Proyectos/libgda/libgda -I/home/despinosa/Proyectos/libgda/_build/libgda -I./. -I../. -I./libgda/. -I../libgda/. -I./libgda/sqlite/sqlite-src -I../libgda/sqlite/sqlite-src -I./libgda/sqlite -I../libgda/sqlite -I./libgda/sql-parser/. -I../libgda/sql-parser/. --filelist=/home/despinosa/Proyectos/libgda/_build/libgda/libgda@@gda-6.0@sha/Gda_6.0_gir_filelist --include=GLib-2.0 --include=GObject-2.0 --include=Gio-2.0 --include=libxml2-2.0 --identifier-prefix=Gda --cflags-begin -Wall -Wextra -Wformat-security -Wno-address -Wno-unused-variable -Wno-unused-parameter -Wno-pointer-sign -Wno-missing-field-initializers -DGSEAL_ENABLE '-DLIBGDA_ABI_NAME="libgda-5.99"' -I./. -I../. -I./libgda/. -I../libgda/. -I./libgda/sqlite/sqlite-src -I../libgda/sqlite/sqlite-src -I./libgda/sqlite -I../libgda/sqlite -I./libgda/sql-parser/. -I../libgda/sql-parser/. -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -pthread -I/usr/include/libxml2 -I/usr/include/libsoup-2.4 --cflags-end -L/home/despinosa/Proyectos/libgda/_build/libgda -lglib-2.0 -lgobject-2.0 -lgio-2.0 -lgmodule-2.0 -pthread -lxml2 -lsoup-2.4 -ldl --library gda-6.0

So as you can see, -l switches are added automatically.
@esodan , that is unrelated, what's missing is the ability to pass multiple libraries to the `-l` (`--library`) switch. Thanks anyway :)

Resolving patch:
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -391,86 +391,49 @@ def fix_ldflags(ldflags):
             external_ldflags = fix_ldflags(external_ldflags)
         return cflags, internal_ldflags, external_ldflags, gi_includes
 
-    @FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])
-    @permittedKwargs({'sources', 'nsversion', 'namespace', 'symbol_prefix', 'identifier_prefix',
-                      'export_packages', 'includes', 'dependencies', 'link_with', 'include_directories',
-                      'install', 'install_dir_gir', 'install_dir_typelib', 'extra_args',
-                      'packages', 'header', 'build_by_default'})
-    def generate_gir(self, state, args, kwargs):
-        if len(args) != 1:
-            raise MesonException('Gir takes one argument')
-        if kwargs.get('install_dir'):
-            raise MesonException('install_dir is not supported with generate_gir(), see "install_dir_gir" and "install_dir_typelib"')
-        giscanner = self.interpreter.find_program_impl('g-ir-scanner')
-        gicompiler = self.interpreter.find_program_impl('g-ir-compiler')
-        girtarget = args[0]
+    def _unwrap_gir_target(self, girtarget):
         while hasattr(girtarget, 'held_object'):
             girtarget = girtarget.held_object
         if not isinstance(girtarget, (build.Executable, build.SharedLibrary)):
             raise MesonException('Gir target must be an executable or shared library')
+        return girtarget
+
+    def _get_gir_dep(self, state):
         try:
-            if not self.gir_dep:
-                self.gir_dep = PkgConfigDependency('gobject-introspection-1.0',
-                                                   state.environment,
-                                                   {'native': True})
-            pkgargs = self.gir_dep.get_compile_args()
+            gir_dep = self.gir_dep or PkgConfigDependency('gobject-introspection-1.0',
+                                                          state.environment,
+                                                          {'native': True})
+            pkgargs = gir_dep.get_compile_args()
         except Exception:
             raise MesonException('gobject-introspection dependency was not found, gir cannot be generated.')
-        ns = kwargs.pop('namespace')
-        nsversion = kwargs.pop('nsversion')
-        libsources = mesonlib.extract_as_list(kwargs, 'sources', pop=True)
-        girfile = '%s-%s.gir' % (ns, nsversion)
-        srcdir = os.path.join(state.environment.get_source_dir(), state.subdir)
-        builddir = os.path.join(state.environment.get_build_dir(), state.subdir)
-        depends = [girtarget]
-        gir_inc_dirs = []
 
-        scan_command = [giscanner]
-        scan_command += pkgargs
-        scan_command += ['--no-libtool', '--namespace=' + ns, '--nsversion=' + nsversion, '--warn-all',
-                         '--output', '@OUTPUT@']
+        return gir_dep, pkgargs
 
+    def _scan_header(self, kwargs):
+        ret = []
         header = kwargs.pop('header', None)
         if header:
             if not isinstance(header, str):
                 raise MesonException('header must be a string')
-            scan_command += ['--c-include=' + header]
-
-        extra_args = mesonlib.stringlistify(kwargs.pop('extra_args', []))
-        scan_command += extra_args
-        scan_command += ['-I' + srcdir,
-                         '-I' + builddir]
-        scan_command += get_include_args(girtarget.get_include_dirs())
+            ret = ['--c-include=' + header]
+        return ret
 
-        gir_filelist_dir = state.backend.get_target_private_dir_abs(girtarget)
-        if not os.path.isdir(gir_filelist_dir):
-            os.mkdir(gir_filelist_dir)
-        gir_filelist_filename = os.path.join(gir_filelist_dir, '%s_%s_gir_filelist' % (ns, nsversion))
-
-        with open(gir_filelist_filename, 'w', encoding='utf-8') as gir_filelist:
-            for s in libsources:
-                if hasattr(s, 'held_object'):
-                    s = s.held_object
-                if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)):
-                    for custom_output in s.get_outputs():
-                        gir_filelist.write(os.path.join(state.environment.get_build_dir(),
-                                                        state.backend.get_target_dir(s),
-                                                        custom_output) + '\n')
-                elif isinstance(s, mesonlib.File):
-                    gir_filelist.write(s.rel_to_builddir(state.build_to_src) + '\n')
-                elif isinstance(s, build.GeneratedList):
-                    for gen_src in s.get_outputs():
-                        gir_filelist.write(os.path.join(srcdir, gen_src) + '\n')
-                else:
-                    gir_filelist.write(os.path.join(srcdir, s) + '\n')
-        scan_command += ['--filelist=' + gir_filelist_filename]
+    def _scan_extra_args(self, kwargs):
+        return mesonlib.stringlistify(kwargs.pop('extra_args', []))
 
+    def _scan_link_withs(self, state, depends, kwargs):
+        ret = []
         if 'link_with' in kwargs:
             link_with = mesonlib.extract_as_list(kwargs, 'link_with', pop = True)
 
             for link in link_with:
-                scan_command += self._get_link_args(state, link.held_object, depends,
-                                                    use_gir_args=True)
+                ret += self._get_link_args(state, link.held_object, depends,
+                                           use_gir_args=True)
+        return ret
+
+    # May mutate depends and gir_inc_dirs
+    def _scan_include(self, state, depends, gir_inc_dirs, kwargs):
+        ret = []
 
         if 'includes' in kwargs:
             includes = mesonlib.extract_as_list(kwargs, 'includes', pop = True)
@@ -478,13 +441,13 @@ def generate_gir(self, state, args, kwargs):
                 if hasattr(inc, 'held_object'):
                     inc = inc.held_object
                 if isinstance(inc, str):
-                    scan_command += ['--include=%s' % (inc, )]
+                    ret += ['--include=%s' % (inc, )]
                 elif isinstance(inc, GirTarget):
                     gir_inc_dirs += [
                         os.path.join(state.environment.get_build_dir(),
                                      inc.get_subdir()),
                     ]
-                    scan_command += [
+                    ret += [
                         "--include-uninstalled=%s" % (os.path.join(inc.get_subdir(), inc.get_basename()), )
                     ]
                     depends += [inc]
@@ -492,17 +455,113 @@ def generate_gir(self, state, args, kwargs):
                     raise MesonException(
                         'Gir includes must be str, GirTarget, or list of them')
 
+        return ret
+
+    def _scan_symbol_prefix(self, kwargs):
+        ret = []
+
+        if 'symbol_prefix' in kwargs:
+            sym_prefixes = mesonlib.stringlistify(kwargs.pop('symbol_prefix', []))
+            ret += ['--symbol-prefix=%s' % sym_prefix for sym_prefix in sym_prefixes]
+
+        return ret
+
+    def _scan_identifier_prefix(self, kwargs):
+        ret = []
+
+        if 'identifier_prefix' in kwargs:
+            identifier_prefix = kwargs.pop('identifier_prefix')
+            if not isinstance(identifier_prefix, str):
+                raise MesonException('Gir identifier prefix must be str')
+            ret += ['--identifier-prefix=%s' % identifier_prefix]
+
+        return ret
+
+    def _scan_export_packages(self, kwargs):
+        ret = []
+
+        if 'export_packages' in kwargs:
+            pkgs = kwargs.pop('export_packages')
+            if isinstance(pkgs, str):
+                ret += ['--pkg-export=%s' % pkgs]
+            elif isinstance(pkgs, list):
+                ret += ['--pkg-export=%s' % pkg for pkg in pkgs]
+            else:
+                raise MesonException('Gir export packages must be str or list')
+
+        return ret
+
+    def _scan_inc_dirs(self, kwargs):
+        ret = mesonlib.extract_as_list(kwargs, 'include_directories', pop = True)
+        for incd in ret:
+            if not isinstance(incd.held_object, (str, build.IncludeDirs)):
+                raise MesonException(
+                    'Gir include dirs should be include_directories().')
+        return ret
+
+    def _scan_langs(self, state, langs):
+        ret = []
+
+        for lang in langs:
+            for link_arg in state.environment.coredata.get_external_link_args(lang):
+                if link_arg.startswith('-L'):
+                    ret.append(link_arg)
+
+        return ret
+
+    def _scan_gir_targets(self, state, girtargets):
+        ret = []
+
+        for girtarget in girtargets:
+            if isinstance(girtarget, build.Executable):
+                ret += ['--program', girtarget]
+            elif isinstance(girtarget, build.SharedLibrary):
+                libname = girtarget.get_basename()
+                # Needed for the following binutils bug:
+                # https://github.com/mesonbuild/meson/issues/1911
+                # However, g-ir-scanner does not understand -Wl,-rpath
+                # so we need to use -L instead
+                for d in state.backend.determine_rpath_dirs(girtarget):
+                    d = os.path.join(state.environment.get_build_dir(), d)
+                    ret.append('-L' + d)
+                ret += ['--library', libname]
+                # need to put our output directory first as we need to use the
+                # generated libraries instead of any possibly installed system/prefix
+                # ones.
+                ret += ["-L@PRIVATE_OUTDIR_ABS_%s@" % girtarget.get_id()]
+
+        return ret
+
+    def _get_girtargets_langs_compilers(self, girtargets):
+        ret = []
+        for girtarget in girtargets:
+            for lang, compiler in girtarget.compilers.items():
+                # XXX: Can you use g-i with any other language?
+                if lang in ('c', 'cpp', 'objc', 'objcpp', 'd'):
+                    ret.append((lang, compiler))
+                    break
+
+        return ret
+
+    def _get_gir_targets_deps(self, girtargets):
+        ret = []
+        for girtarget in girtargets:
+            ret += girtarget.get_all_link_deps()
+            ret += girtarget.get_external_deps()
+        return ret
+
+    def _get_gir_targets_inc_dirs(self, girtargets):
+        ret = []
+        for girtarget in girtargets:
+            ret += girtarget.get_include_dirs()
+        return ret
+
+    def _get_langs_compilers_flags(self, state, langs_compilers):
         cflags = []
         internal_ldflags = []
         external_ldflags = []
-        for lang, compiler in girtarget.compilers.items():
-            # XXX: Can you use g-i with any other language?
-            if lang in ('c', 'cpp', 'objc', 'objcpp', 'd'):
-                break
-        else:
-            lang = None
-            compiler = None
-        if lang and compiler:
+
+        for lang, compiler in langs_compilers:
             if state.global_args.get(lang):
                 cflags += state.global_args[lang]
             if state.project_args.get(lang):
@@ -515,25 +574,67 @@ def generate_gir(self, state, args, kwargs):
                 # FIXME: Linking directly to libasan is not recommended but g-ir-scanner
                 # does not understand -f LDFLAGS. https://bugzilla.gnome.org/show_bug.cgi?id=783892
                 # ldflags += compilers.sanitizer_link_args(sanitize)
-        if 'symbol_prefix' in kwargs:
-            sym_prefixes = mesonlib.stringlistify(kwargs.pop('symbol_prefix', []))
-            scan_command += ['--symbol-prefix=%s' % sym_prefix for sym_prefix in sym_prefixes]
-        if 'identifier_prefix' in kwargs:
-            identifier_prefix = kwargs.pop('identifier_prefix')
-            if not isinstance(identifier_prefix, str):
-                raise MesonException('Gir identifier prefix must be str')
-            scan_command += ['--identifier-prefix=%s' % identifier_prefix]
-        if 'export_packages' in kwargs:
-            pkgs = kwargs.pop('export_packages')
-            if isinstance(pkgs, str):
-                scan_command += ['--pkg-export=%s' % pkgs]
-            elif isinstance(pkgs, list):
-                scan_command += ['--pkg-export=%s' % pkg for pkg in pkgs]
-            else:
-                raise MesonException('Gir export packages must be str or list')
 
-        deps = (girtarget.get_all_link_deps() + girtarget.get_external_deps() +
-                extract_as_list(kwargs, 'dependencies', pop=True, unholder=True))
+        return cflags, internal_ldflags, external_ldflags
+
+    def _make_gir_filelist(self, state, srcdir, ns, nsversion, girtargets, libsources):
+        gir_filelist_dir = state.backend.get_target_private_dir_abs(girtargets[0])
+        if not os.path.isdir(gir_filelist_dir):
+            os.mkdir(gir_filelist_dir)
+        gir_filelist_filename = os.path.join(gir_filelist_dir, '%s_%s_gir_filelist' % (ns, nsversion))
+
+        with open(gir_filelist_filename, 'w', encoding='utf-8') as gir_filelist:
+            for s in libsources:
+                if hasattr(s, 'held_object'):
+                    s = s.held_object
+                if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)):
+                    for custom_output in s.get_outputs():
+                        gir_filelist.write(os.path.join(state.environment.get_build_dir(),
+                                                        state.backend.get_target_dir(s),
+                                                        custom_output) + '\n')
+                elif isinstance(s, mesonlib.File):
+                    gir_filelist.write(s.rel_to_builddir(state.build_to_src) + '\n')
+                elif isinstance(s, build.GeneratedList):
+                    for gen_src in s.get_outputs():
+                        gir_filelist.write(os.path.join(srcdir, gen_src) + '\n')
+                else:
+                    gir_filelist.write(os.path.join(srcdir, s) + '\n')
+
+        return gir_filelist_filename
+
+    def _make_gir_target(self, state, girfile, scan_command, depends, kwargs):
+        scankwargs = {'output': girfile,
+                      'command': scan_command,
+                      'depends': depends}
+
+        if 'install' in kwargs:
+            scankwargs['install'] = kwargs['install']
+            scankwargs['install_dir'] = kwargs.get('install_dir_gir',
+                                                   os.path.join(state.environment.get_datadir(), 'gir-1.0'))
+
+        if 'build_by_default' in kwargs:
+            scankwargs['build_by_default'] = kwargs['build_by_default']
+
+        return GirTarget(girfile, state.subdir, state.subproject, scankwargs)
+
+    def _make_typelib_target(self, state, typelib_output, typelib_cmd, kwargs):
+        typelib_kwargs = {
+            'output': typelib_output,
+            'command': typelib_cmd,
+        }
+
+        if 'install' in kwargs:
+            typelib_kwargs['install'] = kwargs['install']
+            typelib_kwargs['install_dir'] = kwargs.get('install_dir_typelib',
+                                                       os.path.join(state.environment.get_libdir(), 'girepository-1.0'))
+
+        if 'build_by_default' in kwargs:
+            typelib_kwargs['build_by_default'] = kwargs['build_by_default']
+
+        return TypelibTarget(typelib_output, state.subdir, state.subproject, typelib_kwargs)
+
+    # May mutate depends
+    def _gather_typelib_includes_and_update_depends(self, state, deps, depends):
         # Need to recursively add deps on GirTarget sources from our
         # dependencies and also find the include directories needed for the
         # typelib generation custom target below.
@@ -569,6 +670,49 @@ def generate_gir(self, state, args, kwargs):
                 girdir = dep.get_pkgconfig_variable("girdir", {'default': ''})
                 if girdir and girdir not in typelib_includes:
                     typelib_includes.append(girdir)
+
+        return typelib_includes
+
+    def _get_external_args_for_langs(self, state, langs):
+        ret = []
+        for lang in langs:
+            ret += state.environment.coredata.get_external_args(lang)
+        return ret
+
+    @FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])
+    @permittedKwargs({'sources', 'nsversion', 'namespace', 'symbol_prefix', 'identifier_prefix',
+                      'export_packages', 'includes', 'dependencies', 'link_with', 'include_directories',
+                      'install', 'install_dir_gir', 'install_dir_typelib', 'extra_args',
+                      'packages', 'header', 'build_by_default'})
+    def generate_gir(self, state, args, kwargs):
+        if not args:
+            raise MesonException('generate_gir takes at least one argument')
+        if kwargs.get('install_dir'):
+            raise MesonException('install_dir is not supported with generate_gir(), see "install_dir_gir" and "install_dir_typelib"')
+
+        giscanner = self.interpreter.find_program_impl('g-ir-scanner')
+        gicompiler = self.interpreter.find_program_impl('g-ir-compiler')
+
+        girtargets = [self._unwrap_gir_target(arg) for arg in args]
+
+        if len(girtargets) > 1 and any([isinstance(el, build.Executable) for el in girtargets]):
+            raise MesonException('generate_gir only accepts a single argument when one of the arguments is an executable')
+
+        self.gir_dep, pkgargs = self._get_gir_dep(state)
+
+        ns = kwargs.pop('namespace')
+        nsversion = kwargs.pop('nsversion')
+        libsources = mesonlib.extract_as_list(kwargs, 'sources', pop=True)
+        girfile = '%s-%s.gir' % (ns, nsversion)
+        srcdir = os.path.join(state.environment.get_source_dir(), state.subdir)
+        builddir = os.path.join(state.environment.get_build_dir(), state.subdir)
+        depends = [] + girtargets
+        gir_inc_dirs = []
+        langs_compilers = self._get_girtargets_langs_compilers(girtargets)
+        cflags, internal_ldflags, external_ldflags = self._get_langs_compilers_flags(state, langs_compilers)
+        deps = self._get_gir_targets_deps(girtargets)
+        deps += extract_as_list(kwargs, 'dependencies', pop=True, unholder=True)
+        typelib_includes = self._gather_typelib_includes_and_update_depends(state, deps, depends)
         # ldflags will be misinterpreted by gir scanner (showing
         # spurious dependencies) but building GStreamer fails if they
         # are not used here.
@@ -577,74 +721,49 @@ def generate_gir(self, state, args, kwargs):
         cflags += list(dep_cflags)
         internal_ldflags += list(dep_internal_ldflags)
         external_ldflags += list(dep_external_ldflags)
+        girtargets_inc_dirs = self._get_gir_targets_inc_dirs(girtargets)
+        inc_dirs = self._scan_inc_dirs(kwargs)
+
+        scan_command = [giscanner]
+        scan_command += pkgargs
+        scan_command += ['--no-libtool']
+        scan_command += ['--namespace=' + ns, '--nsversion=' + nsversion]
+        scan_command += ['--warn-all']
+        scan_command += ['--output', '@OUTPUT@']
+        scan_command += self._scan_header(kwargs)
+        scan_command += self._scan_extra_args(kwargs)
+        scan_command += ['-I' + srcdir, '-I' + builddir]
+        scan_command += get_include_args(girtargets_inc_dirs)
+        scan_command += ['--filelist=' + self._make_gir_filelist(state, srcdir, ns, nsversion, girtargets, libsources)]
+        scan_command += self._scan_link_withs(state, depends, kwargs)
+        scan_command += self._scan_include(state, depends, gir_inc_dirs, kwargs)
+        scan_command += self._scan_symbol_prefix(kwargs)
+        scan_command += self._scan_identifier_prefix(kwargs)
+        scan_command += self._scan_export_packages(kwargs)
         scan_command += ['--cflags-begin']
         scan_command += cflags
-        scan_command += state.environment.coredata.get_external_args(lang)
+        scan_command += self._get_external_args_for_langs(state, [lc[0] for lc in langs_compilers])
         scan_command += ['--cflags-end']
-        # need to put our output directory first as we need to use the
-        # generated libraries instead of any possibly installed system/prefix
-        # ones.
-        if isinstance(girtarget, build.SharedLibrary):
-            scan_command += ["-L@PRIVATE_OUTDIR_ABS_%s@" % girtarget.get_id()]
-        scan_command += list(internal_ldflags)
-        for i in gi_includes:
-            scan_command += ['--add-include-path=%s' % i]
-
-        inc_dirs = mesonlib.extract_as_list(kwargs, 'include_directories', pop = True)
-        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 += get_include_args(inc_dirs)
-        scan_command += get_include_args(gir_inc_dirs + inc_dirs, prefix='--add-include-path=')
-
-        if isinstance(girtarget, build.Executable):
-            scan_command += ['--program', girtarget]
-        elif isinstance(girtarget, build.SharedLibrary):
-            libname = girtarget.get_basename()
-            # Needed for the following binutils bug:
-            # https://github.com/mesonbuild/meson/issues/1911
-            # However, g-ir-scanner does not understand -Wl,-rpath
-            # so we need to use -L instead
-            for d in state.backend.determine_rpath_dirs(girtarget):
-                d = os.path.join(state.environment.get_build_dir(), d)
-                scan_command.append('-L' + d)
-            scan_command += ['--library', libname]
-
-        for link_arg in state.environment.coredata.get_external_link_args(lang):
-            if link_arg.startswith('-L'):
-                scan_command.append(link_arg)
+        scan_command += get_include_args(list(gi_includes) + gir_inc_dirs + inc_dirs, prefix='--add-include-path=')
+        scan_command += self._scan_gir_targets(state, girtargets)
+        scan_command += self._scan_langs(state, [lc[0] for lc in langs_compilers])
+        scan_command += list(internal_ldflags)
         scan_command += list(external_ldflags)
 
-        scankwargs = {'output': girfile,
-                      'command': scan_command,
-                      'depends': depends}
-        if 'install' in kwargs:
-            scankwargs['install'] = kwargs['install']
-            scankwargs['install_dir'] = kwargs.get('install_dir_gir',
-                                                   os.path.join(state.environment.get_datadir(), 'gir-1.0'))
-        if 'build_by_default' in kwargs:
-            scankwargs['build_by_default'] = kwargs['build_by_default']
-        scan_target = GirTarget(girfile, state.subdir, state.subproject, scankwargs)
+        scan_target = self._make_gir_target(state, girfile, scan_command, depends, kwargs)
 
         typelib_output = '%s-%s.typelib' % (ns, nsversion)
         typelib_cmd = [gicompiler, scan_target, '--output', '@OUTPUT@']
         typelib_cmd += get_include_args(gir_inc_dirs, prefix='--includedir=')
+
         for incdir in typelib_includes:
             typelib_cmd += ["--includedir=" + incdir]
 
-        typelib_kwargs = {
-            'output': typelib_output,
-            'command': typelib_cmd,
-        }
-        if 'install' in kwargs:
-            typelib_kwargs['install'] = kwargs['install']
-            typelib_kwargs['install_dir'] = kwargs.get('install_dir_typelib',
-                                                       os.path.join(state.environment.get_libdir(), 'girepository-1.0'))
-        if 'build_by_default' in kwargs:
-            typelib_kwargs['build_by_default'] = kwargs['build_by_default']
-        typelib_target = TypelibTarget(typelib_output, state.subdir, state.subproject, typelib_kwargs)
+        typelib_target = self._make_typelib_target(state, typelib_output, typelib_cmd, kwargs)
+
         rv = [scan_target, typelib_target]
+
         return ModuleReturnValue(rv, rv)
 
     @FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])


Test patch:
diff --git a/test cases/frameworks/7 gnome/gir/meson-sample2.c b/test cases/frameworks/7 gnome/gir/meson-sample2.c
new file mode 100644
--- /dev/null
+++ b/test cases/frameworks/7 gnome/gir/meson-sample2.c	
@@ -0,0 +1,45 @@
+#include "meson-sample2.h"
+
+struct _MesonSample2
+{
+  GObject parent_instance;
+};
+
+G_DEFINE_TYPE (MesonSample2, meson_sample2, G_TYPE_OBJECT)
+
+/**
+ * meson_sample2_new:
+ *
+ * Allocates a new #MesonSample2.
+ *
+ * Returns: (transfer full): a #MesonSample2.
+ */
+MesonSample2 *
+meson_sample2_new (void)
+{
+  return g_object_new (MESON_TYPE_SAMPLE2, NULL);
+}
+
+static void
+meson_sample2_class_init (MesonSample2Class *klass)
+{
+}
+
+static void
+meson_sample2_init (MesonSample2 *self)
+{
+}
+
+/**
+ * meson_sample2_print_message:
+ * @self: a #MesonSample2.
+ *
+ * Prints Hello.
+ *
+ * Returns: Nothing.
+ */
+void
+meson_sample2_print_message (MesonSample2 *self)
+{
+  g_print ("Message: Hello\n");
+}
diff --git a/test cases/frameworks/7 gnome/gir/meson-sample2.h b/test cases/frameworks/7 gnome/gir/meson-sample2.h
new file mode 100644
--- /dev/null
+++ b/test cases/frameworks/7 gnome/gir/meson-sample2.h	
@@ -0,0 +1,21 @@
+#ifndef MESON_SAMPLE2_H
+#define MESON_SAMPLE2_H
+
+#if !defined (MESON_TEST)
+#error "MESON_TEST not defined."
+#endif
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define MESON_TYPE_SAMPLE2 (meson_sample2_get_type())
+
+G_DECLARE_FINAL_TYPE (MesonSample2, meson_sample2, MESON, SAMPLE2, GObject)
+
+MesonSample2 *meson_sample2_new           (void);
+void          meson_sample2_print_message (MesonSample2 *self);
+
+G_END_DECLS
+
+#endif /* MESON_SAMPLE2_H */
diff --git a/test cases/frameworks/7 gnome/gir/meson.build b/test cases/frameworks/7 gnome/gir/meson.build
--- a/test cases/frameworks/7 gnome/gir/meson.build	
+++ b/test cases/frameworks/7 gnome/gir/meson.build	
@@ -1,6 +1,7 @@
 subdir('dep1')
 
 libsources = ['meson-sample.c', 'meson-sample.h']
+lib2sources = ['meson-sample2.c', 'meson-sample2.h']
 
 girlib = shared_library(
   'gir_lib',
@@ -9,6 +10,13 @@ girlib = shared_library(
   install : true
 )
 
+girlib2 = shared_library(
+  'gir_lib2',
+  sources : lib2sources,
+  dependencies : [gobj],
+  install : true
+)
+
 girexe = executable(
   'girprog',
   sources : 'prog.c',
@@ -19,8 +27,8 @@ girexe = executable(
 fake_dep = dependency('no-way-this-exists', required: false)
 
 gnome.generate_gir(
-  girlib,
-  sources : libsources,
+  girlib, girlib2,
+  sources : libsources + lib2sources,
   nsversion : '1.0',
   namespace : 'Meson',
   symbol_prefix : 'meson',
diff --git a/test cases/frameworks/7 gnome/gir/prog.py b/test cases/frameworks/7 gnome/gir/prog.py
--- a/test cases/frameworks/7 gnome/gir/prog.py	
+++ b/test cases/frameworks/7 gnome/gir/prog.py	
@@ -6,3 +6,6 @@
     dep1 = MesonDep1.Dep1.new()
     dep2 = MesonDep2.Dep2.new("Hello, meson/py!")
     s.print_message(dep1, dep2)
+
+    s2 = Meson.Sample2.new()
+    s2.print_message()