summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjell Ahlstedt <kjellahlstedt@gmail.com>2019-12-10 13:21:45 +0100
committerKjell Ahlstedt <kjellahlstedt@gmail.com>2019-12-24 10:46:51 +0100
commit3feecca2db601a65df305a3e9c5c8e25156cdc79 (patch)
treebb4f2b1dddd6c226695b29581d99753dfea05fd3
parent66590caa31cb61b933d744c593dfdbae03f74914 (diff)
downloadsigc++-3feecca2db601a65df305a3e9c5c8e25156cdc79.tar.gz
Add support for building libsigc++-2.0 with Meson
libsigc++-2.0 can be built with either Autotools or Meson.
-rw-r--r--.gitignore3
-rw-r--r--MSVC_NMake/meson.build17
-rw-r--r--Makefile.am20
-rw-r--r--docs/manual/meson.build96
-rw-r--r--docs/reference/meson.build152
-rw-r--r--examples/meson.build27
-rw-r--r--meson.build284
-rw-r--r--meson_options.txt16
-rw-r--r--sigc++/meson.build232
-rw-r--r--sigc++config.h.meson89
-rw-r--r--tests/meson.build92
-rwxr-xr-xtools/dist-cmd.py12
-rw-r--r--tools/gcc_template_specialization_operator_overload.cc37
-rwxr-xr-xtools/handle-built-files.py133
-rw-r--r--tools/have_sun_reverse_iterator.cc10
-rw-r--r--tools/msvc_template_specialization_operator_overload.cc37
-rw-r--r--tools/pragma_push_pop_macro.cc38
-rwxr-xr-xtools/tutorial-custom-cmd.py173
-rw-r--r--untracked/README38
19 files changed, 1506 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index b8fd212..0fe2211 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,3 +23,6 @@ Makefile.in
/sigc++config.h
/sigc++-*.pc
/stamp-h?
+untracked/build_scripts/
+untracked/docs/
+untracked/sigc++/
diff --git a/MSVC_NMake/meson.build b/MSVC_NMake/meson.build
new file mode 100644
index 0000000..89db786
--- /dev/null
+++ b/MSVC_NMake/meson.build
@@ -0,0 +1,17 @@
+# MSVC_NMake
+
+# Input: pkg_conf_data, project_build_root, python3
+# Output: -
+
+configure_file(
+ input: 'sigc.rc.in',
+ output: '@BASENAME@',
+ configuration: pkg_conf_data,
+)
+
+# Copy the generated configuration header into the MSVC project directory.
+cmd_py = '''
+import shutil
+shutil.copy2("@0@", "@1@")
+'''.format(project_build_root / 'sigc++config.h', meson.current_build_dir())
+meson.add_postconf_script(python3.path(), '-c', cmd_py)
diff --git a/Makefile.am b/Makefile.am
index e04ec3e..ed7f7f3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -39,5 +39,25 @@ dist_noinst_DATA = $(addprefix MSVC_NMake/,$(msvc_nmake_data))
DISTCLEANFILES = MSVC_NMake/sigc++config.h
+# Distribute files needed when building libsigc++ with meson.
+EXTRA_DIST = \
+ meson.build \
+ meson_options.txt \
+ sigc++config.h.meson \
+ MSVC_NMake/meson.build \
+ docs/manual/meson.build \
+ docs/reference/meson.build \
+ examples/meson.build \
+ sigc++/meson.build \
+ tests/meson.build \
+ tools/dist-cmd.py \
+ tools/handle-built-files.py \
+ tools/tutorial-custom-cmd.py \
+ tools/gcc_template_specialization_operator_overload.cc \
+ tools/have_sun_reverse_iterator.cc \
+ tools/msvc_template_specialization_operator_overload.cc \
+ tools/pragma_push_pop_macro.cc \
+ untracked/README
+
# Optional: auto-generate the ChangeLog file from the git log on make dist
include $(top_srcdir)/build/dist-changelog.am
diff --git a/docs/manual/meson.build b/docs/manual/meson.build
new file mode 100644
index 0000000..7036035
--- /dev/null
+++ b/docs/manual/meson.build
@@ -0,0 +1,96 @@
+# docs/manual
+
+# input: install_datadir, sigcxx_pcname, tutorial_custom_cmd, python3,
+# build_documentation, dist_cmd, install_docdir
+# output: can_parse_and_validate, build_pdf_by_default, can_build_pdf,
+# install_tutorialdir
+
+# xsltproc is required by tutorial_custom_cmd html.
+xsltproc = find_program('xsltproc', required: build_documentation)
+xmllint = find_program('xmllint', required: false)
+
+can_parse_and_validate = xmllint.found()
+
+validate = get_option('validation') ? 'true' : 'false'
+
+dblatex = find_program('dblatex', required: false)
+can_build_pdf = dblatex.found() or (xmllint.found() and \
+ find_program('docbook2pdf', required: false).found())
+build_pdf_by_default = get_option('build-pdf')
+
+# Installation directories are relative to {prefix}.
+install_tutorialdir = install_docdir / 'tutorial'
+
+if not build_documentation
+ # Documentation shall not be built or installed.
+ # Return to the calling meson.build file.
+ subdir_done()
+endif
+
+install_data('..' / 'index.html', install_dir: install_docdir)
+install_data('..' / 'images' / 'libsigc_logo.gif',
+ '..' / 'images' / 'top.gif',
+ install_dir: install_docdir / 'images')
+
+doc_dist_dir = 'untracked' / 'docs' / 'manual' # Relative to MESON_DIST_ROOT
+
+sigc_manual_xml = 'libsigc_manual.xml'
+sigc_manual_pdf = 'libsigc_manual.pdf'
+
+# Create an html version of the DocBook.
+custom_target('manual_html',
+ input: sigc_manual_xml,
+ output: 'html',
+ command: [
+ python3, tutorial_custom_cmd, 'html',
+ '@INPUT@',
+ '@OUTPUT@',
+ ],
+ build_by_default: true,
+ install: true,
+ install_dir: install_tutorialdir
+)
+
+if can_parse_and_validate
+ # Parse and possibly validate the DocBook.
+ custom_target('manual_xmllint',
+ input: sigc_manual_xml,
+ output: 'manual_xmllint.stamp',
+ command: [
+ python3, tutorial_custom_cmd, 'xmllint',
+ validate,
+ '@INPUT@',
+ '@OUTPUT@'
+ ],
+ build_by_default: true,
+ )
+endif
+
+if can_build_pdf
+ # Create a PDF file of the DocBook.
+ # Prefer dblatex, if both dblatex and docbook2pdf are available.
+ custom_target('manual_pdf',
+ input: sigc_manual_xml,
+ output: sigc_manual_pdf,
+ command: [
+ python3, tutorial_custom_cmd,
+ dblatex.found() ? 'dblatex' : 'docbook2pdf',
+ '@INPUT@',
+ '@OUTPUT@'
+ ],
+ build_by_default: build_pdf_by_default,
+ )
+endif
+
+if not meson.is_subproject()
+ # Distribute built files.
+ # (add_dist_script() is not allowed in a subproject)
+ meson.add_dist_script(
+ python3.path(), dist_cmd,
+ python3.path(), tutorial_custom_cmd, 'dist_doc',
+ doc_dist_dir,
+ meson.current_build_dir(),
+ meson.current_source_dir() / sigc_manual_xml,
+ meson.current_build_dir() / sigc_manual_pdf,
+ )
+endif
diff --git a/docs/reference/meson.build b/docs/reference/meson.build
new file mode 100644
index 0000000..24a68d8
--- /dev/null
+++ b/docs/reference/meson.build
@@ -0,0 +1,152 @@
+# docs/reference
+
+# Input: built_files_root, project_source_root, sigcxx_pcname,
+# sigcxx_api_version, perl, build_documentation, source_h_files,
+# built_h_files, install_datadir, dist_cmd, python3,
+# built_h_file_targets
+# Output: install_docdir, install_devhelpdir
+
+tag_file_modules = [
+ 'mm-common-libstdc++',
+]
+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 = 'lib' + sigcxx_pcname
+book_title = meson.project_name() + ' Reference Manual'
+
+# Configuration data for Doxyfile.
+doc_conf_data = configuration_data()
+doc_conf_data.set('configure_input',
+ 'docs/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('SIGCXX_API_VERSION', sigcxx_api_version)
+doc_conf_data.set('DOXYGEN_TAGFILES', doxygen_tagfiles)
+doc_conf_data.set('PERL', 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_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.
+blt_h_files = []
+foreach file : built_h_files
+ blt_h_files += built_files_root / 'sigc++' / file
+endforeach
+
+# Hand-coded input .h files to Doxygen.
+src_h_files = []
+foreach file : source_h_files
+ src_h_files += project_source_root / 'sigc++' / file
+endforeach
+src_h_files += project_source_root / 'sigc++' / 'sigc++.h'
+
+doctool_dir = project_source_root / 'untracked' / 'docs' # MMDOCTOOLDIR
+doctool_dist_dir = 'untracked' / 'docs' # Relative to MESON_DIST_ROOT
+
+if built_h_file_targets.length() > 0
+ # .h files have been generated from .hg files (maintainer mode).
+ tag_file = custom_target('html_and_tag',
+ input: src_h_files,
+ output: book_name + '.tag',
+ command: [
+ python3, doc_reference, 'doxygen',
+ doctool_dir,
+ '@OUTPUT@',
+ blt_h_files,
+ '@INPUT@',
+ ],
+ build_by_default: build_documentation,
+ depends: built_h_file_targets,
+ install: true,
+ install_dir: install_reference_docdir,
+ )
+else
+ # All .h files are stored in the source tree (not maintainer mode).
+ tag_file = custom_target('html_and_tag',
+ input: src_h_files + blt_h_files,
+ output: book_name + '.tag',
+ command: [
+ python3, doc_reference, 'doxygen',
+ doctool_dir,
+ '@OUTPUT@',
+ '@INPUT@',
+ ],
+ build_by_default: build_documentation,
+ install: true,
+ install_dir: install_reference_docdir,
+ )
+endif
+
+devhelp_file = custom_target('devhelp',
+ input: tag_file,
+ output: book_name + '.devhelp2',
+ command: [
+ python3, doc_reference, '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, '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(), dist_cmd,
+ python3.path(), doc_reference, '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 0000000..a3c6de2
--- /dev/null
+++ b/examples/meson.build
@@ -0,0 +1,27 @@
+# examples
+
+# input: sigcxx_dep, build_examples
+
+examples = [
+# [[dir-name], exe-name, [sources]]
+ [[], 'hello_world', ['hello_world.cc']],
+ [[], 'member_method', ['member_method.cc']],
+]
+
+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]
+ ex_sources += dir / src
+ endforeach
+
+ exe_file = executable(ex_name, ex_sources,
+ dependencies: sigcxx_dep,
+ gui_app: false,
+ build_by_default: build_examples
+ )
+endforeach
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..548cce9
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,284 @@
+# This file is part of libsigc++.
+
+project('sigc++', 'cpp',
+ version: '2.10.2',
+ license: 'LGPLv2.1+',
+ default_options: [
+ 'cpp_std=c++11',
+ 'warning_level=0',
+ ],
+ meson_version: '>= 0.50.0', # required for python3.path()
+)
+
+sigcxx_api_version = '2.0'
+sigcxx_pcname = meson.project_name() + '-' + sigcxx_api_version
+
+sigcxx_version_array = meson.project_version().split('.')
+sigcxx_major_version = sigcxx_version_array[0].to_int()
+sigcxx_minor_version = sigcxx_version_array[1].to_int()
+sigcxx_micro_version = sigcxx_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 = [0, 0, 0]
+sigcxx_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 exists.
+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(python3, '-c', cmd_py).returncode() == 0
+# In Unix-like system, an alternative is
+# is_git_build = run_command('test', '-d', project_source_root / '.git').returncode() == 0
+# Python code can be used in all operating sytems where Meson can run.
+
+# 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')
+do_benchmark = get_option('benchmark')
+
+# 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.
+# sigcxx_build_dep: Dependencies when building the libsigc++ library.
+# sigcxx_dep (created in sigc++/meson.build):
+# Dependencies when using the libsigc++ library.
+sigcxx_build_dep = [] # No dependencies
+
+benchmark_dep = dependency('boost', modules: ['system', 'timer'],
+ version: '>=1.20.0', required: do_benchmark)
+can_benchmark = benchmark_dep.found()
+
+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')
+endif
+
+# Some dependencies are required only in maintainer mode and/or
+# if documentation shall be built.
+mm_common_get = find_program('mm-common-get', required: maintainer_mode)
+m4 = find_program('m4', required: maintainer_mode) # For building C++ code
+perl = find_program('perl', required: 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_dir = project_source_root / 'untracked' / 'build_scripts'
+doc_reference = script_dir / 'doc-reference.py'
+dist_changelog = script_dir / 'dist-changelog.py'
+dist_build_scripts = script_dir / 'dist-build-scripts.py'
+dist_cmd = project_source_root / 'tools' / 'dist-cmd.py' # Must be committed to git.
+tutorial_custom_cmd = project_source_root / 'tools' / 'tutorial-custom-cmd.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
+
+# 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 -Wsuggest-override -Wshadow -Wzero-as-null-pointer-constant -Wformat-security'.split()
+ endif
+ if warning_level == 'fatal'
+ if is_msvc
+ warning_flags += ['/WX']
+ else
+ warning_flags += ['-Werror']
+ endif
+ 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']
+ disabled_warning = cpp_compiler.get_supported_arguments(wd)
+ add_project_arguments(disabled_warning, language: 'cpp')
+ endforeach
+endif
+
+# Configure files
+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('top_srcdir', project_source_root)
+pkg_conf_data.set('PACKAGE_VERSION', meson.project_version())
+pkg_conf_data.set('SIGCXX_API_VERSION', sigcxx_api_version)
+
+if not build_deprecated_api
+ pkg_conf_data.set('SIGCXX_DISABLE_DEPRECATED', true)
+endif
+pkg_conf_data.set('SIGCXX_MAJOR_VERSION', sigcxx_major_version)
+pkg_conf_data.set('SIGCXX_MINOR_VERSION', sigcxx_minor_version)
+pkg_conf_data.set('SIGCXX_MICRO_VERSION', sigcxx_micro_version)
+foreach conf_test : ['gcc_template_specialization_operator_overload',
+ 'msvc_template_specialization_operator_overload',
+ 'have_sun_reverse_iterator',
+ 'pragma_push_pop_macro']
+ if cpp_compiler.compiles(files('tools' / conf_test + '.cc'))
+ pkg_conf_data.set('SIGC_' + conf_test.to_upper(), true)
+ endif
+endforeach
+
+configure_file(
+ input: 'sigc++.pc.in',
+ output: sigcxx_pcname + '.pc',
+ configuration: pkg_conf_data,
+ install_dir: install_pkgconfigdir,
+)
+
+configure_file(
+ input: 'sigc++-uninstalled.pc.in',
+ output: sigcxx_pcname + '-uninstalled.pc',
+ configuration: pkg_conf_data,
+)
+
+install_includeconfigdir = install_libdir / sigcxx_pcname / 'include'
+configure_file(
+ input: 'sigc++config.h.meson',
+ output: 'sigc++config.h',
+ configuration: pkg_conf_data,
+ install_dir: install_includeconfigdir,
+)
+
+subdir('MSVC_NMake')
+subdir('sigc++')
+subdir('examples')
+subdir('tests')
+subdir('docs/reference')
+subdir('docs/manual')
+
+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_cmd,
+ python3.path(), dist_changelog,
+ 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_cmd,
+ python3.path(), dist_build_scripts,
+ 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
+
+validate = get_option('validation') and can_parse_and_validate
+explain_val = ''
+if get_option('validation') and not validate
+ explain_val = ' (requires xmllint)'
+endif
+
+build_pdf = build_pdf_by_default and can_build_pdf
+explain_pdf = ''
+if build_pdf_by_default and not build_pdf
+ explain_pdf = ' (requires dblatex or (xmllint and docbook2pdf))'
+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),
+ ' XML validation: @0@@1@'.format(validate, explain_val),
+ ' Build PDF: @0@@1@'.format(build_pdf, explain_pdf),
+ ' Build example programs: @0@'.format(build_examples),
+ ' Benchmark: @0@'.format(do_benchmark),
+ 'Directories:',
+ ' prefix: @0@'.format(install_prefix),
+ ' includedir: @0@'.format(install_prefix / install_includedir),
+ ' includesigcxxdir: @0@'.format(install_prefix / install_includedir / sigcxx_pcname),
+ ' libdir: @0@'.format(install_prefix / install_libdir),
+ ' includeconfigdir: @0@'.format(install_prefix / install_includeconfigdir),
+ ' 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),
+ ' tutorialdir: @0@'.format(install_prefix / install_tutorialdir),
+ '------'
+]
+
+message('\n'.join(summary))
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..b1ffd54
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,16 @@
+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('validation', type: 'boolean', value: true,
+ description: 'Validate the tutorial XML file')
+option('build-pdf', type: 'boolean', value: false,
+ description: 'Build tutorial PDF file')
+option('build-examples', type: 'boolean', value: true,
+ description: 'Build example programs')
+option('benchmark', type: 'boolean', value: false,
+ description: 'Build and test benchmark program')
diff --git a/sigc++/meson.build b/sigc++/meson.build
new file mode 100644
index 0000000..0055089
--- /dev/null
+++ b/sigc++/meson.build
@@ -0,0 +1,232 @@
+# sigc++
+
+# Input: sigcxx_build_dep, sigcxx_pcname, sigcxx_libversion, install_includedir,
+# project_source_root
+# Output: source_h_files, built_h_files, sigcxx_dep, built_files_root,
+# built_h_file_targets
+
+source_cc_files = [
+ 'connection.cc',
+ 'signal_base.cc',
+ 'trackable.cc',
+ 'functors' / 'slot_base.cc',
+]
+
+sigc_h_files = [
+ 'bind.h',
+ 'bind_return.h',
+ 'connection.h',
+ 'reference_wrapper.h',
+ 'retype_return.h',
+ 'signal_base.h',
+ 'slot.h',
+ 'trackable.h',
+ 'type_traits.h',
+ 'visit_each.h',
+]
+adaptors_h_files = [
+ 'adaptors' / 'adaptors.h',
+ 'adaptors' / 'bound_argument.h',
+]
+functors_h_files = [
+ 'functors' / 'functors.h',
+ 'functors' / 'slot_base.h',
+]
+
+# .m4 files to build .h and .cc files from.
+adaptors_lambda_cc_m4_files = [
+ 'lambda.cc',
+]
+sigc_h_m4_files = [
+ 'limit_reference.h',
+ 'signal.h',
+]
+adaptors_h_m4_files = [
+ 'adaptor_trait.h',
+ 'bind.h',
+ 'bind_return.h',
+ 'compose.h',
+ 'deduce_result_type.h',
+ 'exception_catch.h',
+ 'hide.h',
+ 'retype.h',
+ 'retype_return.h',
+ 'track_obj.h',
+]
+adaptors_lambda_h_m4_files = [
+ 'base.h',
+ 'select.h',
+]
+functors_h_m4_files = [
+ 'functor_trait.h',
+ 'mem_fun.h',
+ 'ptr_fun.h',
+ 'slot.h',
+]
+
+source_h_files = sigc_h_files + adaptors_h_files + functors_h_files
+
+built_h_files = sigc_h_m4_files
+foreach file : adaptors_h_m4_files
+ built_h_files += 'adaptors' / file
+endforeach
+foreach file : adaptors_lambda_h_m4_files
+ built_h_files += 'adaptors' / 'lambda' / file
+endforeach
+foreach file : functors_h_m4_files
+ built_h_files += 'functors' / file
+endforeach
+
+built_cc_files = []
+foreach file : adaptors_lambda_cc_m4_files
+ built_cc_files += 'adaptors' / 'lambda' / file
+endforeach
+
+install_headers('sigc++.h', subdir: sigcxx_pcname / 'sigc++')
+install_headers(sigc_h_files, subdir: sigcxx_pcname / 'sigc++')
+install_headers(adaptors_h_files, subdir: sigcxx_pcname / 'sigc++' / 'adaptors')
+install_headers(functors_h_files, subdir: sigcxx_pcname / 'sigc++' / 'functors')
+
+untracked_sigcxx = 'untracked' / 'sigc++'
+src_untracked_sigcxx = project_source_root / untracked_sigcxx
+
+handle_built_files = project_source_root / 'tools' / 'handle-built-files.py'
+
+if maintainer_mode
+
+ # Maintainer mode. Generate .h and .cc files from .m4 files in macros/ directories.
+
+ # docs/reference/meson.build needs this.
+ built_files_root = project_build_root
+
+ m4_and_built_files = []
+ foreach file : adaptors_lambda_cc_m4_files + adaptors_lambda_h_m4_files
+ m4_and_built_files += [['adaptors' / 'lambda' / 'macros' / file + '.m4',
+ 'adaptors' / 'lambda' / file]]
+ endforeach
+ foreach file : sigc_h_m4_files
+ m4_and_built_files += [['macros' / file + '.m4', file]]
+ endforeach
+ foreach file : adaptors_h_m4_files
+ m4_and_built_files += [['adaptors' / 'macros' / file + '.m4', 'adaptors' / file]]
+ endforeach
+ foreach file : functors_h_m4_files
+ m4_and_built_files += [['functors' / 'macros' / file + '.m4', 'functors' / file]]
+ endforeach
+
+ # Force meson+ninja to generate source files before anything is compiled.
+ # Compilation must depend on these targets.
+ built_cc_file_targets = []
+ built_h_file_targets = []
+
+ foreach m4_and_built_file : m4_and_built_files
+ input_file = m4_and_built_file[0]
+ output_file = m4_and_built_file[1]
+ if output_file.endswith('.cc')
+ stamp_file = output_file.underscorify() + '.cc'
+ else
+ stamp_file = output_file.underscorify() + '.stamp'
+ endif
+ built_file_target = custom_target(output_file.underscorify(),
+ input: input_file,
+ output: stamp_file,
+ command: [
+ python3, handle_built_files, 'build_from_m4',
+ meson.current_source_dir() / 'macros',
+ '@INPUT@',
+ meson.current_build_dir() / output_file,
+ '@OUTPUT@',
+ ],
+ depend_files: 'macros' / 'template.macros.m4',
+ build_by_default: maintainer_mode,
+ install: false,
+ )
+ if output_file.endswith('.cc')
+ built_cc_file_targets += built_file_target
+ else
+ built_h_file_targets += built_file_target
+ endif
+ endforeach
+
+ extra_include_dirs = ['..']
+ sigcxx_library = library(sigcxx_pcname,
+ source_cc_files, built_cc_file_targets, built_h_file_targets,
+ version: sigcxx_libversion,
+ include_directories: extra_include_dirs,
+ dependencies: sigcxx_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/sigc++.
+
+ # docs/reference/meson.build needs these.
+ built_h_file_targets = []
+ built_files_root = project_source_root / 'untracked'
+
+ # 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, handle_built_files, 'copy_built_files',
+ meson.current_build_dir(),
+ src_untracked_sigcxx,
+ built_h_files + built_cc_files,
+ )
+
+ untracked_built_cc_files = []
+ foreach file : built_cc_files
+ untracked_built_cc_files += '..' / 'untracked' / 'sigc++' / file
+ endforeach
+
+ extra_include_dirs = [ '..', '..' / 'untracked' ]
+ sigcxx_library = library(sigcxx_pcname,
+ source_cc_files, untracked_built_cc_files,
+ version: sigcxx_libversion,
+ include_directories: extra_include_dirs,
+ dependencies: sigcxx_build_dep,
+ install: true,
+ )
+
+ built_h_cc_dir = src_untracked_sigcxx
+
+endif
+
+# Install built .h files.
+meson.add_install_script(
+ python3.path(), handle_built_files, 'install_built_h_files',
+ built_h_cc_dir,
+ install_includedir / sigcxx_pcname / 'sigc++', # subdir below {prefix}
+ built_h_files,
+)
+
+if not meson.is_subproject()
+ # Distribute built files.
+ # (add_dist_script() is not allowed in a subproject)
+ meson.add_dist_script(
+ python3.path(), dist_cmd,
+ python3.path(), handle_built_files, 'dist_built_files',
+ built_h_cc_dir,
+ untracked_sigcxx,
+ built_h_files + built_cc_files,
+ )
+endif
+
+# This is useful in the main project when libsigc++ is used as a subproject.
+# It's also used when building example programs and test programs.
+sigcxx_dep = declare_dependency(
+ sources: built_h_file_targets,
+ link_with: sigcxx_library,
+ include_directories: extra_include_dirs,
+ dependencies: sigcxx_build_dep
+)
diff --git a/sigc++config.h.meson b/sigc++config.h.meson
new file mode 100644
index 0000000..3057648
--- /dev/null
+++ b/sigc++config.h.meson
@@ -0,0 +1,89 @@
+/* This file is part of libsigc++. */
+#ifndef SIGCXXCONFIG_H_INCLUDED
+#define SIGCXXCONFIG_H_INCLUDED
+
+/* Define to omit deprecated API from the library. */
+#mesondefine SIGCXX_DISABLE_DEPRECATED
+
+/* Major version number of sigc++. */
+#mesondefine SIGCXX_MAJOR_VERSION
+
+/* Minor version number of sigc++. */
+#mesondefine SIGCXX_MINOR_VERSION
+
+/* Micro version number of sigc++. */
+#mesondefine SIGCXX_MICRO_VERSION
+
+/* Detect Win32 platform */
+#ifdef _WIN32
+# if defined(_MSC_VER)
+# define SIGC_MSC 1
+# define SIGC_WIN32 1
+# define SIGC_DLL 1
+# elif defined(__CYGWIN__)
+# define SIGC_CONFIGURE 1
+# elif defined(__MINGW32__)
+# define SIGC_WIN32 1
+# define SIGC_CONFIGURE 1
+# else
+# error "libsigc++ config: Unknown win32 architecture (send me gcc --dumpspecs or equiv)"
+# endif
+#else /* !_WIN32 */
+# define SIGC_CONFIGURE 1
+#endif /* !_WIN32 */
+
+#ifdef SIGC_MSC
+/*
+ * MS VC7 Warning 4251 says that the classes to any member objects in an
+ * exported class must also be exported. Some of the libsigc++
+ * template classes contain std::list members. MS KB article 168958 says
+ * that it's not possible to export a std::list instantiation due to some
+ * wacky class nesting issues, so our only options are to ignore the
+ * warning or to modify libsigc++ to remove the std::list dependency.
+ * AFAICT, the std::list members are used internally by the library code
+ * and don't need to be used from the outside, and ignoring the warning
+ * seems to have no adverse effects, so that seems like a good enough
+ * solution for now.
+ */
+# pragma warning(disable:4251)
+
+# define SIGC_MSVC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD 1
+# define SIGC_NEW_DELETE_IN_LIBRARY_ONLY 1 /* To keep ABI compatibility */
+# define SIGC_PRAGMA_PUSH_POP_MACRO 1
+
+#if (_MSC_VER < 1900) && !defined (noexcept)
+#define _ALLOW_KEYWORD_MACROS 1
+#define noexcept _NOEXCEPT
+#endif
+
+#else /* SIGC_MSC */
+
+/* does the C++ compiler support the use of a particular specialization when
+ calling operator() template methods. */
+#mesondefine SIGC_GCC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD
+
+/* Define if the non-standard Sun reverse_iterator must be used. */
+#mesondefine SIGC_HAVE_SUN_REVERSE_ITERATOR
+
+/* does the C++ compiler support the use of a particular specialization when
+ calling operator() template methods omitting the template keyword. */
+#mesondefine SIGC_MSVC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD
+
+/* does the C++ preprocessor support pragma push_macro() and pop_macro(). */
+#mesondefine SIGC_PRAGMA_PUSH_POP_MACRO
+
+#endif /* !SIGC_MSC */
+
+#ifdef SIGC_DLL
+# if defined(SIGC_BUILD) && defined(_WINDLL)
+# define SIGC_API __declspec(dllexport)
+# elif !defined(SIGC_BUILD)
+# define SIGC_API __declspec(dllimport)
+# else
+# define SIGC_API
+# endif
+#else /* !SIGC_DLL */
+# define SIGC_API
+#endif /* !SIGC_DLL */
+
+#endif /* !SIGCXXCONFIG_H_INCLUDED */
diff --git a/tests/meson.build b/tests/meson.build
new file mode 100644
index 0000000..ca5c318
--- /dev/null
+++ b/tests/meson.build
@@ -0,0 +1,92 @@
+# tests
+
+# input: sigcxx_dep, do_benchmark, can_benchmark, benchmark_dep
+
+benchmark_timeout = 100
+
+test_programs = [
+# [[dir-name], exe-name, [sources]]
+ [[], 'test_accum_iter', ['test_accum_iter.cc', 'testutilities.cc']],
+ [[], 'test_accumulated', ['test_accumulated.cc', 'testutilities.cc']],
+ [[], 'test_bind', ['test_bind.cc', 'testutilities.cc']],
+ [[], 'test_bind_as_slot', ['test_bind_as_slot.cc', 'testutilities.cc']],
+ [[], 'test_bind_ref', ['test_bind_ref.cc', 'testutilities.cc']],
+ [[], 'test_bind_refptr', ['test_bind_refptr.cc', 'testutilities.cc']],
+ [[], 'test_bind_return', ['test_bind_return.cc', 'testutilities.cc']],
+ [[], 'test_compose', ['test_compose.cc', 'testutilities.cc']],
+ [[], 'test_copy_invalid_slot', ['test_copy_invalid_slot.cc', 'testutilities.cc']],
+ [[], 'test_cpp11_lambda', ['test_cpp11_lambda.cc', 'testutilities.cc']],
+ [[], 'test_custom', ['test_custom.cc', 'testutilities.cc']],
+ [[], 'test_deduce_result_type', ['test_deduce_result_type.cc', 'testutilities.cc']],
+ [[], 'test_disconnect', ['test_disconnect.cc', 'testutilities.cc']],
+ [[], 'test_disconnect_during_emit', ['test_disconnect_during_emit.cc', 'testutilities.cc']],
+ [[], 'test_exception_catch', ['test_exception_catch.cc', 'testutilities.cc']],
+ [[], 'test_functor_trait', ['test_functor_trait.cc', 'testutilities.cc']],
+ [[], 'test_hide', ['test_hide.cc', 'testutilities.cc']],
+ [[], 'test_limit_reference', ['test_limit_reference.cc', 'testutilities.cc']],
+ [[], 'test_mem_fun', ['test_mem_fun.cc', 'testutilities.cc']],
+ [[], 'test_ptr_fun', ['test_ptr_fun.cc', 'testutilities.cc']],
+ [[], 'test_retype', ['test_retype.cc', 'testutilities.cc']],
+ [[], 'test_retype_return', ['test_retype_return.cc', 'testutilities.cc']],
+ [[], 'test_signal', ['test_signal.cc', 'testutilities.cc']],
+ [[], 'test_signal_move', ['test_signal_move.cc', 'testutilities.cc']],
+ [[], 'test_size', ['test_size.cc', 'testutilities.cc']],
+ [[], 'test_slot', ['test_slot.cc', 'testutilities.cc']],
+ [[], 'test_slot_disconnect', ['test_slot_disconnect.cc', 'testutilities.cc']],
+ [[], 'test_slot_move', ['test_slot_move.cc', 'testutilities.cc']],
+ [[], 'test_trackable', ['test_trackable.cc', 'testutilities.cc']],
+ [[], 'test_trackable_move', ['test_trackable_move.cc', 'testutilities.cc']],
+ [[], 'test_track_obj', ['test_track_obj.cc', 'testutilities.cc']],
+ [[], 'test_visit_each', ['test_visit_each.cc', 'testutilities.cc']],
+]
+
+benchmark_programs = [
+# [[dir-name], exe-name, [sources]]
+ [[], 'benchmark1', ['benchmark.cc']],
+]
+
+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: sigcxx_dep,
+ gui_app: false,
+ build_by_default: true
+ )
+
+ test(ex_name, exe_file)
+endforeach
+
+if can_benchmark
+ foreach ex : benchmark_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: [sigcxx_dep, benchmark_dep],
+ gui_app: false,
+ build_by_default: do_benchmark
+ )
+
+ if do_benchmark
+ test(ex_name, exe_file,
+ timeout: benchmark_timeout,
+ )
+ endif
+ endforeach
+endif
diff --git a/tools/dist-cmd.py b/tools/dist-cmd.py
new file mode 100755
index 0000000..30da5da
--- /dev/null
+++ b/tools/dist-cmd.py
@@ -0,0 +1,12 @@
+#!/usr/bin/env python3
+
+# External command, intended to be called with meson.add_dist_script() in meson.build.
+# meson.add_dist_script() can't call a script that's not committed to git.
+# This script shall be committed. It can be used for calling other non-committed scripts.
+
+# dist-cmd.py <cmd> <args>...
+
+import sys
+import subprocess
+
+sys.exit(subprocess.run(sys.argv[1:]).returncode)
diff --git a/tools/gcc_template_specialization_operator_overload.cc b/tools/gcc_template_specialization_operator_overload.cc
new file mode 100644
index 0000000..81ab860
--- /dev/null
+++ b/tools/gcc_template_specialization_operator_overload.cc
@@ -0,0 +1,37 @@
+// Configuration-time test program, used in Meson build.
+// Corresponds to the M4 macro SIGC_CXX_GCC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD.
+
+#include <iostream>
+
+class Thing
+{
+ public:
+ Thing()
+ {}
+
+ template <class T>
+ void operator()(T a, T b)
+ {
+ T c = a + b;
+ std::cout << c << std::endl;
+ }
+};
+
+template<class T2>
+class OtherThing
+{
+public:
+ void do_something()
+ {
+ Thing thing_;
+ thing_.template operator()<T2>(1, 2);
+ //This fails with or without the template keyword, on SUN Forte C++ 5.3, 5.4, and 5.5:
+ }
+};
+
+int main()
+{
+ OtherThing<int> thing;
+ thing.do_something();
+ return 0;
+}
diff --git a/tools/handle-built-files.py b/tools/handle-built-files.py
new file mode 100755
index 0000000..57409f2
--- /dev/null
+++ b/tools/handle-built-files.py
@@ -0,0 +1,133 @@
+#!/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.
+def build_from_m4():
+ # argv[2] argv[3] argv[4] argv[5]
+ # <include_dir> <input_file> <output_file> <stamp_file>
+
+ include_dir = sys.argv[2]
+ input_file = sys.argv[3]
+ output_file = sys.argv[4]
+ stamp_file = sys.argv[5]
+
+ # 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()
+
+ if result.returncode:
+ return result.returncode
+
+ if stamp_file.endswith('.cc'):
+ shutil.copy(output_file, stamp_file)
+ else:
+ Path(stamp_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> <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():
+ # 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])
+
+ # Distribute .h and .cc files built from .m4 files.
+ for file in sys.argv[4:]:
+ 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 == '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())
+print(sys.argv[0], ': illegal subcommand,', subcommand)
+sys.exit(1)
diff --git a/tools/have_sun_reverse_iterator.cc b/tools/have_sun_reverse_iterator.cc
new file mode 100644
index 0000000..0985b64
--- /dev/null
+++ b/tools/have_sun_reverse_iterator.cc
@@ -0,0 +1,10 @@
+// Configuration-time test program, used in Meson build.
+// Corresponds to the M4 macro SIGC_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/msvc_template_specialization_operator_overload.cc b/tools/msvc_template_specialization_operator_overload.cc
new file mode 100644
index 0000000..55ad69d
--- /dev/null
+++ b/tools/msvc_template_specialization_operator_overload.cc
@@ -0,0 +1,37 @@
+// Configuration-time test program, used in Meson build.
+// Corresponds to the M4 macro SIGC_CXX_MSVC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD.
+
+#include <iostream>
+
+class Thing
+{
+ public:
+ Thing()
+ {}
+
+ template <class T>
+ void operator()(T a, T b)
+ {
+ T c = a + b;
+ std::cout << c << std::endl;
+ }
+};
+
+template<class T2>
+class OtherThing
+{
+public:
+ void do_something()
+ {
+ Thing thing_;
+ thing_.operator()<T2>(1, 2);
+ //This fails with or without the template keyword, on SUN Forte C++ 5.3, 5.4, and 5.5:
+ }
+};
+
+int main()
+{
+ OtherThing<int> thing;
+ thing.do_something();
+ return 0;
+}
diff --git a/tools/pragma_push_pop_macro.cc b/tools/pragma_push_pop_macro.cc
new file mode 100644
index 0000000..e6cab92
--- /dev/null
+++ b/tools/pragma_push_pop_macro.cc
@@ -0,0 +1,38 @@
+// Configuration-time test program, used in Meson build.
+// Corresponds to the M4 macro SIGC_CXX_PRAGMA_PUSH_POP_MACRO.
+
+#define BEGIN {
+#define END }
+#pragma push_macro("BEGIN")
+#pragma push_macro("END")
+#undef BEGIN
+#undef END
+
+// BEGIN and END are not prepreprocessor macros
+struct Test1
+{
+ int BEGIN;
+ double END;
+};
+
+#pragma pop_macro("BEGIN")
+#pragma pop_macro("END")
+
+// BEGIN and END are prepreprocessor macros
+struct Test2
+BEGIN
+ int i;
+ double d;
+END;
+
+void func1(Test1& x);
+void func2(Test2& x);
+
+int main()
+{
+ Test1 test1;
+ Test2 test2;
+ func1(test1);
+ func2(test2);
+ return 0;
+}
diff --git a/tools/tutorial-custom-cmd.py b/tools/tutorial-custom-cmd.py
new file mode 100755
index 0000000..85b22e7
--- /dev/null
+++ b/tools/tutorial-custom-cmd.py
@@ -0,0 +1,173 @@
+#!/usr/bin/env python3
+
+# External command, intended to be called with custom_target() in meson.build
+
+# argv[1] argv[2:]
+# tutorial-custom-cmd.py <subcommand> <xxx>...
+
+import os
+import sys
+import subprocess
+from pathlib import Path
+import shutil
+
+subcommand = sys.argv[1]
+
+def html():
+ # argv[2] argv[3]
+ # <input_xml_file> <output_html_dir>
+
+ input_xml_file = sys.argv[2]
+ output_html_dir = sys.argv[3]
+
+ # For a list of available parameters, see http://docbook.sourceforge.net/release/xsl/current/doc/html/
+ xslt_params = []
+
+ xslt_stylesheet = 'http://docbook.sourceforge.net/release/xsl/current/html/chunk.xsl'
+
+ # Remove old files and create the destination directory.
+ shutil.rmtree(output_html_dir, ignore_errors=True)
+ os.makedirs(output_html_dir, exist_ok=True)
+
+ cmd = [
+ 'xsltproc',
+ ] + xslt_params + [
+ '-o', output_html_dir + '/',
+ '--xinclude',
+ xslt_stylesheet,
+ input_xml_file,
+ ]
+ result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ universal_newlines=True)
+ # xsltproc prints the names of all written files. Don't print those lines.
+ for line in result.stdout.splitlines():
+ if not line.startswith('Writing '):
+ print(line)
+
+ return result.returncode
+
+def xmllint():
+ # argv[2] argv[3] argv[4]
+ # <validate> <input_xml_file> <stamp_file_path>
+
+ validate = sys.argv[2]
+ input_xml_file = sys.argv[3]
+ stamp_file_path = sys.argv[4]
+
+ cmd = [
+ 'xmllint',
+ '--noout',
+ '--noent',
+ '--xinclude',
+ ]
+ if validate == 'true':
+ cmd += ['--postvalid']
+ cmd += [input_xml_file]
+ result = subprocess.run(cmd)
+ if result.returncode:
+ return result.returncode
+
+ Path(stamp_file_path).touch(exist_ok=True)
+ return 0
+
+def dblatex():
+ # argv[2] argv[3]
+ # <input_xml_file> <output_pdf_file>
+ # Create a PDF file, using dblatex.
+
+ input_xml_file = sys.argv[2]
+ output_pdf_file = sys.argv[3]
+
+ # For a list of available parameters, see http://dblatex.sourceforge.net/doc/manual/
+ dblatex_params = [
+ '-P', 'toc.section.depth=2',
+ '-P', 'paper.type=a4paper',
+ ]
+
+ cmd = [
+ 'dblatex',
+ ] + dblatex_params + [
+ '-o', output_pdf_file,
+ '--pdf', input_xml_file,
+ ]
+ return subprocess.run(cmd).returncode
+
+def docbook2pdf():
+ # argv[2] argv[3]
+ # <input_xml_file> <output_pdf_file>
+ # Create a PDF file, using docbook2pdf.
+
+ input_xml_file = sys.argv[2]
+ output_pdf_file = sys.argv[3]
+
+ output_dir = os.path.dirname(output_pdf_file)
+ if not output_dir:
+ output_dir = '.'
+ output_basename = os.path.basename(output_pdf_file)
+ if output_basename.endswith('.pdf'):
+ output_basename = output_basename[:-4]
+ xml_file = os.path.join(output_dir, output_basename + '.xml')
+
+ # We need to produce an XML file with all of the XIncludes done.
+ cmd = [
+ 'xmllint',
+ '--xinclude',
+ '--postvalid',
+ '--output', xml_file,
+ input_xml_file,
+ ]
+ result = subprocess.run(cmd)
+ if result.returncode:
+ return result.returncode
+
+ cmd = [
+ 'docbook2pdf',
+ '--output', output_dir,
+ xml_file,
+ ]
+ return subprocess.run(cmd).returncode
+
+# Invoked from meson.add_dist_script().
+def dist_doc():
+ # argv[2] argv[3] argv[4] argv[5]
+ # <doc_dist_dir> <doc_build_dir> <xml_file> <pdf_file>
+
+ # <doc_dist_dir> is a distribution directory, relative to MESON_DIST_ROOT.
+ # <doc_build_dir> is a relative or absolute path in the build directory.
+ # <xml_file> is a relative or absolute path in the source directory.
+ # <pdf_file> is a relative or absolute path in the build directory.
+ doc_dist_dir = os.path.join(os.getenv('MESON_DIST_ROOT'), sys.argv[2])
+ doc_build_dir = sys.argv[3]
+ xml_file = sys.argv[4]
+ pdf_file = sys.argv[5]
+
+ # Create the distribution directory, if it does not exist.
+ os.makedirs(doc_dist_dir, exist_ok=True)
+
+ # Distribute built html files.
+ shutil.copytree(os.path.join(doc_build_dir, 'html'),
+ os.path.join(doc_dist_dir, 'html'),
+ copy_function=shutil.copy)
+
+ # If there is an updated PDF file, distribute it.
+ if os.path.isfile(pdf_file) and \
+ os.stat(pdf_file).st_mtime > os.stat(xml_file).st_mtime:
+ shutil.copy(pdf_file, doc_dist_dir)
+ else:
+ print('--- Info: No updated PDF file found.')
+
+ return 0
+
+# ----- Main -----
+if subcommand == 'html':
+ sys.exit(html())
+if subcommand == 'xmllint':
+ sys.exit(xmllint())
+if subcommand == 'dblatex':
+ sys.exit(dblatex())
+if subcommand == 'docbook2pdf':
+ sys.exit(docbook2pdf())
+if subcommand == 'dist_doc':
+ sys.exit(dist_doc())
+print(sys.argv[0], ': illegal subcommand,', subcommand)
+sys.exit(1)
diff --git a/untracked/README b/untracked/README
new file mode 100644
index 0000000..bd9ca5a
--- /dev/null
+++ b/untracked/README
@@ -0,0 +1,38 @@
+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 libsigc++ is built.
+
+Files of type 2 exist here only if libsigc++ is built with maintainer-mode=false,
+or the directory comes from a tarball.
+Files of both types exist here only if libsigc++ is built with Meson,
+or the tarball is created with Meson.
+
+1. Files copied by mm-common-get
+--------------------------------
+untracked/docs/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
+
+mm-common-get may copy more files, but they are not used by libsigc++.
+
+2. Generated files
+------------------
+untracked/docs/reference/libsigc++-2.0.devhelp2
+ libsigc++-2.0.tag
+ html/*
+untracked/docs/manual/html/*
+untracked/sigc++/*.h
+ adaptors/*.h
+ adaptors/lambda/*.h
+ adaptors/lambda/*.cc
+ functors/*.h