[atkmm/kjellahl/meson-build-2-28] Add support for building atkmm with Meson



commit 8c37cce65460abe697ff2a7cefed30315363a860
Author: Kjell Ahlstedt <kjellahlstedt gmail com>
Date:   Wed Apr 15 13:21:05 2020 +0200

    Add support for building atkmm with Meson
    
    atkmm-1.6 can be built with either Autotools or Meson.
    New files have been copied from pangomm-1.4 and modified.
    
    See MR !8

 .gitignore                    |   4 +
 MSVC_NMake/atkmm/meson.build  |  17 ++
 MSVC_NMake/gendef/meson.build |   9 ++
 Makefile.am                   |  14 ++
 README                        |  82 ++++++++++
 atk/atkmm/meson.build         | 265 +++++++++++++++++++++++++++++++
 atk/atkmmconfig.h.meson       |  38 +++++
 atk/meson.build               |  60 +++++++
 codegen/dummy-header.py       |  15 ++
 codegen/extradefs/meson.build |  26 +++
 doc/reference/meson.build     | 148 +++++++++++++++++
 meson.build                   | 357 ++++++++++++++++++++++++++++++++++++++++++
 meson_options.txt             |  12 ++
 untracked/README              |  37 +++++
 14 files changed, 1084 insertions(+)
---
diff --git a/.gitignore b/.gitignore
index 2ffd368..842a41c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,3 +32,7 @@ stamp-h?
 /MSVC_NMake/atkmm/atkmm.rc
 /MSVC_NMake/atkmm/atkmmconfig.h
 /MSVC_NMake/pkg-ver.mak
+
+untracked/build_scripts/
+untracked/doc/
+untracked/atk/
diff --git a/MSVC_NMake/atkmm/meson.build b/MSVC_NMake/atkmm/meson.build
new file mode 100644
index 0000000..16d1481
--- /dev/null
+++ b/MSVC_NMake/atkmm/meson.build
@@ -0,0 +1,17 @@
+# MSVC_NMake/atkmm
+
+# Input: pkg_conf_data, atkmmconfig_h
+# Output: atkmm_rc
+
+atkmm_rc = configure_file(
+  input: 'atkmm.rc.in',
+  output: '@BASENAME@',
+  configuration: pkg_conf_data,
+)
+
+# Copy the generated configuration header into the MSVC project directory.
+configure_file(
+  input: atkmmconfig_h,
+  output: 'atkmmconfig.h',
+  copy: true,
+)
diff --git a/MSVC_NMake/gendef/meson.build b/MSVC_NMake/gendef/meson.build
new file mode 100644
index 0000000..32babb7
--- /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/Makefile.am b/Makefile.am
index af71596..afca90d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -49,5 +49,19 @@ dist_noinst_SCRIPTS = autogen.sh
 
 DISTCLEANFILES = $(filter %mmconfig.h,$(msvc_files))
 
+# Distribute files needed when building atkmm with Meson.
+EXTRA_DIST = \
+  meson.build \
+  meson_options.txt \
+  MSVC_NMake/atkmm/meson.build \
+  MSVC_NMake/gendef/meson.build \
+  doc/reference/meson.build \
+  atk/meson.build \
+  atk/atkmm/meson.build \
+  atk/atkmmconfig.h.meson \
+  codegen/dummy-header.py \
+  codegen/extradefs/meson.build \
+  untracked/README
+
 # Auto-generate the ChangeLog file from the git log on make dist
 include $(top_srcdir)/build/dist-changelog.am
diff --git a/README b/README
index e3ac5c9..8e4adee 100644
--- a/README
+++ b/README
@@ -1,2 +1,84 @@
 atkmm is the C++ binding for the ATK library.
 This module is part of the GNOME C++ bindings effort <http://www.gtkmm.org/>.
