Repository: mesonbuild/meson

Issue:
gnome.generate_gir() is failing with address sanitizer.
Compiling fwupd with:

    meson .. -Db_sanitize=address

...completes until it gets to the `g-ir-scanner` calls. This returns:

    [1/4] 'Generating Fwupd-1.0.gir with a custom command.'
    FAILED: libfwupd/Fwupd-1.0.gir 
    '/usr/bin/g-ir-scanner' '../libfwupd/fwupd-client.c' '../libfwupd/fwupd-enums.c' '../libfwupd/fwupd-enums.h' '../libfwupd/fwupd-error.c' '../libfwupd/fwupd-remote.c' '../libfwupd/fwupd-result.c' '-I/usr/include/gobject-introspection-1.0' '-I/usr/include/glib-2.0' '-I/usr/lib64/glib-2.0/include' '-pthread' '--no-libtool' '--namespace=Fwupd' '--nsversion=1.0' '--warn-all' '--output' 'libfwupd/Fwupd-1.0.gir' '-I/home/hughsie/Code/fwupd/libfwupd' '-I/home/hughsie/Code/fwupd/build/libfwupd' '-I./libfwupd/..' '-I../libfwupd/..' '--include=GObject-2.0' '--cflags-begin' '-fstack-protector-strong' '-Wwrite-strings' '--cflags-end' '--symbol-prefix=fwupd' '--identifier-prefix=Fwupd' '--pkg-export=fwupd' '..' '-I/usr/include/gio-unix-2.0/' '-I/usr/include/glib-2.0' '-I/usr/lib64/glib-2.0/include' '-pthread' '-I/usr/include/libsoup-2.4' '-I/usr/include/libxml2' '-L/home/hughsie/Code/fwupd/build/libfwupd' '--extra-library=gio-2.0' '--extra-library=gobject-2.0' '--extra-library=glib-2.0' '--extra-library=soup-2.4' '--library' 'fwupd'
    ==6599==ASan runtime does not come first in initial library list; you should either link runtime to your application or manually preload it with LD_PRELOAD.
    Command '[u'/home/hughsie/Code/fwupd/build/tmp-introspectKke532/Fwupd-1.0', u'--introspect-dump=/home/hughsie/Code/fwupd/build/tmp-introspectKke532/functions.txt,/home/hughsie/Code/fwupd/build/tmp-introspectKke532/dump.xml']' returned non-zero exit status 1

I think the gnome module needs to remove the address sanitization flags before passing them to `/usr/bin/g-ir-scanner`



Discussion:
Here is where these flags are added btw: https://github.com/mesonbuild/meson/blob/master/mesonbuild/modules/gnome.py#L459-L461

So this seems to be a compounding of a few problems:

- `compiler.get_options().get('b_sanitize')` incorrectly returns `None` even thought `mesonconf` shows the correct value. So actually the flags are *not* getting set.
- When they are set this is not enough, `ldflags` need to be passed.
- `sanitizer_link_args()` returns `-fsanitize=foo` which fails with gir `-f` flags are unknown.
   - Having it return `-lasan` works but I believe that is wrong, I tried `-Wl,-fsanitize=foo` but that had errors outside of gir and resulted in unresolved references, which `-lasan` fixed again.

Resolving patch:
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -444,6 +444,7 @@ def generate_gir(self, state, args, kwargs):
                         'Gir includes must be str, GirTarget, or list of them')
 
         cflags = []
+        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'):
@@ -456,9 +457,14 @@ def generate_gir(self, state, args, kwargs):
                 cflags += state.global_args[lang]
             if state.project_args.get(lang):
                 cflags += state.project_args[lang]
-            sanitize = compiler.get_options().get('b_sanitize')
-            if sanitize:
+            if 'b_sanitize' in compiler.base_options:
+                sanitize = state.environment.coredata.base_options['b_sanitize'].value
                 cflags += compilers.sanitizer_compile_args(sanitize)
+                if sanitize == 'address':
+                    ldflags += ['-lasan']
+                # 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 kwargs.get('symbol_prefix'):
             sym_prefix = kwargs.pop('symbol_prefix')
             if not isinstance(sym_prefix, str):
@@ -521,9 +527,10 @@ def generate_gir(self, state, args, kwargs):
         # ldflags will be misinterpreted by gir scanner (showing
         # spurious dependencies) but building GStreamer fails if they
         # are not used here.
-        dep_cflags, ldflags, gi_includes = self._get_dependencies_flags(deps, state, depends,
-                                                                        use_gir_args=True)
+        dep_cflags, dep_ldflags, gi_includes = self._get_dependencies_flags(deps, state, depends,
+                                                                            use_gir_args=True)
         cflags += list(dep_cflags)
+        ldflags += list(dep_ldflags)
         scan_command += ['--cflags-begin']
         scan_command += cflags
         scan_command += ['--cflags-end']


Test patch: