summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjell Ahlstedt <kjellahlstedt@gmail.com>2019-10-21 13:36:39 +0000
committerKjell Ahlstedt <kjellahlstedt@gmail.com>2019-10-21 13:36:39 +0000
commita0daa2b074923f115bfd9ae9ff1101563f6ba5d5 (patch)
treeea0b0cf89aeb26bb7022bf51ea9e84346aea4b1c
parent532d7a4218b43859db36b12b3a87e59ffb90a1f6 (diff)
parentc2e9ff1dd3fc820e5dc7aad1678e124b7fd820ef (diff)
downloadmm-common-a0daa2b074923f115bfd9ae9ff1101563f6ba5d5.tar.gz
Merge branch 'wip/kjellahl/meson-build' into 'master'
Support modules that are built with Meson See merge request GNOME/mm-common!2
-rw-r--r--Makefile.am22
-rw-r--r--README97
-rw-r--r--configure.ac1
-rw-r--r--meson.build47
-rwxr-xr-xutil/build_scripts/dist-build-scripts.py42
-rwxr-xr-xutil/build_scripts/dist-changelog.py26
-rwxr-xr-xutil/build_scripts/doc-reference.py175
-rwxr-xr-xutil/build_scripts/generate-binding.py185
-rw-r--r--util/mm-common-get.1.in64
-rw-r--r--util/mm-common-get.in62
-rw-r--r--util/mm-common-prepare.1.in5
-rw-r--r--util/mm-common-prepare.in2
12 files changed, 697 insertions, 31 deletions
diff --git a/Makefile.am b/Makefile.am
index 9b59a9f..1cd5df1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,17 +18,22 @@
# Pick up aclocal flags from the environment.
ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS}
-bin_SCRIPTS = util/mm-common-prepare
-man1_MANS = util/mm-common-prepare.1
+bin_SCRIPTS = util/mm-common-prepare util/mm-common-get
+man1_MANS = util/mm-common-prepare.1 util/mm-common-get.1
-# These are installed so that mm-common-prepare can copy them
-# into projects at autogen.sh time:
+# These are installed so that mm-common-prepare can copy the .am files
+# into projects at autogen.sh time, and mm-common-get can copy the .py files
+# at Meson setup or configure time:
build_supportdir = $(pkgdatadir)/build
dist_build_support_DATA = \
am_include/compile-binding.am \
am_include/dist-changelog.am \
am_include/doc-reference.am \
- am_include/generate-binding.am
+ am_include/generate-binding.am \
+ util/build_scripts/dist-build-scripts.py \
+ util/build_scripts/dist-changelog.py \
+ util/build_scripts/doc-reference.py \
+ util/build_scripts/generate-binding.py
# These are installed so that aclocal can copy them into aclocal.m4
# at autogen.sh time:
@@ -47,6 +52,7 @@ dist_aclocal_macro_DATA = \
# at autogen.sh time if a directory path is given to MM_CONFIG_DOCTOOL_DIR(),
# or they can be found via pkg-config --variable=doctooldir mm-common-util,
# which is preferrable.
+# mm-common-get can copy them at Meson setup or configure time.
doctooldir = $(pkgdatadir)/doctool
dist_doctool_DATA = \
util/doc-install.pl \
@@ -118,7 +124,7 @@ skeletonmm_script_files = \
skeletonmm_files = $(skeletonmm_script_files) $(skeletonmm_data_files)
-dist_noinst_DATA = util/mm-common-prepare.1.in $(skeletonmm_data_files)
+dist_noinst_DATA = util/mm-common-prepare.1.in util/mm-common-get.1.in $(skeletonmm_data_files)
dist_noinst_SCRIPTS = autogen.sh $(skeletonmm_script_files)
CLEANFILES = $(man1_MANS) $(doc_DATA)
@@ -170,6 +176,10 @@ doctags/libstdc++.tag:
util/mm-common-prepare.1: $(srcdir)/util/mm-common-prepare.1.in Makefile
$(AM_V_GEN)$(subst_manpage) $(srcdir)/util/mm-common-prepare.1.in >$@
+# Build the mm-common-get(1) manual page.
+util/mm-common-get.1: $(srcdir)/util/mm-common-get.1.in Makefile
+ $(AM_V_GEN)$(subst_manpage) $(srcdir)/util/mm-common-get.1.in >$@
+
# Create tar archive of skeletonmm for installation.
skeletonmm.tar.gz: $(skeletonmm_files)
$(AM_V_GEN)($(srctar_stdout) $(skeletonmm_files)) | gzip -c -n >$@
diff --git a/README b/README
index 4995ef8..3d7286b 100644
--- a/README
+++ b/README
@@ -14,13 +14,16 @@ is available at <http://gcc.gnu.org/onlinedocs/libstdc++/>.
Autotools or Meson?
===================
-mm-common can be built with autotools or meson. Building with autotools
+mm-common can be built with Autotools or Meson. Building with Autotools
may be phased out in the future.
-Most of the files that mm-common installs and mm-common-prepare copies to
-other modules are useful only if those modules are built with autotools.
+The files that mm-common installs and mm-common-prepare copies to other
+modules are useful in modules that are built with Autotools.
+The files that mm-common installs and mm-common-get copies to other
+modules are useful in modules that are built with Meson.
+
The files in the skeletonmm directory show the start of a project that will
-use autotools.
+use Autotools.
Skeleton C++ binding module
===========================
@@ -28,7 +31,7 @@ Skeleton C++ binding module
When creating a new C++ binding module based on mm-common, the easiest way
to get started is to copy the skeletonmm directory shipped with mm-common.
It contains the build support files required for a C++ binding module using
-gmmproc and glibmm.
+Autotools, gmmproc and glibmm.
In order to create a new binding project from the copied skeleton directory,
any files which have "skeleton" in the filename must be renamed. References
@@ -42,8 +45,8 @@ The following sections provide an overview of the various files shipped
with mm-common, and briefly explain their purpose. Detailed documentation
and usage instructions can be found in the files themselves.
-mm-common-prepare
------------------
+mm-common-prepare and Autotools
+-------------------------------
The mm-common-prepare shell script is installed in ${bindir} and must be
invoked from the bootstrap script of a binding module in order to set up
@@ -70,8 +73,39 @@ Also note that mm-common-prepare inspects the project's configure.ac file
for the AC_CONFIG_AUX_DIR([...]) argument. This is explained in further
detail below in the section on Automake include files.
-Autoconf M4 macros
-------------------
+mm-common-get and Meson
+-----------------------
+
+The mm-common-get shell script is installed in ${bindir} and must be
+invoked with run_command() early in a meson.build file. The meson.build file
+should contain code similar to
+
+ python = import('python').find_installation('python3')
+ cmd_py = '''
+ import os
+ import sys
+ sys.exit(0 if os.path.isdir("@0@") else 1)
+ '''.format(project_source_root / '.git')
+ is_git_build = run_command(python, '-c', cmd_py).returncode() == 0
+ maintainer_mode_opt = get_option('maintainer-mode')
+ maintainer_mode = maintainer_mode_opt == 'true' or \
+ (maintainer_mode_opt == 'if-git-build' and is_git_build)
+ mm_common_get = find_program('mm-common-get', required: maintainer_mode)
+
+ if maintainer_mode and mm_common_get.found()
+ # Copy files to untracked/build_scripts and untracked/docs.
+ run_command(mm_common_get, '--force',
+ project_source_root / 'untracked' / 'build_scripts',
+ project_source_root / 'untracked' / 'docs')
+ endif
+
+In a Unix-like system the first few lines can be replaced with
+
+ is_git_build = run_command('test', '-d', project_source_root/'.git').returncode() == 0
+
+
+Autoconf M4 macros (Autotools)
+------------------------------
The Autoconf M4 macros are installed into the system-wide macro repository
in the ${datadir}/aclocal directory. Since all used M4 macros are copied
@@ -131,8 +165,8 @@ macros/mm-ax_cxx_compile_stdcxx.m4:
http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html,
except for the MM_ prefix.
-Automake include files
-----------------------
+Automake include files (Autotools)
+----------------------------------
The Automake include files are located in the am_include/ directory.
The installed mm-common-prepare program copies all of the .am files into
@@ -159,14 +193,43 @@ am_include/dist-changelog.am:
a release, intended to be used by modules which use the version control
log exclusively to document changes.
-Documentation utilities
------------------------
+Python build scripts (Meson)
+----------------------------
+
+These scripts can be called from meson.build files with run_command(),
+custom_target(), meson.add_postconf_script(), meson.add_install_script()
+and meson.add_dist_script().
+
+util/build_scripts/generate-binding.py:
+ Commands for running the gmmproc code generator to produce
+ the source code files for a C++ binding module.
+
+util/build_scripts/doc-reference.py:
+ Commands for building the API reference documentation using
+ Doxygen, and to create a Devhelp book for the library. The installation
+ rules also take care of translating references to external documentation
+ in the generated hypertext documents.
+
+util/build_scripts/dist-changelog.py:
+ A git command to generate a ChangeLog file when making a release,
+ intended to be used by modules which use the version control
+ log exclusively to document changes.
+
+util/build_scripts/dist-build-scripts.py:
+ Commands that trim the distribution directory before a tarball is made.
+ The scripts copied by mm-common-get are distributed, although they are
+ not checked into the git repository. All .gitignore files and an empty build/
+ directory are removed
+
+Documentation utilities (Meson and Autotools)
+---------------------------------------------
These are two Perl scripts, a style sheet, and one XSL transformation
which assist with the task of generating and installing the Doxygen
reference documentation. At least doc-install.pl is also required for
tarball builds.
-To avoid copying these files into all binding modules, they are
+
+Autotools: To avoid copying these files into all binding modules, they are
distributed and installed with the mm-common module. Those binding modules
which shall depend on mm-common only in maintainer-mode must call
MM_CONFIG_DOCTOOL_DIR([...]) in configure.ac to indicate to mm-common-prepare
@@ -219,9 +282,9 @@ doctags/libstdc++.tag:
The Doxygen tag file for the GNU libstdc++ reference documentation
hosted at <http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/>.
This file is distributed with release archives of mm-common, but not
- checked into version control on gnome.org. If mm-common is built in
- maintainer-mode, the file will be downloaded automatically from the
- gcc.gnu.org web server.
+ checked into version control on gnome.org. If mm-common is built with
+ Autotools in maintainer-mode or with Meson and use-network=true,
+ the file will be downloaded automatically from the gcc.gnu.org web server.
The file libstdc++.tag is installed into the package data directory
of mm-common. The mm-common-libstdc++ pkg-config module defines the
variables ${doxytagfile} and ${htmlrefpub}, which can be queried for
diff --git a/configure.ac b/configure.ac
index 461a310..18da79c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -56,6 +56,7 @@ AC_CONFIG_FILES([
doctags/mm-common-libstdc++-uninstalled.pc
macros/mm-common.m4
util/mm-common-prepare
+ util/mm-common-get
util/mm-common-util.pc
util/mm-common-util-uninstalled.pc
])
diff --git a/meson.build b/meson.build
index f61fa9e..a14b535 100644
--- a/meson.build
+++ b/meson.build
@@ -41,6 +41,8 @@ install_man1dir = install_mandir / 'man1'
# doctags/mm-common-libstdc++.pc.in -> mm-common-libstdc++.pc
# doctags/mm-common-libstdc++-uninstalled.pc.in -> mm-common-libstdc++-uninstalled.pc
# macros/mm-common.m4.in -> mm-common.m4
+# util/mm-common-get.1.in -> mm-common-get.1
+# util/mm-common-get.in -> mm-common-get
# util/mm-common-prepare.1.in -> mm-common-prepare.1
# util/mm-common-prepare.in -> mm-common-prepare
# util/mm-common-util.pc.in -> mm-common-util.pc
@@ -57,16 +59,28 @@ conf_data.set('PACKAGE_STRING', meson.project_name() + ' ' + meson.project_versi
# These are installed so that mm-common-prepare can copy them
# into projects at autogen.sh time.
-build_support_basefiles = [
+autotools_build_support_basefiles = [
'compile-binding.am',
'dist-changelog.am',
'doc-reference.am',
'generate-binding.am',
]
build_support_files = []
-foreach file : build_support_basefiles
+foreach file : autotools_build_support_basefiles
build_support_files += 'am_include' / file
endforeach
+
+# These are installed so that mm-common-get can copy them
+# into projects at Meson setup or configure time.
+meson_build_support_basefiles = [
+ 'dist-build-scripts.py',
+ 'dist-changelog.py',
+ 'doc-reference.py',
+ 'generate-binding.py',
+]
+foreach file : meson_build_support_basefiles
+ build_support_files += 'util' / 'build_scripts' / file
+endforeach
install_data(build_support_files, install_dir: install_build_supportdir)
# These are installed so that aclocal can copy them into aclocal.m4
@@ -107,6 +121,8 @@ endif
# These are installed so that mm-common-prepare can copy them into projects
# at autogen.sh time, if a directory path is given to MM_CONFIG_DOCTOOL_DIR(),
# or they can be found via pkg-config --variable=doctooldir mm-common-util.
+# They are also installed so that mm-common-get can copy them
+# into projects at Meson setup or configure time.
doctool_basefiles = [
'doc-install.pl',
'doc-postprocess.pl',
@@ -147,18 +163,39 @@ configure_file(
configuration: conf_data,
)
-# mm-common-prepare command.
+# mm-common-get command.
conf_data3 = configuration_data()
conf_data3.merge_from(conf_data)
-conf_data3.set('configure_input', 'mm-common-prepare. Generated from util/mm-common-prepare.in')
+conf_data3.set('configure_input', 'mm-common-get. Generated from util/mm-common-get.in')
+conf_data3.set('datadir_py', install_prefix / install_datadir)
configure_file(
- input: 'util' / 'mm-common-prepare.in',
+ input: 'util' / 'mm-common-get.in',
output: '@BASENAME@',
configuration: conf_data3,
install_dir: install_bindir,
install_mode: 'rwxr-xr-x'
)
+# mm-common-get.1 manual page.
+configure_file(
+ input: 'util' / 'mm-common-get.1.in',
+ output: '@BASENAME@',
+ configuration: conf_data,
+ install_dir: install_man1dir
+)
+
+# mm-common-prepare command.
+conf_data4 = configuration_data()
+conf_data4.merge_from(conf_data)
+conf_data4.set('configure_input', 'mm-common-prepare. Generated from util/mm-common-prepare.in')
+configure_file(
+ input: 'util' / 'mm-common-prepare.in',
+ output: '@BASENAME@',
+ configuration: conf_data4,
+ install_dir: install_bindir,
+ install_mode: 'rwxr-xr-x'
+)
+
# mm-common-prepare.1 manual page.
configure_file(
input: 'util' / 'mm-common-prepare.1.in',
diff --git a/util/build_scripts/dist-build-scripts.py b/util/build_scripts/dist-build-scripts.py
new file mode 100755
index 0000000..7318bc7
--- /dev/null
+++ b/util/build_scripts/dist-build-scripts.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python3
+
+# External command, intended to be called with meson.add_dist_script() in meson.build
+
+# sys.argv[1] sys.argv[2]
+# dist-build-scripts.py <root_src_dir> <relative_script_dir>
+
+# <relative_script_dir> is the directory with the build scripts, relative to <root_source_dir>.
+
+import os
+import sys
+import shutil
+
+src_script_dir = os.path.join(sys.argv[1], sys.argv[2])
+dist_script_dir = os.path.join(os.getenv('MESON_DIST_ROOT'), sys.argv[2])
+
+# Create the distribution script directory, if it does not exist.
+os.makedirs(dist_script_dir, exist_ok=True)
+
+# Distribute files that mm-common-get has copied to src_script_dir.
+files = [
+ 'dist-build-scripts.py',
+ 'dist-changelog.py',
+ 'doc-reference.py',
+ 'generate-binding.py'
+]
+for file in files:
+ shutil.copy(os.path.join(src_script_dir, file), dist_script_dir)
+
+# Don't distribute .gitignore files.
+for dirpath, dirnames, filenames in os.walk(os.getenv('MESON_DIST_ROOT')):
+ if '.gitignore' in filenames:
+ os.remove(os.path.join(dirpath, '.gitignore'))
+
+# Remove an empty MESON_DIST_ROOT/build directory.
+dist_build_dir = os.path.join(os.getenv('MESON_DIST_ROOT'), 'build')
+if os.path.isdir(dist_build_dir):
+ try:
+ os.rmdir(dist_build_dir)
+ except OSError:
+ # Ignore the error, if not empty.
+ pass
diff --git a/util/build_scripts/dist-changelog.py b/util/build_scripts/dist-changelog.py
new file mode 100755
index 0000000..c38fde3
--- /dev/null
+++ b/util/build_scripts/dist-changelog.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+
+# External command, intended to be called with meson.add_dist_script() in meson.build
+
+# sys.argv[1]
+# dist-changelog.py <root_source_dir>
+
+import os
+import sys
+import subprocess
+
+# Make a ChangeLog file for distribution.
+cmd = [
+ 'git',
+ '--git-dir=' + os.path.join(sys.argv[1], '.git'),
+ '--work-tree=' + sys.argv[1],
+ 'log',
+ '--no-merges',
+ '--date=short',
+ '--max-count=200',
+ '--pretty=tformat:%cd %an <%ae>%n%n %s%n%w(0,0,2)%+b',
+]
+logfile = open(os.path.join(os.getenv('MESON_DIST_ROOT'), 'ChangeLog'), mode='w')
+result = subprocess.run(cmd, stdout=logfile)
+logfile.close()
+sys.exit(result.returncode)
diff --git a/util/build_scripts/doc-reference.py b/util/build_scripts/doc-reference.py
new file mode 100755
index 0000000..c798d48
--- /dev/null
+++ b/util/build_scripts/doc-reference.py
@@ -0,0 +1,175 @@
+#!/usr/bin/env python3
+
+# External command, intended to be called with custom_target(),
+# meson.add_install_script() or meson.add_dist_script() in meson.build.
+
+# argv[1] argv[2] argv[3:]
+# doc-reference.py <subcommand> <MMDOCTOOLDIR> <xxx>...
+
+# <MMDOCTOOLDIR> is an absolute path in the source directory.
+
+import os
+import sys
+import subprocess
+import shutil
+
+subcommand = sys.argv[1]
+MMDOCTOOLDIR = sys.argv[2]
+
+# Invoked from custom_target() in meson.build.
+def doxygen():
+ # argv[3] argv[4:]
+ # <doxytagfile> <doc_input_files>...
+
+ # <doxytagfile> is a relative or absolute path in the build directory.
+ # <doc_input_files> are absolute paths in the source or build directory.
+ doxytagfile = sys.argv[3]
+ doc_outdir = os.path.dirname(doxytagfile)
+
+ # Export this variable for use in the Doxygen configuration file.
+ child_env = os.environ.copy()
+ child_env['MMDOCTOOLDIR'] = MMDOCTOOLDIR
+
+ # Remove old files.
+ if os.path.isfile(doxytagfile):
+ os.remove(doxytagfile)
+ shutil.rmtree(os.path.join(doc_outdir, 'html'), ignore_errors=True)
+
+ # Relative paths in Doxyfile assume that Doxygen is run from the
+ # build directory one level above Doxyfile.
+ doxygen_cwd = os.path.join(doc_outdir, '..')
+
+ DOXYGEN = child_env.get('DOXYGEN', None)
+ if not DOXYGEN:
+ DOXYGEN = 'doxygen'
+ doxygen_input = '@INCLUDE = ' + os.path.join('reference', 'Doxyfile') + '\n' \
+ + 'INPUT = "' + '" "'.join(sys.argv[4:]) + '"\n'
+ # (Starting with Python 3.7 text=True is a more understandable equivalent to
+ # universal_newlines=True. Let's use only features in Python 3.5.)
+ result = subprocess.run([DOXYGEN, '-'], input=doxygen_input,
+ universal_newlines=True, env=child_env, cwd=doxygen_cwd)
+ if result.returncode:
+ return result.returncode
+
+ cmd = [
+ 'perl',
+ '--',
+ os.path.join(MMDOCTOOLDIR, 'doc-postprocess.pl'),
+ os.path.join(doc_outdir, 'html', '*.html'),
+ ]
+ return subprocess.run(cmd).returncode
+
+# Invoked from custom_target() in meson.build.
+def devhelp():
+ # argv[3] argv[4] argv[5] argv[6]
+ # <doxytagfile> <devhelpfile> <book_name> <book_title>
+
+ # <doxytagfile> and <devhelpfile> are relative or absolute paths in the build directory.
+ doxytagfile = sys.argv[3]
+ devhelpfile = sys.argv[4]
+ book_name = sys.argv[5]
+ book_title = sys.argv[6]
+ tagfile_to_devhelp = os.path.join(MMDOCTOOLDIR, 'tagfile-to-devhelp2.xsl')
+
+ # The parameters to the Doxygen-to-Devhelp XSLT script.
+ cmd = [
+ 'xsltproc',
+ '--stringparam', 'book_title', book_title,
+ '--stringparam', 'book_name', book_name,
+ '--stringparam', 'book_base', 'html',
+ '-o', devhelpfile,
+ tagfile_to_devhelp,
+ doxytagfile,
+ ]
+ return subprocess.run(cmd).returncode
+
+# Invoked from meson.add_install_script().
+def install_doc():
+ # argv[3] argv[4] argv[5] argv[6:]
+ # <devhelpfile> <devhelpdir> <htmlrefdir> <docinstall_flags>...
+
+ # <devhelpfile> is a relative or absolute path in the build directory.
+ # <htmlrefdir> and <devhelpdir> are installation directories, relative to {prefix}.
+ devhelpfile = sys.argv[3]
+ devhelpdir = os.path.join(os.getenv('MESON_INSTALL_DESTDIR_PREFIX'), sys.argv[4])
+ htmlrefdir = os.path.join(os.getenv('MESON_INSTALL_DESTDIR_PREFIX'), sys.argv[5])
+ build_dir = os.path.dirname(devhelpfile)
+
+ # Create the installation directories, if they do not exist.
+ os.makedirs(htmlrefdir, exist_ok=True)
+ os.makedirs(devhelpdir, exist_ok=True)
+
+ # Install html files.
+ cmd = [
+ 'perl',
+ '--',
+ os.path.join(MMDOCTOOLDIR, 'doc-install.pl'),
+ '--verbose',
+ '--mode=0644',
+ ] + sys.argv[6:] + [
+ '-t', htmlrefdir,
+ '--glob',
+ '--',
+ os.path.join(build_dir, 'html', '*'),
+ ]
+ result1 = subprocess.run(cmd)
+
+ # Install the Devhelp file.
+ # rstrip('/') means remove trailing /, if any.
+ cmd = [
+ 'perl',
+ '--',
+ os.path.join(MMDOCTOOLDIR, 'doc-install.pl'),
+ '--verbose',
+ '--mode=0644',
+ '--book-base=' + htmlrefdir.rstrip('/'),
+ '-t', devhelpdir,
+ '--',
+ devhelpfile,
+ ]
+ result2 = subprocess.run(cmd)
+
+ if result1.returncode:
+ return result1.returncode
+ return result2.returncode
+
+# Invoked from meson.add_dist_script().
+def dist_doc():
+ # argv[3] argv[4] argv[5] argv[6]
+ # <doctool_dist_dir> <doc_ref_build_dir> <tagfile> <devhelpfile>
+
+ # <doctool_dist_dir> is a distribution directory, relative to MESON_DIST_ROOT.
+ # <doc_ref_build_dir> is a relative or absolute path in the build directory.
+ # <tagfile> and <devhelpfile> are relative or absolute paths in the build directory.
+ doctool_dist_dir = os.path.join(os.getenv('MESON_DIST_ROOT'), sys.argv[3])
+ doc_ref_build_dir = sys.argv[4]
+ tagfile = sys.argv[5]
+ devhelpfile = sys.argv[6]
+
+ # Create the distribution directory, if it does not exist.
+ os.makedirs(os.path.join(doctool_dist_dir, 'reference'), exist_ok=True)
+
+ # Distribute files that mm-common-get has copied to MMDOCTOOLDIR.
+ # shutil.copy() does not copy timestamps.
+ for file in ['doc-install.pl', 'doc-postprocess.pl', 'doxygen-extra.css', 'tagfile-to-devhelp2.xsl']:
+ shutil.copy(os.path.join(MMDOCTOOLDIR, file), doctool_dist_dir)
+
+ # Distribute built files: tag file, devhelp file, html files.
+ for file in [tagfile, devhelpfile]:
+ shutil.copy(file, os.path.join(doctool_dist_dir, 'reference'))
+ shutil.copytree(os.path.join(doc_ref_build_dir, 'html'),
+ os.path.join(doctool_dist_dir, 'reference', 'html'),
+ copy_function=shutil.copy)
+ return 0
+
+# ----- Main -----
+if subcommand == 'doxygen':
+ sys.exit(doxygen())
+if subcommand == 'devhelp':
+ sys.exit(devhelp())
+if subcommand == 'install_doc':
+ sys.exit(install_doc())
+if subcommand == 'dist_doc':
+ sys.exit(dist_doc())
+print(sys.argv[0], ': illegal subcommand,', subcommand)
+sys.exit(1)
diff --git a/util/build_scripts/generate-binding.py b/util/build_scripts/generate-binding.py
new file mode 100755
index 0000000..a1244a8
--- /dev/null
+++ b/util/build_scripts/generate-binding.py
@@ -0,0 +1,185 @@
+#!/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:]
+# generate-binding.py <subcommand> <xxx>...
+
+import os
+import sys
+import subprocess
+from pathlib import Path
+import shutil
+
+subcommand = sys.argv[1]
+
+# Invoked from custom_target() in meson.build.
+def generate_wrap_init():
+ # argv[2] argv[3] argv[4] argv[5:]
+ # <gmmproc_dir> <output_file> <namespace> <hg_files>...
+
+ # <gmmproc_dir> is an absolute path in glibmm's installation directory.
+ # <output_file> is a relative or absolute path in the build directory.
+ # <hg_files> are relative or absolute paths in the source directory.
+ gmmproc_dir = sys.argv[2]
+ output_file = sys.argv[3]
+ parent_dir = os.path.basename(os.path.dirname(output_file))
+ namespace = sys.argv[4]
+ cmd = [
+ 'perl',
+ '--',
+ os.path.join(gmmproc_dir, 'generate_wrap_init.pl'),
+ '--namespace=' + namespace,
+ '--parent_dir=' + parent_dir,
+ ] + sys.argv[5:]
+ 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 custom_target() in meson.build.
+def gmmproc():
+ # argv[2] argv[3] argv[4] argv[5] argv[6:]
+ # <gmmproc_dir> <output_file> <basefilename> <src_dir> <m4_dirs>...
+
+ # <gmmproc_dir> is an absolute path in glibmm's installation 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]
+ output_file = sys.argv[3]
+ output_dir = os.path.dirname(output_file)
+ basefilename = sys.argv[4] # name without filetype
+ src_dir = sys.argv[5]
+
+ include_m4_dirs = []
+ for dir in sys.argv[6:]:
+ 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' + os.path.join(gmmproc_dir, 'pm'),
+ '--',
+ 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 meson.add_install_script().
+def install_built_h_files():
+ # argv[2] argv[3] argv[4:]
+ # <built_h_dir> <install_subdir> <basefilenames>...
+
+ # <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 = os.path.join(os.getenv('MESON_INSTALL_DESTDIR_PREFIX'), sys.argv[3])
+
+ # Create the installation directory, if it does not exist.
+ os.makedirs(os.path.join(install_dir, 'private'), exist_ok=True)
+
+ for file in sys.argv[4:]:
+ path_h = os.path.join(built_h_dir, file+'.h')
+ print('Installing ', path_h, ' to ', install_dir)
+ # shutil.copy2() copies timestamps and some other file metadata.
+ shutil.copy2(path_h, install_dir)
+
+ path_h = os.path.join(built_h_dir, 'private', file+'_p.h')
+ install_priv_dir = os.path.join(install_dir, 'private')
+ print('Installing ', path_h, ' to ', install_priv_dir)
+ shutil.copy2(path_h, install_priv_dir)
+ return 0
+
+# Invoked from meson.add_dist_script().
+def dist_built_files():
+ # argv[2] argv[3] argv[4:]
+ # <built_h_cc_dir> <dist_dir> <basefilenames>...
+
+ # <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 = os.path.join(os.getenv('MESON_DIST_ROOT'), sys.argv[3])
+
+ # Create the distribution directory, if it does not exist.
+ os.makedirs(os.path.join(dist_dir, 'private'), exist_ok=True)
+
+ # Distribute wrap_init.cc.
+ # shutil.copy() does not copy timestamps.
+ shutil.copy(os.path.join(built_h_cc_dir, 'wrap_init.cc'), dist_dir)
+
+ # Distribute .h/.cc/_p.h files built from .hg/.ccg files.
+ for file in sys.argv[4:]:
+ shutil.copy(os.path.join(built_h_cc_dir, file+'.h'), dist_dir)
+ shutil.copy(os.path.join(built_h_cc_dir, file+'.cc'), dist_dir)
+ shutil.copy(os.path.join(built_h_cc_dir, 'private', file+'_p.h'),
+ os.path.join(dist_dir, 'private'))
+ return 0
+
+# Invoked from run_command() in meson.build.
+def copy_built_files():
+ # argv[2] argv[3] argv[4:]
+ # <from_dir> <to_dir> <basefilenames>...
+
+ # <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 = sys.argv[2]
+ to_dir = sys.argv[3]
+
+ # Create the destination directory, if it does not exist.
+ os.makedirs(os.path.join(to_dir, 'private'), exist_ok=True)
+
+ # 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 wrap_init.cc.
+ from_file = os.path.join(from_dir, 'wrap_init.cc')
+ to_file = os.path.join(to_dir, 'wrap_init.cc')
+ 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)):
+ shutil.copy(from_file, to_file)
+
+ # Copy .h/.cc/_p.h files built from .hg/.ccg files.
+ for basefile in sys.argv[4:]:
+ for file in [basefile+'.h', basefile+'.cc', os.path.join('private', basefile+'_p.h')]:
+ from_file = os.path.join(from_dir, file)
+ to_file = os.path.join(to_dir, 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)):
+ shutil.copy(from_file, to_file)
+ return 0
+
+# ----- Main -----
+if subcommand == 'generate_wrap_init':
+ sys.exit(generate_wrap_init())
+if subcommand == 'gmmproc':
+ sys.exit(gmmproc())
+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())
+print(sys.argv[0], ': illegal subcommand,', subcommand)
+sys.exit(1)
diff --git a/util/mm-common-get.1.in b/util/mm-common-get.1.in
new file mode 100644
index 0000000..ff8996c
--- /dev/null
+++ b/util/mm-common-get.1.in
@@ -0,0 +1,64 @@
+.TH MM-COMMON-GET 1 2019-09-12 GNOME "@PACKAGE_STRING@"
+.SH NAME
+mm-common-get \- Copy files from mm-common to a C++ binding module that uses Meson
+.SH SYNOPSIS
+.B mm-common-get
+.RI [ OPTION "]... " "BUILDSCRIPT-DIR DOCTOOL-DIR"
+.SH DESCRIPTION
+Run
+.B mm-common-get
+to copy the
+.I mm-common
+build support files into the source tree of a C++ binding module.
+.SH OPTIONS
+.TP
+.BR \-f ", " \-\-force
+forcefully replace existing files
+.TP
+.B \-\-help
+display a help message and exit
+.TP
+.B \-\-version
+show version information and exit
+.SH "EXIT STATUS"
+The exit status is 0 if OK, or 1 if an error occurred.
+.SH FILES
+The build support files currently copied by
+.B mm-common-get
+are listed below.
+.TP
+.BI "Meson build scripts copied to " BUILDSCRIPT-DIR :
+.PD 0
+.IP
+.I dist-build-scripts.py
+.IP
+.I dist-changelog.py
+.IP
+.I doc-reference.py
+.IP
+.I generate-binding.py
+.PD
+.TP
+.BI "Documentation utilities copied to " DOCTOOL-DIR :
+.PD 0
+.IP
+.I doc-install.pl
+.IP
+.I doc-postprocess.pl
+.IP
+.I doxygen.css
+.IP
+.I doxygen-extra.css
+.IP
+.I tagfile-to-devhelp2.xsl
+.PD
+.SH "SEE ALSO"
+.PD 0
+.BR mm-common-prepare (1)
+.PP
+.I @docdir@/README
+.PP
+.I @docdir@/skeletonmm.tar.xz or
+.PP
+.I @docdir@/skeletonmm.tar.gz
+.PD
diff --git a/util/mm-common-get.in b/util/mm-common-get.in
new file mode 100644
index 0000000..e0b28f0
--- /dev/null
+++ b/util/mm-common-get.in
@@ -0,0 +1,62 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2019 The gtkmm Development Team
+#
+# @configure_input@
+#
+# mm-common is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published
+# by the Free Software Foundation, either version 2 of the License,
+# or (at your option) any later version.
+#
+# mm-common is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with mm-common. If not, see <http://www.gnu.org/licenses/>.
+
+import sys
+import os
+import argparse
+import shutil
+import filecmp
+
+pkgdatadir = os.path.join('@datadir_py@', '@PACKAGE_TARNAME@')
+progname = os.path.basename(sys.argv[0])
+
+parser = argparse.ArgumentParser(
+ description='Copy files from mm-common to a C++ binding module that uses Meson')
+parser.add_argument('--version', action='version', version='%(prog)s @PACKAGE_VERSION@')
+parser.add_argument('-f', '--force', help='replace existing files', action='store_true')
+parser.add_argument('buildscript_dir', help='where to store build scripts')
+parser.add_argument('doctool_dir', help='where to store doc tool files')
+args = parser.parse_args()
+
+forceflag = args.force
+buildscriptdir = args.buildscript_dir
+doctooldir = args.doctool_dir
+
+print(progname + ': putting Meson build scripts in ' + buildscriptdir)
+# Create the destination directory, if it does not exist.
+os.makedirs(buildscriptdir, exist_ok=True)
+for file in ['dist-build-scripts.py', 'dist-changelog.py', 'doc-reference.py', 'generate-binding.py']:
+ src_file = os.path.join(pkgdatadir, 'build', file)
+ dest_file = os.path.join(buildscriptdir, file)
+ # Don't update the timestamp of dest_file, if it's equal to src_file.
+ # if file-does-not-exist or (force and files-are-not-equal)
+ if (not os.path.isfile(dest_file)) or (forceflag and (not filecmp.cmp(src_file, dest_file))):
+ print(progname + ': copying file ' + file)
+ # shutil.copy() does not copy timestamps.
+ shutil.copy(src_file, dest_file)
+
+print(progname + ': putting documentation utilities in ' + doctooldir)
+os.makedirs(doctooldir, exist_ok=True)
+for file in ['doc-install.pl', 'doc-postprocess.pl',
+ 'doxygen.css', 'doxygen-extra.css', 'tagfile-to-devhelp2.xsl']:
+ src_file = os.path.join(pkgdatadir, 'doctool', file)
+ dest_file = os.path.join(doctooldir, file)
+ if (not os.path.isfile(dest_file)) or (forceflag and (not filecmp.cmp(src_file, dest_file))):
+ print(progname + ': copying file ' + file)
+ shutil.copy(src_file, dest_file)
diff --git a/util/mm-common-prepare.1.in b/util/mm-common-prepare.1.in
index a9ebd50..edbe042 100644
--- a/util/mm-common-prepare.1.in
+++ b/util/mm-common-prepare.1.in
@@ -1,6 +1,6 @@
.TH MM-COMMON-PREPARE 1 2014-08-13 GNOME "@PACKAGE_STRING@"
.SH NAME
-mm-common-prepare \- Prepare a C++ binding module to use mm-common
+mm-common-prepare \- Prepare a C++ binding module to use mm-common and Autotools
.SH SYNOPSIS
.B mm-common-prepare
.RI [ OPTION "]... [" SOURCE-DIR ]
@@ -94,7 +94,8 @@ are listed below.
.PD
.SH "SEE ALSO"
.PD 0
-.BR autoreconf (1)
+.BR autoreconf (1),
+.BR mm-common-get (1)
.PP
.I @docdir@/README
.PP
diff --git a/util/mm-common-prepare.in b/util/mm-common-prepare.in
index 5285095..3a0a7de 100644
--- a/util/mm-common-prepare.in
+++ b/util/mm-common-prepare.in
@@ -35,7 +35,7 @@ do
cat <<EOF
Usage: $progname [OPTION]... [DIRECTORY | CONFIGURE-FILE]
-Prepare a C++ binding module to use mm-common.
+Prepare a C++ binding module to use mm-common and Autotools.
-c, --copy copy files rather than symlinking them
-f, --force replace existing files