[glibmm/kjellahl/meson-build-master] Add support for building glibmm with Meson



commit d378578484718d267bf429ef2e6eded695446b46
Author: Kjell Ahlstedt <kjellahlstedt gmail com>
Date:   Sun Mar 1 13:30:00 2020 +0100

    Add support for building glibmm with Meson
    
    glibmm can be built with either Autotools or Meson.
    
    See MR !27

 MSVC_NMake/gendef/meson.build                      |   9 +
 MSVC_NMake/giomm/meson.build                       |  17 +
 MSVC_NMake/glibmm/meson.build                      |  17 +
 docs/reference/meson.build                         | 170 +++++++++
 examples/meson.build                               |  64 ++++
 gio/giomm/meson.build                              | 418 +++++++++++++++++++++
 gio/giommconfig.h.meson                            |  40 ++
 gio/meson.build                                    |  29 ++
 glib/glibmm/meson.build                            | 373 ++++++++++++++++++
 glib/glibmmconfig.h.meson                          | 125 ++++++
 glib/meson.build                                   | 103 +++++
 meson.build                                        | 314 ++++++++++++++++
 meson_options.txt                                  |  12 +
 tests/meson.build                                  |  62 +++
 tools/build_scripts/compile-schemas.py             |  30 ++
 tools/build_scripts/dummy-header.py                |  15 +
 tools/build_scripts/handle-built-files.py          | 182 +++++++++
 tools/conf_tests/allows_static_inline_npos.cc      |  21 ++
 ...assign_non_extern_c_functions_to_extern_c_cb.cc |  22 ++
 ...n_use_dynamic_cast_in_unused_template_wo_def.cc |  21 ++
 ..._disambiguous_const_template_specializations.cc |  37 ++
 tools/conf_tests/have_std_iterator_traits.cc       |  11 +
 tools/conf_tests/have_sun_reverse_iterator.cc      |  11 +
 tools/conf_tests/have_template_sequence_ctors.cc   |  17 +
 tools/conf_tests/have_wide_stream.cc               |  12 +
 tools/extra_defs_gen/meson.build                   |  27 ++
 tools/meson.build                                  | 100 +++++
 untracked/README                                   |  39 ++
 28 files changed, 2298 insertions(+)