+
+# Building
+
+Whenever possible, you should use the official binary packages approved by the
+supplier of your operating system, such as your Linux distribution.
+
+## Building on Windows
+
+See README.win32
+
+## Building from a release tarball
+
+Extract the tarball and go to the extracted directory:
+  $ tar xf atkmm-@ATKMM_VERSION  tar xz
+  $ cd atkmm-@ATKMM_VERSION@
+
+It's easiest to build with Meson, if the tarball was made with Meson,
+and to build with Autotools, if the tarball was made with Autotools.
+Then you don't have to use maintainer-mode.
+
+How do you know how the tarball was made? If it was made with Meson,
+it contains files in untracked/atk/atkmm/ and other subdirectories
+of untracked/.
+
+### Building from a tarball with Meson
+
+Don't call the builddir 'build'. There is a directory called 'build' with
+files used by Autotools.
+
+  $ meson --prefix /some_directory --libdir lib your_builddir .
+  $ cd your_builddir
+
+If the tarball was made with Autotools, you must enable maintainer-mode:
+  $ meson configure -Dmaintainer-mode=true
+
+Then, regardless of how the tarball was made:
+  $ ninja
+  $ ninja install
+
+### Building from a tarball with Autotools
+
+If the tarball was made with Autotools:
+  $ ./configure --prefix=/some_directory
+If the tarball was made with Meson, you must enable maintainer-mode:
+  $ ./autogen.sh --prefix=/some_directory
+
+Then, regardless of how the tarball was made:
+  $ make
+  $ make install
+
+## Building from git
+
+Building from git can be difficult so you should prefer building from
+a release tarball unless you need to work on the atkmm code itself.
+
+jhbuild can be a good help
+  https://gitlab.gnome.org/GNOME/jhbuild
+  https://wiki.gnome.org/Projects/Jhbuild
+
+### Building from git with Meson
+
+Maintainer-mode is enabled by default when you build from a git clone.
+
+Don't call the builddir 'build'. There is a directory called 'build' with
+files used by Autotools.
+
+  $ meson --prefix /some_directory --libdir lib your_builddir .
+  $ cd your_builddir
+  $ ninja
+  $ ninja install
+You can create a tarball like so:
+  $ ninja dist
+
+### Building from git with Autotools
+
+  $ ./autogen.sh --prefix=/some_directory
+  $ make
+  $ make install
+You can create a tarball like so:
+  $ make distcheck
+or
+  $ make dist
diff --git a/atk/atkmm/meson.build b/atk/atkmm/meson.build
new file mode 100644
index 0000000..e3e217e
--- /dev/null
+++ b/atk/atkmm/meson.build
@@ -0,0 +1,265 @@
+# atk/atkmm
+
+# Input: atkmm_build_dep, atkmm_pcname, maintainer_mode, project_source_root,
+#        generate_binding_py, m4_files, atkmm_libversion, install_includedir,
+#        python3, atkmm_rc, dummy_header_py, gmmproc_dir, build_shared_libs_directly
+# Output: hg_ccg_basenames, extra_h_files, built_h_file_targets, built_files_root,
+#         atkmm_dep
+
+defs_basefiles = [
+  'atk.defs',
+  'atk_enums.defs',
+  'atk_methods.defs',
+  'atk_signals.defs',
+  'atk_vfuncs.defs',
+  'atk_docs.xml',
+  'atk_docs_override.xml',
+]
+
+defs_files = []
+foreach file : defs_basefiles
+  defs_files += '..' / 'src' / file
+endforeach
+
+hg_ccg_basenames = [
+  'action',
+  'component',
+  'document',
+  'editabletext',
+  'hyperlink',
+  'hypertext',
+  'image',
+  'implementor',
+  'noopobject',
+  'object',
+  'objectaccessible',
+  'range',
+  'relation',
+  'relationset',
+  'selection',
+  'stateset',
+  'streamablecontent',
+  'table',
+  'text',
+  'value',
+]
+
+extra_cc_files = [
+  'init.cc',
+]
+
+extra_h_files = [
+  'init.h',
+  'wrap_init.h',
+]
+
+install_headers('..' / 'atkmm.h', subdir: atkmm_pcname)
+install_headers(extra_h_files, subdir: atkmm_pcname / 'atkmm')
+
+untracked_atkmm = 'untracked' / 'atk' / 'atkmm'
+src_untracked_atkmm = project_source_root / untracked_atkmm
+
+atkmm_cpp_args = [ '-DATKMM_BUILD=1' ]
+
+if is_msvc and not build_shared_libs_directly
+  atkmm_cpp_args += '-DATKMM_USE_GENDEF'
+endif
+
+if maintainer_mode
+
+  # Maintainer mode. Generate .h and .cc files from .hg and .ccg files in ../src.
+
+  # doc/reference/meson.build needs these.
+  built_files_root = project_build_root
+  built_h_file_targets = []
+
+  # Force meson+ninja to generate source files before anything is compiled.
+  # Compilation must depend on these targets.
+  built_cc_file_targets = []
+
+  hg_files = []
+  foreach file : hg_ccg_basenames
+    hg_files += '..' / 'src' / file + '.hg'
+  endforeach
+
+  # Create wrap_init.cc in project_build_root/atk/atkmm.
+  built_cc_file_targets += custom_target('wrap_init.cc',
+    input: hg_files,
+    output: 'wrap_init.cc',
+    command: [
+      python3, generate_binding_py, 'generate_wrap_init',
+      gmmproc_dir,
+      '@OUTPUT@',
+      'Atk', # namespace
+      '@INPUT@',
+    ],
+    build_by_default: maintainer_mode,
+    install: false,
+  )
+
+  # Create .h/_p.h/.cc files from .hg/.ccg files in project_build_root/atk/atkmm.
+  foreach file : hg_ccg_basenames
+    hg_file = '..' / 'src' / file + '.hg'
+    ccg_file = '..' / 'src' / file + '.ccg'
+    built_file_target = custom_target(file + '.cc',
+      input: [hg_file, ccg_file],
+      output: [file + '.stamp', file + '.cc', file + '.h'],
+      command: [
+        python3, generate_binding_py, 'gmmproc',
+        gmmproc_dir,
+        '@OUTPUT0@',
+        file,
+        meson.current_source_dir() / '..' / 'src',
+        project_source_root / 'codegen' / 'm4',
+      ],
+      depend_files: defs_files + m4_files,
+      build_by_default: maintainer_mode,
+      install: false,
+    )
+    built_cc_file_targets += built_file_target[1]
+    built_h_file_targets += built_file_target[2]
+  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 atkmm_library
+  # is built, at the same time avoiding unnecessary recompilations.
+  # If built_h_file_targets would be listed as sources to atkmm_library,
+  # all generated .cc files could be recompiled if one generated .h file has
+  # been changed.
+  built_dummy_h_file_target = custom_target('dummy_header.h',
+    input: built_h_file_targets,
+    output: 'dummy_header.h',
+    command: [
+      python3, dummy_header_py,
+      '@OUTPUT@',
+    ],
+    build_by_default: maintainer_mode,
+    install: false,
+  )
+
+  extra_include_dirs = ['..']
+
+  atk_gen_sources = built_cc_file_targets
+
+  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/atk/atkmm.
+
+  # doc/reference/meson.build needs these.
+  built_files_root = project_source_root / 'untracked'
+  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_atkmm,
+    hg_ccg_basenames,
+  )
+
+  built_cc_files = [ src_untracked_atkmm / 'wrap_init.cc' ]
+  foreach file : hg_ccg_basenames
+    built_cc_files += src_untracked_atkmm / file + '.cc'
+  endforeach
+
+  atk_gen_sources = built_cc_files
+  built_dummy_h_file_target = []
+
+  extra_include_dirs = [ '..', '..' / '..' / 'untracked' / 'atk' ]
+
+  built_h_cc_dir = src_untracked_atkmm
+
+endif
+
+extra_atkmm_objects = []
+
+# Build the .rc file for Windows builds and link to it
+if host_machine.system() == 'windows'
+  windows = import('windows')
+  atkmm_res = windows.compile_resources(atkmm_rc)
+  extra_atkmm_objects += atkmm_res
+endif
+
+if build_shared_libs_directly
+  atkmm_library = library(atkmm_pcname, extra_atkmm_objects,
+    atk_gen_sources, built_dummy_h_file_target, extra_cc_files,
+    include_directories: extra_include_dirs,
+    cpp_args: atkmm_cpp_args,
+    version: atkmm_libversion,
+    dependencies: atkmm_build_dep,
+    install: true,
+  )
+else
+  # Building with headers generated from *.hg files with
+  # gmmproc < 2.64.0 on Visual Studio: We need this so
+  # that we can run gendef.exe to get the .def file
+  # needed for obtaining the .lib file for the atkmm DLL
+  atk_int_lib = static_library('atkmm-int',
+    atk_gen_sources, built_dummy_h_file_target, extra_cc_files,
+    include_directories: extra_include_dirs,
+    cpp_args: atkmm_cpp_args,
+    dependencies: atkmm_build_dep,
+    install: false,
+  )
+
+  atkmm_def = custom_target('atkmm.def',
+    output: 'atkmm.def',
+    depends: atk_int_lib,
+    command: [ gendef,
+      '@OUTPUT@',
+      '@0@-@1@.dll'.format(atkmm_pcname, atkmm_libversion.split('.')[0]),
+      atk_int_lib.full_path(),
+    ],
+    install: false,
+  )
+  atkmm_extra_link_args = ['/def:@0@'.format(atkmm_def.full_path())]
+
+  atkmm_library = library(atkmm_pcname, extra_atkmm_objects,
+    objects: atk_int_lib.extract_all_objects(),
+    version: atkmm_libversion,
+    dependencies: atkmm_build_dep,
+    link_depends: atkmm_def,
+    link_args: atkmm_extra_link_args,
+    install: true,
+  )
+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 / atkmm_pcname / 'atkmm', # subdir below {prefix}
+  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_atkmm,
+    hg_ccg_basenames,
+  )
+endif
+
+# This is useful in the main project when atkmm is used as a subproject.
+# It can also be used if there are example programs and test programs to build.
+atkmm_dep = declare_dependency(
+  sources: built_h_file_targets,
+  link_with: atkmm_library,
+  include_directories: extra_include_dirs,
+  dependencies: atkmm_build_dep
+)
diff --git a/atk/atkmmconfig.h.meson b/atk/atkmmconfig.h.meson
new file mode 100644
index 0000000..a039354
--- /dev/null
+++ b/atk/atkmmconfig.h.meson
@@ -0,0 +1,38 @@
+/* atkmm library configuration header */
+
+#ifndef ATKMMCONFIG_H_INCLUDED
+#define ATKMMCONFIG_H_INCLUDED
+
+#include <glibmmconfig.h>
+
+/* Define to omit deprecated API from the library. */
+#mesondefine ATKMM_DISABLE_DEPRECATED
+
+/* Major version number of atkmm. */
+#mesondefine ATKMM_MAJOR_VERSION
+
+/* Minor version number of atkmm. */
+#mesondefine ATKMM_MINOR_VERSION
+
+/* Micro version number of atkmm. */
+#mesondefine ATKMM_MICRO_VERSION
+
+/* Define when building atkmm as a static library. */
+#mesondefine ATKMM_STATIC_LIB
+
+/* Enable DLL-specific stuff only when not building a static library */
+#if !defined(ATKMM_STATIC_LIB) && ((defined(__MINGW32__) && !defined(__CYGWIN__)) || defined (_MSC_VER)) && 
!defined (ATKMM_USE_GENDEF)
+# define ATKMM_DLL 1
+#endif
+
+#ifdef ATKMM_DLL
+# ifdef ATKMM_BUILD
+#  define ATKMM_API __declspec(dllexport)
+# else
+#  define ATKMM_API __declspec(dllimport)
+# endif
+#else
+# define ATKMM_API
+#endif
+
+#endif /* !ATKMMCONFIG_H_INCLUDED */
diff --git a/atk/meson.build b/atk/meson.build
new file mode 100644
index 0000000..ba29d23
--- /dev/null
+++ b/atk/meson.build
@@ -0,0 +1,60 @@
+# atk
+
+# Input: install_prefix, install_datadir, install_includedir,
+#        atkmm_pcname, atkmm_api_version, atkmm_requires,
+#        install_pkgconfigdir, install_libdir, build_deprecated_api,
+#        atkmm_major_version, atkmm_minor_version, atkmm_micro_version
+# Output: pkg_conf_data, install_includeconfigdir, atkmmconfig_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('srcdir', meson.current_source_dir())
+pkg_conf_data.set('PACKAGE_TARNAME', meson.project_name())
+pkg_conf_data.set('PACKAGE_VERSION', meson.project_version())
+pkg_conf_data.set('ATKMM_MODULE_NAME', atkmm_pcname)
+pkg_conf_data.set('ATKMM_API_VERSION', atkmm_api_version)
+pkg_conf_data.set('ATKMM_MODULES', atkmm_requires)
+if not build_deprecated_api
+  pkg_conf_data.set('ATKMM_DISABLE_DEPRECATED', 1)
+endif
+pkg_conf_data.set('ATKMM_MAJOR_VERSION', atkmm_major_version)
+pkg_conf_data.set('ATKMM_MINOR_VERSION', atkmm_minor_version)
+pkg_conf_data.set('ATKMM_MICRO_VERSION', atkmm_micro_version)
+
+library_build_type = get_option('default_library')
+
+if cpp_compiler.get_argument_syntax() == 'msvc'
+  if library_build_type == 'static' or library_build_type == 'both'
+    error('Static builds are not supported by MSVC-style builds')
+  endif
+endif
+
+if library_build_type == 'static'
+  pkg_conf_data.set('ATKMM_STATIC_LIB', 1)
+endif
+
+configure_file(
+  input: 'atkmm.pc.in',
+  output: atkmm_pcname + '.pc',
+  configuration: pkg_conf_data,
+  install_dir: install_pkgconfigdir,
+)
+
+configure_file(
+  input: 'atkmm-uninstalled.pc.in',
+  output: atkmm_pcname + '-uninstalled.pc',
+  configuration: pkg_conf_data,
+)
+
+install_includeconfigdir = install_libdir / atkmm_pcname / 'include'
+atkmmconfig_h = configure_file(
+  input: 'atkmmconfig.h.meson',
+  output: 'atkmmconfig.h',
+  configuration: pkg_conf_data,
+  install_dir: install_includeconfigdir,
+)
diff --git a/codegen/dummy-header.py b/codegen/dummy-header.py
new file mode 100755
index 0000000..8c61464
--- /dev/null
+++ b/codegen/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/codegen/extradefs/meson.build b/codegen/extradefs/meson.build
new file mode 100644
index 0000000..6d432b2
--- /dev/null
+++ b/codegen/extradefs/meson.build
@@ -0,0 +1,26 @@
+# codegen/extradefs
+
+# Input: cpp_compiler, atkmm_build_dep, install_libdir, atkmm_pcname
+# Output: m4_files, install_m4dir
+
+glibmm_generate_extra_defs_dep = cpp_compiler.find_library(
+  'glibmm_generate_extra_defs-2.4',
+)
+
+executable('generate_extra_defs', 'generate_extra_defs_atk.cc',
+  dependencies: [atkmm_build_dep, glibmm_generate_extra_defs_dep],
+  install: false,
+)
+
+# Install m4 files for reuse by other *mm projects, when building from git.
+m4_basefiles = [
+  'convert.m4',
+  'convert_atk.m4',
+]
+m4_files = []
+foreach file : m4_basefiles
+  m4_files += '..' / 'm4' / file
+endforeach
+m4_files = files(m4_files)
+install_m4dir = install_libdir / atkmm_pcname / 'proc' / 'm4'
+install_data(m4_files, install_dir: install_m4dir)
diff --git a/doc/reference/meson.build b/doc/reference/meson.build
new file mode 100644
index 0000000..d2cd38c
--- /dev/null
+++ b/doc/reference/meson.build
@@ -0,0 +1,148 @@
+# doc/reference
+
+# Input: built_files_root, project_source_root, atkmm_pcname, perl,
+#        hg_ccg_basenames, extra_h_files, built_h_file_targets, install_datadir,
+#        python3, doc_reference_py
+# Output: install_docdir, install_devhelpdir
+
+tag_file_modules = [
+  'mm-common-libstdc++',
+  'sigc++-2.0',
+  'glibmm-2.4',
+]
+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 = atkmm_pcname
+book_title = meson.project_name() + ' Reference Manual'
+
+# Configuration data for Doxyfile.
+doc_conf_data = configuration_data()
+doc_conf_data.set('configure_input',
+  'doc/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('ATKMM_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 : hg_ccg_basenames
+  built_h_files += built_files_root / 'atk' / 'atkmm' / file + '.h'
+endforeach
+
+# Hand-coded input .h files to Doxygen.
+src_h_files = []
+foreach file : extra_h_files
+  if file != 'wrap_init.h'
+    src_h_files += project_source_root / 'atk' / 'atkmm' / file
+  endif
+endforeach
+src_h_files += project_source_root / 'atk' / 'atkmm.h'
+
+doctool_dir = project_source_root / 'untracked' / 'doc' # MMDOCTOOLDIR
+doctool_dist_dir = 'untracked' / 'doc' # Relative to MESON_DIST_ROOT
+
+doc_h_files = src_h_files
+if 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 += 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
+)
+
+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/meson.build b/meson.build
new file mode 100644
index 0000000..93f5dd4
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,357 @@
+# This file is part of atkmm.
+
+project('atkmm', 'cpp',
+  version: '2.28.0',
+  license: 'LGPLv2.1+',
+  default_options: [
+    'cpp_std=c++11'
+  ],
+  meson_version: '>= 0.50.0', # required for python3.path()
+)
+
+atkmm_api_version = '1.6'
+atkmm_pcname = meson.project_name() + '-' + atkmm_api_version
+
+atkmm_version_array = meson.project_version().split('.')
+atkmm_major_version = atkmm_version_array[0].to_int()
+atkmm_minor_version = atkmm_version_array[1].to_int()
+atkmm_micro_version = atkmm_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 = [2, 0, 1]
+atkmm_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'
+python3 = import('python').find_installation('python3')
+
+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
+
+# Are we testing a dist tarball while it's being built?
+# There ought to be a better way. https://github.com/mesonbuild/meson/issues/6866
+is_dist_check = project_source_root.contains('dist-unpack') and \
+                project_build_root.contains('dist-build')
+
+# 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)
+if is_dist_check
+  message('Looks like a tarball is being tested. ' + \
+  'Option "dist-warnings" is used instead of "warnings".')
+  warning_level = get_option('dist-warnings')
+else
+  warning_level = get_option('warnings')
+endif
+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)
+
+# 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.
+# atkmm_build_dep: Dependencies when building the atkmm library.
+# atkmm_dep (created in atk/atkmm/meson.build):
+#   Dependencies when using the atkmm library.
+
+# glibmm recently gained Meson build support, so we can try looking
+# for its pkg-config files on Visual Studio as well
+glibmm_req = '>= 2.46.2'
+
+# Atk supported pkg-config files on MSVC files for a good while, so just use that
+atk_req = '>= 1.18.0'
+atk_dep = dependency('atk', version: atk_req)
+
+# The -mm libraries do not yet have pkg-config files for MSVC builds,
+# so check for them manually
+glibmm_req_minor_ver = '4'
+
+glibmm_dep = dependency('glibmm-2.@0@'.format(glibmm_req_minor_ver), version: glibmm_req, required: not 
is_msvc)
+
+# Where to find gmmproc and generate_wrap_init.pl.
+if glibmm_dep.found() and glibmm_dep.type_name() == 'pkgconfig'
+  gmmproc_dir = glibmm_dep.get_pkgconfig_variable('gmmprocdir')
+else
+  # We don't have a pkg-config file for glibmm, so use build option.
+  gmmproc_dir = get_option('gmmproc-dir')
+endif
+
+if is_msvc
+  # We must have Visual Studio 2013 or later...
+  assert(cpp_compiler.version().split('.')[0].to_int() >= 18, 'Visual Studio 2013 or later is required')
+
+  sigc_major_ver = '2'
+
+  if not glibmm_dep.found()
+    assert(cpp_compiler.has_header('sigc++-@0@.0/sigc++/sigc++.h'.format(sigc_major_ver)) and 
cpp_compiler.has_header('sigc++-@0@.0/include/sigc++config.h'.format(sigc_major_ver)),
+           'sigc++-@0@.x headers are required'.format(sigc_major_ver))
+    assert(cpp_compiler.has_header('glibmm-2.@0@/glibmm.h'.format(glibmm_req_minor_ver)) and 
cpp_compiler.has_header('glibmm-2.@0@/include/glibmmconfig.h'.format(glibmm_req_minor_ver)),
+           'glibmm-2.@0@ headers are required'.format(glibmm_req_minor_ver))
+
+  else
+    sigc_dep = dependency('', required: false) # glibmm covers for libsigc++ in its pkg-config file
+  endif
+  message('Ensure your INCLUDE and LIB contain the paths that lead to the appropriate headers and .lib\'s 
for glibmm-2.@0@ and libsigc++-2.x'.format(glibmm_req_minor_ver))
+
+  # We need to look for appropriate versions of Visual
+  # Studio since those built by NMake and the former
+  # Visual Studio projects are versioned by the VS versions
+  if cpp_compiler.version().split('.')[0].to_int() == 18
+    msvc_check_range = [12] # Visual Studio 2013
+    warning('Visual Studio 2013 must configure without -Dwarnings=fatal, which is the default')
+  elif cpp_compiler.version().split('.')[0].to_int() == 19
+    # Visual Studio 2019 can consume libraries built with 2017 and 2015
+    # and Visual Studio 2017 can consume libraries built with 2015
+    msvc_check_range = [14] # Visual Studio 2015, 2017, 2019
+    message('It is safe to ignore warnings from Meson that MSVC does not support C++11')
+  endif
+
+  debugsuffix = ''
+  if get_option('buildtype') == 'debug'
+    debugsuffix = '-d'
+  endif
+
+  # We can be looking for MSVC 2015-built libraries on 2017 and 2019 builds as well,
+  # as well as 2017-built libraries on 2019 as well, so we can't just assume that
+  # libraries exist, but check that compatible versions are really found
+  foreach v : msvc_check_range
+    glibmm_dep = glibmm_dep.found() ? glibmm_dep : 
cpp_compiler.find_library('glibmm-vc@0@0@1@-2_@2@'.format(v.to_string(), debugsuffix, glibmm_req_minor_ver), 
required: false)
+  endforeach
+
+  # Check whether we compile atkmm without using gendef
+  build_shared_libs_directly = false
+
+  if glibmm_dep.type_name() == 'library'
+    warning('Note: Be sure to check that this finds the same libsigc++ .lib your glibmm is linked to')
+    sigc_dep = cpp_compiler.find_library('sigc-@0@.0'.format(sigc_major_ver), required: false)
+    foreach v : msvc_check_range
+      sigc_dep = sigc_dep.found() ? sigc_dep : 
cpp_compiler.find_library('sigc-vc@0@0@1@-2_0'.format(v.to_string(), debugsuffix), required: false)
+    endforeach
+  endif
+
+  # Now make sure the appropriate -mm libraries are found
+  assert(glibmm_dep.found() and (glibmm_dep.type_name() == 'pkgconfig' or sigc_dep.found()), 'Appropriate 
glibmm-vcxx0@0@-2_@1@.lib and sigc-vcxx0@0@-@2@_0.lib are required'.format(debugsuffix, glibmm_req_minor_ver, 
sigc_major_ver))
+
+  # Put glibmm in the required packages if we find it by pkg-config
+  mm_lib_requires = ''
+  if glibmm_dep.type_name() == 'pkgconfig'
+    mm_lib_requires += ' '.join([
+      'glibmm-2.@0@'.format(glibmm_req_minor_ver), glibmm_req,
+    ]) + ' '
+  endif
+
+  atkmm_requires = mm_lib_requires + ' '.join([
+    'atk', atk_req,
+  ])
+
+  atkmm_build_dep = [glibmm_dep, sigc_dep, atk_dep]
+else
+  # not MSVC
+  atkmm_build_dep = [glibmm_dep, atk_dep]
+  atkmm_requires = ' '.join([
+    'glibmm-2.@0@'.format(glibmm_req_minor_ver), glibmm_req,
+    'atk', atk_req,
+  ])
+
+  build_shared_libs_directly = true
+endif
+
+# 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: false)
+if maintainer_mode and not mm_common_get.found()
+  error('mm-common-get not found. mm-common >= 1.0.0 is required.')
+endif
+m4 = find_program('m4', required: maintainer_mode) # Used by gmmproc (in glibmm)
+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)
+
+# 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'
+check_dllexport_usage_py = script_dir / 'check-dllexport-usage.py'
+
+if maintainer_mode
+  # Copy files to untracked/build_scripts and untracked/doc.
+  run_command(mm_common_get, '--force', script_dir,
+    project_source_root / 'untracked' / 'doc')
+else
+  cmd_py = '''
+import os
+import sys
+sys.exit(os.path.isfile("@0@"))
+'''.format(generate_binding_py)
+  file_exists = run_command(python3, '-c', cmd_py).returncode() != 0
+  if not file_exists
+    error('Missing files in untracked/. You must enable maintainer-mode.')
+  endif
+endif
+
+# atkmm's own script files.
+atkmm_script_dir = project_source_root / 'codegen'
+dummy_header_py = atkmm_script_dir / 'dummy-header.py'
+
+if is_msvc
+  add_project_arguments(cpp_compiler.get_supported_arguments([ '/utf-8', '/wd4828']), language: 'cpp')
+
+  # Check for the first line in a file generated with gmmproc,
+  # to see which gmmproc version was used
+  if maintainer_mode
+    check_gmmproc_ver_cmd = [
+      python3, check_dllexport_usage_py,
+      '--gmmprocdir=@0@'.format(gmmproc_dir),
+    ]
+  else
+    check_gmmproc_ver_cmd = [
+      python3, check_dllexport_usage_py,
+      '--file=@0@/untracked/atk/atkmm/action.h'.format('/'.join(project_source_root.split('\\')))
+    ]
+  endif
+
+  # Enable __declspec(dllexport) if the atkmm headers generated from the .hg files
+  # were generated using a recent enough gmmproc
+  build_shared_libs_directly = run_command(check_gmmproc_ver_cmd).returncode() == 0
+  message('Using __declspec(dllexport) to build atkmm: @0@'.format(build_shared_libs_directly ? 'YES' : 
'NO'))
+endif
+
+# 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 ATK GLIBMM 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
+  foreach wd : ['/FImsvc_recommended_pragmas.h', '/wd4267', '/wd4530', '/wd4251']
+    disabled_warning = cpp_compiler.get_supported_arguments(wd)
+    add_project_arguments(disabled_warning, language: 'cpp')
+  endforeach
+endif
+
+subdir('codegen/extradefs')
+subdir('MSVC_NMake/gendef')
+subdir('atk')
+subdir('MSVC_NMake/atkmm')
+subdir('atk/atkmm')
+subdir('doc/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),
+  'Directories:',
+  '                  prefix: @0@'.format(install_prefix),
+  '              includedir: @0@'.format(install_prefix / install_includedir),
+  '         includeatkmmdir: @0@'.format(install_prefix / install_includedir / atkmm_pcname),
+  '                  libdir: @0@'.format(install_prefix / install_libdir),
+  '        includeconfigdir: @0@'.format(install_prefix / install_includeconfigdir),
+  '                   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),
+]
+if maintainer_mode
+  summary += [
+    '              gmmprocdir: @0@'.format(gmmproc_dir),
+  ]
+endif
+summary += ['------']
+
+message('\n'.join(summary))
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..0a88938
--- /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: 'min',
+  description: 'Compiler warning level')
+option('dist-warnings', type: 'combo', choices: ['no', 'min', 'max', 'fatal'], value: 'fatal',
+  description: 'Compiler warning level when a tarball is created')
+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('gmmproc-dir', type: 'string', value: '',
+  description: 'Directory containing gmmproc and its PERL modules (for MSVC builds only)')
diff --git a/untracked/README b/untracked/README
new file mode 100644
index 0000000..0537acb
--- /dev/null
+++ b/untracked/README
@@ -0,0 +1,37 @@
+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 atkmm is built.
+
+Files of type 2 exist here only if atkmm is built with maintainer-mode=false,
+or the directory comes from a tarball.
+Files of both types exist here only if atkmm is built with Meson,
+or the tarball is created with Meson.
+
+1. Files copied by mm-common-get
+--------------------------------
+untracked/doc/doc-install.pl
+              doc-postprocess.pl
+              doxygen-extra.css
+              tagfile-to-devhelp2.xsl
+untracked/build_scripts/check-dllexport-usage.py
+                        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 atkmm.
+
+2. Generated files
+------------------
+untracked/atk/atkmm/*.h
+                    *.cc
+                    private/*_p.h
+untracked/doc/reference/atkmm-1.6.devhelp2
+                        atkmm-1.6.tag
+                        html/*



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