summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjell Ahlstedt <kjellahlstedt@gmail.com>2019-09-25 15:02:45 +0200
committerKjell Ahlstedt <kjellahlstedt@gmail.com>2019-09-25 15:02:45 +0200
commit532d7a4218b43859db36b12b3a87e59ffb90a1f6 (patch)
tree820b06a46e2ee7c3265e479f1e0d591f98660a81
parent3c63b147ec412515a492dc4bc1d56c59259c95eb (diff)
downloadmm-common-532d7a4218b43859db36b12b3a87e59ffb90a1f6.tar.gz
util/meson_aux: Replace shell scripts with Python scripts
Python scripts can be used on all operating systems where Meson can be used. Shell scripts are restricted to Unix-like systems.
-rw-r--r--Makefile.am8
-rw-r--r--meson.build47
-rwxr-xr-xutil/meson_aux/extra-dist-cmd.py39
-rwxr-xr-xutil/meson_aux/extra-dist-cmd.sh17
-rwxr-xr-xutil/meson_aux/extra-install-cmd.py43
-rwxr-xr-xutil/meson_aux/extra-install-cmd.sh25
-rwxr-xr-xutil/meson_aux/libstdcxx-tag.py77
-rwxr-xr-xutil/meson_aux/libstdcxx-tag.sh45
-rwxr-xr-xutil/meson_aux/skeletonmm-tarball.py53
-rwxr-xr-xutil/meson_aux/skeletonmm-tarball.sh24
10 files changed, 246 insertions, 132 deletions
diff --git a/Makefile.am b/Makefile.am
index 4f7ad94..9b59a9f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -128,10 +128,10 @@ MAINTAINERCLEANFILES = $(dist_doctags_DATA)
EXTRA_DIST = \
meson.build \
meson_options.txt \
- util/meson_aux/extra-dist-cmd.sh \
- util/meson_aux/extra-install-cmd.sh \
- util/meson_aux/libstdcxx-tag.sh \
- util/meson_aux/skeletonmm-tarball.sh
+ util/meson_aux/extra-dist-cmd.py \
+ util/meson_aux/extra-install-cmd.py \
+ util/meson_aux/libstdcxx-tag.py \
+ util/meson_aux/skeletonmm-tarball.py
# Remote location of the GNU libstdc++ Doxygen tag file.
libstdcxx_tag_url = http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/libstdc++.tag
diff --git a/meson.build b/meson.build
index 57fe072..f61fa9e 100644
--- a/meson.build
+++ b/meson.build
@@ -2,10 +2,24 @@
project('mm-common',
version: '0.9.12',
- meson_version: '>= 0.49.0',
+ meson_version: '>= 0.50.0', # required for python3.path()
license: 'GPLv2+'
)
+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
+
+# Use these instead of meson.source_root() and meson.build_root().
+# 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()
+
+script_dir = project_source_root / 'util' / 'meson_aux'
+
# Install directories are relative to {prefix}.
install_prefix = get_option('prefix')
install_bindir = get_option('bindir')
@@ -84,7 +98,8 @@ configure_file(
if find_program('aclocal', required: false).found()
meson.add_install_script(
- 'util' / 'meson_aux' / 'extra-install-cmd.sh',
+ python3.path(),
+ script_dir / 'extra-install-cmd.py',
install_prefix / install_aclocal_macrodir
)
endif
@@ -201,22 +216,18 @@ foreach file : skeletonmm_basefiles
skeletonmm_files += 'skeletonmm' / file
endforeach
-# tar and either xz or gzip are required for the skeletonmm.tar.[xz|gz] file.
-tar = find_program('tar', required: true)
-xz = find_program('xz', required: false)
-if not xz.found()
- gzip = find_program('gzip', required: true)
-endif
-
# Create tar archive of skeletonmm for installation.
-tarball_filename = xz.found() ? 'skeletonmm.tar.xz' : 'skeletonmm.tar.gz'
+skeletonmm_tarball_script = script_dir / 'skeletonmm-tarball.py'
+tarball_filetype = run_command(python3, skeletonmm_tarball_script, 'check')
+tarball_filename = 'skeletonmm' + tarball_filetype.stdout()
custom_target(tarball_filename,
input: skeletonmm_files,
output: tarball_filename,
command: [
- files('util' / 'meson_aux' / 'skeletonmm-tarball.sh'),
- meson.current_source_dir(),
+ python3,
+ skeletonmm_tarball_script,
'@OUTPUT@',
+ project_source_root,
skeletonmm_files,
],
build_by_default: true,
@@ -241,9 +252,10 @@ endif
custom_target('libstdc++.tag',
output: 'libstdc++.tag',
command: [
- files('util' / 'meson_aux' / 'libstdcxx-tag.sh'),
+ python3,
+ script_dir / 'libstdcxx-tag.py',
download_cmd,
- meson.current_source_dir() / 'doctags',
+ project_source_root / 'doctags',
'@OUTPUT@',
],
build_by_default: true,
@@ -255,9 +267,10 @@ custom_target('libstdc++.tag',
if not meson.is_subproject()
# Modify the contents of the distribution directory. (not allowed in a subproject)
meson.add_dist_script(
- 'util' / 'meson_aux' / 'extra-dist-cmd.sh',
- meson.current_source_dir(),
- meson.current_build_dir(),
+ python3.path(),
+ script_dir / 'extra-dist-cmd.py',
+ project_source_root,
+ project_build_root,
)
endif
diff --git a/util/meson_aux/extra-dist-cmd.py b/util/meson_aux/extra-dist-cmd.py
new file mode 100755
index 0000000..5b04f06
--- /dev/null
+++ b/util/meson_aux/extra-dist-cmd.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python3
+
+# External command, intended to be called with meson.add_dist_script() in meson.build
+
+# argv[1] argv[2]
+# extra-dist-cmd.py <root_source_dir> <root_build_dir>
+
+# Meson does not preserve timestamps on distributed files.
+# But this script preserves the timestamps on libstdc++.tag.
+
+import os
+import sys
+import subprocess
+import shutil
+
+root_source_dir = sys.argv[1]
+root_build_dir = sys.argv[2]
+
+# Make a ChangeLog file for distribution.
+cmd = [
+ 'git',
+ '--git-dir=' + os.path.join(root_source_dir, '.git'),
+ '--work-tree=' + root_source_dir,
+ '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()
+
+# Distribute the libstdc++.tag file in addition to the files in the local git clone.
+# shutil.copy2() copies timestamps and some other file metadata.
+shutil.copy2(os.path.join(root_build_dir, 'libstdc++.tag'),
+ os.path.join(os.getenv('MESON_DIST_ROOT'), 'doctags'))
+
+sys.exit(result.returncode)
diff --git a/util/meson_aux/extra-dist-cmd.sh b/util/meson_aux/extra-dist-cmd.sh
deleted file mode 100755
index 1c61ed1..0000000
--- a/util/meson_aux/extra-dist-cmd.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/sh -e
-
-# External command, intended to be called with meson.add_dist_script() in meson.build
-
-# extra-dist-cmd.sh <root_source_dir> <root_build_dir>
-
-# Meson does not preserve timestamps on distributed files.
-# But this script preserves the timestamps on libstdc++.tag.
-
-# Make a ChangeLog file for distribution.
-git --git-dir="$1/.git" --work-tree="$1" log --no-merges --date=short --max-count=200 \
- --pretty='tformat:%cd %an <%ae>%n%n %s%n%w(0,0,2)%+b' > "$MESON_DIST_ROOT/ChangeLog"
-
-# Distribute the libstdc++.tag file in addition to the files in the local git clone.
-# -p == --preserve=mode,ownership,timestamps (Posix does not support long options.)
-# Only the preservation of timestamps is essential here.
-cp -p "$2/libstdc++.tag" "$MESON_DIST_ROOT/doctags/"
diff --git a/util/meson_aux/extra-install-cmd.py b/util/meson_aux/extra-install-cmd.py
new file mode 100755
index 0000000..8414847
--- /dev/null
+++ b/util/meson_aux/extra-install-cmd.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+
+# External command, intended to be called with meson.add_install_script() in meson.build
+
+# argv[1]
+# extra-install-cmd.py <aclocal_macrodir>
+
+import os
+import sys
+import subprocess
+
+if not os.getenv('DESTDIR'):
+ # Inform the installer that M4 macro files installed in a directory
+ # not known to aclocal will not be picked up automatically.
+ # (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(['aclocal', '--print-ac-dir'],
+ stdout=subprocess.PIPE, stderr=subprocess.DEVNULL,
+ universal_newlines=True)
+ acdir = result.stdout
+ aclocal_path = os.getenv('ACLOCAL_PATH')
+ # acdir and aclocal_path can be sequences of os.pathsep-separated paths.
+ # Merge them to one sequence with leading and trailing os.pathsep.
+ # os.pathsep is ':' for Linux, ';' for Windows.
+ acdirs = os.pathsep
+ if aclocal_path:
+ acdirs += aclocal_path + os.pathsep
+ if acdir:
+ acdirs += acdir + os.pathsep
+
+ if (os.pathsep + sys.argv[1] + os.pathsep) not in acdirs:
+ # f'''.....''' would require Python 3.6. Avoid it.
+ print('''\
+ NOTE
+ ----
+The mm-common Autoconf macro files have been installed in a different
+directory than the system aclocal directory. In order for the installed
+macros to be found, it may be necessary to add the mm-common include
+path to the ACLOCAL_PATH environment variable:
+ ACLOCAL_PATH="$ACLOCAL_PATH:{}"
+ export ACLOCAL_PATH'''.format(sys.argv[1])
+ )
+sys.exit(0)
diff --git a/util/meson_aux/extra-install-cmd.sh b/util/meson_aux/extra-install-cmd.sh
deleted file mode 100755
index e07a692..0000000
--- a/util/meson_aux/extra-install-cmd.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh -e
-
-# External command, intended to be called with meson.add_install_script() in meson.build
-
-# extra-install-cmd.sh <aclocal_macrodir>
-
-if [ -z "$DESTDIR" ]; then
- # Inform the installer that M4 macro files installed in a directory
- # not known to aclocal will not be picked up automatically.
- acdir="$(aclocal --print-ac-dir 2>/dev/null || :)"
- case ":$ACLOCAL_PATH:$acdir:" in
- *":$1:"*)
- ;;
- *)
- echo "NOTE"
- echo "----"
- echo "The mm-common Autoconf macro files have been installed in a different"
- echo "directory than the system aclocal directory. In order for the installed"
- echo "macros to be found, it may be necessary to add the mm-common include"
- echo "path to the ACLOCAL_PATH environment variable:"
- echo " ACLOCAL_PATH=\"\$ACLOCAL_PATH:$1\""
- echo " export ACLOCAL_PATH"
- ;;
- esac
-fi
diff --git a/util/meson_aux/libstdcxx-tag.py b/util/meson_aux/libstdcxx-tag.py
new file mode 100755
index 0000000..2873498
--- /dev/null
+++ b/util/meson_aux/libstdcxx-tag.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python3
+
+# External command, intended to be called with custom_target() in meson.build
+
+# argv[1] argv[2] argv[3]
+# libstdcxx-tag.py <curl-or-wget-or-none> <srcdir> <output_path>
+
+import os
+import sys
+import subprocess
+import shutil
+
+subcommand = sys.argv[1]
+srcdir = sys.argv[2]
+output_path = sys.argv[3]
+output_dirname, output_filename = os.path.split(output_path)
+if not output_dirname:
+ output_dirname = '.'
+
+# Remote location of the GNU libstdc++ Doxygen tag file.
+libstdcxx_tag_url = 'http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/' + output_filename
+
+def curl():
+ cmd = [
+ 'curl',
+ '--compressed',
+ '--connect-timeout', '300',
+ '--globoff',
+ '--location',
+ '--max-time', '3600',
+ '--remote-time',
+ '--retry', '5',
+ ]
+ if os.path.isfile(output_path):
+ # Don't download the tag file unless it's newer than the local file.
+ cmd += ['--time-cond', output_path]
+
+ cmd += [
+ '--output', output_path,
+ libstdcxx_tag_url,
+ ]
+ return subprocess.run(cmd).returncode
+
+def wget():
+ cmd = [
+ 'wget',
+ '--timestamping',
+ '--no-directories',
+ '--timeout=300',
+ '--tries=5',
+ '--directory-prefix=' + output_dirname,
+ libstdcxx_tag_url,
+ ]
+ return subprocess.run(cmd).returncode
+
+def dont_download_tag_file():
+ if os.path.isfile(output_path):
+ print('Did not check status of', output_path, 'because network is disabled.')
+ elif os.path.isfile(os.path.join(srcdir, output_filename)):
+ print('Warning:', output_path, 'does not exist.')
+ print('Copying from the source directory because network is disabled.')
+ print('If you want an up-to-date copy, reconfigure with the -Duse-network=true option.')
+ # shutil.copy2() copies timestamps and some other file metadata.
+ shutil.copy2(os.path.join(srcdir, output_filename), output_path)
+ else:
+ print('Error:', output_path, 'does not exist.', file=sys.stderr)
+ print('Downloading it is not possible because network is disabled.', file=sys.stderr)
+ print('Please reconfigure with the -Duse-network=true option.', file=sys.stderr)
+ return 1
+ return 0
+
+# ----- Main -----
+if subcommand == 'curl':
+ sys.exit(curl())
+if subcommand == 'wget':
+ sys.exit(wget())
+sys.exit(dont_download_tag_file())
diff --git a/util/meson_aux/libstdcxx-tag.sh b/util/meson_aux/libstdcxx-tag.sh
deleted file mode 100755
index c05d8e8..0000000
--- a/util/meson_aux/libstdcxx-tag.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/sh -e
-
-# External command, intended to be called with custom_target() in meson.build
-
-# libstdcxx-tag.sh <curl-or-wget-or-none> <srcdir> <output_path>
-
-output_dirname="$(dirname "$3")"
-output_filename="$(basename "$3")"
-
-# Remote location of the GNU libstdc++ Doxygen tag file.
-libstdcxx_tag_url="http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/$output_filename"
-
-case "$1" in
- curl)
- # These options don't contain filenames, and thus no spaces that
- # must be preserved in the call to curl.
- simple_curl_options="--compressed --connect-timeout 300 --globoff --location --max-time 3600 --remote-time --retry 5"
- if [ -f "$3" ]; then
- curl $simple_curl_options --time-cond "$3" --output "$3" "$libstdcxx_tag_url"
- else
- curl $simple_curl_options --output "$3" "$libstdcxx_tag_url"
- fi
- ;;
- wget)
- wget --timestamping --no-directories --timeout=300 --tries=5 \
- --directory-prefix="$output_dirname" "$libstdcxx_tag_url"
- ;;
- *)
- if [ -f "$3" ]; then
- echo "Did not check status of $3 because network is disabled."
- elif [ -f "$2/$output_filename" ]; then
- echo "Warning: $3 does not exist."
- echo "Copying from the source directory because network is disabled."
- echo "If you want an up-to-date copy, reconfigure with the -Duse-network=true option."
- # -p == --preserve=mode,ownership,timestamps (Posix does not support long options.)
- # Only the preservation of timestamps is essential here.
- cp -p "$2/$output_filename" "$3"
- else
- echo "Error: $3 does not exist." >&2
- echo "Downloading it is not possible because network is disabled." >&2
- echo "Please reconfigure with the -Duse-network=true option." >&2
- exit 1
- fi
- ;;
-esac
diff --git a/util/meson_aux/skeletonmm-tarball.py b/util/meson_aux/skeletonmm-tarball.py
new file mode 100755
index 0000000..576b522
--- /dev/null
+++ b/util/meson_aux/skeletonmm-tarball.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python3
+
+# External command, intended to be called with run_command() or custom_target()
+# in meson.build
+
+# argv[1] argv[2] argv[3:]
+# skeletonmm-tarball.py <output_file_or_check> <source_dir> <input_files...>
+
+import os
+import sys
+import shutil
+import tarfile
+
+if sys.argv[1] == 'check':
+ # Called from run_command() during setup or configuration.
+ # Check which archive format can be used.
+ # In order from most wanted to least wanted: .tar.xz, .tar.gz, .tar
+ available_archive_formats = []
+ for af in shutil.get_archive_formats():
+ # Keep the formats in a list, skip the descriptions.
+ available_archive_formats += [af[0]]
+ if 'xztar' in available_archive_formats:
+ suffix = '.tar.xz'
+ elif 'gztar' in available_archive_formats:
+ suffix = '.tar.gz'
+ else: # Uncompressed tar format is always available.
+ suffix = '.tar'
+ print(suffix, end='') # stdout can be read in the meson.build file.
+ sys.exit(0)
+
+# Create an archive.
+output_file = sys.argv[1]
+source_dir = sys.argv[2]
+
+if output_file.endswith('.xz'):
+ mode = 'w:xz'
+elif output_file.endswith('.gz'):
+ mode = 'w:gz'
+else:
+ mode = 'w'
+
+tar_file = tarfile.open(output_file, mode=mode)
+os.chdir(source_dir) # Input filenames are relative to source_dir.
+for file in sys.argv[3:]:
+ tar_file.add(file)
+tar_file.close()
+# Errors raise exceptions. If an exception is raised, Meson+ninja will notice
+# that the command failed, despite exit(0).
+sys.exit(0)
+
+# shutil.make_archive() might be an alternative, but it only archives
+# whole directories. It's not useful, if you want to have full control
+# of which files are archived.
diff --git a/util/meson_aux/skeletonmm-tarball.sh b/util/meson_aux/skeletonmm-tarball.sh
deleted file mode 100755
index f0fd17d..0000000
--- a/util/meson_aux/skeletonmm-tarball.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh -e
-
-# External command, intended to be called with custom_target() in meson.build
-
-# skeletonmm-tarball.sh <source_dir> <output_file> <input_files...>
-
-source_dir="$1"
-output_file="$2"
-shift 2
-
-# -chof == --create --dereference --old-archive --file (Posix does not support long options.)
-tar_options="-chof -"
-
-case "$output_file" in
- *.xz)
- ( cd "$source_dir"; tar $tar_options "$@" ) | xz --to-stdout --extreme >"$output_file"
- ;;
- *.gz)
- ( cd "$source_dir"; tar $tar_options "$@" ) | gzip --to-stdout --best --no-name >"$output_file"
- ;;
- *) echo "Error: Unknown filetype, $output_file"
- exit 1
- ;;
-esac