---
diff --git a/MSVC_NMake/gendef/meson.build b/MSVC_NMake/gendef/meson.build
new file mode 100644
index 00000000..3dc9cc25
--- /dev/null
+++ b/MSVC_NMake/gendef/meson.build
@@ -0,0 +1,9 @@
+# MSVC_NMake/gendef
+
+# Input: is_msvc
+# Output: gendef
+
+# Used to generate the .def file required to obtain the import .lib file
+if is_msvc
+  gendef = executable('gendef', 'gendef.cc', install: false)
+endif
diff --git a/MSVC_NMake/giomm/meson.build b/MSVC_NMake/giomm/meson.build
new file mode 100644
index 00000000..658147df
--- /dev/null
+++ b/MSVC_NMake/giomm/meson.build
@@ -0,0 +1,17 @@
+# MSVC_NMake/giomm
+
+# Input: pkg_conf_data, giommconfig_h
+# Output: giomm_rc
+
+giomm_rc = configure_file(
+  input: 'giomm.rc.in',
+  output: '@BASENAME@',
+  configuration: pkg_conf_data,
+)
+
+# Copy the generated configuration header into the MSVC project directory.
+configure_file(
+  input: giommconfig_h,
+  output: 'giommconfig.h',
+  copy: true,
+)
diff --git a/MSVC_NMake/glibmm/meson.build b/MSVC_NMake/glibmm/meson.build
new file mode 100644
index 00000000..5112281c
--- /dev/null
+++ b/MSVC_NMake/glibmm/meson.build
@@ -0,0 +1,17 @@
+# MSVC_NMake/glibmm
+
+# Input: pkg_conf_data, glibmmconfig_h
+# Output: glibmm_rc
+
+glibmm_rc = configure_file(
+  input: 'glibmm.rc.in',
+  output: '@BASENAME@',
+  configuration: pkg_conf_data,
+)
+
+# Copy the generated configuration header into the MSVC project directory.
+configure_file(
+  input: glibmmconfig_h,
+  output: 'glibmmconfig.h',
+  copy: true,
+)
diff --git a/docs/reference/meson.build b/docs/reference/meson.build
new file mode 100644
index 00000000..029a61cf
--- /dev/null
+++ b/docs/reference/meson.build
@@ -0,0 +1,170 @@
+# docs/reference
+
+# Input: built_files_root, project_source_root, glibmm_pcname, giomm_pcname,
+#        perl, glibmm_hg_ccg_basenames, giomm_hg_ccg_basenames,
+#        glibmm_extra_h_files, giomm_extra_h_files, glibmm_built_h_file_targets,
+#        giomm_built_h_file_targets, install_datadir,python3, doc_reference_py,
+#        build_documentation
+# Output: install_docdir, install_devhelpdir
+
+tag_file_modules = [
+  'mm-common-libstdc++',
+  'sigc++-3.0',
+]
+doxygen_tagfiles = ''
+docinstall_flags = []
+foreach module : tag_file_modules
+  depmod = dependency(module, required: false)
+  if depmod.found()
+    doxytagfile = depmod.get_pkgconfig_variable('doxytagfile')
+    htmlrefpub = depmod.get_pkgconfig_variable('htmlrefpub', default: '')
+    htmlrefdir = depmod.get_pkgconfig_variable('htmlrefdir', default: '')
+    if htmlrefpub == ''
+      htmlrefpub = htmlrefdir
+    elif htmlrefdir == ''
+      htmlrefdir = htmlrefpub
+    endif
+    doxygen_tagfiles += ' "' + doxytagfile + '=' + htmlrefpub + '"'
+    if not htmlrefdir.endswith('/')
+      htmlrefdir += '/'
+    endif
+    docinstall_flags += ['-l', doxytagfile.split('/')[-1] + '@' + htmlrefdir]
+  endif
+endforeach
+
+book_name = glibmm_pcname
+book_title = meson.project_name() + ' Reference Manual'
+
+# Configuration data for Doxyfile.
+doc_conf_data = configuration_data()
+doc_conf_data.set('configure_input',
+  'docs/reference/Doxyfile. Generated from Doxyfile.in by meson.configure_file().')
+doc_conf_data.set('PACKAGE_NAME', meson.project_name())
+doc_conf_data.set('PACKAGE_VERSION', meson.project_version())
+doc_conf_data.set('abs_top_builddir', built_files_root)
+doc_conf_data.set('abs_top_srcdir', project_source_root)
+doc_conf_data.set('GLIBMM_MODULE_NAME', book_name)
+doc_conf_data.set('DOXYGEN_TAGFILES', doxygen_tagfiles)
+doc_conf_data.set('PERL', perl.found() ? perl.path() : '')
+
+configure_file(
+  input: 'Doxyfile.in',
+  output: '@BASENAME@',
+  configuration: doc_conf_data,
+)
+
+# Installation directories relative to {prefix}.
+install_docdir = install_datadir / 'doc' / book_name
+install_reference_docdir = install_docdir / 'reference'
+install_image_docdir = install_docdir / 'images'
+install_devhelpdir = install_datadir / 'devhelp' / 'books' / book_name
+
+if not build_documentation
+  # Documentation shall not be built or installed.
+  # Return to the calling meson.build file.
+  subdir_done()
+endif
+
+# Built input .h files to Doxygen.
+built_h_files = []
+foreach file : glibmm_hg_ccg_basenames
+  built_h_files += built_files_root / 'glib' / 'glibmm' / file + '.h'
+endforeach
+foreach file : giomm_hg_ccg_basenames
+  built_h_files += built_files_root / 'gio' / 'giomm' / file + '.h'
+endforeach
+
+# Hand-coded input .h files to Doxygen.
+src_h_files = []
+foreach file : glibmm_extra_h_files
+  if file != 'wrap_init.h'
+    src_h_files += project_source_root / 'glib' / 'glibmm' / file
+  endif
+endforeach
+foreach file : giomm_extra_h_files
+  if file != 'wrap_init.h'
+    src_h_files += project_source_root / 'gio' / 'giomm' / file
+  endif
+endforeach
+src_h_files += project_source_root / 'glib' / 'glibmm.h'
+src_h_files += project_source_root / 'gio' / 'giomm.h'
+
+doctool_dir = project_source_root / 'untracked' / 'docs' # MMDOCTOOLDIR
+doctool_dist_dir = 'untracked' / 'docs' # Relative to MESON_DIST_ROOT
+
+doc_h_files = src_h_files
+if glibmm_built_h_file_targets.length() + giomm_built_h_file_targets.length() > 0
+  # .h files have been generated from .hg files (maintainer mode).
+  # Use built_h_file_targets instead of built_h_files here, or else Meson won't
+  # know that Doxygen must not be executed until the .h files have been built.
+  doc_h_files += glibmm_built_h_file_targets + giomm_built_h_file_targets
+else
+  # All .h files are stored in the source tree (not maintainer mode).
+  doc_h_files += built_h_files
+endif
+
+# Can't use @INPUT@ in the command. It requires absolute file paths.
+# Paths in built_h_file_targets are relative to project_build_root.
+tag_file = custom_target('html_and_tag',
+  input: doc_h_files,
+  output: book_name + '.tag',
+  command: [
+    python3, doc_reference_py, 'doxygen',
+    doctool_dir,
+    '@OUTPUT@',
+    src_h_files,
+    built_h_files,
+  ],
+  build_by_default: build_documentation,
+  install: true,
+  install_dir: install_reference_docdir,
+)
+
+devhelp_file = custom_target('devhelp',
+  input: tag_file,
+  output: book_name + '.devhelp2',
+  command: [
+    python3, doc_reference_py, 'devhelp',
+    doctool_dir,
+    '@INPUT@',
+    '@OUTPUT@',
+    book_name,
+    book_title,
+  ],
+  build_by_default: build_documentation,
+)
+
+# Install Devhelp file and html files.
+meson.add_install_script(
+  python3.path(), doc_reference_py, 'install_doc',
+  doctool_dir,
+  devhelp_file.full_path(),
+  install_devhelpdir,
+  install_reference_docdir / 'html',
+  docinstall_flags
+)
+
+# Install images.
+image_basefiles = [
+  'gtkmm_logo.gif',
+  'top.gif',
+]
+image_files = []
+foreach file : image_basefiles
+  image_files += '..' / 'images' / file
+endforeach
+
+install_data(image_files, install_dir: install_image_docdir)
+
+if not meson.is_subproject()
+  # Distribute built files and files copied by mm-common-get.
+  # (add_dist_script() is not allowed in a subproject)
+  meson.add_dist_script(
+    python3.path(), doc_reference_py, 'dist_doc',
+    doctool_dir,
+    doctool_dist_dir,
+    meson.current_build_dir(),
+    tag_file.full_path(),
+    devhelp_file.full_path(),
+  )
+endif
diff --git a/examples/meson.build b/examples/meson.build
new file mode 100644
index 00000000..73f2400d
--- /dev/null
+++ b/examples/meson.build
@@ -0,0 +1,64 @@
+# examples
+
+# input: glibmm_dep, giomm_dep, build_examples, compile_schemas_py
+
+examples = [
+# [[dir-name], exe-name, [sources], giomm-example (not just glibmm-example)]
+  [['child_watch'], 'child_watch', ['main.cc'], false],
+  [['compose'], 'example', ['main.cc'], false],
+  [['dbus'], 'session_bus_service', ['session_bus_service.cc'], true],
+  [['dbus'], 'server_without_bus', ['server_without_bus.cc'], true],
+  [['dbus'], 'client_bus_listnames', ['client_bus_listnames.cc'], true],
+  [['iochannel_stream'], 'example', ['fdstream.cc', 'main.cc'], false],
+  [['keyfile'], 'example', ['main.cc'], false],
+  [['markup'], 'parser', ['parser.cc'], false],
+  [['network'], 'resolver', ['resolver.cc'], true],
+  [['network'], 'socket-client', ['socket-client.cc'], true],
+  [['network'], 'socket-server', ['socket-server.cc'], true],
+  [['options'], 'example', ['main.cc'], false],
+  [['properties'], 'example', ['properties_example.cc'], false],
+  [['regex'], 'example', ['main.cc'], false],
+  [['settings'], 'settings', ['settings.cc', 'org.gtkmm.demo.gschema.xml'], true],
+  [['thread'], 'dispatcher', ['dispatcher.cc'], false],
+  [['thread'], 'dispatcher2', ['dispatcher2.cc'], false],
+]
+
+# import('gnome').compile_schemas() can't be use here.
+# It can only compile schemas in the current directory.
+glib_compile_schemas = find_program('glib-compile-schemas', required: false)
+
+foreach ex : examples
+  dir = ''
+  foreach dir_part : ex[0]
+    dir = dir / dir_part
+  endforeach
+  ex_name = (dir / ex[1]).underscorify()
+  ex_sources = []
+  foreach src : ex[2]
+    if src.endswith('.gschema.xml')
+      if glib_compile_schemas.found()
+        custom_target(dir.underscorify() + '_schemas',
+          input: dir / src,
+          output: dir.underscorify() + '_gschemas.compiled',
+          command: [
+            python3, compile_schemas_py,
+            meson.current_source_dir() / dir,
+            meson.current_build_dir() / dir,
+            '@OUTPUT@'
+          ],
+          build_by_default: build_examples,
+          install: false,
+        )
+      endif
+    else
+      ex_sources += dir / src
+    endif
+  endforeach
+
+  executable(ex_name, ex_sources,
+    dependencies: ex[3] ? giomm_dep : glibmm_dep,
+    gui_app: false,
+    build_by_default: build_examples,
+    install: false,
+  )
+endforeach
diff --git a/gio/giomm/meson.build b/gio/giomm/meson.build
new file mode 100644
index 00000000..4029864c
--- /dev/null
+++ b/gio/giomm/meson.build
@@ -0,0 +1,418 @@
+# gio/giomm
+
+# Input: giomm_build_dep, giomm_pcname, maintainer_mode, project_source_root,
+#        generate_binding_py, handle_built_files_py, m4_files, pm_files,
+#        glibmm_libversion, install_includedir, python3, giomm_rc, gmmproc_dir,
+#        is_host_windows, gendef
+# Output: giomm_hg_ccg_basenames, giomm_extra_h_files, built_files_root,
+#         giomm_built_h_file_targets, giomm_dep
+
+giomm_defs_basefiles = [
+  'gio.defs',
+  'gio_enums.defs',
+  'gio_methods.defs',
+  'gio_signals.defs',
+  'gio_extra_objects.defs',
+  'gio_vfuncs.defs',
+  'gio_docs.xml',
+  'gio_docs_override.xml',
+]
+
+giomm_defs_files = []
+foreach file : giomm_defs_basefiles
+  giomm_defs_files += '..' / 'src' / file
+endforeach
+
+# Generated from pairs of .hg and .ccg files.
+giomm_any_hg_ccg_basenames = [
+  'action',
+  'actiongroup',
+  'actionmap',
+  'applaunchcontext',
+  'appinfo',
+  'application',
+  'applicationcommandline',
+  'asyncinitable',
+  'asyncresult',
+  'bufferedinputstream',
+  'bufferedoutputstream',
+  'cancellable',
+  'charsetconverter',
+  'converter',
+  'converterinputstream',
+  'converteroutputstream',
+  'credentials',
+  'datainputstream',
+  'dataoutputstream',
+  'dbusactiongroup',
+  'dbusaddress',
+  'dbusauthobserver',
+  'dbusconnection',
+  'dbuserror',
+  'dbuserrorutils',
+  'dbusinterface',
+  'dbusinterfaceskeleton',
+  'dbusinterfacevtable',
+  'dbusintrospection',
+  'dbusmenumodel',
+  'dbusmessage',
+  'dbusmethodinvocation',
+  'dbusobject',
+  'dbusobjectmanager',
+  'dbusobjectmanagerclient',
+  'dbusobjectmanagerserver',
+  'dbusobjectproxy',
+  'dbusobjectskeleton',
+  'dbusownname',
+  'dbusproxy',
+  'dbusserver',
+  'dbussubtreevtable',
+  'dbusutils',
+  'dbuswatchname',
+  'drive',
+  'emblem',
+  'emblemedicon',
+  'enums',
+  'error',
+  'file',
+  'fileattributeinfo',
+  'fileattributeinfolist',
+  'fileenumerator',
+  'fileicon',
+  'fileinfo',
+  'fileinputstream',
+  'fileiostream',
+  'filemonitor',
+  'filenamecompleter',
+  'fileoutputstream',
+  'filterinputstream',
+  'filteroutputstream',
+  'icon',
+  'inetaddress',
+  'inetsocketaddress',
+  'initable',
+  'inputstream',
+  'iostream',
+  'listmodel',
+  'liststore',
+  'loadableicon',
+  'memoryinputstream',
+  'memoryoutputstream',
+  'menuattributeiter',
+  'menulinkiter',
+  'menu',
+  'menuitem',
+  'menumodel',
+  'mount',
+  'mountoperation',
+  'networkaddress',
+  'networkmonitor',
+  'networkservice',
+  'notification',
+  'outputstream',
+  'permission',
+  'pollableinputstream',
+  'pollableoutputstream',
+  'propertyaction',
+  'proxy',
+  'proxyaddress',
+  'proxyresolver',
+  'remoteactiongroup',
+  'resolver',
+  'resource',
+  'seekable',
+  'settings',
+  'settingsschema',
+  'settingsschemakey',
+  'settingsschemasource',
+  'simpleaction',
+  'simpleactiongroup',
+  'simpleiostream',
+  'simplepermission',
+  'socket',
+  'socketaddress',
+  'socketaddressenumerator',
+  'socketclient',
+  'socketconnectable',
+  'socketconnection',
+  'socketcontrolmessage',
+  'socketlistener',
+  'socketservice',
+  'srvtarget',
+  'tcpconnection',
+  'tcpwrapperconnection',
+  'threadedsocketservice',
+  'themedicon',
+  'tlscertificate',
+  'tlsclientconnection',
+  'tlsconnection',
+  'tlsdatabase',
+  'tlsinteraction',
+  'tlspassword',
+  'tlsserverconnection',
+  'volume',
+  'volumemonitor',
+  'zlibdecompressor',
+  'zlibcompressor',
+]
+
+giomm_posix_hg_ccg_basenames = [
+  'filedescriptorbased',
+  'unixconnection',
+  'unixcredentialsmessage',
+  'unixfdlist',
+  'unixfdmessage',
+  'unixinputstream',
+  'unixoutputstream',
+  'unixsocketaddress',
+]
+
+giomm_not_mac_hg_ccg_basenames = [
+  'desktopappinfo',
+]
+
+# All .hg/.ccg files, regardless of type of host.
+giomm_hg_ccg_basenames = \
+  giomm_any_hg_ccg_basenames + \
+  giomm_posix_hg_ccg_basenames + \
+  giomm_not_mac_hg_ccg_basenames
+
+# Used .hg/.ccg files in present type of host.
+giomm_used_hg_ccg_basenames = giomm_any_hg_ccg_basenames
+if not is_host_windows
+  giomm_used_hg_ccg_basenames += giomm_posix_hg_ccg_basenames
+  if not is_os_cocoa
+    giomm_used_hg_ccg_basenames += giomm_not_mac_hg_ccg_basenames
+  endif
+endif
+
+# Pairs of hand-coded .h and .cc files.
+giomm_extra_h_cc_basenames = [
+  'contenttype',
+  'init',
+  'slot_async',
+  'socketsource',
+]
+
+giomm_extra_h_files = [
+  'wrap_init.h',
+]
+
+giomm_extra_cc_files = []
+
+foreach file : giomm_extra_h_cc_basenames
+  giomm_extra_h_files += file + '.h'
+  giomm_extra_cc_files += file + '.cc'
+endforeach
+
+install_headers('..' / 'giomm.h', subdir: giomm_pcname)
+install_headers(giomm_extra_h_files, subdir: giomm_pcname / 'giomm')
+
+untracked_giomm = 'untracked' / 'gio' / 'giomm'
+src_untracked_giomm = project_source_root / untracked_giomm
+
+if maintainer_mode
+
+  # Maintainer mode. Generate .h and .cc files from .hg and .ccg files in ../src.
+
+  # docs/reference/meson.build needs these.
+  built_files_root = project_build_root
+  giomm_built_h_file_targets = []
+
+  # Force meson+ninja to generate source files before anything is compiled.
+  # Compilation must depend on these targets.
+  giomm_used_built_cc_file_targets = []
+  giomm_used_built_h_file_targets = []
+
+  hg_files = []
+  foreach file : giomm_hg_ccg_basenames
+    hg_files += '..' / 'src' / file + '.hg'
+  endforeach
+
+  # Create wrap_init.cc in project_build_root/gio/giomm.
+  giomm_used_built_cc_file_targets += custom_target('giomm-wrap_init.cc',
+    input: hg_files,
+    output: 'wrap_init.cc',
+    command: [
+      python3, generate_binding_py, 'generate_wrap_init',
+      gmmproc_dir,
+      '@OUTPUT@',
+      'Gio', # namespace
+      '@INPUT@',
+    ],
+    build_by_default: maintainer_mode,
+    install: false,
+  )
+
+  # Create .h/_p.h/.cc files in project_build_root/gio/giomm
+  # from .hg/.ccg files in project_source_root/gio/src.
+  foreach file : giomm_hg_ccg_basenames
+    hg_file = '..' / 'src' / file + '.hg'
+    ccg_file = '..' / 'src' / file + '.ccg'
+    built_file_target = custom_target('giomm-' + file + '.cc',
+      input: [hg_file, ccg_file],
+      output: [file + '.stamp', file + '.cc', file + '.h'],
+      command: [
+        python3, handle_built_files_py, 'gmmproc',
+        gmmproc_dir,
+        project_source_root / 'tools' / 'pm',
+        '@OUTPUT0@',
+        file,
+        meson.current_source_dir() / '..' / 'src',
+        project_source_root / 'tools' / 'm4',
+      ],
+      depend_files: giomm_defs_files + m4_files + pm_files,
+      build_by_default: maintainer_mode,
+      install: false,
+    )
+    giomm_built_h_file_targets += built_file_target[2]
+    if giomm_used_hg_ccg_basenames.contains(file)
+      giomm_used_built_cc_file_targets += built_file_target[1]
+      giomm_used_built_h_file_targets += built_file_target[2]
+    endif
+  endforeach
+
+  # Create dummy_header.h, depending on all generated headers.
+  # It's created if it does not exist, but it's never updated.
+  # It guarantees that all generated headers are built before giomm_library
+  # is built, at the same time avoiding unnecessary recompilations.
+  # If giomm_used_built_h_file_targets would be listed as sources to giomm_library,
+  # all generated .cc files could be recompiled if one generated .h file has
+  # been changed.
+  built_dummy_h_file_target = custom_target('giomm-dummy_header.h',
+    input: giomm_used_built_h_file_targets,
+    output: 'dummy_header.h',
+    command: [
+      python3, dummy_header_py,
+      '@OUTPUT@',
+    ],
+    build_by_default: maintainer_mode,
+    install: false,
+  )
+
+  extra_include_dirs = ['..', '..' / '..' / 'glib']
+  giomm_library = library(giomm_pcname,
+    giomm_used_built_cc_file_targets, giomm_extra_cc_files, built_dummy_h_file_target,
+    version: glibmm_libversion,
+    include_directories: extra_include_dirs,
+    cpp_args: '-DGIOMM_BUILD=1',
+    dependencies: giomm_build_dep,
+    link_with: glibmm_library,
+    install: true,
+  )
+
+  built_h_cc_dir = meson.current_build_dir()
+
+else # not maintainer_mode
+
+  # Not maintainer mode. Compile built source code files in
+  # project_source_root/untracked/gio/giomm.
+
+  giomm_used_built_h_file_targets = []
+
+  # docs/reference/meson.build needs these.
+  built_files_root = project_source_root / 'untracked'
+  giomm_built_h_file_targets = []
+
+  # Two cases:
+  # 1. The source code comes from a tarball, where the built files
+  #    are stored in project_source_root/untracked.
+  #    There are no built files in the build tree.
+  # 2. Files have been built in the build tree. Then maintainer_mode has
+  #    been changed from true to false. Files that are missing or not up to date
+  #    in project_source_root/untracked are copied from the build tree.
+
+  # Try to copy built source code files to the source tree.
+  run_command(
+    python3, generate_binding_py, 'copy_built_files',
+    meson.current_build_dir(),
+    src_untracked_giomm,
+    giomm_hg_ccg_basenames,
+  )
+
+  built_cc_files = [ src_untracked_giomm / 'wrap_init.cc' ]
+  foreach file : giomm_used_hg_ccg_basenames
+    built_cc_files += src_untracked_giomm / file + '.cc'
+  endforeach
+
+  extra_include_dirs = [ '..', '..' / '..' / 'untracked' / 'gio',
+         '..' / '..' / 'glib', '..' / '..' / 'untracked' / 'glib',
+  ]
+
+  # We need this so that we can run gendef.exe to get the .def file
+  # needed for obtaining the .lib file for the giomm DLL
+  gio_int_lib = static_library('giomm-int',
+    built_cc_files, giomm_extra_cc_files,
+    include_directories: extra_include_dirs,
+    cpp_args: '-DGIOMM_BUILD=1',
+    dependencies: giomm_build_dep,
+    link_with: glibmm_library,
+    install: false,
+  )
+
+  giomm_def = []
+  giomm_extra_link_args = []
+  extra_giomm_objects = []
+
+  if is_msvc
+    giomm_def = custom_target('giomm.def',
+      output: 'giomm.def',
+      depends: gio_int_lib,
+      command: [ gendef,
+        '@OUTPUT@',
+        '@0@-@1@.dll'.format(giomm_pcname, glibmm_libversion.split('.')[0]),
+        gio_int_lib.full_path(),
+      ],
+      install: false,
+    )
+    giomm_extra_link_args = ['/def:@0@'.format(giomm_def.full_path())]
+  endif
+
+  # Build the .rc file for Windows builds and link to it
+  if is_host_windows
+    windows = import('windows')
+    giomm_res = windows.compile_resources(giomm_rc)
+    extra_giomm_objects += giomm_res
+  endif
+
+  giomm_library = library(giomm_pcname, extra_giomm_objects,
+    objects: gio_int_lib.extract_all_objects(),
+    version: glibmm_libversion,
+    dependencies: giomm_build_dep,
+    link_depends: giomm_def,
+    link_args: giomm_extra_link_args,
+    link_with: glibmm_library,
+    install: true,
+  )
+
+  built_h_cc_dir = src_untracked_giomm
+
+endif
+
+# Install built .h and _p.h files.
+meson.add_install_script(
+  python3.path(), generate_binding_py, 'install_built_h_files',
+  built_h_cc_dir,
+  install_includedir / giomm_pcname / 'giomm', # subdir below {prefix}
+  giomm_used_hg_ccg_basenames
+)
+
+if not meson.is_subproject()
+  # Distribute built files.
+  # (add_dist_script() is not allowed in a subproject)
+  meson.add_dist_script(
+    python3.path(), generate_binding_py, 'dist_built_files',
+    built_h_cc_dir,
+    untracked_giomm,
+    giomm_hg_ccg_basenames,
+  )
+endif
+
+# This is useful in the main project when giomm is used as a subproject.
+# It's also used when building example programs and test programs.
+giomm_dep = declare_dependency(
+  sources: glibmm_built_h_file_targets + giomm_used_built_h_file_targets,
+  link_with: [glibmm_library, giomm_library],
+  include_directories: extra_include_dirs,
+  dependencies: giomm_build_dep,
+)
diff --git a/gio/giommconfig.h.meson b/gio/giommconfig.h.meson
new file mode 100644
index 00000000..82aedddf
--- /dev/null
+++ b/gio/giommconfig.h.meson
@@ -0,0 +1,40 @@
+#ifndef _GIOMM_CONFIG_H
+#define _GIOMM_CONFIG_H
+
+#include <glibmmconfig.h>
+
+/* Define to omit deprecated API from the library. */
+#mesondefine GIOMM_DISABLE_DEPRECATED
+
+/* Major version number of giomm. */
+#mesondefine GIOMM_MAJOR_VERSION
+
+/* Minor version number of giomm. */
+#mesondefine GIOMM_MINOR_VERSION
+
+/* Micro version number of giomm. */
+#mesondefine GIOMM_MICRO_VERSION
+
+/* Define if giomm is built as a static library */
+#mesondefine GIOMM_STATIC_LIB
+
+// Enable DLL-specific stuff only when not building a static library
+#if !defined(__CYGWIN__) && defined(__MINGW32__) && !defined(GIOMM_STATIC_LIB)
+# define GIOMM_DLL 1
+#endif
+
+#ifdef GIOMM_DLL
+# if defined(GIOMM_BUILD) && defined(_WINDLL)
+   /* Do not dllexport as it is handled by gendef on MSVC */
+#  define GIOMM_API
+# elif !defined(GIOMM_BUILD)
+#  define GIOMM_API __declspec(dllimport)
+# else
+   /* Build a static library */
+#  define GIOMM_API
+# endif /* GIOMM_BUILD - _WINDLL */
+#else
+# define GIOMM_API
+#endif /* GIOMM_DLL */
+
+#endif /* _GIOMM_CONFIG_H */
diff --git a/gio/meson.build b/gio/meson.build
new file mode 100644
index 00000000..4213109f
--- /dev/null
+++ b/gio/meson.build
@@ -0,0 +1,29 @@
+# gio
+
+# Input: pkg_conf_data, giomm_pcname, install_pkgconfigdir,
+# Output: install_giommconfigdir, giommconfig_h
+
+configure_file(
+  input: 'giomm.pc.in',
+  output: giomm_pcname + '.pc',
+  configuration: pkg_conf_data,
+  install_dir: install_pkgconfigdir,
+)
+
+giomm_pkg_uninst_conf_data = configuration_data()
+giomm_pkg_uninst_conf_data.merge_from(pkg_conf_data)
+giomm_pkg_uninst_conf_data.set('srcdir', meson.current_source_dir())
+
+configure_file(
+  input: 'giomm-uninstalled.pc.in',
+  output: giomm_pcname + '-uninstalled.pc',
+  configuration: giomm_pkg_uninst_conf_data,
+)
+
+install_giommconfigdir = install_libdir / giomm_pcname / 'include'
+giommconfig_h = configure_file(
+  input: 'giommconfig.h.meson',
+  output: 'giommconfig.h',
+  configuration: pkg_conf_data,
+  install_dir: install_giommconfigdir,
+)
diff --git a/glib/glibmm/meson.build b/glib/glibmm/meson.build
new file mode 100644
index 00000000..29acfdac
--- /dev/null
+++ b/glib/glibmm/meson.build
@@ -0,0 +1,373 @@
+# glib/glibmm
+
+# Input: glibmm_build_dep, glibmm_pcname, maintainer_mode, project_source_root,
+#        generate_binding_py, handle_built_files_py, m4_files, pm_files,
+#        glibmm_libversion, install_includedir, python3, glibmm_rc, gmmproc_dir,
+#        is_host_windows, gendef
+# Output: glibmm_hg_ccg_basenames, glibmm_extra_h_files, built_files_root,
+#         glibmm_built_h_file_targets, glibmm_dep
+
+glibmm_defs_basefiles = [
+  'glib.defs',
+  'glib_enums.defs',
+  'glib_functions.defs',
+  'glib_signals.defs',
+  'glib_extra_objects.defs',
+  'gmodule_enums.defs',
+  'gmodule_functions.defs',
+  'gobject_enums.defs',
+  'gobject_functions.defs',
+  'glib_docs.xml',
+  'glib_docs_override.xml',
+]
+
+glibmm_defs_files = []
+foreach file : glibmm_defs_basefiles
+  glibmm_defs_files += '..' / 'src' / file
+endforeach
+
+# Generated from pairs of .hg and .ccg files.
+glibmm_hg_ccg_basenames = [
+  'balancedtree',
+  'binding',
+  'bytes',
+  'bytearray',
+  'checksum',
+  'convert',
+  'date',
+  'datetime',
+  'enums',
+  'fileutils',
+  'iochannel',
+  'keyfile',
+  'markup',
+  'miscutils',
+  'module',
+  'nodetree',
+  'optioncontext',
+  'optionentry',
+  'optiongroup',
+  'regex',
+  'shell',
+  'spawn',
+  'timezone',
+  'unicode',
+  'uriutils',
+  'variant',
+  'variantdict',
+  'variantiter',
+  'varianttype',
+]
+
+# Generated from .m4 files.
+glibmm_h_m4_files = [
+  'value_basictypes.h',
+  'variant_basictypes.h',
+]
+
+glibmm_cc_m4_files = [
+  'value_basictypes.cc',
+  'variant_basictypes.cc',
+]
+
+# Pairs of hand-coded .h and .cc files.
+glibmm_extra_h_cc_basenames = [
+  'base64',
+  'class',
+  'debug',
+  'dispatcher',
+  'error',
+  'exceptionhandler',
+  'extraclassinit',
+  'init',
+  'interface',
+  'main',
+  'object',
+  'objectbase',
+  'pattern',
+  'property',
+  'propertyproxy',
+  'propertyproxy_base',
+  'quark',
+  'random',
+  'signalproxy',
+  'signalproxy_connectionnode',
+  'stringutils',
+  'timer',
+  'ustring',
+  'utility',
+  'value',
+  'value_custom',
+  'variantdbusstring',
+  'vectorutils',
+  'wrap',
+]
+
+glibmm_extra_h_files = [
+  'containerhandle_shared.h',
+  'i18n-lib.h',
+  'i18n.h',
+  'priorities.h',
+  'refptr.h',
+  'wrap_init.h',
+]
+
+glibmm_extra_ph_files = [
+  'private' / 'interface_p.h',
+  'private' / 'object_p.h',
+]
+
+glibmm_extra_cc_files = []
+
+foreach file : glibmm_extra_h_cc_basenames
+  glibmm_extra_h_files += file + '.h'
+  glibmm_extra_cc_files += file + '.cc'
+endforeach
+
+install_headers('..' / 'glibmm.h', subdir: glibmm_pcname)
+install_headers(glibmm_extra_h_files, subdir: glibmm_pcname / 'glibmm')
+install_headers(glibmm_extra_ph_files, subdir: glibmm_pcname / 'glibmm' / 'private')
+
+untracked_glibmm = 'untracked' / 'glib' / 'glibmm'
+src_untracked_glibmm = project_source_root / untracked_glibmm
+
+if maintainer_mode
+
+  # Maintainer mode. Generate .h and .cc files from .hg and .ccg files in ../src.
+
+  # docs/reference/meson.build needs these.
+  built_files_root = project_build_root
+  glibmm_built_h_file_targets = []
+
+  # Force meson+ninja to generate source files before anything is compiled.
+  # Compilation must depend on these targets.
+  glibmm_built_cc_file_targets = []
+
+  hg_files = []
+  foreach file : glibmm_hg_ccg_basenames
+    hg_files += '..' / 'src' / file + '.hg'
+  endforeach
+
+  # Create wrap_init.cc in project_build_root/glib/glibmm.
+  glibmm_built_cc_file_targets += custom_target('glibmm-wrap_init.cc',
+    input: hg_files,
+    output: 'wrap_init.cc',
+    command: [
+      python3, generate_binding_py, 'generate_wrap_init',
+      gmmproc_dir,
+      '@OUTPUT@',
+      'Glib', # namespace
+      '@INPUT@',
+    ],
+    build_by_default: maintainer_mode,
+    install: false,
+  )
+
+  # Create .h/_p.h/.cc files in project_build_root/glib/glibmm
+  # from .hg/.ccg files in project_source_root/glib/src.
+  foreach file : glibmm_hg_ccg_basenames
+    hg_file = '..' / 'src' / file + '.hg'
+    ccg_file = '..' / 'src' / file + '.ccg'
+    built_file_target = custom_target('glibmm-' + file + '.cc',
+      input: [hg_file, ccg_file],
+      output: [file + '.stamp', file + '.cc', file + '.h'],
+      command: [
+        python3, handle_built_files_py, 'gmmproc',
+        gmmproc_dir,
+        project_source_root / 'tools' / 'pm',
+        '@OUTPUT0@',
+        file,
+        meson.current_source_dir() / '..' / 'src',
+        project_source_root / 'tools' / 'm4',
+      ],
+      depend_files: glibmm_defs_files + m4_files + pm_files,
+      build_by_default: maintainer_mode,
+      install: false,
+    )
+    glibmm_built_cc_file_targets += built_file_target[1]
+    glibmm_built_h_file_targets += built_file_target[2]
+  endforeach
+
+  # Create .h and .cc files in project_build_root/glib/glibmm
+  # from .m4 files in project_source_root/glib/src.
+  foreach output_file : glibmm_h_m4_files + glibmm_cc_m4_files
+    input_file = '..' / 'src' / output_file + '.m4'
+    built_file_target = custom_target('glibmm-' + output_file,
+      input: input_file,
+      output: output_file,
+      command: [
+        python3, handle_built_files_py, 'build_from_m4',
+        meson.current_source_dir() / '..' / 'src',
+        '@INPUT@',
+        '@OUTPUT@',
+      ],
+      depend_files: '..' / 'src' / 'template.macros.m4',
+      build_by_default: maintainer_mode,
+      install: false,
+    )
+    if output_file.endswith('.cc')
+      glibmm_built_cc_file_targets += built_file_target
+    else
+      glibmm_built_h_file_targets += built_file_target
+    endif
+  endforeach
+
+  # Create dummy_header.h, depending on all generated headers.
+  # It's created if it does not exist, but it's never updated.
+  # It guarantees that all generated headers are built before glibmm_library
+  # is built, at the same time avoiding unnecessary recompilations.
+  # If glibmm_built_h_file_targets would be listed as sources to glibmm_library,
+  # all generated .cc files could be recompiled if one generated .h file has
+  # been changed.
+  built_dummy_h_file_target = custom_target('glibmm-dummy_header.h',
+    input: glibmm_built_h_file_targets,
+    output: 'dummy_header.h',
+    command: [
+      python3, dummy_header_py,
+      '@OUTPUT@',
+    ],
+    build_by_default: maintainer_mode,
+    install: false,
+  )
+
+  extra_include_dirs = ['..']
+  glibmm_library = library(glibmm_pcname,
+    glibmm_built_cc_file_targets, glibmm_extra_cc_files, built_dummy_h_file_target,
+    version: glibmm_libversion,
+    include_directories: extra_include_dirs,
+    cpp_args: '-DGLIBMM_BUILD=1',
+    dependencies: glibmm_build_dep,
+    install: true,
+  )
+
+  built_h_cc_dir = meson.current_build_dir()
+
+else # not maintainer_mode
+
+  # Not maintainer mode. Compile built source code files in
+  # project_source_root/untracked/glib/glibmm.
+
+  # docs/reference/meson.build needs these.
+  built_files_root = project_source_root / 'untracked'
+  glibmm_built_h_file_targets = []
+
+  # Two cases:
+  # 1. The source code comes from a tarball, where the built files
+  #    are stored in project_source_root/untracked.
+  #    There are no built files in the build tree.
+  # 2. Files have been built in the build tree. Then maintainer_mode has
+  #    been changed from true to false. Files that are missing or not up to date
+  #    in project_source_root/untracked are copied from the build tree.
+
+  # Try to copy built source code files to the source tree.
+  run_command(
+    python3, generate_binding_py, 'copy_built_files',
+    meson.current_build_dir(),
+    src_untracked_glibmm,
+    glibmm_hg_ccg_basenames,
+  )
+  run_command(
+    python3, handle_built_files_py, 'copy_built_files',
+    meson.current_build_dir(),
+    src_untracked_glibmm,
+    glibmm_h_m4_files + glibmm_cc_m4_files,
+  )
+
+  built_cc_files = [ src_untracked_glibmm / 'wrap_init.cc' ]
+  foreach file : glibmm_hg_ccg_basenames
+    built_cc_files += src_untracked_glibmm / file + '.cc'
+  endforeach
+  foreach file : glibmm_cc_m4_files
+    built_cc_files += src_untracked_glibmm / file
+  endforeach
+
+  extra_include_dirs = [ '..', '..' / '..' / 'untracked' / 'glib' ]
+
+  # We need this so that we can run gendef.exe to get the .def file
+  # needed for obtaining the .lib file for the glibmm DLL
+  glib_int_lib = static_library('glibmm-int',
+    built_cc_files, glibmm_extra_cc_files,
+    include_directories: extra_include_dirs,
+    cpp_args: '-DGLIBMM_BUILD=1',
+    dependencies: glibmm_build_dep,
+    install: false,
+  )
+
+  glibmm_def = []
+  glibmm_extra_link_args = []
+  extra_glibmm_objects = []
+
+  if is_msvc
+    glibmm_def = custom_target('glibmm.def',
+      output: 'glibmm.def',
+      depends: glib_int_lib,
+      command: [ gendef,
+        '@OUTPUT@',
+        '@0@-@1@.dll'.format(glibmm_pcname, glibmm_libversion.split('.')[0]),
+        glib_int_lib.full_path(),
+      ],
+      install: false,
+    )
+    glibmm_extra_link_args = ['/def:@0@'.format(glibmm_def.full_path())]
+  endif
+
+  # Build the .rc file for Windows builds and link to it
+  if is_host_windows
+    windows = import('windows')
+    glibmm_res = windows.compile_resources(glibmm_rc)
+    extra_glibmm_objects += glibmm_res
+  endif
+
+  glibmm_library = library(glibmm_pcname, extra_glibmm_objects,
+    objects: glib_int_lib.extract_all_objects(),
+    version: glibmm_libversion,
+    dependencies: glibmm_build_dep,
+    link_depends: glibmm_def,
+    link_args: glibmm_extra_link_args,
+    install: true,
+  )
+
+  built_h_cc_dir = src_untracked_glibmm
+
+endif
+
+# Install built .h and _p.h files.
+meson.add_install_script(
+  python3.path(), generate_binding_py, 'install_built_h_files',
+  built_h_cc_dir,
+  install_includedir / glibmm_pcname / 'glibmm', # subdir below {prefix}
+  glibmm_hg_ccg_basenames
+)
+# Install .h files built from .m4 files.
+meson.add_install_script(
+  python3.path(), handle_built_files_py, 'install_built_h_files',
+  built_h_cc_dir,
+  install_includedir / glibmm_pcname / 'glibmm', # subdir below {prefix}
+  glibmm_h_m4_files,
+)
+
+if not meson.is_subproject()
+  # Distribute built files.
+  # (add_dist_script() is not allowed in a subproject)
+  meson.add_dist_script(
+    python3.path(), generate_binding_py, 'dist_built_files',
+    built_h_cc_dir,
+    untracked_glibmm,
+    glibmm_hg_ccg_basenames,
+  )
+  meson.add_dist_script(
+    python3.path(), handle_built_files_py, 'dist_built_files',
+    built_h_cc_dir,
+    untracked_glibmm,
+    glibmm_h_m4_files + glibmm_cc_m4_files,
+  )
+endif
+
+# This is useful in the main project when glibmm is used as a subproject.
+# It's also used when building example programs and test programs.
+glibmm_dep = declare_dependency(
+  sources: glibmm_built_h_file_targets,
+  link_with: glibmm_library,
+  include_directories: extra_include_dirs,
+  dependencies: glibmm_build_dep,
+)
diff --git a/glib/glibmmconfig.h.meson b/glib/glibmmconfig.h.meson
new file mode 100644
index 00000000..177f745b
--- /dev/null
+++ b/glib/glibmmconfig.h.meson
@@ -0,0 +1,125 @@
+#ifndef _GLIBMM_CONFIG_H
+#define _GLIBMM_CONFIG_H
+
+/* Define to omit deprecated API from the library. */
+#mesondefine GLIBMM_DISABLE_DEPRECATED
+
+/* Major version number of glibmm. */
+#mesondefine GLIBMM_MAJOR_VERSION
+
+/* Minor version number of glibmm. */
+#mesondefine GLIBMM_MINOR_VERSION
+
+/* Micro version number of glibmm. */
+#mesondefine GLIBMM_MICRO_VERSION
+
+/* Define if glibmm is built as a static library */
+#mesondefine GLIBMM_STATIC_LIB
+
+/* The size of wchar_t, as computed by sizeof. */
+#mesondefine GLIBMM_SIZEOF_WCHAR_T
+
+/* Defined when the -Ddebug-refcounting configure argument was given */
+#mesondefine GLIBMM_DEBUG_REFCOUNTING
+
+#ifdef _WIN32
+  /* Win32 compilers have a lot of varation */
+# if defined(_MSC_VER)
+#  define GLIBMM_MSC 1
+#  define GLIBMM_WIN32 1
+#  define GLIBMM_DLL 1
+# elif defined(__CYGWIN__)
+#  define GLIBMM_CONFIGURE 1
+# elif defined(__MINGW32__)
+#  define GLIBMM_WIN32 1
+#  define GLIBMM_CONFIGURE 1
+# else
+   /* AIX clR compiler complains about this even though it doesn't get this far */
+#  error "Unknown architecture (send me gcc --dumpspecs or equiv)"
+# endif
+#else
+# define GLIBMM_CONFIGURE 1
+#endif /* _WIN32 */
+
+#ifdef GLIBMM_CONFIGURE
+
+/* Define only on Mac OS, COCOA */
+#mesondefine GLIBMM_OS_COCOA
+
+/* Define if extern "C" and extern "C++" function pointers are compatible. */
+#mesondefine GLIBMM_CAN_ASSIGN_NON_EXTERN_C_FUNCTIONS_TO_EXTERN_C_CALLBACKS
+
+/* Define if non-instantiated templates may dynamic_cast<> to an undefined
+   type. */
+#mesondefine GLIBMM_CAN_USE_DYNAMIC_CAST_IN_UNUSED_TEMPLATE_WITHOUT_DEFINITION
+
+/* Defined if a static member variable may be initialized inline to
+   std::string::npos */
+#mesondefine GLIBMM_HAVE_ALLOWS_STATIC_INLINE_NPOS
+
+/* Define if the compiler disambiguates template specializations for const and
+   non-const types. */
+#mesondefine GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS
+
+/* Defined if std::iterator_traits<> is standard-conforming */
+#mesondefine GLIBMM_HAVE_STD_ITERATOR_TRAITS
+
+/* Defined if std::reverse_iterator is in Sun libCstd style */
+#mesondefine GLIBMM_HAVE_SUN_REVERSE_ITERATOR
+
+/* Defined if the STL containers have templated sequence ctors */
+#mesondefine GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
+
+/* Define to 1 if wide stream is available. */
+#mesondefine GLIBMM_HAVE_WIDE_STREAM
+
+#endif /* GLIBMM_CONFIGURE */
+
+#ifdef GLIBMM_MSC
+# define GLIBMM_HAVE_STD_ITERATOR_TRAITS 1
+# define GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS 1
+# define GLIBMM_HAVE_WIDE_STREAM 1
+# define GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS 1
+# define GLIBMM_CAN_USE_DYNAMIC_CAST_IN_UNUSED_TEMPLATE_WITHOUT_DEFINITION 1
+# define GLIBMM_CAN_ASSIGN_NON_EXTERN_C_FUNCTIONS_TO_EXTERN_C_CALLBACKS 1
+# pragma warning (disable: 4786 4355 4800 4181)
+
+#if (_MSC_VER < 1900)
+/* The C++-11 keywords noexcept and thread_local are supported on
+ * Visual Studio 2013 via Microsoft-specific extensions, but are
+ * supported directly in Visual Studio 2015
+ */
+
+#define _ALLOW_KEYWORD_MACROS 1
+
+#ifndef noexcept
+#define noexcept _NOEXCEPT
+#endif
+
+#ifndef thread_local
+#define thread_local __declspec (thread)
+#endif
+
+#endif /* _MSC_VER < 1900 */
+#endif /* GLIBMM_MSC */
+
+/* Enable DLL-specific stuff only when not building a static library */
+#if !defined(__CYGWIN__) && defined(__MINGW32__) && !defined(GLIBMM_STATIC_LIB)
+# define GLIBMM_DLL 1
+#endif
+
+#ifdef GLIBMM_DLL
+# if defined(GLIBMM_BUILD) && defined(_WINDLL)
+   /* Do not dllexport as it is handled by gendef on MSVC */
+#  define GLIBMM_API
+# elif !defined(GLIBMM_BUILD)
+#  define GLIBMM_API __declspec(dllimport)
+# else
+   /* Build a static library */
+#  define GLIBMM_API
+# endif /* GLIBMM_BUILD - _WINDLL */
+#else
+# define GLIBMM_API
+#endif /* GLIBMM_DLL */
+
+#endif /* _GLIBMM_CONFIG_H */
diff --git a/glib/meson.build b/glib/meson.build
new file mode 100644
index 00000000..bf9141c7
--- /dev/null
+++ b/glib/meson.build
@@ -0,0 +1,103 @@
+# glib
+
+# Input: install_prefix, install_libdir, install_datadir, install_includedir,
+#        glibmm_pcname, giomm_pcname, glibmm_api_version, glibmm_requires,
+#        giomm_requires, build_deprecated_api, install_pkgconfigdir,
+#        is_os_cocoa, cpp_compiler, glibmm_major_version, glibmm_minor_version,
+#        glibmm_micro_version
+# Output: pkg_conf_data, install_glibmmconfigdir, glibmmconfig_h
+
+pkg_conf_data = configuration_data()
+pkg_conf_data.set('prefix', install_prefix)
+pkg_conf_data.set('exec_prefix', '${prefix}')
+pkg_conf_data.set('libdir', '${exec_prefix}' / install_libdir)
+pkg_conf_data.set('datarootdir', '${prefix}' / install_datadir)
+pkg_conf_data.set('datadir', '${datarootdir}')
+pkg_conf_data.set('includedir', '${prefix}' / install_includedir)
+pkg_conf_data.set('PACKAGE_TARNAME', meson.project_name())
+pkg_conf_data.set('PACKAGE_VERSION', meson.project_version())
+pkg_conf_data.set('GLIBMM_MODULE_NAME', glibmm_pcname)
+pkg_conf_data.set('GLIBMM_API_VERSION', glibmm_api_version)
+pkg_conf_data.set('GLIBMM_MODULES', glibmm_requires)
+pkg_conf_data.set('GIOMM_MODULE_NAME', giomm_pcname)
+pkg_conf_data.set('GIOMM_API_VERSION', glibmm_api_version)
+pkg_conf_data.set('GIOMM_MODULES', giomm_requires)
+if not build_deprecated_api
+  pkg_conf_data.set('GLIBMM_DISABLE_DEPRECATED', 1)
+  pkg_conf_data.set('GIOMM_DISABLE_DEPRECATED', 1)
+endif
+pkg_conf_data.set('GLIBMM_MAJOR_VERSION', glibmm_major_version)
+pkg_conf_data.set('GLIBMM_MINOR_VERSION', glibmm_minor_version)
+pkg_conf_data.set('GLIBMM_MICRO_VERSION', glibmm_micro_version)
+pkg_conf_data.set('GIOMM_MAJOR_VERSION', glibmm_major_version)
+pkg_conf_data.set('GIOMM_MINOR_VERSION', glibmm_minor_version)
+pkg_conf_data.set('GIOMM_MICRO_VERSION', glibmm_micro_version)
+if get_option('default_library') == 'static'
+  pkg_conf_data.set('GLIBMM_STATIC_LIB', 1)
+  pkg_conf_data.set('GIOMM_STATIC_LIB', 1)
+endif
+
+configure_file(
+  input: 'glibmm.pc.in',
+  output: glibmm_pcname + '.pc',
+  configuration: pkg_conf_data,
+  install_dir: install_pkgconfigdir,
+)
+
+glibmm_pkg_uninst_conf_data = configuration_data()
+glibmm_pkg_uninst_conf_data.merge_from(pkg_conf_data)
+glibmm_pkg_uninst_conf_data.set('srcdir', meson.current_source_dir())
+
+configure_file(
+  input: 'glibmm-uninstalled.pc.in',
+  output: glibmm_pcname + '-uninstalled.pc',
+  configuration: glibmm_pkg_uninst_conf_data,
+)
+
+glibmm_config_conf_data = configuration_data()
+glibmm_config_conf_data.merge_from(pkg_conf_data)
+if get_option('debug-refcounting')
+  glibmm_config_conf_data.set('GLIBMM_DEBUG_REFCOUNTING', 1)
+endif
+if is_os_cocoa
+  glibmm_config_conf_data.set('GLIBMM_OS_COCOA', 1)
+endif
+glibmm_config_conf_data.set('GLIBMM_SIZEOF_WCHAR_T', cpp_compiler.sizeof('wchar_t'))
+
+conf_tests = [
+# [preprocessor-macro-name, file-name, message]
+  ['GLIBMM_HAVE_WIDE_STREAM', 'have_wide_stream.cc', 'Wide stream support'],
+  ['GLIBMM_HAVE_STD_ITERATOR_TRAITS', 'have_std_iterator_traits.cc',
+     'std::iterator_traits<> is standard-conforming'],
+  ['GLIBMM_HAVE_SUN_REVERSE_ITERATOR', 'have_sun_reverse_iterator.cc',
+    'std::reverse_iterator is in Sun libCstd style'],
+  ['GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS', 'have_template_sequence_ctors.cc',
+    'STL containers have templated sequence ctors'],
+  ['GLIBMM_HAVE_DISAMBIGUOUS_CONST_TEMPLATE_SPECIALIZATIONS', 
+    'have_disambiguous_const_template_specializations.cc',
+    'Disambiguates template specializations for const and non-const types'],
+  ['GLIBMM_CAN_USE_DYNAMIC_CAST_IN_UNUSED_TEMPLATE_WITHOUT_DEFINITION',
+    'can_use_dynamic_cast_in_unused_template_wo_def.cc',
+    'Non-instantiated templates may dynamic_cast<> to an undefined type'],
+  ['GLIBMM_CAN_ASSIGN_NON_EXTERN_C_FUNCTIONS_TO_EXTERN_C_CALLBACKS',
+    'can_assign_non_extern_c_functions_to_extern_c_cb.cc',
+    'extern "C" and extern "C++" function pointers are compatible'],
+  ['GLIBMM_HAVE_ALLOWS_STATIC_INLINE_NPOS', 'allows_static_inline_npos.cc',
+    'A static member variable may be initialized inline to std::string::npos'],
+]
+
+foreach conf_test : conf_tests
+  if cpp_compiler.compiles(
+      files('..' / 'tools' / 'conf_tests' / conf_test[1]),
+      name: conf_test[2])
+    glibmm_config_conf_data.set(conf_test[0], 1)
+  endif
+endforeach
+
+install_glibmmconfigdir = install_libdir / glibmm_pcname / 'include'
+glibmmconfig_h = configure_file(
+  input: 'glibmmconfig.h.meson',
+  output: 'glibmmconfig.h',
+  configuration: glibmm_config_conf_data,
+  install_dir: install_glibmmconfigdir,
+)
diff --git a/meson.build b/meson.build
new file mode 100644
index 00000000..33a1741a
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,314 @@
+# This file is part of glibmm.
+
+project('glibmm', 'cpp',
+  version: '2.63.1',
+  license: 'LGPLv2.1+',
+  default_options: [
+    'cpp_std=c++17'
+  ],
+  meson_version: '>= 0.50.0', # required for python3.path()
+)
+
+glibmm_api_version = '2.64'
+glibmm_pcname = meson.project_name() + '-' + glibmm_api_version
+giomm_pcname = 'giomm-' + glibmm_api_version
+
+glibmm_version_array = meson.project_version().split('.')
+glibmm_major_version = glibmm_version_array[0].to_int()
+glibmm_minor_version = glibmm_version_array[1].to_int()
+glibmm_micro_version = glibmm_version_array[2].to_int()
+
+# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
+# The relation between libtool's current:revison:age interface versioning
+# and the .so filename, .so.x.y.z, is
+# x = current - age
+# y = age
+# z = revision
+# If libtool_soversion is updated as described in libtool's documentation,
+# x.y.z will usually *not* be equal to meson.project_version().
+libtool_soversion = [4, 0, 3]
+glibmm_libversion = '@0@.@1@.@2@'.format(
+  libtool_soversion[0] - libtool_soversion[2],
+  libtool_soversion[2],
+  libtool_soversion[1])
+
+# Use these instead of meson.source_root() and meson.build_root() in subdirectories.
+# source_root() and build_root() are not useful, if this is a subproject.
+project_source_root = meson.current_source_dir()
+project_build_root = meson.current_build_dir()
+
+cpp_compiler = meson.get_compiler('cpp')
+is_msvc = cpp_compiler.get_id() == 'msvc'
+is_host_windows = host_machine.system() == 'windows'
+
+is_os_cocoa = false
+if not is_host_windows
+  # This test for Mac OS is copied from glib. If the result of glib's test
+  # is ever made available outside glib, use glib's result instead of this test.
+  # glib: https://bugzilla.gnome.org/show_bug.cgi?id=780309
+  # glibmm: https://bugzilla.gnome.org/show_bug.cgi?id=781947
+  is_os_cocoa = cpp_compiler.compiles(
+    '''#include <Cocoa/Cocoa.h>
+    #ifdef GNUSTEP_BASE_VERSION
+    #error "Detected GNUstep, not Cocoa"
+    #endif''',
+    name: 'Mac OS X Cocoa support'
+  )
+endif
+
+python3 = import('python').find_installation()
+python_version = python3.language_version()
+python_version_req = '>= 3.5'
+if not python_version.version_compare(python_version_req)
+  error('Requires Python @0@, found @1@.'.format(python_version_req, python_version))
+endif
+
+# Do we build from a git repository?
+# Suppose we do if and only if a '.git' directory or file exists.
+cmd_py = '''
+import os
+import sys
+sys.exit(os.path.isdir("@0@") or os.path.isfile("@0@"))
+'''.format(project_source_root / '.git')
+is_git_build = run_command(python3, '-c', cmd_py).returncode() != 0
+
+# Unfortunately due to m4 requirements, we cannot support MSVC builds
+# directly from GIT checkouts
+assert(not is_msvc or not is_git_build, 'Direct builds from GIT is not supported for MSVC builds')
+
+# Options.
+maintainer_mode_opt = get_option('maintainer-mode')
+maintainer_mode = maintainer_mode_opt == 'true' or \
+                 (maintainer_mode_opt == 'if-git-build' and is_git_build)
+warning_level = get_option('warnings')
+build_deprecated_api = get_option('build-deprecated-api')
+build_documentation_opt = get_option('build-documentation')
+build_documentation = build_documentation_opt == 'true' or \
+                     (build_documentation_opt == 'if-maintainer-mode' and maintainer_mode)
+build_examples = get_option('build-examples')
+
+# Installation directories are relative to {prefix}.
+install_prefix = get_option('prefix')
+install_includedir = get_option('includedir')
+install_libdir = get_option('libdir')
+install_datadir = get_option('datadir')
+install_pkgconfigdir = install_libdir / 'pkgconfig'
+
+# Dependencies. <pkg> = glib and gio
+# <pkg>mm_build_dep: Dependencies when building the <pkg>mm library.
+# <pkg>mm_dep (created in <pkg>/<pkg>mm/meson.build):
+#   Dependencies when using the <pkg>mm library.
+
+sigcxx_req = '>= 3.0.0'
+glib_req = '>= 2.63.0'
+
+# Glib supported pkg-config files on MSVC files for a good while,
+# so just use that.
+glib_dep = dependency('glib-2.0', version: glib_req)
+gobject_dep = dependency('gobject-2.0', version: glib_req)
+gmodule_dep = dependency('gmodule-2.0', version: glib_req)
+
+glibmm_build_dep = [glib_dep, gobject_dep, gmodule_dep]
+glibmm_requires = [
+  'glib-2.0', glib_req,
+  'gobject-2.0', glib_req,
+  'gmodule-2.0', glib_req,
+]
+
+gio_dep = dependency('gio-2.0', version: glib_req)
+giomm_build_dep = glibmm_build_dep + [gio_dep]
+giomm_requires = glibmm_requires + ['gio-2.0', glib_req]
+if not is_host_windows
+  gio_unix_dep = dependency('gio-unix-2.0', version: glib_req)
+  giomm_build_dep += gio_unix_dep
+  giomm_requires += ['gio-unix-2.0', glib_req]
+endif
+
+if is_msvc
+  # We must have Visual Studio 2017 15.7 or later...
+  assert(cpp_compiler.version().split('.')[0].to_int() >= 19 and \
+         cpp_compiler.version().split('.')[1].to_int() >= 15,
+         'Visual Studio 2017 15.7 or later is required')
+
+  assert(cpp_compiler.has_header('sigc++-3.0/sigc++/sigc++.h') and \
+         cpp_compiler.has_header('sigc++-3.0/include/sigc++config.h'),
+         'sigc++-3.x headers are required')
+  message('Ensure your INCLUDE and LIB contain the paths that lead to ' + \
+          'the appropriate headers and .lib for libsigc++-3.x')
+
+  # Visual Studio 2019 can consume libraries built with 2017, so check for
+  # 2017-built libraries as well if 2019-built libraries cannot be found
+  msvc_check_range = [15]
+  msvc_minor = cpp_compiler.version().split('.')[1].to_int()
+  if msvc_minor >= 20
+    msvc_check_range = [16, 15]
+  endif
+
+  debugsuffix = ''
+  if get_option('buildtype') == 'debug'
+    debugsuffix = '-d'
+  endif
+
+  # We can be looking for MSVC 2017-built libraries on 2019 builds as well,
+  # so we can't just assume that libraries exist, but check that compatible
+  # versions are really found
+  sigcxx_dep = dependency('', required: false)
+
+  foreach v : msvc_check_range
+    sigcxx_dep = sigcxx_dep.found() ? sigcxx_dep : cpp_compiler.find_library(
+      'sigc-vc@0@0@1@-3_0'.format(v.to_string(), debugsuffix), required: false)
+  endforeach
+
+  # Now make sure the appropriate -mm libraries are found
+  assert(sigcxx_dep.found(),
+    'Appropriate sigc-vcxx0@0@-3_0.lib is required'.format(debugsuffix))
+
+else # not is_msvc
+
+  sigcxx_dep = dependency('sigc++-3.0', version: sigcxx_req)
+  glibmm_requires += ['sigc++-3.0', sigcxx_req]
+  giomm_requires += ['sigc++-3.0', sigcxx_req]
+
+endif # is_msvc
+
+glibmm_build_dep += [sigcxx_dep]
+giomm_build_dep += [sigcxx_dep]
+glibmm_requires = ' '.join(glibmm_requires)
+giomm_requires = ' '.join(giomm_requires)
+
+# Some dependencies are required only in maintainer mode and/or if
+# reference documentation shall be built.
+mm_common_get = find_program('mm-common-get', required: maintainer_mode)
+m4 = find_program('m4', required: maintainer_mode) # Used by gmmproc
+perl = find_program('perl', required: maintainer_mode or build_documentation)
+doxygen = find_program('doxygen', required: build_documentation)
+dot = find_program('dot', required: build_documentation) # Used by Doxygen
+xsltproc = find_program('xsltproc', required: build_documentation)
+
+# Where to find gmmproc and generate_wrap_init.pl.
+gmmproc_dir = project_build_root / 'tools'
+
+# Script files copied to 'untracked' by mm-common-get.
+script_dir = project_source_root / 'untracked' / 'build_scripts'
+generate_binding_py = script_dir / 'generate-binding.py'
+doc_reference_py = script_dir / 'doc-reference.py'
+dist_changelog_py = script_dir / 'dist-changelog.py'
+dist_build_scripts_py = script_dir / 'dist-build-scripts.py'
+
+if maintainer_mode and mm_common_get.found()
+  # Copy files to untracked/build_scripts and untracked/docs.
+  run_command(mm_common_get, '--force', script_dir,
+    project_source_root / 'untracked' / 'docs')
+endif
+
+# glibmm's own script files.
+glibmm_script_dir = project_source_root / 'tools' / 'build_scripts'
+handle_built_files_py = glibmm_script_dir / 'handle-built-files.py'
+dummy_header_py = glibmm_script_dir / 'dummy-header.py'
+compile_schemas_py = glibmm_script_dir / 'compile-schemas.py'
+
+# Set compiler warnings.
+warning_flags = []
+if warning_level == 'min'
+  if is_msvc
+    warning_flags = ['/W3']
+  else
+    warning_flags = ['-Wall']
+  endif
+elif warning_level == 'max' or warning_level == 'fatal'
+  if is_msvc
+    warning_flags = ['/W4']
+  else
+    warning_flags = '-pedantic -Wall -Wextra -Wformat-security -Wsuggest-override -Wshadow 
-Wno-long-long'.split()
+  endif
+  if warning_level == 'fatal'
+    if is_msvc
+      warning_flags += ['/WX']
+    else
+      warning_flags += ['-Werror']
+    endif
+    deprecations = 'G SIGCXX'.split()
+    foreach d : deprecations
+      warning_flags += '-D@0@_DISABLE_DEPRECATED'.format(d)
+    endforeach
+  endif
+endif
+
+warning_flags = cpp_compiler.get_supported_arguments(warning_flags)
+add_project_arguments(warning_flags, language: 'cpp')
+
+# MSVC: Ignore warnings that aren't really harmful, but make those
+#       that should not be overlooked stand out.
+if is_msvc
+  disabled_warnings = cpp_compiler.get_supported_arguments([
+    '/FImsvc_recommended_pragmas.h', '/wd4267', '/wd4530'
+  ])
+  add_project_arguments(disabled_warnings, language: 'cpp')
+endif
+
+subdir('tools')
+subdir('MSVC_NMake/gendef')
+subdir('glib')
+subdir('MSVC_NMake/glibmm')
+subdir('glib/glibmm')
+subdir('gio')
+subdir('MSVC_NMake/giomm')
+subdir('gio/giomm')
+subdir('examples')
+subdir('tests')
+subdir('docs/reference')
+
+if not meson.is_subproject()
+  # Add a ChangeLog file to the distribution directory.
+  # (add_dist_script() is not allowed in a subproject)
+  meson.add_dist_script(
+    python3.path(), dist_changelog_py,
+    project_source_root,
+  )
+  # Add build scripts to the distribution directory, and delete .gitignore
+  # files and an empty $MESON_DIST_ROOT/build/ directory.
+  meson.add_dist_script(
+    python3.path(), dist_build_scripts_py,
+    project_source_root,
+    'untracked' / 'build_scripts',
+  )
+endif
+
+# Print a summary.
+real_maintainer_mode = ''
+if maintainer_mode_opt == 'if-git-build'
+  real_maintainer_mode = ' (@0@)'.format(maintainer_mode)
+endif
+
+real_build_documentation = ''
+if build_documentation_opt == 'if-maintainer-mode'
+  real_build_documentation = ' (@0@)'.format(build_documentation)
+endif
+
+summary = [
+  '',
+  '------',
+  meson.project_name() + ' ' + meson.project_version(),
+  '',
+  '         Maintainer mode: @0@@1@'.format(maintainer_mode_opt, real_maintainer_mode),
+  '       Compiler warnings: @0@'.format(warning_level),
+  '    Build deprecated API: @0@'.format(build_deprecated_api),
+  'Build HTML documentation: @0@@1@'.format(build_documentation_opt, real_build_documentation),
+  '  Build example programs: @0@'.format(build_examples),
+  'Directories:',
+  '                  prefix: @0@'.format(install_prefix),
+  '              includedir: @0@'.format(install_prefix / install_includedir),
+  '        includeglibmmdir: @0@'.format(install_prefix / install_includedir / glibmm_pcname),
+  '         includegiommdir: @0@'.format(install_prefix / install_includedir / giomm_pcname),
+  '                  libdir: @0@'.format(install_prefix / install_libdir),
+  '         glibmmconfigdir: @0@'.format(install_prefix / install_glibmmconfigdir),
+  '          giommconfigdir: @0@'.format(install_prefix / install_giommconfigdir),
+  '                   m4dir: @0@'.format(install_prefix / install_m4dir),
+  '            pkgconfigdir: @0@'.format(install_prefix / install_pkgconfigdir),
+  '                 datadir: @0@'.format(install_prefix / install_datadir),
+  '                  docdir: @0@'.format(install_prefix / install_docdir),
+  '              devhelpdir: @0@'.format(install_prefix / install_devhelpdir),
+  '------'
+]
+
+message('\n'.join(summary))
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 00000000..b5a526c3
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,12 @@
+option('maintainer-mode', type: 'combo', choices: ['false', 'if-git-build', 'true'],
+  value: 'if-git-build', description: 'Generate source code from .hg and .ccg files')
+option('warnings', type: 'combo', choices: ['no', 'min', 'max', 'fatal'], value: 'fatal',
+  description: 'Compiler warning level')
+option('build-deprecated-api', type: 'boolean', value: true,
+  description: 'Build deprecated API and include it in the library')
+option('build-documentation', type: 'combo', choices: ['false', 'if-maintainer-mode', 'true'],
+  value: 'if-maintainer-mode', description: 'Build and install the documentation')
+option('debug-refcounting', type: 'boolean', value: false,
+  description: 'Print debug messages in connection with reference counting')
+option('build-examples', type: 'boolean', value: true,
+  description: 'Build example programs')
diff --git a/tests/meson.build b/tests/meson.build
new file mode 100644
index 00000000..94088ea4
--- /dev/null
+++ b/tests/meson.build
@@ -0,0 +1,62 @@
+# tests
+
+# input: glibmm_dep, giomm_dep
+
+test_programs = [
+# [[dir-name], exe-name, [sources], giomm-example (not just glibmm-example)]
+  [['giomm_ioerror'], 'test', ['main.cc'], true],
+  [['giomm_ioerror_and_iodbuserror'], 'test', ['main.cc'], true],
+  [['giomm_memoryinputstream'], 'test', ['main.cc'], true],
+  [['giomm_simple'], 'test', ['main.cc'], true],
+  [['giomm_stream_vfuncs'], 'test', ['main.cc'], true],
+  [['giomm_asyncresult_sourceobject'], 'test', ['main.cc'], true],
+  [['giomm_tls_client'], 'test', ['main.cc'], true],
+  [['giomm_listmodel'], 'test', ['main.cc'], true],
+  [['glibmm_bool_vector'], 'test', ['main.cc'], false],
+  [['glibmm_btree'], 'test', ['main.cc'], false],
+  [['glibmm_base64'], 'test', ['main.cc'], false],
+  [['glibmm_binding'], 'test', ['main.cc'], false],
+  [['glibmm_bytearray'], 'test', ['main.cc'], false],
+  [['glibmm_date'], 'test', ['main.cc'], false],
+  [['glibmm_buildfilename'], 'test', ['main.cc'], false],
+  [['glibmm_interface_implementation'], 'test', ['main.cc'], true],
+  [['glibmm_interface_move'], 'test', ['main.cc'], false],
+  [['glibmm_mainloop'], 'test', ['main.cc'], false],
+  [['glibmm_nodetree'], 'test', ['main.cc'], false],
+  [['glibmm_null_vectorutils'], 'test', ['main.cc'], true],
+  [['glibmm_object'], 'test', ['main.cc'], false],
+  [['glibmm_object_move'], 'test', ['main.cc'], false],
+  [['glibmm_objectbase'], 'test', ['main.cc'], false],
+  [['glibmm_objectbase_move'], 'test', ['main.cc'], false],
+  [['glibmm_refptr'], 'test', ['main.cc'], false],
+  [['glibmm_refptr_sigc_bind'], 'test', ['main.cc'], false],
+  [['glibmm_regex'], 'test', ['main.cc'], false],
+  [['glibmm_ustring_compare'], 'test', ['main.cc'], false],
+  [['glibmm_ustring_format'], 'test', ['main.cc'], false],
+  [['glibmm_ustring_make_valid'], 'test', ['main.cc'], false],
+  [['glibmm_ustring_sprintf'], 'test', ['main.cc'], false],
+  [['glibmm_value'], 'test', ['main.cc'], false],
+  [['glibmm_variant'], 'test', ['main.cc'], false],
+  [['glibmm_vector'], 'test', ['main.cc'], true],
+]
+
+foreach ex : test_programs
+  dir = ''
+  foreach dir_part : ex[0]
+    dir = dir / dir_part
+  endforeach
+  ex_name = (dir / ex[1]).underscorify()
+  ex_sources = []
+  foreach src : ex[2]
+    ex_sources += dir / src
+  endforeach
+
+  exe_file = executable(ex_name, ex_sources,
+    dependencies: ex[3] ? giomm_dep : glibmm_dep,
+    gui_app: false,
+    build_by_default: true,
+    install: false,
+  )
+
+  test(ex_name, exe_file)
+endforeach
diff --git a/tools/build_scripts/compile-schemas.py b/tools/build_scripts/compile-schemas.py
new file mode 100755
index 00000000..e0136e32
--- /dev/null
+++ b/tools/build_scripts/compile-schemas.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python3
+
+# External command, intended to be called with custom_target() in meson.build
+
+#                      argv[1]      argv[2]       argv[3]
+# compile-schemas.py <schema_dir> <target_dir> <output_file>
+
+import os
+import sys
+import subprocess
+import shutil
+
+schema_dir = sys.argv[1]
+target_dir = sys.argv[2]
+output_file = sys.argv[3]
+
+# Create the target directory, if it does not exist.
+os.makedirs(target_dir, exist_ok=True)
+
+cmd = [
+  'glib-compile-schemas',
+  '--strict',
+  '--targetdir=' + target_dir,
+  schema_dir,
+]
+
+result = subprocess.run(cmd)
+if result.returncode == 0:
+  shutil.copy(os.path.join(target_dir, 'gschemas.compiled'), output_file)
+sys.exit(result.returncode)
diff --git a/tools/build_scripts/dummy-header.py b/tools/build_scripts/dummy-header.py
new file mode 100755
index 00000000..8c614645
--- /dev/null
+++ b/tools/build_scripts/dummy-header.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python3
+
+# External command, intended to be called with custom_target() in meson.build.
+
+# dummy-header.py <output_file>
+
+import os
+import sys
+
+output_file = sys.argv[1]
+
+# A dummy header file is created if it does not exist, but it's never updated.
+if not os.path.isfile(output_file):
+  with open(output_file, 'w') as f:
+    f.write('// Dummy header file. Created and used by meson.build\n')
diff --git a/tools/build_scripts/handle-built-files.py b/tools/build_scripts/handle-built-files.py
new file mode 100755
index 00000000..1b23f166
--- /dev/null
+++ b/tools/build_scripts/handle-built-files.py
@@ -0,0 +1,182 @@
+#!/usr/bin/env python3
+
+# External command, intended to be called with run_command(), custom_target(),
+# meson.add_install_script() and meson.add_dist_script().
+
+#                         argv[1]   argv[2:]
+# handle-built-files.py <subcommand> <xxx>...
+
+import os
+import sys
+import shutil
+import subprocess
+from pathlib import Path
+
+subcommand = sys.argv[1]
+
+# Invoked from custom_target() in meson.build.
+# This is similar to gmmproc() in mm-common's generate-binding.py.
+# It's slightly different because glibmm uses its uninstalled gmmproc.
+def gmmproc():
+  #  argv[2]       argv[3]    argv[4]       argv[5]      argv[6]   argv[7:]
+  # <gmmproc_dir> <pm_dir> <output_file> <basefilename> <src_dir> <m4_dirs>...
+
+  # <gmmproc_dir> is an absolute path in the build directory.
+  # <pm_dir> is an absolute path in the source directory.
+  # <output_file> is a relative or absolute path in the build directory.
+  # <src_dir> is an absolute path in the source directory.
+  # <m4_dirs> are absolute paths in the source directory.
+  gmmproc_dir = sys.argv[2]
+  pm_dir = sys.argv[3]
+  output_file = sys.argv[4]
+  output_dir = os.path.dirname(output_file)
+  basefilename = sys.argv[5] # name without filetype
+  src_dir = sys.argv[6]
+
+  include_m4_dirs = []
+  for dir in sys.argv[7:]:
+    include_m4_dirs += ['-I', dir]
+
+  # Create the private/ directory, if it does not exist.
+  os.makedirs(os.path.join(output_dir, 'private'), exist_ok=True)
+
+  # gmmproc generates output_dir/basefilename.cc, output_dir/basefilename.h
+  # and output_dir/private/{basefilename}_p.h
+  cmd = [
+    'perl',
+    '-I' + pm_dir,
+    '--',
+    os.path.join(gmmproc_dir, 'gmmproc'),
+  ] + include_m4_dirs + [
+    '--defs',
+    src_dir,
+    basefilename,
+    src_dir,
+    output_dir,
+  ]
+  result = subprocess.run(cmd)
+  if result.returncode:
+    return result.returncode
+
+  # gmmproc does not update the timestamps of output files that have not changed.
+  # That's by design, to avoid unnecessary recompilations.
+  # The updated timestamp of output_file shows meson that this custom_target()
+  # has been updated.
+  Path(output_file).touch(exist_ok=True)
+  return 0
+
+# Invoked from custom_target() in meson.build.
+def build_from_m4():
+  #     argv[2]      argv[3]      argv[4]
+  # <include_dir> <input_file> <output_file>
+
+  include_dir = sys.argv[2]
+  input_file = sys.argv[3]
+  output_file = sys.argv[4]
+
+  # Create the destination directory, if it does not exist.
+  output_dir = os.path.dirname(output_file)
+  os.makedirs(output_dir, exist_ok=True)
+
+  cmd = [
+    'm4',
+    '-I', include_dir,
+    input_file,
+  ]
+  output_file_obj = open(output_file, mode='w')
+  result = subprocess.run(cmd, stdout=output_file_obj)
+  output_file_obj.close()
+
+  return result.returncode
+
+# Invoked from meson.add_install_script().
+def install_built_h_files():
+  #    argv[2]       argv[3]          argv[4:]
+  # <built_h_dir> <install_subdir> <built_h_files>...
+
+  # <built_h_dir> is an absolute path in the build directory or source directory.
+  # <install_subdir> is an installation directory, relative to {prefix}.
+  built_h_dir = sys.argv[2]
+  install_dir_root = os.path.join(os.getenv('MESON_INSTALL_DESTDIR_PREFIX'), sys.argv[3])
+
+  for file in sys.argv[4:]:
+    path_h = os.path.join(built_h_dir, file)
+    rel_dir = os.path.dirname(file)
+    if rel_dir:
+      install_dir = os.path.join(install_dir_root, rel_dir)
+    else:
+      install_dir = install_dir_root
+    print('Installing ', path_h, ' to ', install_dir)
+
+    # Create the installation directory, if it does not exist.
+    os.makedirs(install_dir, exist_ok=True)
+
+    # shutil.copy2() copies timestamps and some other file metadata.
+    shutil.copy2(path_h, install_dir)
+  return 0
+
+# Invoked from meson.add_dist_script().
+def dist_built_files(is_msvc_files=False):
+  #     argv[2]        argv[3]     argv[4:]
+  # <built_h_cc_dir> <dist_dir> <built_files>...
+
+  # <built_h_cc_dir> is an absolute path in the build directory or source directory.
+  # <dist_dir> is a distribution directory, relative to MESON_DIST_ROOT.
+  built_h_cc_dir = sys.argv[2]
+  dist_dir_root = os.path.join(os.getenv('MESON_DIST_ROOT'), sys.argv[3])
+  dist_dir = dist_dir_root
+
+  # Distribute .h and .cc files built from .m4 files, or generated MSVC files.
+  for file in sys.argv[4:]:
+    if not is_msvc_files:
+      dist_dir = os.path.join(dist_dir_root, os.path.dirname(file))
+
+    # Create the distribution directory, if it does not exist.
+    os.makedirs(dist_dir, exist_ok=True)
+
+    shutil.copy(os.path.join(built_h_cc_dir, file), dist_dir)
+  return 0
+
+# Invoked from run_command() in meson.build.
+def copy_built_files():
+  #  argv[2]    argv[3]    argv[4:]
+  # <from_dir> <to_dir> <file_names>...
+
+  # <from_dir> is an absolute or relative path of the directory to copy from.
+  # <to_dir> is an absolute or relative path of the directory to copy to.
+  from_dir_root = sys.argv[2]
+  to_dir_root = sys.argv[3]
+
+  # Copy some built files if they exist in from_dir, but not in the destination
+  # directory, or if they are not up to date in the destination directory.
+  # (The term "source directory" is avoided here, because from_dir might not
+  # be what Meson calls a source directory as opposed to a build directory.)
+
+  # Copy .h and .cc files built from .m4 files.
+  for file in sys.argv[4:]:
+    from_file = os.path.join(from_dir_root, file)
+    to_file = os.path.join(to_dir_root, file)
+    if os.path.isfile(from_file) and ((not os.path.isfile(to_file))
+       or (os.stat(from_file).st_mtime > os.stat(to_file).st_mtime)):
+
+      # Create the destination directory, if it does not exist.
+      os.makedirs(os.path.dirname(to_file), exist_ok=True)
+
+      shutil.copy(from_file, to_file)
+  return 0
+
+# ----- Main -----
+if subcommand == 'gmmproc':
+  sys.exit(gmmproc())
+if subcommand == 'build_from_m4':
+  sys.exit(build_from_m4())
+if subcommand == 'install_built_h_files':
+  sys.exit(install_built_h_files())
+if subcommand == 'dist_built_files':
+  sys.exit(dist_built_files())
+if subcommand == 'copy_built_files':
+  sys.exit(copy_built_files())
+if subcommand == 'dist_gen_msvc_files':
+  sys.exit(dist_built_files(True))
+print(sys.argv[0], ': illegal subcommand,', subcommand)
+sys.exit(1)
diff --git a/tools/conf_tests/allows_static_inline_npos.cc b/tools/conf_tests/allows_static_inline_npos.cc
new file mode 100644
index 00000000..ac11b5d4
--- /dev/null
+++ b/tools/conf_tests/allows_static_inline_npos.cc
@@ -0,0 +1,21 @@
+// Configuration-time test program, used in Meson build.
+// Check whether a static member variable may be initialized inline to std::string::npos.
+// The MipsPro (IRIX) compiler does not like this.
+// Corresponds to the M4 macro GLIBMM_CXX_ALLOWS_STATIC_INLINE_NPOS.
+
+#include <string>
+#include <iostream>
+
+class ustringtest
+{
+public:
+  // The MipsPro compiler (IRIX) says "The indicated constant value is not known",
+  // so we need to initialize the static member data elsewhere.
+  static const std::string::size_type ustringnpos = std::string::npos;
+};
+
+int main()
+{
+  std::cout << "npos=" << ustringtest::ustringnpos << std::endl;
+  return 0;
+}
diff --git a/tools/conf_tests/can_assign_non_extern_c_functions_to_extern_c_cb.cc 
b/tools/conf_tests/can_assign_non_extern_c_functions_to_extern_c_cb.cc
new file mode 100644
index 00000000..d3c937fb
--- /dev/null
+++ b/tools/conf_tests/can_assign_non_extern_c_functions_to_extern_c_cb.cc
@@ -0,0 +1,22 @@
+// Configuration-time test program, used in Meson build.
+// Check whether the compiler allows us to use a non-extern "C" function,
+// such as a static member function, to an extern "C" function pointer,
+// such as a GTK callback.
+// Corresponds to the M4 macro GLIBMM_CXX_CAN_ASSIGN_NON_EXTERN_C_FUNCTIONS_TO_EXTERN_C_CALLBACKS.
+
+extern "C"
+{
+struct somestruct
+{
+  void (*callback) (int);
+};
+} // extern "C"
+
+void somefunction(int) {}
+
+int main()
+{
+  somestruct something;
+  something.callback = &somefunction;
+  return 0;
+}
diff --git a/tools/conf_tests/can_use_dynamic_cast_in_unused_template_wo_def.cc 
b/tools/conf_tests/can_use_dynamic_cast_in_unused_template_wo_def.cc
new file mode 100644
index 00000000..9620d80c
--- /dev/null
+++ b/tools/conf_tests/can_use_dynamic_cast_in_unused_template_wo_def.cc
@@ -0,0 +1,21 @@
+// Configuration-time test program, used in Meson build.
+// Check whether the compiler allows us to define a template that uses
+// dynamic_cast<> with an object whose type is not defined, even if we do
+// not use that template before we have defined the type. This should
+// probably not be allowed anyway.
+// Corresponds to the M4 macro GLIBMM_CXX_CAN_USE_DYNAMIC_CAST_IN_UNUSED_TEMPLATE_WITHOUT_DEFINITION.
+
+class SomeClass;
+
+SomeClass* some_function();
+
+template <class T>
+class SomeTemplate
+{
+  static bool do_something()
+  {
+    // This does not compile with the MipsPro (IRIX) compiler
+    // even if we don't use this template at all.
+    return (dynamic_cast<T*>(some_function()) != 0);
+  }
+};
diff --git a/tools/conf_tests/have_disambiguous_const_template_specializations.cc 
b/tools/conf_tests/have_disambiguous_const_template_specializations.cc
new file mode 100644
index 00000000..3f4eaf1f
--- /dev/null
+++ b/tools/conf_tests/have_disambiguous_const_template_specializations.cc
@@ -0,0 +1,37 @@
+// Configuration-time test program, used in Meson build.
+// Check whether the compiler finds it ambiguous to have both const and
+// non-const template specializations. The SUN Forte compiler has this
+// problem, though we are not 100% sure that it's a C++ standard violation.
+// Corresponds to the M4 macro GLIBMM_CXX_CAN_DISAMBIGUATE_CONST_TEMPLATE_SPECIALIZATIONS.
+
+template <class T> class Foo {};
+
+template <class T> class Traits
+{
+public:
+  const char* whoami() { return "generic template"; }
+};
+
+template <class T> class Traits< Foo<T> >
+{
+public:
+  const char* whoami() { return "partial specialization for Foo<T>"; }
+};
+
+template <class T> class Traits< Foo<const T> >
+{
+public:
+  const char* whoami() { return "partial specialization for Foo<const T>"; }
+};
+
+int main()
+{
+  Traits<int> it;
+  Traits< Foo<int> > fit;
+  Traits< Foo<const int> > cfit;
+
+  (void) it.whoami();
+  (void) fit.whoami();
+  (void) cfit.whoami();
+  return 0;
+}
diff --git a/tools/conf_tests/have_std_iterator_traits.cc b/tools/conf_tests/have_std_iterator_traits.cc
new file mode 100644
index 00000000..1e1f2b0f
--- /dev/null
+++ b/tools/conf_tests/have_std_iterator_traits.cc
@@ -0,0 +1,11 @@
+// Configuration-time test program, used in Meson build.
+// Check for standard-conforming std::iterator_traits<>.
+// Corresponds to the M4 macro GLIBMM_CXX_HAS_STD_ITERATOR_TRAITS.
+
+#include <iterator>
+
+int main()
+{
+  typedef std::iterator_traits<char*>::value_type ValueType;
+  return 0;
+}
diff --git a/tools/conf_tests/have_sun_reverse_iterator.cc b/tools/conf_tests/have_sun_reverse_iterator.cc
new file mode 100644
index 00000000..43721e01
--- /dev/null
+++ b/tools/conf_tests/have_sun_reverse_iterator.cc
@@ -0,0 +1,11 @@
+// Configuration-time test program, used in Meson build.
+// Check for Sun libCstd style std::reverse_iterator,
+// Corresponds to the M4 macro GLIBMM_CXX_HAS_SUN_REVERSE_ITERATOR.
+
+#include <iterator>
+
+int main()
+{
+  typedef std::reverse_iterator<char*, std::random_access_iterator_tag, char, char&, char*, int> ReverseIter;
+  return 0;
+}
diff --git a/tools/conf_tests/have_template_sequence_ctors.cc 
b/tools/conf_tests/have_template_sequence_ctors.cc
new file mode 100644
index 00000000..6423684b
--- /dev/null
+++ b/tools/conf_tests/have_template_sequence_ctors.cc
@@ -0,0 +1,17 @@
+// Configuration-time test program, used in Meson build.
+// Check whether the STL containers have templated sequence ctors,
+// Corresponds to the M4 macro GLIBMM_CXX_HAS_TEMPLATE_SEQUENCE_CTORS.
+
+#include <vector>
+#include <deque>
+#include <list>
+
+int main()
+{
+  const int array[8] = { 0, };
+  std::vector<int>  test_vector(&array[0], &array[8]);
+  std::deque<short> test_deque(test_vector.begin(), test_vector.end());
+  std::list<long>   test_list(test_deque.begin(),  test_deque.end());
+  test_vector.assign(test_list.begin(), test_list.end());
+  return 0;
+}
diff --git a/tools/conf_tests/have_wide_stream.cc b/tools/conf_tests/have_wide_stream.cc
new file mode 100644
index 00000000..9cfd19dd
--- /dev/null
+++ b/tools/conf_tests/have_wide_stream.cc
@@ -0,0 +1,12 @@
+// Configuration-time test program, used in Meson build.
+// Check whether std::wostringstream exists.
+// Corresponds to some code in configure.ac.
+
+#include <sstream>
+
+int main()
+{
+  std::wostringstream s;
+  (void) s.str();
+  return 0;
+}
diff --git a/tools/extra_defs_gen/meson.build b/tools/extra_defs_gen/meson.build
new file mode 100644
index 00000000..06c3b703
--- /dev/null
+++ b/tools/extra_defs_gen/meson.build
@@ -0,0 +1,27 @@
+# tools/extra_defs_gen
+
+# Input: is_msvc, glibmm_build_dep, giomm_build_dep, glibmm_api_version,
+#        glibmm_libversion
+# Output: -
+
+glibmm_generate_extra_defs_library = library(
+  'glibmm_generate_extra_defs-' + glibmm_api_version,
+  'generate_extra_defs.cc',
+  version: glibmm_libversion,
+  dependencies: glibmm_build_dep,
+  install: true,
+)
+
+if not is_msvc
+  executable('generate_defs_glib', 'generate_defs_glib.cc',
+    dependencies: glibmm_build_dep,
+    link_with: glibmm_generate_extra_defs_library,
+    install: false,
+  )
+
+  executable('generate_defs_gio', 'generate_defs_gio.cc',
+    dependencies: giomm_build_dep,
+    link_with: glibmm_generate_extra_defs_library,
+    install: false,
+  )
+endif
diff --git a/tools/meson.build b/tools/meson.build
new file mode 100644
index 00000000..f1288171
--- /dev/null
+++ b/tools/meson.build
@@ -0,0 +1,100 @@
+# tools
+
+# Input: perl, m4, install_prefix, install_libdir, glibmm_pcname
+# Output: m4_files, install_m4dir, pm_files, install_pmdir
+
+subdir('extra_defs_gen')
+
+install_procdir = install_libdir / glibmm_pcname / 'proc'
+
+# Configuration data for gmmproc.
+gmmproc_conf_data = configuration_data()
+gmmproc_conf_data.set('PERL', perl.found() ? perl.path() : '')
+gmmproc_conf_data.set('configure_input', 'tools/gmmproc.  Generated from gmmproc.in')
+gmmproc_conf_data.set('prefix', install_prefix)
+gmmproc_conf_data.set('exec_prefix', '${prefix}')
+gmmproc_conf_data.set('libdir', '${exec_prefix}' / install_libdir)
+gmmproc_conf_data.set('GLIBMM_MODULE_NAME', glibmm_pcname)
+gmmproc_conf_data.set('M4', m4.found() ? m4.path() : '')
+gmmproc_conf_data.set('PACKAGE_VERSION', meson.project_version())
+
+configure_file(
+  input: 'gmmproc.in',
+  output: '@BASENAME@',
+  configuration: gmmproc_conf_data,
+  install_dir: install_procdir,
+)
+
+# Configuration data for generate_wrap_init.pl.
+gen_wrap_init_conf_data = configuration_data()
+gen_wrap_init_conf_data.set('PERL', perl.found() ? perl.path() : '')
+gen_wrap_init_conf_data.set('configure_input',
+  'tools/generate_wrap_init.pl.  Generated from generate_wrap_init.pl.in')
+
+configure_file(
+  input: 'generate_wrap_init.pl.in',
+  output: '@BASENAME@',
+  configuration: gen_wrap_init_conf_data,
+  install_dir: install_procdir,
+)
+
+# Install m4 files for reuse by other *mm projects, when building from git.
+m4_basefiles = [
+  'base.m4',
+  'class_boxedtype.m4',
+  'class_boxedtype_static.m4',
+  'class_generic.m4',
+  'class_gobject.m4',
+  'class_interface.m4',
+  'class_opaque_copyable.m4',
+  'class_opaque_refcounted.m4',
+  'class_shared.m4',
+  'compare.m4',
+  'convert.m4',
+  'convert_base.m4',
+  'convert_gio.m4',
+  'convert_glib.m4',
+  'convert_glibmm.m4',
+  'ctor.m4',
+  'doc.m4',
+  'enum.m4',
+  'gerror.m4',
+  'initialize.m4',
+  'initialize_base.m4',
+  'initialize_gio.m4',
+  'initialize_glib.m4',
+  'initialize_glibmm.m4',
+  'member.m4',
+  'method.m4',
+  'property.m4',
+  'signal.m4',
+  'vfunc.m4',
+]
+m4_files = []
+foreach file : m4_basefiles
+  m4_files += 'm4' / file
+endforeach
+m4_files = files(m4_files)
+install_m4dir = install_procdir / 'm4'
+install_data(m4_files, install_dir: install_m4dir)
+
+# Install pm files for reuse by other *mm projects, when building from git.
+pm_basefiles = [
+  'DocsParser.pm',
+  'Enum.pm',
+  'Function.pm',
+  'FunctionBase.pm',
+  'GtkDefs.pm',
+  'Object.pm',
+  'Output.pm',
+  'Property.pm',
+  'Util.pm',
+  'WrapParser.pm',
+]
+pm_files = []
+foreach file : pm_basefiles
+  pm_files += 'pm' / file
+endforeach
+pm_files = files(pm_files)
+install_pmdir = install_procdir / 'pm'
+install_data(pm_files, install_dir: install_pmdir)
diff --git a/untracked/README b/untracked/README
new file mode 100644
index 00000000..34c4cdeb
--- /dev/null
+++ b/untracked/README
@@ -0,0 +1,39 @@
+untracked/README
+
+This directory contains files not tracked by a source code control program,
+such as git. (This README file is the exception.)
+
+The files can have one of two origins.
+
+1. Copied by the mm-common-get command.
+2. Generated when glibmm is built.
+
+Files of type 2 exist here only if glibmm is built with maintainer-mode=false,
+or the directory comes from a tarball.
+Files of both types exist here only if glibmm is built with Meson,
+or the tarball is created with Meson.
+
+1. Files copied by mm-common-get
+--------------------------------
+untracked/docs/doc-install.pl
+               doc-postprocess.pl
+               doxygen-extra.css
+               tagfile-to-devhelp2.xsl
+untracked/build_scripts/dist-build-scripts.py
+                        dist-changelog.py
+                        doc-reference.py
+                        generate-binding.py
+
+mm-common-get may copy more files, but they are not used by glibmm.
+
+2. Generated files
+------------------
+untracked/gio/giomm/*.h
+                    *.cc
+                    private/*_p.h
+untracked/glib/glibmm/*.h
+                      *.cc
+                      private/*_p.h
+untracked/docs/reference/glibmm-2.64.devhelp2
+                         glibmm-2.64.tag
+                         html/*


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