[gjs: 1/7] build: Meson build system



commit 00a7b5f78a8a9185d4f5f5fee52aa97f04fcc2a0
Author: Philip Chimento <philip chimento gmail com>
Date:   Wed Mar 27 21:45:40 2019 -0700

    build: Meson build system
    
    This adds a Meson build system which should be functionally equivalent
    to the existing Autotools build system, but easier to deal with and
    faster.
    
    Equivalents:
        ./configure -> meson _build
        make -j5 -> ninja -C _build
        make install -> ninja -C _build install
        make check -> meson test -C _build
    
    It's also easy to run the tests under Valgrind or using the GC zeal
    variables, by adding e.g. --setup=valgrind to the meson test command.
    
    Dependencies (except SpiderMonkey) will be downloaded and built if not
    present (or not new enough), using Meson's wrap system.
    
    There were a small number of things the Autotools build did better. One
    is export-symbols-regex which doesn't exist in Meson; we must write two
    separate linker config files for GNU ld and macOS's linker, and I'm not
    sure what happens in this case on Windows.
    
    The other thing is merging the JS and C code coverage files
    automatically. Since this isn't possible using Meson's b_coverage
    option, we add a script, tools/run_coverage.sh, which generates a code
    coverage report from start to finish. This is actually kind of better
    than the old situation, since the script builds in a different build
    tree, so you cannot accidentally leave coverage-instrumented build
    artifacts sitting in your build tree.

 Makefile.am                            |  13 +
 build/compile-gschemas.sh              |   8 +
 installed-tests/extra/gjs.supp         |  12 +
 installed-tests/js/meson.build         | 167 +++++++++
 installed-tests/meson.build            |  85 +++++
 libgjs.map                             |  11 +
 libgjs.symbols                         |   8 +
 meson.build                            | 613 +++++++++++++++++++++++++++++++++
 meson_options.txt                      |  27 ++
 subprojects/.gitignore                 |   5 +
 subprojects/glib.wrap                  |   4 +
 subprojects/gobject-introspection.wrap |   4 +
 subprojects/libffi.wrap                |   4 +
 subprojects/proxy-libintl.wrap         |   4 +
 subprojects/zlib.wrap                  |  10 +
 test/meson.build                       |  22 ++
 tools/lcovrc                           |  14 +
 tools/run_coverage.sh                  |  19 +
 18 files changed, 1030 insertions(+)
---
diff --git a/Makefile.am b/Makefile.am
index 41858c81..a93efb17 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -180,12 +180,25 @@ include Makefile-insttest.am
 EXTRA_DIST +=                                  \
        autogen.sh                              \
        build/choose-tests-locale.sh            \
+       build/compile-gschemas.sh               \
        COPYING.LGPL                            \
        doc/ByteArray.md                        \
        doc/cairo.md                            \
        doc/Hacking.md                          \
        doc/SpiderMonkey_Memory.md              \
        doc/Style_Guide.md                      \
+       installed-tests/js/meson.build          \
+       installed-tests/meson.build             \
+       libgjs.map                              \
+       libgjs.symbols                          \
+       meson.build                             \
+       meson_options.txt                       \
+       subprojects/glib.wrap                   \
+       subprojects/gobject-introspection.wrap  \
+       subprojects/libffi.wrap                 \
+       subprojects/proxy-libintl.wrap          \
+       subprojects/zlib.wrap                   \
+       test/meson.build                        \
        win32/build-rules-msvc.mak              \
        win32/config-msvc.mak                   \
        win32/config.h.win32                    \
diff --git a/build/compile-gschemas.sh b/build/compile-gschemas.sh
new file mode 100755
index 00000000..545ff7a0
--- /dev/null
+++ b/build/compile-gschemas.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+SCHEMADIR="$MESON_INSTALL_PREFIX/share/glib-2.0/schemas"
+
+if test -z "$DESTDIR"; then
+    echo "Compiling GSettings schemas..."
+    glib-compile-schemas "$SCHEMADIR"
+fi
diff --git a/installed-tests/extra/gjs.supp b/installed-tests/extra/gjs.supp
index 111144b1..f45aaeb1 100644
--- a/installed-tests/extra/gjs.supp
+++ b/installed-tests/extra/gjs.supp
@@ -169,6 +169,18 @@
    fun:register_internal
 }
 
+# Workaround for https://github.com/mesonbuild/meson/issues/4427
+# When fixed, valgrind should already not trace bash
+{
+   bash-workaround
+   Memcheck:Leak
+   match-leak-kinds: definite
+   fun:malloc
+   fun:xmalloc
+   fun:set_default_locale
+   fun:main
+}
+
 # SpiderMonkey data races
 
 # These are in SpiderMonkey's atomics / thread barrier stuff so presumably
diff --git a/installed-tests/js/meson.build b/installed-tests/js/meson.build
new file mode 100644
index 00000000..0d4ba3de
--- /dev/null
+++ b/installed-tests/js/meson.build
@@ -0,0 +1,167 @@
+### Jasmine tests ##############################################################
+
+jsunit_resources_files = gnome.compile_resources('jsunit-resources',
+    'jsunit.gresources.xml', c_name: 'jsunit_resources')
+
+minijasmine = executable('minijasmine', '../minijasmine.cpp',
+    jsunit_resources_files, dependencies: libgjs_dep,
+    cpp_args: [
+        '-DINSTTESTDIR="@0@"'.format(get_option('prefix') / installed_tests_dir),
+        '-DPKGLIBDIR="@0@"'.format(get_option('prefix') / pkglibdir)
+    ],
+    include_directories: top_include,
+    install: get_option('installed_tests'), install_dir: installed_tests_dir)
+
+gidatadir = gi.get_pkgconfig_variable('gidatadir')
+gi_tests = gidatadir / 'tests'
+
+regress_dependencies = [glib, gobject, gio]
+regress_gir_includes = ['Gio-2.0']
+regress_gir_cpp_args = []
+if build_cairo
+    regress_gir_includes += 'cairo-1.0'
+    regress_dependencies += [cairo, cairo_gobject]
+else
+    regress_gir_cpp_args = ['-D_GI_DISABLE_CAIRO']
+endif
+
+regress_sources = [
+    gi_tests / 'regress.c',
+    gi_tests / 'regress.h',
+]
+libregress = library('regress', regress_sources, cpp_args: regress_gir_cpp_args,
+    dependencies: regress_dependencies, install: get_option('installed_tests'),
+    install_dir: pkglibdir)
+regress_gir = gnome.generate_gir(libregress, includes: regress_gir_includes,
+    sources: regress_sources, namespace: 'Regress', nsversion: '1.0',
+    identifier_prefix: 'Regress', symbol_prefix: 'regress_',
+    extra_args: ['--warn-all', '--warn-error'] + regress_gir_cpp_args,
+    install: get_option('installed_tests'), install_dir_gir: false,
+    install_dir_typelib: installed_tests_dir)
+regress_typelib = regress_gir[1]
+
+warnlib_sources = [
+    gi_tests / 'warnlib.c',
+    gi_tests / 'warnlib.h',
+]
+libwarnlib = library('warnlib', warnlib_sources,
+    dependencies: [glib, gobject, gio])
+# This should have --warn-all turned off, but there is currently no way to do so
+# in gnome.generate_gir(). See https://github.com/mesonbuild/meson/issues/5876
+warnlib_gir = gnome.generate_gir(libwarnlib, includes: ['Gio-2.0'],
+    sources: warnlib_sources, namespace: 'WarnLib', nsversion: '1.0',
+    symbol_prefix: 'warnlib_', header: 'warnlib.h',
+    install: get_option('installed_tests'), install_dir_gir: false,
+    install_dir_typelib: installed_tests_dir)
+warnlib_typelib = warnlib_gir[1]
+
+gimarshallingtests_sources = [
+    gi_tests / 'gimarshallingtests.c',
+    gi_tests / 'gimarshallingtests.h',
+]
+libgimarshallingtests = library('gimarshallingtests',
+    gimarshallingtests_sources, dependencies: [glib, gobject, gio],
+    install: get_option('installed_tests'), install_dir: pkglibdir)
+gimarshallingtests_gir = gnome.generate_gir(libgimarshallingtests,
+    includes: ['Gio-2.0'], sources: gimarshallingtests_sources,
+    namespace: 'GIMarshallingTests', nsversion: '1.0',
+    symbol_prefix: 'gi_marshalling_tests_', extra_args: '--warn-error',
+    install: get_option('installed_tests'), install_dir_gir: false,
+    install_dir_typelib: installed_tests_dir)
+gimarshallingtests_typelib = gimarshallingtests_gir[1]
+
+jasmine_tests = [
+    'self',
+    'ByteArray',
+    'Exceptions',
+    'Format',
+    'Fundamental',
+    'Gettext',
+    'GIMarshalling',
+    'Gio',
+    'GLib',
+    'GObject',
+    'GObjectClass',
+    'GObjectInterface',
+    'GTypeClass',
+    'Importer',
+    'Introspection',
+    'Lang',
+    'LegacyByteArray',
+    'LegacyClass',
+    'LegacyGObject',
+    'Locale',
+    'Mainloop',
+    'Namespace',
+    'Package',
+    'ParamSpec',
+    'Regress',
+    'Signals',
+    'System',
+    'Tweener',
+    'WarnLib',
+]
+
+if build_cairo
+    jasmine_tests += 'Cairo'
+endif
+
+if not get_option('skip_gtk_tests')
+    jasmine_tests += [
+        'Gtk',
+        'GObjectDestructionAccess',
+        'LegacyGtk',
+    ]
+endif
+
+installed_js_tests_dir = installed_tests_dir / 'js'
+
+gschemas_compiled = gnome.compile_schemas(
+    depend_files: 'org.gnome.GjsTest.gschema.xml')
+
+foreach test : jasmine_tests
+    test_file = files('test@0@.js'.format(test))
+
+    test(test, minijasmine, args: test_file,
+        depends: [gschemas_compiled, regress_typelib, gimarshallingtests_typelib],
+        env: tests_environment, protocol: 'tap', suite: 'JS')
+
+    test_description_subst = {
+        'name': 'test@0@.js'.format(test),
+        'pkglibexecdir': abs_pkglibexecdir,
+    }
+    test_description = configure_file(configuration: test_description_subst,
+        input: '../minijasmine.test.in',
+        output: 'test@0@.test'.format(test),
+        install: get_option('installed_tests'),
+        install_dir: test_descriptions_dir)
+
+    if get_option('installed_tests')
+        install_data(test_file, install_dir: installed_js_tests_dir)
+    endif
+endforeach
+
+# testGDBus.js is separate, because it can be skipped, and during build should
+# be run using dbus-run-session
+
+if not get_option('skip_dbus_tests')
+    test_file = files('testGDBus.js')
+    bus_config = files('../../test/test-bus.conf')
+    test('GDBus', dbus_run_session,
+        args: ['--config-file', bus_config, '--', minijasmine, test_file],
+        env: tests_environment, protocol: 'tap', suite: 'dbus')
+endif
+
+gdbus_test_description_subst = {
+    'name': 'testGDBus.js',
+    'pkglibexecdir': abs_pkglibexecdir,
+}
+gdbus_test_description = configure_file(
+    configuration: gdbus_test_description_subst,
+    input: '../minijasmine.test.in', output: 'testGDBus.test',
+    install: get_option('installed_tests'),
+    install_dir: test_descriptions_dir)
+
+if get_option('installed_tests')
+    install_data('testGDBus.js', install_dir: installed_js_tests_dir)
+endif
diff --git a/installed-tests/meson.build b/installed-tests/meson.build
new file mode 100644
index 00000000..5e2b5abf
--- /dev/null
+++ b/installed-tests/meson.build
@@ -0,0 +1,85 @@
+### Installed tests ############################################################
+
+installed_tests_dir = pkglibexecdir / 'installed-tests'
+test_descriptions_dir = (get_option('datadir') / 'installed-tests' /
+    meson.project_name())
+
+# Simple shell script tests #
+
+simple_tests = [
+    'CommandLine',
+    'Warnings',
+]
+
+foreach test : simple_tests
+    test_file = files('scripts' / 'test@0@.sh'.format(test))
+
+    test(test, test_file, env: tests_environment, protocol: 'tap',
+        suite: 'Scripts')
+
+    test_description_subst = {
+        'name': 'test@0@.sh'.format(test),
+        'pkglibexecdir': abs_pkglibexecdir,
+    }
+    test_description = configure_file(configuration: test_description_subst,
+        input: 'script.test.in', output: 'test@0  sh test'.format(test),
+        install: get_option('installed_tests'),
+        install_dir: test_descriptions_dir)
+
+    if get_option('installed_tests')
+        install_data(test_file, install_dir: installed_tests_dir / 'scripts')
+    endif
+endforeach
+
+# Jasmine tests #
+
+subdir('js')
+
+# Debugger script tests #
+
+debugger_tests = [
+    'backtrace',
+    'breakpoint',
+    'continue',
+    'delete',
+    'detach',
+    'down-up',
+    'finish',
+    'frame',
+    'keys',
+    'next',
+    'print',
+    'quit',
+    'return',
+    'set',
+    'step',
+    'throw',
+    'until',
+]
+
+debugger_test_driver = find_program(files('debugger-test.sh'))
+if get_option('installed_tests')
+    install_data('debugger-test.sh', install_dir: installed_tests_dir)
+endif
+
+foreach test : debugger_tests
+    test_file = files('debugger' / '@0@.debugger'.format(test))
+
+    test('@0@ command'.format(test), debugger_test_driver,
+        args: test_file, env: tests_environment, protocol: 'tap',
+        suite: 'Debugger')
+
+    test_description_subst = {
+        'name': '@0@.debugger'.format(test),
+        'pkglibexecdir': abs_pkglibexecdir,
+    }
+    test_description = configure_file(configuration: test_description_subst,
+        input: 'debugger.test.in',
+        output: '@0@.test'.format(test),
+        install: get_option('installed_tests'),
+        install_dir: test_descriptions_dir)
+
+    if get_option('installed_tests')
+        install_data(test_file, install_dir: installed_tests_dir / 'debugger')
+    endif
+endforeach
diff --git a/libgjs.map b/libgjs.map
new file mode 100644
index 00000000..74b34ec1
--- /dev/null
+++ b/libgjs.map
@@ -0,0 +1,11 @@
+# Remove when https://gitlab.gnome.org/GNOME/gjs/issues/194 is completed
+{
+global:
+    gjs_*;
+    extern "C++" {
+        gjs_*;
+        GjsContextPrivate::from_object*;
+    };
+local:
+    *;
+};
diff --git a/libgjs.symbols b/libgjs.symbols
new file mode 100644
index 00000000..5ebe9e4c
--- /dev/null
+++ b/libgjs.symbols
@@ -0,0 +1,8 @@
+# Workaround for https://github.com/mesonbuild/meson/issues/3047
+# Linker scripts are not understood by the macOS linker, we need to use a
+# symbol export file instead.
+# With autotools, this was all done transparently by -export-symbols-regex.
+# Remove when https://gitlab.gnome.org/GNOME/gjs/issues/194 is completed
+_gjs_*
+__Z*[0-9]gjs_*
+__ZN*GjsContextPrivate*from_object*
diff --git a/meson.build b/meson.build
new file mode 100644
index 00000000..c4c8fb05
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,613 @@
+project('gjs', 'cpp', 'c', version: '1.63.1', license: ['MIT', 'LGPL2+'],
+    meson_version: '>= 0.50.0',
+    default_options: ['cpp_std=c++14', 'c_std=c99', 'warning_level=2'])
+
+api_version = '1.0'
+api_name = '@0@-@1@'.format(meson.project_name(), api_version)
+
+gnome = import('gnome')
+pkg = import('pkgconfig')
+
+top_include = include_directories('.')
+
+add_project_arguments('-DG_LOG_DOMAIN="Gjs"', language: ['c', 'cpp'])
+
+### Check for conflicting build options ########################################
+
+if get_option('systemtap') and not get_option('dtrace')
+    error('-Ddtrace=true is required for -Dsystemtap=true')
+endif
+
+if get_option('buildtype').startswith('release') and get_option('verbose_logs')
+    error('-Dverbose_logs=true is not allowed with --buildtype=release')
+endif
+
+### Check for compiler args ####################################################
+
+cxx = meson.get_compiler('cpp')
+cc = meson.get_compiler('c')
+
+add_project_arguments(cxx.get_supported_arguments([
+    '-fno-strict-aliasing',
+
+    # Ignore spurious compiler warnings for things that GLib and SpiderMonkey
+    # header files commonly do
+    '-Wno-variadic-macros',  # GLib uses these in header files
+    '-Wno-missing-field-initializers',  # SpiderMonkey JSClass, among others
+]), language: 'cpp')
+
+if get_option('bsymbolic_functions')
+    if not cxx.has_link_argument('-Bsymbolic-functions')
+        error('''-Bsymbolic-functions not supported, configure with
+-Dbsymbolic_functions=false''')
+    endif
+    add_project_link_arguments('-Bsymbolic-functions', language: ['cpp', 'c'])
+endif
+
+# SpiderMonkey can be compiled with or without runtime type information, we must
+# match that option because we need to derive from SpiderMonkey classes
+if get_option('spidermonkey_rtti')
+    if cxx.has_argument('-GR-')
+        add_project_arguments('-GR-', language: 'cpp')  # MSVC option
+    endif
+else
+    if cxx.has_argument('-fno-rtti')
+        add_project_arguments('-fno-rtti', language: 'cpp')
+        # -fno-rtti is not compatible with the vptr sanitizer (part of ubsan)
+        if get_option('b_sanitize') != 'none' and \
+            cxx.has_argument('-fno-sanitize=vptr')
+            add_project_arguments('-fno-sanitize=vptr', language: 'cpp')
+        endif
+    endif
+endif
+
+if get_option('verbose_logs')
+    add_project_arguments([
+        '-DGJS_VERBOSE_ENABLE_PROPS=1',
+        '-DGJS_VERBOSE_ENABLE_MARSHAL=1',
+        '-DGJS_VERBOSE_ENABLE_LIFECYCLE=1',
+        '-DGJS_VERBOSE_ENABLE_GI_USAGE=1',
+        '-DGJS_VERBOSE_ENABLE_GCLOSURE=1',
+        '-DGJS_VERBOSE_ENABLE_GSIGNAL=1',
+    ], language: 'cpp')
+endif
+
+if get_option('buildtype').startswith('release')
+    add_project_arguments('-DG_DISABLE_CAST_CHECKS', language: ['c', 'cpp'])
+endif
+
+### Check for required libraries ###############################################
+
+glib_required_version = '>= 2.58.0'
+glib = dependency('glib-2.0', version: glib_required_version,
+    fallback: ['glib', 'libglib_dep'])
+gthread = dependency('gthread-2.0', version: glib_required_version,
+    fallback: ['glib', 'libgthread_dep'])
+gobject = dependency('gobject-2.0', version: glib_required_version,
+    fallback: ['glib', 'libgobject_dep'])
+gio = dependency('gio-2.0', version: glib_required_version,
+    fallback: ['glib', 'libgio_dep'])
+ffi = dependency('libffi', fallback: ['libffi', 'ffi_dep'])
+gi = dependency('gobject-introspection-1.0', version: '>= 1.41.4',
+    fallback: ['gobject-introspection', 'girepo_dep'])
+spidermonkey = dependency('mozjs-60')
+cairo = dependency('cairo', required: get_option('cairo'))
+cairo_gobject = dependency('cairo-gobject', required: cairo.found())
+cairo_xlib = dependency('cairo-xlib', required: false)
+sysprof_capture = dependency('sysprof-capture-3', version: '>= 3.33.32',
+    required: get_option('profiler'),
+    fallback: ['sysprof', 'libsysprof_capture_dep'])
+
+readline = cxx.find_library('readline', required: get_option('readline'))
+# On some systems we need to link readline to a termcap compatible library
+readline_code = '''
+#include <cstdio>
+#include <readline/readline.h>
+int main(void) {
+    readline("foo");
+    return 0;
+}'''
+readline_deps = [readline]
+if readline.found() and not cxx.links(readline_code, dependencies: readline)
+    extra_readline_libs = ['ncursesw', 'ncurses', 'curses', 'termcap']
+    found = false
+    foreach lib : extra_readline_libs
+        termcap = cxx.find_library(lib, required: false)
+        if cxx.links(readline_code, dependencies: [readline, termcap])
+            found = true
+            readline_deps += termcap
+            break
+        endif
+    endforeach
+    if not found
+        error('''Couldn't figure out how to link readline library. Configure
+with -Dreadline=disabled to skip the readline features.''')
+    endif
+endif
+
+build_profiler = sysprof_capture.found() and not get_option('profiler').disabled()
+profiler_deps = [sysprof_capture]
+if build_profiler and not cxx.has_function('timer_settime')
+    extra_timer_libs = ['rt', 'posix4']
+    found = false
+    foreach lib : extra_timer_libs
+        timer_lib = cxx.find_library(lib, required: false)
+        if cxx.has_function('timer_settime', dependencies: timer_lib)
+            found = true
+            profiler_deps += timer_lib
+            break
+        endif
+    endforeach
+    if not found or not cxx.has_header_symbol('signal.h', 'SIGEV_THREAD_ID')
+        if get_option('profiler').enabled()
+            error('''The profiler is currently only supported on Linux.
+The standard library must support timer_settime() and SIGEV_THREAD_ID.
+Configure with -Dprofiler=auto or -Dprofiler=disabled to skip it on other
+platforms.''')
+        endif
+        build_profiler = false
+    endif
+endif
+
+build_cairo = cairo.found() and not get_option('cairo').disabled()
+build_readline = readline.found() and not get_option('readline').disabled()
+
+### Check for library features #################################################
+
+# Check if SpiderMonkey was compiled with --enable-debug. If this is the case,
+# you must compile all your sources with -DDEBUG=1
+# See https://bugzilla.mozilla.org/show_bug.cgi?id=1261161
+debug_arg = []
+nondebug_spidermonkey = cxx.compiles('''
+#include <js-config.h>
+#ifdef JS_DEBUG
+#error debug yes, if we did not already error out due to DEBUG not being defined
+#endif
+''',
+    dependencies: spidermonkey,
+    name: 'SpiderMonkey is a non-debug build')
+
+if not nondebug_spidermonkey
+    debug_arg = ['-DDEBUG=1']  # for compile tests
+    add_project_arguments('-DDEBUG=1', language: 'cpp')
+endif
+
+if get_option('buildtype').startswith('release') and not nondebug_spidermonkey
+    error('''You are trying to make a release build with a debug-enabled copy of
+SpiderMonkey. This is probably not what you want, since it will have bad
+performance and is not binary-compatible with release builds of SpiderMonkey.
+Try configuring SpiderMonkey with --disable-debug.''')
+endif
+
+# Check if a minimal SpiderMonkey program compiles, links, and runs. If not,
+# it's most likely the case that SpiderMonkey was configured incorrectly, for
+# example by building mozglue as a shared library.
+minimal_program = cxx.run('''
+#include <js/Initialization.h>
+int main(void) {
+    if (!JS_Init()) return 1;
+    JS_ShutDown();
+    return 0;
+}
+''',
+    args: debug_arg, dependencies: spidermonkey,
+    name: 'SpiderMonkey sanity check')
+
+if not minimal_program.compiled() or minimal_program.returncode() != 0
+    error('''A minimal SpiderMonkey program could not be compiled, linked, or
+run. Most likely you should build it with a different configuration. Check the
+recommended configuration:
+https://github.com/spidermonkey-embedders/spidermonkey-embedding-examples/blob/esr60/docs/Building%20SpiderMonkey.md''')
+endif
+
+have_printf_alternative_int = cc.compiles('''
+#include <stdio.h>
+int main(void) {
+    printf("%Id", (int)0);
+    return 0;
+}
+''',
+    args: ['-Werror', '-Wformat'],
+    name: 'printf() supports %I alternative int syntax')
+
+### Check for external programs ################################################
+
+dtrace = find_program('dtrace', required: get_option('dtrace'))
+dbus_run_session = find_program('dbus-run-session',
+    required: not get_option('skip_dbus_tests'))
+glib_compile_schemas = find_program('glib-compile-schemas')
+
+### Generate config.h ##########################################################
+
+header_conf = configuration_data()
+
+versions = meson.project_version().split('.')
+major_version = versions[0].to_int()
+minor_version = versions[1].to_int()
+micro_version = versions[2].to_int()
+int_version = (major_version * 100 + minor_version) * 100 + micro_version
+header_conf.set_quoted('VERSION', meson.project_version())
+header_conf.set('GJS_VERSION', int_version,
+    description: 'The GJS version as an integer')
+header_conf.set_quoted('PACKAGE_STRING', '@0@ @1@'.format(meson.project_name(),
+    meson.project_version()))
+
+header_conf.set('ENABLE_CAIRO', build_cairo,
+    description: 'Build with Cairo support')
+header_conf.set('ENABLE_PROFILER', build_profiler,
+    description: 'Build the profiler')
+header_conf.set('HAVE_DEBUG_SPIDERMONKEY', not nondebug_spidermonkey,
+    description: 'SpiderMonkey was compiled with --enable-debug')
+header_conf.set('HAVE_DTRACE', get_option('dtrace'),
+    description: 'Using dtrace probes')
+header_conf.set('HAVE_PRINTF_ALTERNATIVE_INT', have_printf_alternative_int,
+    description: 'printf() accepts "%Id" for alternative integer output')
+if build_readline
+    header_conf.set('HAVE_READLINE_READLINE_H',
+        cxx.check_header('readline/readline.h', prefix: '#include <cstdio>',
+            required: readline.found()))
+endif
+header_conf.set('HAVE_SYS_SYSCALL_H', cxx.check_header('sys/syscall.h'))
+header_conf.set('HAVE_UNISTD_H', cxx.check_header('unistd.h'))
+
+# enable GNU extensions on systems that have them
+header_conf.set('_GNU_SOURCE', 1)
+
+configure_file(output: 'config.h', configuration: header_conf)
+
+### Generate config.h for win32 ################################################
+
+win32_header_conf = configuration_data()
+win32_header_conf.set('GJS_VERSION', int_version)
+win32_header_conf.set('PACKAGE', meson.project_name())
+win32_header_conf.set('PACKAGE_BUGREPORT', 'https://gitlab.gnome.org/GNOME/gjs')
+win32_header_conf.set('PACKAGE_NAME', meson.project_name())
+win32_header_conf.set('PACKAGE_VERSION', meson.project_version())
+win32_header_conf.set('PACKAGE_TARNAME', meson.project_name())
+configure_file(input: 'win32/config.h.win32.in', output: 'config.h.win32',
+    configuration: win32_header_conf)
+
+### Check for environment ######################################################
+
+tests_locale = run_command('build/choose-tests-locale.sh').stdout().strip()
+
+gjsjsdir = get_option('datadir') / api_name
+pkglibexecdir = get_option('libexecdir') / meson.project_name()
+abs_pkglibexecdir = get_option('prefix') / pkglibexecdir
+pkglibdir = get_option('libdir') / meson.project_name()
+
+### Build dtrace probes ########################################################
+
+if get_option('dtrace')
+    probes_header_gen = generator(dtrace, output: '@BASENAME@.h',
+        arguments: ['-C', '-h', '-s', '@INPUT@', '-o', '@OUTPUT@'])
+    probes_objfile_gen = generator(dtrace, output: '@BASENAME@.o',
+        arguments: ['-G', '-s', '@INPUT@', '-o', '@OUTPUT@'])
+    probes_header = probes_header_gen.process('gi/gjs_gi_probes.d')
+    probes_objfile = probes_objfile_gen.process('gi/gjs_gi_probes.d')
+else
+    probes_header = []
+    probes_objfile = []
+endif
+
+tapset_subst = configuration_data({
+    'EXPANDED_LIBDIR': get_option('libdir'),
+})
+tapset = configure_file(input: 'gjs/gjs.stp.in', output: 'gjs.stp',
+    configuration: tapset_subst)
+if get_option('systemtap')
+    install_data(tapset,
+        install_dir: get_option('datadir') / 'systemtap/tapset')
+endif
+
+### Build library ##############################################################
+
+directory_defines = [
+    '-DGJS_JS_DIR="@0@"'.format(get_option('prefix') / gjsjsdir),
+    '-DPKGLIBDIR="@0@"'.format(get_option('prefix') / pkglibdir),
+]
+
+gjs_public_headers = [
+    'gjs/context.h',
+    'gjs/coverage.h',
+    'gjs/error-types.h',
+    'gjs/gjs.h',
+    'gjs/macros.h',
+    'gjs/mem.h',
+    'gjs/profiler.h',
+]
+
+# For historical reasons, some files live in gi/
+# Some headers in the following list were formerly public
+
+libgjs_sources = [
+    'gi/arg.cpp', 'gi/arg.h',
+    'gi/boxed.cpp', 'gi/boxed.h',
+    'gi/closure.cpp', 'gi/closure.h',
+    'gi/enumeration.cpp', 'gi/enumeration.h',
+    'gi/foreign.cpp', 'gi/foreign.h',
+    'gi/fundamental.cpp', 'gi/fundamental.h',
+    'gi/function.cpp', 'gi/function.h',
+    'gi/gerror.cpp', 'gi/gerror.h',
+    'gi/gjs_gi_trace.h',
+    'gi/gobject.cpp', 'gi/gobject.h',
+    'gi/gtype.cpp', 'gi/gtype.h',
+    'gi/interface.cpp', 'gi/interface.h',
+    'gi/ns.cpp', 'gi/ns.h',
+    'gi/object.cpp', 'gi/object.h',
+    'gi/param.cpp', 'gi/param.h',
+    'gi/private.cpp', 'gi/private.h',
+    'gi/repo.cpp', 'gi/repo.h',
+    'gi/toggle.cpp', 'gi/toggle.h',
+    'gi/union.cpp', 'gi/union.h',
+    'gi/value.cpp', 'gi/value.h',
+    'gi/wrapperutils.cpp', 'gi/wrapperutils.h',
+    'gjs/atoms.cpp', 'gjs/atoms.h',
+    'gjs/byteArray.cpp', 'gjs/byteArray.h',
+    'gjs/context.cpp', 'gjs/context-private.h',
+    'gjs/coverage.cpp',
+    'gjs/debugger.cpp',
+    'gjs/deprecation.cpp', 'gjs/deprecation.h',
+    'gjs/engine.cpp', 'gjs/engine.h',
+    'gjs/error-types.cpp',
+    'gjs/global.cpp', 'gjs/global.h',
+    'gjs/importer.cpp', 'gjs/importer.h',
+    'gjs/jsapi-class.h',
+    'gjs/jsapi-dynamic-class.cpp',
+    'gjs/jsapi-util.cpp', 'gjs/jsapi-util.h',
+    'gjs/jsapi-util-args.h',
+    'gjs/jsapi-util-error.cpp',
+    'gjs/jsapi-util-root.h',
+    'gjs/jsapi-util-string.cpp',
+    'gjs/jsapi-wrapper.h',
+    'gjs/mem.cpp', 'gjs/mem-private.h',
+    'gjs/module.cpp', 'gjs/module.h',
+    'gjs/native.cpp', 'gjs/native.h',
+    'gjs/profiler.cpp', 'gjs/profiler-private.h',
+    'gjs/stack.cpp',
+    'modules/console.cpp', 'modules/console.h',
+    'modules/modules.cpp', 'modules/modules.h',
+    'modules/system.cpp', 'modules/system.h',
+    'util/log.cpp', 'util/log.h',
+    'util/misc.cpp', 'util/misc.h',
+]
+
+# GjsPrivate introspection sources
+libgjs_private_sources = [
+    'libgjs-private/gjs-gdbus-wrapper.c', 'libgjs-private/gjs-gdbus-wrapper.h',
+    'libgjs-private/gjs-util.c', 'libgjs-private/gjs-util.h',
+]
+
+module_cairo_srcs = [
+    'modules/cairo-private.h',
+    'modules/cairo-module.h',
+    'modules/cairo-region.cpp',
+    'modules/cairo-context.cpp',
+    'modules/cairo-path.cpp',
+    'modules/cairo-surface.cpp',
+    'modules/cairo-image-surface.cpp',
+    'modules/cairo-ps-surface.cpp',
+    'modules/cairo-pdf-surface.cpp',
+    'modules/cairo-svg-surface.cpp',
+    'modules/cairo-pattern.cpp',
+    'modules/cairo-gradient.cpp',
+    'modules/cairo-linear-gradient.cpp',
+    'modules/cairo-radial-gradient.cpp',
+    'modules/cairo-surface-pattern.cpp',
+    'modules/cairo-solid-pattern.cpp',
+    'modules/cairo.cpp',
+]
+
+module_resource_srcs = gnome.compile_resources('modules-resources',
+    'modules/modules.gresource.xml',
+    c_name: 'modules_resources')
+
+libgjs_dependencies = [glib, gobject, gthread, gio, gi, ffi, spidermonkey,
+    readline]
+pkg_dependencies = [glib, gobject, gthread, gio, gi, ffi, spidermonkey]
+
+if build_cairo
+    libgjs_sources += module_cairo_srcs
+    libgjs_dependencies += [cairo, cairo_gobject]
+    pkg_dependencies += [cairo, cairo_gobject]
+    if cairo_xlib.found()
+        libgjs_dependencies += cairo_xlib
+        pkg_dependencies += cairo_xlib
+    endif
+endif
+
+if build_profiler
+    libgjs_dependencies += profiler_deps
+endif
+
+symbol_map = files('libgjs.map')
+symbol_list = files('libgjs.symbols')
+link_args = cxx.get_supported_link_arguments([
+    '-Wl,--version-script,@0@/@1@'.format(meson.current_source_dir(),
+        symbol_map[0]),
+    '-Wl,-exported_symbols_list,@0@/@1@'.format(meson.current_source_dir(),
+        symbol_list[0]),  # macOS linker
+])
+
+if cxx.has_link_argument('-Wl,-no-undefined')
+    link_args += '-Wl,-no-undefined'
+else
+    # -undefined error is the equivalent of -no-undefined for the macOS linker,
+    # but -undefined would also be understood as a valid argument for GNU ld!
+    link_args += cxx.get_supported_link_arguments('-Wl,-undefined,error')
+endif
+
+libgjs = shared_library(meson.project_name(),
+    libgjs_sources, libgjs_private_sources, module_resource_srcs,
+    probes_header, probes_objfile,
+    cpp_args: ['-DGJS_COMPILATION'] + directory_defines,
+    link_args: link_args, link_depends: [symbol_map, symbol_list],
+    dependencies: libgjs_dependencies,
+    version: '0.0.0', soversion: '0',
+    install: true)
+
+install_headers(gjs_public_headers, subdir: api_name / 'gjs')
+
+# Allow using libgjs as a subproject
+libgjs_dep = declare_dependency(link_with: libgjs,
+    dependencies: libgjs_dependencies, include_directories: top_include)
+
+### Build GjsPrivate introspection library #####################################
+
+gjs_private_gir = gnome.generate_gir(libgjs,
+    includes: ['GObject-2.0', 'Gio-2.0'], sources: libgjs_private_sources,
+    namespace: 'GjsPrivate', nsversion: '1.0', identifier_prefix: 'Gjs',
+    symbol_prefix: 'gjs_', extra_args: '--warn-error', install: true,
+    install_dir_gir: false, install_dir_typelib: pkglibdir / 'girepository-1.0')
+gjs_private_typelib = gjs_private_gir[1]
+
+### Build gjs-console interpreter ##############################################
+
+gjs_console_srcs = ['gjs/console.cpp']
+
+gjs_console = executable('gjs-console', gjs_console_srcs,
+    dependencies: libgjs_dep, install: true)
+
+meson.add_install_script('sh', '-c',
+    'ln -sf gjs-console ${DESTDIR}/${MESON_INSTALL_PREFIX}/@0@/gjs'.format(
+        get_option('bindir')))
+
+### Install data files #########################################################
+
+install_data('installed-tests/extra/gjs.supp',
+    install_dir: get_option('datadir') / api_name / 'valgrind')
+install_data('installed-tests/extra/lsan.supp',
+    install_dir: get_option('datadir') / api_name / 'lsan')
+
+if get_option('installed_tests')
+    install_data('installed-tests/js/org.gnome.GjsTest.gschema.xml',
+        install_dir: get_option('datadir') / 'glib-2.0/schemas')
+    meson.add_install_script('build/compile-gschemas.sh')
+endif
+
+### Generate pkg-config file ###################################################
+
+pkg.generate(libgjs, name: api_name, description: 'JS bindings for GObjects',
+    requires: [glib, gobject, gio], requires_private: pkg_dependencies,
+    subdirs: api_name,
+    variables: [
+        'exec_prefix=${prefix}',
+        'bindir=${exec_prefix}' / get_option('bindir'),
+        'datarootdir=${prefix}' / get_option('datadir'),
+        'datadir=${datarootdir}',
+        'gjs_console=${bindir}/gjs-console',
+    ])
+
+### Test environment ###########################################################
+
+tests_environment = environment()
+js_tests_builddir = meson.current_build_dir() / 'installed-tests' / 'js'
+# GJS_PATH is empty here since we want to force the use of our own
+# resources. G_FILENAME_ENCODING ensures filenames are not UTF-8
+tests_environment.set('TOP_BUILDDIR', meson.build_root())
+tests_environment.set('GJS_USE_UNINSTALLED_FILES', '1')
+tests_environment.set('GJS_PATH', '')
+tests_environment.prepend('GI_TYPELIB_PATH', meson.current_build_dir(),
+    js_tests_builddir)
+tests_environment.prepend('LD_LIBRARY_PATH', meson.current_build_dir(),
+    js_tests_builddir)
+tests_environment.set('G_FILENAME_ENCODING', 'latin1')
+tests_environment.set('LSAN_OPTIONS', 'suppressions=@0@'.format(
+    meson.current_source_dir() / 'installed-tests' / 'extra' / 'lsan.supp'))
+tests_environment.set('NO_AT_BRIDGE', '1')
+tests_environment.set('LC_ALL', tests_locale)
+tests_environment.set('GSETTINGS_SCHEMA_DIR', js_tests_builddir)
+tests_environment.set('G_DEBUG', 'fatal-warnings,fatal-criticals')
+
+if not get_option('skip_gtk_tests')
+    tests_environment.set('ENABLE_GTK', 'yes')
+endif
+
+if get_option('b_coverage')
+    tests_environment.set('GJS_UNIT_COVERAGE_OUTPUT', 'lcov')
+    tests_environment.set('GJS_UNIT_COVERAGE_PREFIX',
+        'resource:///org/gnome/gjs')
+endif
+
+### Tests and test setups ######################################################
+
+subdir('test')
+subdir('installed-tests')
+
+valgrind_environment = environment()
+valgrind_environment.set('G_SLICE', 'always-malloc,debug-blocks')
+valgrind_environment.set('G_DEBUG',
+    'fatal-warnings,fatal-criticals,gc-friendly')
+valgrind_environment.set('VALGRIND', 'valgrind')
+
+glib_suppresssions = (glib.get_pkgconfig_variable('prefix') / 'share' /
+    'glib-2.0' / 'valgrind' / 'glib.supp')
+gjs_suppressions = (meson.current_source_dir() / 'installed-tests' / 'extra' /
+    'gjs.supp')
+valgrind_args = [
+    '--suppressions=@0@'.format(glib_suppresssions),
+    '--suppressions=@0@'.format(gjs_suppressions),
+    '--leak-check=full',
+    '--num-callers=15',
+    '--trace-children=yes',
+    '--trace-children-skip=*basename,*cat,*diff,*echo,*grep,*rm,*sed,*true',
+    '--error-exitcode=1'
+]
+
+add_test_setup('valgrind', timeout_multiplier: 10, env: valgrind_environment,
+    exe_wrapper: ['valgrind'] + valgrind_args)
+
+zeal2_environment = environment()
+zeal2_environment.set('JS_GC_ZEAL', '2,10')
+add_test_setup('extra_gc', timeout_multiplier: 10, env: zeal2_environment)
+
+zeal4_environment = environment()
+zeal4_environment.set('JS_GC_ZEAL', '4')
+add_test_setup('pre_verify', timeout_multiplier: 2, env: zeal4_environment)
+
+zeal11_environment = environment()
+zeal11_environment.set('JS_GC_ZEAL', '11')
+add_test_setup('post_verify', timeout_multiplier: 2, env: zeal11_environment)
+
+### Warn about conditions that may affect runtime ##############################
+
+if gi.version().version_compare('<1.61.2')
+    warning('''You do not have a new enough version of
+gobject-introspection to run the tests. You can still build GJS, but some
+tests will fail.''')
+endif
+
+if tests_locale == 'C'
+    warning('''Your libc does not have the C.UTF-8 locale and no other
+suitable UTF-8 fallback locale could be found. You can still build GJS, but
+some tests will fail.''')
+endif
+
+if get_option('buildtype').startswith('debug') and nondebug_spidermonkey
+    warning('''Your copy of SpiderMonkey is not debug-enabled, but you are
+building a debug or debugoptimized build. This will make development more
+difficult. Consider reconfiguring SpiderMonkey with --enable-debug.''')
+endif
+
+if not build_cairo
+    warning('Building without Cairo support, not all tests will be run.')
+endif
+
+if get_option('skip_gtk_tests')
+    warning('Not using GTK, not all tests will be run.')
+endif
+
+if get_option('skip_dbus_tests')
+    warning('Not using DBus, not all tests will be run.')
+endif
+
+### Summarize options ##########################################################
+
+message('\n'.join([
+    'Optional features',
+    '==========================',
+    'Build Cairo module: @0@'.format(build_cairo),
+    'Use readline for input in interactive shell and debugger: @0@'.format(
+        build_readline),
+    'Build profiler (Linux only): @0@'.format(build_profiler),
+]))
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 00000000..641766b0
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,27 @@
+# Features
+
+option('cairo', type: 'feature', value: 'auto',
+    description: 'Build cairo module')
+option('readline', type: 'feature', value: 'auto',
+    description: 'Use readline for input in interactive shell and debugger')
+option('profiler', type: 'feature', value: 'auto',
+    description: 'Build profiler (Linux only)')
+
+# Flags
+
+option('installed_tests', type: 'boolean', value: true,
+    description: 'Install test programs')
+option('dtrace', type: 'boolean', value: false,
+    description: 'Include dtrace trace support')
+option('systemtap', type: 'boolean', value: false,
+    description: 'Include systemtap trace support (requires -Ddtrace=true)')
+option('bsymbolic_functions', type: 'boolean', value: true,
+    description: 'Link with -Bsymbolic-functions linker flag used to avoid intra-library PLT jumps, if 
supported')
+option('spidermonkey_rtti', type: 'boolean', value: false,
+    description: 'Needs to match SpiderMonkey\'s config option')
+option('skip_dbus_tests', type: 'boolean', value: false,
+    description: 'Skip tests that use a DBus session bus')
+option('skip_gtk_tests', type: 'boolean', value: false,
+    description: 'Skip tests that need a display connection')
+option('verbose_logs', type: 'boolean', value: false,
+    description: 'Enable extra log messages that may decrease performance (not allowed in release builds)')
diff --git a/subprojects/.gitignore b/subprojects/.gitignore
new file mode 100644
index 00000000..08d9fe62
--- /dev/null
+++ b/subprojects/.gitignore
@@ -0,0 +1,5 @@
+glib
+gobject-introspection
+libffi
+proxy-libintl
+zlib
diff --git a/subprojects/glib.wrap b/subprojects/glib.wrap
new file mode 100644
index 00000000..e4de7eed
--- /dev/null
+++ b/subprojects/glib.wrap
@@ -0,0 +1,4 @@
+[wrap-git]
+directory=glib
+url=https://gitlab.gnome.org/GNOME/glib.git
+revision=origin/master
diff --git a/subprojects/gobject-introspection.wrap b/subprojects/gobject-introspection.wrap
new file mode 100644
index 00000000..108b80c8
--- /dev/null
+++ b/subprojects/gobject-introspection.wrap
@@ -0,0 +1,4 @@
+[wrap-git]
+directory=gobject-introspection
+url=https://gitlab.gnome.org/GNOME/gobject-introspection.git
+revision=origin/master
diff --git a/subprojects/libffi.wrap b/subprojects/libffi.wrap
new file mode 100644
index 00000000..6dea9ebe
--- /dev/null
+++ b/subprojects/libffi.wrap
@@ -0,0 +1,4 @@
+[wrap-git]
+directory=libffi
+url=https://gitlab.freedesktop.org/gstreamer/meson-ports/libffi.git
+revision=meson
diff --git a/subprojects/proxy-libintl.wrap b/subprojects/proxy-libintl.wrap
new file mode 100644
index 00000000..b53c8f7c
--- /dev/null
+++ b/subprojects/proxy-libintl.wrap
@@ -0,0 +1,4 @@
+[wrap-git]
+directory=proxy-libintl
+url=https://github.com/frida/proxy-libintl.git
+revision=0.1
diff --git a/subprojects/zlib.wrap b/subprojects/zlib.wrap
new file mode 100644
index 00000000..6aff13ff
--- /dev/null
+++ b/subprojects/zlib.wrap
@@ -0,0 +1,10 @@
+[wrap-file]
+directory = zlib-1.2.11
+
+source_url = https://zlib.net/fossils/zlib-1.2.11.tar.gz
+source_filename = zlib-1.2.11.tar.gz
+source_hash = c3e5e9fdd5004dcb542feda5ee4f0ff0744628baf8ed2dd5d66f8ca1197cb1a1
+
+patch_url = https://wrapdb.mesonbuild.com/v1/projects/zlib/1.2.11/3/get_zip
+patch_filename = zlib-1.2.11-3-wrap.zip
+patch_hash = f07dc491ab3d05daf00632a0591e2ae61b470615b5b73bcf9b3f061fff65cff0
diff --git a/test/meson.build b/test/meson.build
new file mode 100644
index 00000000..de2d7c0e
--- /dev/null
+++ b/test/meson.build
@@ -0,0 +1,22 @@
+### Unit tests #################################################################
+
+mock_js_resources_files = gnome.compile_resources('mock-js-resources',
+    'mock-js-resources.gresource.xml', c_name: 'mock_js_resources',
+    source_dir: '..')
+
+gjs_tests_sources = [
+    'gjs-tests.cpp',
+    'gjs-test-common.cpp', 'gjs-test-common.h',
+    'gjs-test-utils.cpp', 'gjs-test-utils.h',
+    'gjs-test-call-args.cpp',
+    'gjs-test-coverage.cpp',
+    'gjs-test-rooting.cpp',
+]
+
+gjs_tests = executable('gjs-tests', gjs_tests_sources, mock_js_resources_files,
+    cpp_args: ['-DGJS_COMPILATION'] + directory_defines,
+    include_directories: top_include, dependencies: libgjs_dep)
+
+test('API tests', gjs_tests, args: ['--tap', '--keep-going', '--verbose'],
+    depends: gjs_private_typelib, env: tests_environment, protocol: 'tap',
+    suite: 'C')
diff --git a/tools/lcovrc b/tools/lcovrc
new file mode 100644
index 00000000..cc5da987
--- /dev/null
+++ b/tools/lcovrc
@@ -0,0 +1,14 @@
+# lcov and genhtml configuration
+# See http://ltp.sourceforge.net/coverage/lcov/lcovrc.5.php
+# Adapted from GLib's lcovrc
+
+# Always enable branch coverage
+lcov_branch_coverage = 1
+
+# Exclude precondition assertions, as we can never reasonably get full branch
+# coverage of them, as they should never normally fail.
+# See https://github.com/linux-test-project/lcov/issues/44
+lcov_excl_br_line = LCOV_EXCL_BR_LINE|g_return_if_fail|g_return_val_if_fail|g_assert|g_assert_
+
+# Similarly for unreachable assertions.
+lcov_excl_line = LCOV_EXCL_LINE|g_return_if_reached|g_return_val_if_reached|g_assert_not_reached
diff --git a/tools/run_coverage.sh b/tools/run_coverage.sh
new file mode 100755
index 00000000..16ee691e
--- /dev/null
+++ b/tools/run_coverage.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+SOURCEDIR=$(pwd)
+GIDATADIR=$(pkg-config --variable=gidatadir gobject-introspection-1.0)
+
+BUILDDIR="$(pwd)/_coverage_build"
+LCOV_ARGS="--config-file $SOURCEDIR/tools/lcovrc"
+GENHTML_ARGS='--legend --show-details --branch-coverage'
+IGNORE="*/gjs/test/* *-resources.c *minijasmine.cpp"
+
+rm -rf "$BUILDDIR"
+meson "$BUILDDIR" -Db_coverage=true
+ninja -C "$BUILDDIR"
+mkdir -p _coverage
+ninja -C "$BUILDDIR" test
+lcov --directory "$BUILDDIR" --capture --output-file _coverage/gjs.lcov.run --no-checksum $LCOV_ARGS
+lcov --extract _coverage/gjs.lcov.run "$SOURCEDIR/*" "$GIDATADIR/tests/*" $LCOV_ARGS -o 
_coverage/gjs.lcov.sources
+lcov --remove _coverage/gjs.lcov.sources $IGNORE $LCOV_ARGS -o _coverage/gjs.lcov
+genhtml --prefix "$BUILDDIR/lcov/org/gnome/gjs" --prefix "$BUILDDIR" --prefix "$SOURCEDIR" --prefix 
"$GIDATADIR" --output-directory _coverage/html --title "gjs-x.y.z Code Coverage" $GENHTML_ARGS 
_coverage/gjs.lcov "$BUILDDIR"/lcov/coverage.lcov



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]