summaryrefslogtreecommitdiffstats
path: root/packaging/macos/jhb
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--packaging/macos/jhb/README.md17
-rw-r--r--packaging/macos/jhb/etc/jhb.conf.sh53
l---------packaging/macos/jhb/etc/jhb.conf/10.sh1
l---------packaging/macos/jhb/etc/jhb.conf/20.sh1
l---------packaging/macos/jhb/etc/jhb.conf/30.sh1
-rw-r--r--packaging/macos/jhb/etc/jhb.conf/README.md12
-rw-r--r--packaging/macos/jhb/etc/jhb.conf/bash_d.sh30
-rw-r--r--packaging/macos/jhb/etc/jhb.conf/ccache.sh49
-rw-r--r--packaging/macos/jhb/etc/jhb.conf/ci.sh42
-rw-r--r--packaging/macos/jhb/etc/jhb.conf/directories.sh83
-rw-r--r--packaging/macos/jhb/etc/jhb.conf/dmgbuild.sh96
-rw-r--r--packaging/macos/jhb/etc/jhb.conf/home.sh24
-rw-r--r--packaging/macos/jhb/etc/jhb.conf/jhbuild.sh229
-rw-r--r--packaging/macos/jhb/etc/jhb.conf/path.sh23
-rw-r--r--packaging/macos/jhb/etc/jhb.conf/pip.sh26
-rw-r--r--packaging/macos/jhb/etc/jhb.conf/release.sh35
-rw-r--r--packaging/macos/jhb/etc/jhb.conf/sdkroot.sh41
-rw-r--r--packaging/macos/jhb/etc/jhb.conf/sys.sh121
-rw-r--r--packaging/macos/jhb/etc/jhb.conf/temp.sh27
-rw-r--r--packaging/macos/jhb/etc/jhb.conf/version.sh24
-rw-r--r--packaging/macos/jhb/etc/jhb.conf/xdg.sh25
-rw-r--r--packaging/macos/jhb/etc/jhbuildrc613
-rw-r--r--packaging/macos/jhb/etc/modulesets/jhb/bootstrap.modules158
-rw-r--r--packaging/macos/jhb/etc/modulesets/jhb/jhb.modules60
-rw-r--r--packaging/macos/jhb/etc/modulesets/jhb/moduleset.dtd240
-rw-r--r--packaging/macos/jhb/etc/modulesets/jhb/moduleset.xsl196
-rw-r--r--packaging/macos/jhb/etc/modulesets/jhb/patches/libtool-apple-sort.patch38
-rw-r--r--packaging/macos/jhb/etc/modulesets/jhb/patches/vasnprintf.patch11
-rwxr-xr-xpackaging/macos/jhb/usr/bin/archive205
-rwxr-xr-xpackaging/macos/jhb/usr/bin/bootstrap135
-rwxr-xr-xpackaging/macos/jhb/usr/bin/jhb63
-rwxr-xr-xpackaging/macos/jhb/usr/bin/run-parts73
-rw-r--r--packaging/macos/jhb/usr/src/bash_d/README.md9
-rw-r--r--packaging/macos/jhb/usr/src/bash_d/ansi.sh76
-rw-r--r--packaging/macos/jhb/usr/src/bash_d/assert.sh42
-rw-r--r--packaging/macos/jhb/usr/src/bash_d/bash_d.sh98
-rw-r--r--packaging/macos/jhb/usr/src/bash_d/echo.sh52
-rw-r--r--packaging/macos/jhb/usr/src/bash_d/error.sh45
-rw-r--r--packaging/macos/jhb/usr/src/bash_d/lib.sh174
-rw-r--r--packaging/macos/jhb/usr/src/bash_d/readlinkf.sh27
40 files changed, 3275 insertions, 0 deletions
diff --git a/packaging/macos/jhb/README.md b/packaging/macos/jhb/README.md
new file mode 100644
index 0000000..04c025e
--- /dev/null
+++ b/packaging/macos/jhb/README.md
@@ -0,0 +1,17 @@
+# bootstrapped JHBuild for macOS
+
+This is my version of setting up JHBuild on macOS. It is inspired by and uses components of [gtk-osx](https://gitlab.gnome.org/GNOME/gtk-osx), but deviates from it in a few significant ways:
+
+- It uses a [FSH](https://refspecs.linuxfoundation.org/FHS_3.0/fhs-3.0.html)-inspired directory layout.
+
+- It is fully self-contained to its directories, allowing for co-existence of multiple installations in locations of your choosing.
+
+- It uses a pre-built [Python.framework](https://gitlab.com/dehesselle/python_macos) to run JHBuild on OS X El Capitan up to macOS Monterey without relying on the system's Python.
+
+## usage
+
+TBD
+
+## license
+
+[GPL-2.0-or-later](LICENSE)
diff --git a/packaging/macos/jhb/etc/jhb.conf.sh b/packaging/macos/jhb/etc/jhb.conf.sh
new file mode 100644
index 0000000..398e9d3
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf.sh
@@ -0,0 +1,53 @@
+# SPDX-FileCopyrightText: 2022 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# This is a convenience wrapper to source all individual configuration files.
+# It also takes care of placing a custom configuration file in the appropriate
+# location.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+
+### dependencies ###############################################################
+
+SELF_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" || exit 1; pwd)
+
+CUSTOM_CONFIG=$SELF_DIR/jhb-custom.conf.sh
+# copy a custom configuration file to the appropriate place
+if [[ $1 == *.conf.sh ]] && [ -f "$1" ]; then
+ cp "$1" "$CUSTOM_CONFIG"
+fi
+
+# source a custom configuration file if present
+if [ -f "$CUSTOM_CONFIG" ]; then
+ # shellcheck disable=SC1090 # file is optional
+ source "$CUSTOM_CONFIG"
+fi
+unset CUSTOM_CONFIG
+
+# source items from jhb.conf directory
+for CONFIG_ITEM in $(\
+ "$SELF_DIR"/../usr/bin/run-parts list "$SELF_DIR"/jhb.conf/'*.sh' \
+ ); do
+ # shellcheck disable=SC1090 # can't point to a single source here
+ source "$CONFIG_ITEM"
+done
+unset CONFIG_ITEM
+
+unset SELF_DIR
+
+### variables ##################################################################
+
+# Nothing here.
+
+### functions ##################################################################
+
+# Nothing here.
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/etc/jhb.conf/10.sh b/packaging/macos/jhb/etc/jhb.conf/10.sh
new file mode 120000
index 0000000..b7ae2b7
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/10.sh
@@ -0,0 +1 @@
+version.sh \ No newline at end of file
diff --git a/packaging/macos/jhb/etc/jhb.conf/20.sh b/packaging/macos/jhb/etc/jhb.conf/20.sh
new file mode 120000
index 0000000..96f9d20
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/20.sh
@@ -0,0 +1 @@
+ci.sh \ No newline at end of file
diff --git a/packaging/macos/jhb/etc/jhb.conf/30.sh b/packaging/macos/jhb/etc/jhb.conf/30.sh
new file mode 120000
index 0000000..c1d5631
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/30.sh
@@ -0,0 +1 @@
+directories.sh \ No newline at end of file
diff --git a/packaging/macos/jhb/etc/jhb.conf/README.md b/packaging/macos/jhb/etc/jhb.conf/README.md
new file mode 100644
index 0000000..c79b3ad
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/README.md
@@ -0,0 +1,12 @@
+# JHB configuration
+
+Files in here are being sourced by `../../usr/bin/run-parts`
+
+- in their lexical order _and_
+- only once in case a symlink exists.
+
+This way we don't have to prefix the filenames themselves to influnce the order of inclusion (a "poor man's dependency management").
+
+The filename is also the prefix for any variable or function name within.
+
+A file is not allowed to depend on any function or variable outside this directory, with the exception of functions included from `bash_d.sh`.
diff --git a/packaging/macos/jhb/etc/jhb.conf/bash_d.sh b/packaging/macos/jhb/etc/jhb.conf/bash_d.sh
new file mode 100644
index 0000000..5ab11b2
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/bash_d.sh
@@ -0,0 +1,30 @@
+# SPDX-FileCopyrightText: 2022 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# Enable bash_d usage by providing bash_d_include function.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+
+### dependencies ###############################################################
+
+# shellcheck source=../../usr/src/bash_d/bash_d.sh
+source "$(dirname "${BASH_SOURCE[0]}")"/../../usr/src/bash_d/bash_d.sh
+
+bash_d_include echo
+
+### variables ##################################################################
+
+# Nothing here.
+
+### functions ##################################################################
+
+# Nothing here.
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/etc/jhb.conf/ccache.sh b/packaging/macos/jhb/etc/jhb.conf/ccache.sh
new file mode 100644
index 0000000..82a2208
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/ccache.sh
@@ -0,0 +1,49 @@
+# SPDX-FileCopyrightText: 2022 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# Settings and functions to setup ccache.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+
+### variables ##################################################################
+
+export CCACHE_DIR=${CCACHE_DIR:-$WRK_DIR/ccache}
+
+# https://ccache.dev
+# https://github.com/ccache/ccache
+# https://gitlab.com/dehesselle/ccache_macos
+CCACHE_VER=4.6.3r1
+CCACHE_URL=https://gitlab.com/api/v4/projects/29039216/packages/generic/\
+ccache_macos/$CCACHE_VER/ccache_$(uname -m).tar.xz
+
+### functions ##################################################################
+
+function ccache_configure
+{
+ mkdir -p "$CCACHE_DIR"
+
+ cat <<EOF > "$CCACHE_DIR/ccache.conf"
+base_dir = $WRK_DIR
+hash_dir = false
+max_size = 3.0G
+temporary_dir = $CCACHE_DIR/tmp
+EOF
+}
+
+function ccache_install
+{
+ curl -L "$CCACHE_URL" | tar -C "$USR_DIR"/bin --exclude="ccache.sha256" -xJ
+
+ for compiler in clang clang++ gcc g++; do
+ ln -sf ccache "$USR_DIR"/bin/$compiler
+ done
+}
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/etc/jhb.conf/ci.sh b/packaging/macos/jhb/etc/jhb.conf/ci.sh
new file mode 100644
index 0000000..727cb2a
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/ci.sh
@@ -0,0 +1,42 @@
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# check if running in CI (GitHub or GitLab)
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+# shellcheck disable=SC2034 # we only use exports if we really need them
+
+### variables ##################################################################
+
+if [ -z "$CI" ]; then # both GitHub and GitLab set this
+ CI=false
+ CI_GITHUB=false
+ CI_GITLAB=false
+else
+ CI=true
+
+ if [ -z "$CI_PROJECT_NAME" ]; then # this is a GitLab-only variable
+ CI_GITHUB=true
+ CI_GITLAB=false
+ else
+ CI_GITHUB=false
+ CI_GITLAB=true
+
+ # Since GitLab uses colors in their CI there's no need to disable ours.
+ # shellcheck disable=SC2034 # this is a bash_d setting
+ ANSI_TERM_ONLY=false # use ANSI control characters even if not in terminal
+ fi
+fi
+
+### functions ##################################################################
+
+# Nothing here.
+
+### main #######################################################################
+
+# Nothing here. \ No newline at end of file
diff --git a/packaging/macos/jhb/etc/jhb.conf/directories.sh b/packaging/macos/jhb/etc/jhb.conf/directories.sh
new file mode 100644
index 0000000..4119456
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/directories.sh
@@ -0,0 +1,83 @@
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# FSH-inspired directory layout
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+# shellcheck disable=SC2034 # we only use exports if we really need them
+
+### variables ##################################################################
+
+#--------------------------------------------------------- main directory layout
+
+# WRK_DIR (/Users/Shared/work)
+# ┃
+# ┣━━ REP_DIR (repo)
+# ┃
+# ┗━━ VER_DIR (jhb-$VERSION)
+# ┃
+# ┣━━ BIN_DIR (bin)
+# ┣━━ ETC_DIR (etc)
+# ┣━━ INC_DIR (include)
+# ┣━━ LIB_DIR (lib)
+# ┣━━ OPT_DIR (opt)
+# ┃
+# ┣━━ TMP_DIR (tmp)
+# ┃
+# ┣━━ USR_DIR (usr)
+# ┃ ┗━━ SRC_DIR (src)
+# ┃
+# ┗━━ VAR_DIR (var)
+# ┣━━ BLD_DIR (build)
+# ┗━━ PKG_DIR (cache/pkg)
+#
+# You can either override a variable directly or use a corresponding
+# "*_TEMPLATE" variable if you want to reference other variables, e.g.
+#
+# VER_DIR_TEMPLATE="\$WRK_DIR/myFoo-\$VERSION"
+
+WRK_DIR=$(eval echo "${WRK_DIR:-${WRK_DIR_TEMPLATE:-/Users/Shared/work}}")
+
+REP_DIR=$(eval echo "${REP_DIR:-${REP_DIR_TEMPLATE:-$WRK_DIR/repo}}")
+
+VER_DIR=$(eval echo "${VER_DIR:-${VER_DIR_TEMPLATE:-$WRK_DIR/jhb-$VERSION}}")
+
+BIN_DIR=$(eval echo "${BIN_DIR:-${BIN_DIR_TEMPLATE:-$VER_DIR/bin}}")
+ETC_DIR=$(eval echo "${ETC_DIR:-${ETC_DIR_TEMPLATE:-$VER_DIR/etc}}")
+INC_DIR=$(eval echo "${INC_DIR:-${INC_DIR_TEMPLATE:-$VER_DIR/include}}")
+LIB_DIR=$(eval echo "${LIB_DIR:-${LIB_DIR_TEMPLATE:-$VER_DIR/lib}}")
+OPT_DIR=$(eval echo "${OPT_DIR:-${OPT_DIR_TEMPLATE:-$VER_DIR/opt}}")
+
+USR_DIR=$(eval echo "${USR_DIR:-${USR_DIR_TEMPLATE:-$VER_DIR/usr}}")
+SRC_DIR=$(eval echo "${SRC_DIR:-${SRC_DIR_TEMPLATE:-$USR_DIR/src}}")
+
+TMP_DIR=$(eval echo "${TMP_DIR:-${TMP_DIR_TEMPLATE:-$VER_DIR/tmp}}")
+
+VAR_DIR=$(eval echo "${VAR_DIR:-${VAR_DIR_TEMPLATE:-$VER_DIR/var}}")
+BLD_DIR=$(eval echo "${BLD_DIR:-${BLD_DIR_TEMPLATE:-$VAR_DIR/build}}")
+PKG_DIR=$(eval echo "${PKG_DIR:-${PKG_DIR_TEMPLATE:-$VAR_DIR/cache/pkg}}")
+
+#------------------------------------------------------------ artifact directory
+
+if [ -z "$ARTIFACT_DIR" ]; then
+ if $CI_GITHUB; then
+ ARTIFACT_DIR=$GITHUB_WORKSPACE
+ elif $CI_GITLAB; then
+ ARTIFACT_DIR=$CI_PROJECT_DIR
+ else
+ ARTIFACT_DIR=$VER_DIR
+ fi
+fi
+
+### functions ##################################################################
+
+# Nothing here.
+
+### main #######################################################################
+
+# Nothing here. \ No newline at end of file
diff --git a/packaging/macos/jhb/etc/jhb.conf/dmgbuild.sh b/packaging/macos/jhb/etc/jhb.conf/dmgbuild.sh
new file mode 100644
index 0000000..d957703
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/dmgbuild.sh
@@ -0,0 +1,96 @@
+# SPDX-FileCopyrightText: 2022 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# dmgbuild is a Python package that simplifies the process of creating a
+# disk image (dmg) for distribution.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+
+### dependencies ###############################################################
+
+# Nothing here.
+
+### variables ##################################################################
+
+# https://dmgbuild.readthedocs.io/en/latest/
+# https://github.com/al45tair/dmgbuild
+# including optional dependencies:
+# - biplist: binary plist parser/generator
+# - pyobjc-*: framework wrappers
+DMGBUILD_PIP="\
+ biplist==1.0.3\
+ dmgbuild==1.5.2\
+ ds-store==1.3.0\
+ mac-alias==2.2.0\
+ pyobjc-core==8.5.1\
+ pyobjc-framework-Cocoa==8.5.1\
+ pyobjc-framework-Quartz==8.5.1\
+"
+
+### functions ##################################################################
+
+function dmgbuild_install
+{
+ # shellcheck disable=SC2086 # we need word splitting here
+ jhb run $JHBUILD_PYTHON_PIP install --prefix=$USR_DIR wheel $DMGBUILD_PIP
+
+ # dmgbuild has issues with detaching, workaround is to increase max retries
+ gsed -i '$ s/HiDPI)/HiDPI, detach_retries=15)/g' "$USR_DIR"/bin/dmgbuild
+}
+
+function dmgbuild_run
+{
+ local config=$1
+ local plist=$2
+ local dmg=$3 # optional; default is <name>_<version>_<build>_<arch>.dmg
+
+ local app_dir
+ app_dir=$(echo "$ARTIFACT_DIR"/*.app)
+
+ if [ -z "$dmg" ]; then
+ local version
+ version=$(/usr/libexec/PlistBuddy \
+ -c "Print :CFBundleShortVersionString" "$plist")
+ local build
+ build=$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "$plist")
+
+ dmg=$(basename -s .app "$app_dir")_${version}+${build}_$(uname -m).dmg
+ fi
+
+ # Copy templated version of the file (it contains placeholders) to source
+ # directory. They copy will be modified to contain the actual values.
+ cp "$config" "$SRC_DIR"
+ config=$SRC_DIR/$(basename "$config")
+
+ # set application
+ gsed -i "s|PLACEHOLDERAPPLICATION|$app_dir|" "$config"
+
+ # set disk image icon (if it exists)
+ local icon
+ icon=$SRC_DIR/$(basename -s .py "$config").icns
+ if [ -f "$icon" ]; then
+ gsed -i "s|PLACEHOLDERICON|$icon|" "$config"
+ fi
+
+ # set background image (if it exists)
+ local background
+ background=$SRC_DIR/$(basename -s .py "$config").png
+ if [ -f "$background" ]; then
+ gsed -i "s|PLACEHOLDERBACKGROUND|$background|" "$config"
+ fi
+
+ # Create disk image in temporary location and move to target location
+ # afterwards. This way we can run multiple times without requiring cleanup.
+ dmgbuild -s "$config" "$(basename -s .app "$app_dir")" \
+ "$TMP_DIR"/"$(basename "$dmg")"
+ mv "$TMP_DIR"/"$(basename "$dmg")" "$dmg"
+}
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/etc/jhb.conf/home.sh b/packaging/macos/jhb/etc/jhb.conf/home.sh
new file mode 100644
index 0000000..31bf892
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/home.sh
@@ -0,0 +1,24 @@
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# Redirect user's home directory.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+# shellcheck disable=SC2034 # we only use exports if we really need them
+
+### variables ##################################################################
+
+export HOME=$VER_DIR/home
+
+### functions ##################################################################
+
+# Nothing here.
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/etc/jhb.conf/jhbuild.sh b/packaging/macos/jhb/etc/jhb.conf/jhbuild.sh
new file mode 100644
index 0000000..31df78c
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/jhbuild.sh
@@ -0,0 +1,229 @@
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# This file contains functions to download, install and configure JHBuild.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+
+### dependencies ###############################################################
+
+# Nothing here.
+
+### variables ##################################################################
+
+export JHBUILDRC=$ETC_DIR/jhbuildrc
+export JHBUILDRC_CUSTOM=$JHBUILDRC-custom
+
+JHBUILD_REQUIREMENTS="\
+ certifi==2022.9.24\
+ meson==0.59.2\
+ ninja==1.10.2.3\
+"
+
+# JHBuild build system >3.38.0 (current master as of 08.03.2022)
+# The last stable release (3.38.0) is missing a critical fix (commit
+# a896cbf404461cab979fa3cd1c83ddf158efe83b) so we have to stay on master branch
+# for the time being.
+# https://gitlab.gnome.org/GNOME/jhbuild
+# https://wiki.gnome.org/Projects/Jhbuild/Introduction
+JHBUILD_VER=d1c5316
+JHBUILD_URL=https://gitlab.gnome.org/GNOME/jhbuild/-/archive/$JHBUILD_VER/\
+jhbuild-$JHBUILD_VER.tar.bz2
+
+# A dedicated Python runtime (only) for JHBuild. It is installed and kept
+# separately from the rest of the system. It won't interfere with a Python
+# that might get installed as part of building modules with JHBuild.
+JHBUILD_PYTHON_VER_MAJOR=3
+JHBUILD_PYTHON_VER_MINOR=8
+JHBUILD_PYTHON_VER=$JHBUILD_PYTHON_VER_MAJOR.$JHBUILD_PYTHON_VER_MINOR
+JHBUILD_PYTHON_URL="https://gitlab.com/api/v4/projects/26780227/packages/\
+generic/python_macos/15/python_${JHBUILD_PYTHON_VER/./}_$(uname -m).tar.xz"
+JHBUILD_PYTHON_DIR=$OPT_DIR/Python.framework/Versions/$JHBUILD_PYTHON_VER
+JHBUILD_PYTHON_BIN_DIR=$JHBUILD_PYTHON_DIR/bin
+
+export JHBUILD_PYTHON_BIN=$JHBUILD_PYTHON_BIN_DIR/python$JHBUILD_PYTHON_VER
+export JHBUILD_PYTHON_PIP=$JHBUILD_PYTHON_BIN_DIR/pip$JHBUILD_PYTHON_VER
+
+### functions ##################################################################
+
+function jhbuild_install_python
+{
+ # Download and extract Python.framework to OPT_DIR.
+ curl -L "$JHBUILD_PYTHON_URL" | tar -C "$OPT_DIR" -x
+
+ # Create a pkg-config configuration to match our installation location.
+ # Note: sed changes the prefix and exec_prefix lines!
+ find "$JHBUILD_PYTHON_DIR"/lib/pkgconfig/*.pc \
+ -type f \
+ -exec sed -i "" "s|prefix=.*|prefix=$JHBUILD_PYTHON_DIR|" {} \;
+
+ jhbuild_set_python_interpreter
+
+ # add to PYTHONPATH
+ echo "../../../../../../../usr/lib/python$JHBUILD_PYTHON_VER/site-packages"\
+ > "$OPT_DIR"/Python.framework/Versions/$JHBUILD_PYTHON_VER/lib/\
+python$JHBUILD_PYTHON_VER/site-packages/jhb.pth
+}
+
+function jhbuild_set_python_interpreter
+{
+ # Symlink binaries to USR_DIR/bin.
+ if command -v gln 1>/dev/null; then
+ local gnu=g # necessary for union mount
+ fi
+ ${gnu}ln -sf "$JHBUILD_PYTHON_BIN" "$USR_DIR"/bin
+ ${gnu}ln -sf "$JHBUILD_PYTHON_PIP" "$USR_DIR"/bin
+
+ # Set interpreter to the one in USR_DIR/bin.
+ while IFS= read -r -d '' file; do
+ local file_type
+ file_type=$(file "$file")
+ if [[ $file_type = *"Python script"* ]]; then
+ sed -i "" "1 s|.*|#!$USR_DIR/bin/python$JHBUILD_PYTHON_VER|" "$file"
+ fi
+ done < <(find "$USR_DIR"/bin/ -maxdepth 1 -type f -print0)
+}
+
+function jhbuild_install
+{
+ # We use our own custom Python.
+ jhbuild_install_python
+
+ # Install dependencies.
+ # shellcheck disable=SC2086 # we need word splitting for requirements
+ $JHBUILD_PYTHON_PIP install --prefix=$USR_DIR $JHBUILD_REQUIREMENTS
+
+ function pem_remove_expired
+ {
+ local pem_bundle=$1
+
+ # BSD's csplit does not support '{*}' (it's a GNU extension)
+ csplit -n 3 -k -f "$TMP_DIR"/pem- "$pem_bundle" \
+ '/END CERTIFICATE/+1' '{999}' >/dev/null 2>&1 || true
+
+ for pem in "$TMP_DIR"/pem-*; do
+ if [ "$(stat -f%z "$pem")" -eq 0 ]; then
+ rm "$pem" # the csplit command above created one superfluous empty file
+ elif ! openssl x509 -checkend 0 -noout -in "$pem"; then
+ echo_d "removing $pem: $(openssl x509 -enddate -noout -in "$pem")"
+ rm "$pem"
+ fi
+ done
+
+ cat "$TMP_DIR"/pem-??? > "$pem_bundle"
+ }
+
+ local cacert="$USR_DIR"/lib/python$JHBUILD_PYTHON_VER/site-packages/certifi/\
+cacert.pem
+
+ pem_remove_expired "$cacert"
+
+ # Download JHBuild. Setting CURL_CA_BUNDLE is required on older macOS, e.g.
+ # High Sierra.
+ local archive
+ archive=$PKG_DIR/$(basename $JHBUILD_URL)
+ CURL_CA_BUNDLE=$cacert curl -o "$archive" -L "$JHBUILD_URL"
+ tar -C "$SRC_DIR" -xf "$archive"
+
+ ( # Install JHBuild.
+ cd "$SRC_DIR"/jhbuild-$JHBUILD_VER || exit 1
+ ./autogen.sh \
+ --prefix="$USR_DIR" \
+ --with-python="$JHBUILD_PYTHON_BIN"
+ make
+ make install
+ )
+}
+
+function jhbuild_configure
+{
+ local moduleset=$1
+
+ moduleset=${moduleset:-jhb.modules}
+ local suffix
+ suffix=$(basename -s .modules "$moduleset")
+
+ # install custom moduleset
+ if [ "$suffix" != "jhb" ]; then
+ local moduleset_dir
+ moduleset_dir=$(dirname "$(greadlink -f "$moduleset")")
+ rsync -a --delete "$moduleset_dir"/ "$ETC_DIR/modulesets/$suffix/"
+ fi
+
+ local target
+ target=$(/usr/libexec/PlistBuddy -c "Print \
+ :DefaultProperties:MACOSX_DEPLOYMENT_TARGET" "$SDKROOT"/SDKSettings.plist)
+
+ # create custom jhbuildrc configuration
+ {
+ echo "# -*- mode: python -*-"
+
+ # moduleset
+ echo "modulesets_dir = '$ETC_DIR/modulesets/$suffix'"
+ echo "moduleset = '$(basename "$moduleset")'"
+ echo "use_local_modulesets = True"
+
+ # basic directory layout
+ echo "buildroot = '$BLD_DIR'"
+ echo "checkoutroot = '$SRC_DIR'"
+ echo "prefix = '$VER_DIR'"
+ echo "tarballdir = '$PKG_DIR'"
+ echo "top_builddir = '$VAR_DIR/jhbuild'"
+
+ # setup macOS SDK
+ echo "setup_sdk(target=\"$target\")"
+
+ # set release build
+ echo "setup_release()"
+
+ # Use compiler binaries from our own USR_DIR/bin if present, the intention
+ # being that these are symlinks pointing to ccache if that has been
+ # installed (see ccache.sh for details).
+ if [ -x "$USR_DIR/bin/gcc" ]; then
+ echo "os.environ[\"CC\"] = \"$USR_DIR/bin/gcc\""
+ echo "os.environ[\"OBJC\"] = \"$USR_DIR/bin/gcc\""
+ fi
+ if [ -x "$USR_DIR/bin/g++" ]; then
+ echo "os.environ[\"CXX\"] = \"$USR_DIR/bin/g++\""
+ fi
+
+ # certificates for https
+ echo "os.environ[\"SSL_CERT_FILE\"] = \
+ \"$USR_DIR/lib/python$JHBUILD_PYTHON_VER/site-packages/certifi/cacert.pem\""
+ echo "os.environ[\"REQUESTS_CA_BUNDLE\"] = \
+ \"$USR_DIR/lib/python$JHBUILD_PYTHON_VER/site-packages/certifi/cacert.pem\""
+
+ # user home directory
+ echo "os.environ[\"HOME\"] = \"$HOME\""
+
+ # less noise on the terminal if not CI
+ if ! $CI; then
+ echo "quiet_mode = True"
+ echo "progress_bar = True"
+ fi
+
+ # add moduleset-specific settings if exist
+ local moduleset_rc=$ETC_DIR/modulesets/$suffix/jhbuildrc
+ if [ -f "$moduleset_rc" ]; then
+ cat "$moduleset_rc"
+ fi
+
+ } > "$JHBUILDRC-$suffix"
+
+ if command -v gln 1>/dev/null; then
+ local gnu=g # necessary for union mount
+ fi
+ ${gnu}ln -sf "$(basename "$JHBUILDRC-$suffix")" "$JHBUILDRC_CUSTOM"
+
+ # Update the paths to Python.
+ jhbuild_set_python_interpreter
+}
+
+### main #######################################################################
+
+# Nothing here. \ No newline at end of file
diff --git a/packaging/macos/jhb/etc/jhb.conf/path.sh b/packaging/macos/jhb/etc/jhb.conf/path.sh
new file mode 100644
index 0000000..07e7adc
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/path.sh
@@ -0,0 +1,23 @@
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# Set PATH.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+
+### variables ##################################################################
+
+export PATH=$BIN_DIR:$USR_DIR/bin:/usr/bin:/bin:/usr/sbin:/sbin
+
+### functions ##################################################################
+
+# Nothing here.
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/etc/jhb.conf/pip.sh b/packaging/macos/jhb/etc/jhb.conf/pip.sh
new file mode 100644
index 0000000..5804468
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/pip.sh
@@ -0,0 +1,26 @@
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# Redirect pip cache directories.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+# shellcheck disable=SC2034 # we only use exports if we really need them
+
+### variables ##################################################################
+
+export PIP_CACHE_DIR=$VAR_DIR/cache/pip # instead ~/Library/Caches/pip
+export PIPENV_CACHE_DIR=$VAR_DIR/cache/pipenv # instead ~/Library/Caches/pipenv
+export PYTHONPYCACHEPREFIX=$VAR_DIR/cache/pycache
+
+### functions ##################################################################
+
+# Nothing here.
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/etc/jhb.conf/release.sh b/packaging/macos/jhb/etc/jhb.conf/release.sh
new file mode 100644
index 0000000..6fe8708
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/release.sh
@@ -0,0 +1,35 @@
+# SPDX-FileCopyrightText: 2022 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# Release artifact.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+# shellcheck disable=SC2034 # we only use exports if we really need them
+
+### variables ##################################################################
+
+RELEASE_ARCHIVE=${RELEASE_ARCHIVE:-$(basename "$VER_DIR")_$(uname -m).tar.xz}
+
+# GitHub and GitLab
+# shellcheck disable=2206 # we need expansion for the array to work
+RELEASE_URLS=(${RELEASE_URLS[@]:-
+ "https://github.com/dehesselle/jhb/releases/download/\
+v$VERSION/$RELEASE_ARCHIVE"
+ "https://gitlab.com/api/v4/projects/35965804/packages/generic/jhb/\
+$VERSION/$RELEASE_ARCHIVE"
+})
+
+RELEASE_OVERLAY=overlay
+
+### functions ##################################################################
+
+# Nothing here.
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/etc/jhb.conf/sdkroot.sh b/packaging/macos/jhb/etc/jhb.conf/sdkroot.sh
new file mode 100644
index 0000000..deda692
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/sdkroot.sh
@@ -0,0 +1,41 @@
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# If SDKROOT is set, use that. If it is not set, use whatever SDK is available.
+# This might still end up being invalid if neither Xcode nor CLT have been
+# installed, and that's what sdkroot_exists is for.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+# shellcheck disable=SC2034 # we only use exports if we really need them
+
+### variables ##################################################################
+
+if [ -z "$SDKROOT" ]; then
+ if xcodebuild --help 2>/dev/null; then
+ SDKROOT=$(xcodebuild -version -sdk macosx Path)
+ else
+ SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
+ fi
+fi
+export SDKROOT
+
+### functions ##################################################################
+
+function sdkroot_exists
+{
+ if [ -d "$SDKROOT" ]; then
+ return 0 # SDK found
+ else
+ echo_e "SDK not found: $SDKROOT"
+ return 1
+ fi
+}
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/etc/jhb.conf/sys.sh b/packaging/macos/jhb/etc/jhb.conf/sys.sh
new file mode 100644
index 0000000..1871b21
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/sys.sh
@@ -0,0 +1,121 @@
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# System and version checks.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+# shellcheck disable=SC2034 # we only use exports if we really need them
+
+### dependencies ###############################################################
+
+# Nothing here.
+
+### variables ##################################################################
+
+SYS_ARCH=$(uname -m | tr '[:lower:]' '[:upper:]')
+
+if [ "$SYS_USRLOCAL_IGNORE" != "true" ]; then
+ SYS_USRLOCAL_IGNORE=false
+fi
+
+SYS_MACOS_VER=$(sw_vers -productVersion)
+
+# descending order on purpose: most recent platform first
+# shellcheck disable=2206 # we need expansion for the array to work
+SYS_MACOS_VER_RECOMMENDED=(${SYS_MACOS_VER_RECOMMENDED:-
+ 12.6.1
+ 12.6
+ 11.7
+})
+
+SYS_SDK_VER="$(/usr/libexec/PlistBuddy -c \
+ "Print :DefaultProperties:MACOSX_DEPLOYMENT_TARGET" \
+ "$SDKROOT"/SDKSettings.plist)"
+
+SYS_SDK_VER_RECOMMENDED_X86_64=${SYS_SDK_VER_RECOMMENDED_X86_64:-10.13}
+SYS_SDK_VER_RECOMMENDED_ARM64=${SYS_SDK_VER_RECOMMENDED_ARM64:-11.3}
+SYS_SDK_VER_RECOMMENDED=$(eval echo \$SYS_SDK_VER_RECOMMENDED_"$SYS_ARCH")
+
+### functions ##################################################################
+
+function sys_create_log
+{
+ # Create jhb.log file.
+
+ mkdir -p "$VAR_DIR"/log
+
+ for var in SYS_MACOS_VER SYS_SDK_VER VERSION VER_DIR WRK_DIR; do
+ echo "$var = $(eval echo \$$var)" >> "$VAR_DIR"/log/jhb.log
+ done
+}
+
+function sys_macos_is_recommended
+{
+ for version in "${SYS_MACOS_VER_RECOMMENDED[@]}"; do
+ if [ "$version" = "$SYS_MACOS_VER" ]; then
+ return 0
+ fi
+ done
+
+ echo_w "using macOS $SYS_MACOS_VER (recommended: \
+${SYS_MACOS_VER_RECOMMENDED[0]})"
+ return 1
+}
+
+function sys_sdk_is_recommended
+{
+ if [ "$SYS_SDK_VER_RECOMMENDED" = "$SYS_SDK_VER" ]; then
+ return 0
+ fi
+
+ echo_w "using SDK $SYS_SDK_VER (recommended: $SYS_SDK_VER_RECOMMENDED)"
+ return 1
+}
+
+function sys_usrlocal_is_clean
+{
+ local count=0
+
+ # Based on GitHub CI experience, it appears to be enough to make sure
+ # the following folders do not contain files.
+ for dir in include lib share; do
+ count=$(( count + \
+ $(find /usr/local/$dir -type f 2>/dev/null | wc -l | awk '{ print $1 }')\
+ ))
+ done
+
+ if [ "$count" -ne 0 ]; then
+ if $SYS_USRLOCAL_IGNORE; then
+ echo_w "Found files in '/usr/local/[include|lib|share]'."
+ else
+ echo_e "Found files in '/usr/local/[include|lib|share]'!"
+ echo_e "This is known to cause trouble, but you can downgrade this error"
+ echo_e "to a warning at your own risk:"
+ echo_e " "
+ echo_e " export SYS_USRLOCAL_IGNORE=true"
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
+function sys_wrkdir_is_usable
+{
+ if mkdir -p "$WRK_DIR" 2>/dev/null &&
+ [ -w "$WRK_DIR" ] ; then
+ return 0 # WRK_DIR has been created or was already there and is writable
+ else
+ echo_e "WRK_DIR not usable: $WRK_DIR"
+ return 1
+ fi
+}
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/etc/jhb.conf/temp.sh b/packaging/macos/jhb/etc/jhb.conf/temp.sh
new file mode 100644
index 0000000..5de20a7
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/temp.sh
@@ -0,0 +1,27 @@
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# Redirect temporary locations.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+# shellcheck disable=SC2034 # we only use exports if we really need them
+
+### variables ##################################################################
+
+# shellcheck disable=SC2153 # this is no misspelling
+export TMP=$TMP_DIR
+export TEMP=$TMP_DIR
+export TMPDIR=$TMP_DIR # TMPDIR is the common macOS default
+
+### functions ##################################################################
+
+# Nothing here.
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/etc/jhb.conf/version.sh b/packaging/macos/jhb/etc/jhb.conf/version.sh
new file mode 100644
index 0000000..edd851b
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/version.sh
@@ -0,0 +1,24 @@
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# The main version number.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+# shellcheck disable=SC2034 # we only use exports if we really need them
+
+### variables ##################################################################
+
+VERSION=${VERSION:-0.22}
+
+### functions ##################################################################
+
+# Nothing here.
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/etc/jhb.conf/xdg.sh b/packaging/macos/jhb/etc/jhb.conf/xdg.sh
new file mode 100644
index 0000000..28a786e
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhb.conf/xdg.sh
@@ -0,0 +1,25 @@
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# Redirect some XDG directories.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+# shellcheck disable=SC2034 # we only use exports if we really need them
+
+### variables ##################################################################
+
+export XDG_CACHE_HOME=$VAR_DIR/cache # instead ~/.cache
+export XDG_CONFIG_HOME=$ETC_DIR # instead ~/.config
+
+### functions ##################################################################
+
+# Nothing here.
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/etc/jhbuildrc b/packaging/macos/jhb/etc/jhbuildrc
new file mode 100644
index 0000000..2e3fb6f
--- /dev/null
+++ b/packaging/macos/jhb/etc/jhbuildrc
@@ -0,0 +1,613 @@
+# -*- mode: python -*-
+#
+# Copyright (C) 2006, 2007, 2008 Imendio AB
+# Copyright 2009, 2010, 2011 John Ralls, Fremont, CA
+#
+# Default setup for building GTK+ on Mac OS X. Note that you should
+# normally never need to edit this file. Any custom settings should be
+# done in ~/.jhbuildrc-custom.
+#
+# Specific builds can be set up by creating files named
+# ~/.jhbuildrc-<build>. When setting the environment variable JHB to
+# such a name, the corresponding rc file will be read (e.g.:
+# JHB=mybuild jhbuild shell).
+#
+# Use .jhbuildrc-custom to override the moduleset, modules to build,
+# the source checkout location, installation prefix, or svn usernames
+# etc.
+#
+# Please email richard@imendio.com if you have suggestions for
+# improving this setup, or have any patches that you would like to get
+# included.
+
+import sys
+import errno
+import re
+
+#some variables we'll need defined later
+_default_arch = ""
+_osx_version = 0.0
+_target = '10.11'
+
+def _popen(cmd_arg):
+ from subprocess import Popen, PIPE
+ devnull = open('/dev/null')
+ cmd = Popen(cmd_arg, stdout=PIPE, stderr=devnull, shell=True)
+ retval = cmd.stdout.read().strip()
+ err = cmd.wait()
+ cmd.stdout.close()
+ devnull.close()
+ if err:
+ raise RuntimeError("Failed to close %s stream" % cmd_arg)
+ return retval.decode('utf-8')
+
+# Register an extra command to get the checkout dir for a module.
+#
+import jhbuild
+class _cmd_get_srcdir(jhbuild.commands.Command):
+ doc = 'Display information about one or more modules'
+
+ from jhbuild.errors import FatalError
+
+ name = 'gtk-osx-get-srcdir'
+ usage_args = 'module'
+
+ def run(self, config, options, args, help=None):
+ module_set = jhbuild.moduleset.load(config)
+
+ if args:
+ modname = args[0]
+ try:
+ module = module_set.get_module(modname, ignore_case = True)
+ except KeyError:
+ raise RuntimeError(_('unknown module %s') % modname)
+ print(module.get_srcdir(None))
+ else:
+ raise FatalError('no module specified')
+
+jhbuild.commands.register_command(_cmd_get_srcdir)
+
+class _cmd_bootstrap_gtk_osx(jhbuild.commands.base.cmd_build):
+ doc = 'Build buildsystem tools not provided by MacOS.'
+
+ name = 'bootstrap-gtk-osx'
+
+ def run(self, config, options, args, help=None):
+ global use_local_modulesets
+ moduleset="bootstrap"
+ modulesets_dir = os.path.dirname(config.moduleset)
+ if (use_local_modulesets and
+ os.path.exists(os.path.join(modulesets_dir,
+ moduleset + '.modules'))):
+ config.modulesets_dir = modulesets_dir
+ config.moduleset = moduleset
+ elif (use_local_modulesets and config.modulesets_dir and
+ os.path.exists(os.path.join(config.modulesets_dir,
+ moduleset + '.modules'))):
+ config.moduleset = moduleset
+ else:
+ config.moduleset = 'https://raw.githubusercontent.com/dehesselle/jhb/master/etc/modulesets/jhb/bootstrap.modules'
+
+ args = ['meta-bootstrap']
+
+ for item in options.skip:
+ config.skip += item.split(',')
+ options.skip = []
+
+ rc = jhbuild.commands.base.cmd_build.run(self, config, options, args)
+ return rc
+
+jhbuild.commands.register_command(_cmd_bootstrap_gtk_osx)
+
+class _getenv(jhbuild.commands.Command):
+ doc = "Retrieve an environment variable set within jhbuild"
+
+ name = "gtk-osx-getenv"
+ usage_args = 'envvar'
+
+ def run(self, config, options, args):
+ # module_set = jhbuild.moduleset.load(config)
+
+ if not args:
+ raise FatalError("No environment variable")
+
+ var = args[0]
+ if var not in os.environ:
+ raise FatalError("variable " + var + " not defined in jhbuild environment")
+ print(os.environ[var])
+
+jhbuild.commands.register_command(_getenv)
+
+# Determine the native system:
+def osx_ver():
+ global _default_arch, _osx_version, _target
+ vstring = _popen("uname -r")
+ mstring = _popen("machine")
+ exp = re.compile(r'(\d+\.\d+)\.\d+')
+ vernum = exp.match(vstring)
+ _osx_version = float(vernum.group(1)) - 4.0
+ if _osx_version < 16:
+ _target = '10.%d' % int(_osx_version)
+ else:
+ _target = '%d' % (_osx_version - 5)
+
+ _default_arch = _popen("uname -m")
+
+# Determine the XCode Version:
+def xcode_ver():
+ global conditions
+ devdir = _popen("xcode-select -p")
+ if devdir != "/Library/Developer/CommandLineTools":
+ ver = _popen("xcodebuild -version")
+ exp = re.compile(r'Xcode (\d+\.\d+)')
+ vernum = exp.match(ver)
+ if vernum:
+ _xcode_ver = float(vernum.group(1))
+ if _xcode_ver < 5.0:
+ raise EnvironmentError("Xcode Version %f is not supported; if you want to build with Xcode versions earlier than 5.0 checkout tag Last-Lion." % _xcode_ver)
+ if _xcode_ver < 10.0:
+ conditions.add('pre-Mavericks')
+ return _xcode_ver
+ else:
+ raise EnvironmentError("No suitable Xcode found. Xcode 5.0 or later is required.")
+ else: #Command-Line Tools instead of Xcode
+ ver_str = _popen("pkgutil --pkg-info=com.apple.pkg.CLTools_Executables | grep version*")
+ print("Found Command Line Tools '%s'" % ver_str)
+ exp = re.compile(r'version: (\d+\.\d+)')
+ vernum = exp.match(ver_str)
+ if vernum:
+ print("Command Line Tools version %f" % float(vernum.group(1)))
+ return float(vernum.group(1))
+ else:
+ return 8.0
+
+# Some utitily functions used here and in custom files:
+#
+def environ_append(key, value, separator=' '):
+ old_value = os.environ.get(key)
+ if old_value is not None:
+ value = old_value + separator + value
+ os.environ[key] = value
+
+def environ_prepend(key, value, separator=' '):
+ old_value = os.environ.get(key)
+ if old_value is not None:
+ value = value + separator + old_value
+ os.environ[key] = value
+
+def environ_remove(key, value, separator=':'):
+ old_value = os.environ.get(key)
+ if old_value is not None:
+ old_value_split = old_value.split(separator)
+ value_split = [x for x in old_value_split if x != value]
+ value = separator.join(value_split)
+ os.environ[key] = value
+
+def parse_custom_argument(key):
+ for i, arg in enumerate(sys.argv[:-1]):
+ if arg == key:
+ return sys.argv[i+1]
+ return None
+
+def append_autogenargs(module, args):
+ old_value = module_autogenargs.get(module, autogenargs)
+ module_autogenargs[module] = old_value + " " + args
+
+def remove_autogenargs(module, args):
+ arg_string = module_autogenargs.get(module, autogenargs)
+ module_autogenargs[module] = arg_string.replace(args, "")
+
+# Call either setup_debug or setup_release in your .jhbuildrc-custom
+# or other customization file to get the compilation flags.
+def setup_debug():
+ global autogenargs
+# The enable-debug option generally turns on ASSERTS, which can slow
+# down code and in the case of WebKit, breaks it on OSX because of
+# threading problems. It's better to set it for individual packages
+# with append_autogenargs().
+
+# autogenargs = autogenargs + " --enable-debug=yes"
+
+# Gtk+ crashes in gdk_window_quartz_raise() -- in a call to [NSWindow
+# orderFront:] if gcc is passed -O0 for 64-bit compilation. The old
+# stabs+ debug format also doesn't work. See Snow Leopard in the Wiki
+# for more information about debugging.
+ environ_prepend('CFLAGS', "-O0 -g")
+ environ_prepend('CXXFLAGS', "-O0 -g")
+ environ_prepend('OBJCFLAGS', "-O0 -g")
+
+def setup_release():
+ environ_prepend('CFLAGS', "-O2")
+ environ_prepend('CXXFLAGS', "-O2")
+ environ_prepend('OBJCFLAGS', "-O2")
+
+# Set up the environment for building against particular SDK.
+#
+
+#We call osx_ver() here so that we can set up _default_arch for setup_sdk
+osx_ver()
+
+#
+# This is the workhorse of the setup. Call this function from
+# .jhbuildrc-custom to configure compile and link flags. Optionally
+# specify a minimum MacOS version (10.11, 10.12, 10.13, etc.) and a list
+# of architectures.
+#
+# The sdk_version does nothing, as since Xcode 5 it is preferred to
+# build with the SDK that goes with the selected Xcode or command-line
+# tools, which we retrieve via xcrun. sdk_version remains in the
+# setup_sdk signature to prevent breaking existing jhbuildrc-customs.
+#
+# For most users accepting the defaults is the right course.
+
+def setup_sdk(target=_target, sdk_version=None, architectures=[_default_arch]):
+
+ global use_local_modulesets, conditions
+ os.environ["MACOSX_DEPLOYMENT_TARGET"] = target
+ sdkdir = None
+ xcodepath = None
+ xcodeversion = xcode_ver()
+
+ sdkdir = _popen("xcrun --show-sdk-path")
+
+ if sdkdir:
+ environ_prepend("LDFLAGS", "-L" + sdkdir + "/usr/lib")
+ environ_prepend("CFLAGS", "-I" + sdkdir + "/usr/include")
+ environ_prepend("CXXFLAGS", "-I" + sdkdir + "/usr/include")
+ environ_prepend("OBJCFLAGS", "-I" + sdkdir + "/usr/include")
+ environ_prepend("CPPFLAGS", "-I" + sdkdir + "/usr/include")
+ environ_prepend("CMAKE_PREFIX_PATH", os.path.join(sdkdir, 'usr'), ':')
+ environ_prepend("LIBRARY_PATH", sdkdir + "/usr/lib", ':')
+
+ # It's often necessary to look for things in the SDK when
+ # developing, and it takes a lot of typing, so define a
+ # convenience environment variable:
+ environ_append('SDKDIR', sdkdir)
+ os.environ["SDKROOT"] = sdkdir
+
+ # Apple Documentation says that "-syslibroot" is the arg to pass to the
+ # linker, but we are using the compiler to control the linker, and
+ # everything seems to be working correctly.
+ environ_append("CFLAGS", "-isysroot " + sdkdir)
+ environ_append("CPPFLAGS", "-isysroot " + sdkdir)
+ environ_append("CXXFLAGS", "-isysroot " + sdkdir)
+ environ_append("OBJCFLAGS", "-isysroot " + sdkdir)
+ environ_append("LDFLAGS", "-isysroot " + sdkdir)
+
+ # To pick up cups-config from the right place.
+ os.environ["CUPS_CONFIG"] = os.path.join(sdkdir, "usr/bin/cups-config")
+
+ if architectures == ["i386"]:
+ # The '#' on openssl is to stop jhbuild from appending any more autogen
+ # arguments such as --disable-Werror; they cause openssl to error out
+ append_autogenargs("openssl", "darwin-i386-cc #")
+ elif architectures == ["x86_64"]:
+ conditions.add('64-bit')
+ append_autogenargs("glib", "ac_cv_c_bigendian=no")
+ append_autogenargs("openssl", "darwin64-x86_64-cc #")
+ elif architectures == ["arm64"]:
+ conditions.add('64-bit')
+ conditions.add('arm64')
+ append_autogenargs("glib", "ac_cv_c_bigendian=no")
+ append_autogenargs("openssl", "darwin64-arm64-cc #") # Not a legal value
+ elif len(set(architectures) - {"i386", "x86_64", 'arm64'}) > 0:
+ raise EnvironmentError("Only architectures i386, x86_64, and arm64 are supported.")
+ if len(set(architectures)) > 1:
+ print("WARNING: Universal builds are neither prohibited nor supported. It might work, but if it doesn't you're on your own.")
+ # For unknown reasons, iconv is not picked up correctly without this
+ #
+ gcc = _popen("xcrun -f gcc")
+ gpp = _popen("xcrun -f g++")
+ ld = _popen("xcrun -f ld")
+ os.environ["CC"] = gcc
+ os.environ["OBJC"] = gcc
+ os.environ["CXX"] = gpp
+ os.environ['LD'] = ld
+
+ # Set the -arch flags for everything we're building.
+ #
+ for arch in architectures:
+ environ_prepend("CFLAGS", "-arch " + arch)
+ environ_prepend("CXXFLAGS", "-arch " + arch)
+ environ_prepend("CPPFLAGS", "-arch " + arch)
+ environ_prepend("OBJCFLAGS", "-arch " + arch)
+ environ_prepend("LDFLAGS", "-arch " + arch)
+ # For intel, set glib's build parameter so that it builds the
+ # correct atomic asm functions
+ #
+ if architectures == ["i386"]:
+ append_autogenargs("glib", "--build=i486-apple-darwin")
+ append_autogenargs("gmp", "ABI=32")
+ append_autogenargs("liboil", "--host=i486-apple-darwin")
+ append_autogenargs("gnutls", "--host=i486-apple-darwin")
+ elif architectures == ["x86_64"]:
+ append_autogenargs("glib", "--build=x86_64-apple-darwin")
+ append_autogenargs("gmp", "--host=x86_64-apple-darwin ABI=64")
+ append_autogenargs("liboil", "--host=x86_64-apple-darwin")
+ append_autogenargs("gnutls", "--host=x86_64-apple-darwin")
+ elif architectures == ["arm64"]:
+ append_autogenargs("glib", "--build=aarch64-apple-darwin")
+ append_autogenargs("gmp", "--host=aarch64-apple-darwin ABI=64")
+ append_autogenargs("liboil", "--host=aarch64-apple-darwin")
+ append_autogenargs("libffi", "--host=aarch64-apple-darwin")
+
+ # El Capitan needs bash to work around SIP. If you're using a
+ # common bootstrap directory (e.g. $HOME/.local) then override
+ # CONFIG_SHELL in .jhbuildrc-custom after calling setup_sdk().
+ config_shell = os.path.join(prefix, 'bin', 'bash')
+ if _osx_version < 11.0:
+ skip.append('bash')
+ elif os.path.exists(config_shell):
+ os.environ['CONFIG_SHELL'] = config_shell
+
+ if not sdkdir:
+ sdkdir = '/'
+ if os.path.exists(os.path.join(sdkdir, "usr", "include", "openssl")):
+ skip.append('openssl') # openssl removed in El Capitan
+
+ # gettext-fw rebuilds gettext with an in-tree libiconv to get
+ # around the Apple-provided one not defining _libiconv_init for
+ # x86_64
+ append_autogenargs("gettext-fw", "--with-libiconv-prefix=" + prefix)
+
+ environ_append("CFLAGS", "-mmacosx-version-min=" + target)
+ environ_append("CXXFLAGS", "-mmacosx-version-min=" + target)
+ environ_append("OBJCFLAGS", "-mmacosx-version-min=" + target)
+ environ_append("LDFLAGS", "-mmacosx-version-min=" + target)
+
+ #Overcome Python's obnoxious misconfiguration of portable builds
+ if len(architectures) == 1:
+ os.environ["BUILDCFLAGS"] = os.environ["CFLAGS"]
+ append_autogenargs("gnutls", "--disable-guile")
+ append_autogenargs("guile", 'CFLAGS="$CFLAGS -O1"')
+ #Some packages require special arguments or flags to compile with Clang:
+ module_extra_env["pkg-config"] = {'CFLAGS': os.environ['CFLAGS'] + ' -std=gnu89'}
+ append_autogenargs('libgcrypt', 'CFLAGS="$CFLAGS -fheinous-gnu-extensions"')
+ module_makeargs['liboil'] = 'CFLAGS="$CFLAGS -DHAVE_SYMBOL_UNDERSCORE -fheinous-gnu-extensions"'
+
+ # openssl doesn't understand DESTDIR, but luckily it has its own mechanism.
+ module_extra_env['openssl'] = {'INSTALL_PREFIX': os.path.join(prefix, '_jhbuild', 'root-openssl')}
+ # GMP deliberately attempts to use CC_FOR_BUILD with no separate
+ # cflags so we need to force it:
+ module_extra_env['gmp'] = {'CC_FOR_BUILD':os.environ['CC'] + ' ' + os.environ['CFLAGS']}
+ # Kill a couple of noisy warnings for webkit1:
+ module_extra_env["webkit"] = {'CPPFLAGS':os.environ['CPPFLAGS'] + " -Wno-unused-local-typedef -Wno-missing-field-initializsers"}
+ module_extra_env["webkit1gtk3"] = {'CPPFLAGS':os.environ['CPPFLAGS'] + " -Wno-unused-local-typedef -Wno-missing-field-initializsers -Wno-undefined-bool-conversion"}
+ module_extra_env["webkit"] = {'CXXFLAGS':os.environ['CXXFLAGS'] + ' -Wno-inconsistent-missing-override'}
+ module_extra_env["webkit1gtk3"] = {'CXXFLAGS':os.environ['CXXFLAGS'] + ' -Wno-inconsistent-missing-override'}
+
+ # Finally when building normally we need to force CFLAGS_FOR_BUILD
+ # to our current CFLAGS so that everything will link with other
+ # build products. Note that this will generally break
+ # cross-compilation, not that it works anyway.
+ os.environ['CFLAGS_FOR_BUILD'] = os.environ['CFLAGS']
+
+ # Make sure we don't link against XQuartz whose freetype-config is on PATH
+ # when XQuartz is installed by removing it from PATH
+ environ_remove('PATH', '/opt/X11/bin')
+ return sdkdir
+
+
+###### End Function Definitions #######
+
+
+##### The following configuration can be overridden in custom files ######
+
+# Moduleset to use. You can override this in .jhbuildrc-custom or on
+# the command line.
+#
+moduleset = ""
+use_local_modulesets = False
+modulesets_dir = ""
+
+# A list of the modules to build. You can override this in
+# .jhbuildrc-custom or on the command line.
+#
+modules = [ 'meta-gtk-osx-bootstrap', 'meta-gtk-osx-gtk3' ]
+
+# A list of modules to skip.
+#
+# Source and installation locations.
+#
+_root = os.path.expanduser("~/gtk")
+checkoutroot = os.path.join(_root, "source")
+prefix = os.path.join(_root, "inst")
+_exec_prefix = None
+tarballdir = None
+# Extra arguments to pass to all autogen.sh scripts.
+#
+autogenargs=''
+
+# Extra meson args. --wrapmode=nofallback prevents meson projects from
+# building dependencies on their own. We generally want failed
+# dependencies to error out so that we know to add them to the
+# appropriate modules.
+
+mesonargs='--wrap-mode=nofallback'
+
+# Use the included install-check program if available. It won't update
+# timestamps if the header hasn't changed, which speeds up builds.
+#
+_path = os.path.expanduser('~/.local/bin/install-check')
+if os.path.exists(_path):
+ os.environ['INSTALL'] = _path
+
+_gtk_osx_prompt_prefix = "JH"
+
+_gtk_osx_default_build = ""
+
+#print "Default Architecture %s\n" % _default_arch
+
+if _osx_version < 11.0:
+ print("Error: Mac OS X 10.11 or newer is required, exiting.")
+ raise SystemExit
+
+###### Import Customizations ######
+
+# Import optional user RC for further customization. You can override
+# the prefix or default build setup for example, or CFLAGS or
+# module_autogenargs, etc.
+#
+_this_dir = os.path.dirname(__file__);
+_home = os.path.expanduser('~')
+_user_config_dir = os.environ.get('XDG_CONFIG_HOME',
+ os.path.join(_home, '.config'))
+
+_user_rc = ''
+if ('JHBUILDRC_CUSTOM' in os.environ and
+ os.environ['JHBUILDRC_CUSTOM']):
+ _user_rc = os.environ['JHBUILDRC_CUSTOM']
+if not os.path.exists(_user_rc):
+ _user_rc = os.path.join(_this_dir, 'jhbuildrc-custom');
+if not os.path.exists(_user_rc):
+ _user_rc = os.path.join(_this_dir, '.jhbuildrc-custom')
+if not os.path.exists(_user_rc):
+ _user_rc = os.path.join(_user_config_dir, 'jhbuildrc-custom')
+if not os.path.exists(_user_rc):
+ _user_rc = os.path.join(_user_config_dir, '.jhbuildrc-custom')
+if not os.path.exists(_user_rc):
+ _user_rc = os.path.join(_home, 'jhbuildrc-custom')
+if not os.path.exists(_user_rc):
+ _user_rc = os.path.join(_home, '.jhbuildrc-custom')
+
+if os.path.exists(_user_rc):
+ exec(compile(open(_user_rc, "rb").read(), _user_rc, 'exec'))
+
+# Allow including different variants depending on the environment
+# variable JHB. This can be used to have different setups for SDK
+# builds, for example.
+#
+_build = os.environ.get('JHB', _gtk_osx_default_build)
+disable_Werror = False
+
+###### Everything Below Uses (and Overrides) customizations! #######
+# jhbuild turns on 'nice' by default ut that messes up some of the
+# custom autogen-templates Gtk-OSX needs to use:"
+nice_build = False
+
+# Harfbuzz needs to be built twice, once before cairo and again after
+# gobject-introspection because cairo needs harfbuzz and
+# gobject-introspection needs cairo. The only way to get jhbuild to
+# run the configuration for harfbuzz the second time is to set
+# alwaysautogen to true.
+
+alwaysautogen = True
+
+# Freetype2 if left to itself will create an install name without the
+# path so none of the libraries that depend on it can link. Require
+# the install name to be an absolute path.
+
+module_cmakeargs["freetype"] = '-DCMAKE_INSTALL_NAME_DIR="' + os.path.join(prefix, 'lib') + '"'
+module_cmakeargs["freetype-no-harfbuzz"] = '-DCMAKE_INSTALL_NAME_DIR="' + os.path.join(prefix, 'lib') + '"'
+module_cmakeargs["webkit2gtk3"] = '-DCMAKE_INSTALL_NAME_DIR="' + os.path.join(prefix, 'lib') + '"'
+module_cmakeargs["zlib"] = '-DCMAKE_INSTALL_NAME_DIR="' + os.path.join(prefix, 'lib') + '"'
+
+# Check and warn if jhbuild is started from within jhbuild, since that
+# will mess up environment variables, especially if different build
+# setups are used.
+#
+_old_prefix = os.environ.get('JHBUILD_PREFIX', "")
+_old_build = os.environ.get('JHBUILD_CONFIG', "")
+_ran_recursively = _old_prefix != ""
+if _ran_recursively:
+ if _old_build != _build:
+ print("Error: jhbuild is already running with a different build setup, exiting.")
+ raise SystemExit
+
+ print("Warning: jhbuild is started from within a jhbuild session.")
+
+if _build != "":
+ try:
+ exec(compile(open(os.path.join(os.environ['HOME'], '.jhbuildrc-' + _build), "rb").read(), os.path.join(os.environ['HOME'], '.jhbuildrc-' + _build), 'exec'))
+ except EnvironmentError as e:
+ print("Couldn't find the file '.jhbuildrc-" + _build + "', exiting.")
+ raise SystemExit
+
+# The following parameters were set to None at the top of the file;
+# they're set here to their default values after processing the
+# customizations, but tested to make sure that if they've been
+# customized, it will stick.
+
+# Default location for tarball download is into checkoutroot/pkgs. If
+# you do multiple builds with different checkoutroots, you'll want to
+# override this to somewhere common (~/.local/pkgs is one alternative)
+if tarballdir == None:
+ tarballdir = os.path.join(checkoutroot, 'pkgs')
+# _exec_prefix is used to set $M4 and $LIBTOOLIZE. We set it here to
+# prefix if it wasn't over-ridden in .jhbuildrc-custom
+if _exec_prefix == None:
+ _exec_prefix = prefix
+
+
+os.environ['PREFIX'] = prefix # Deprecated, please move to JHBUILD_PREFIX.
+os.environ['JHBUILD_PREFIX'] = prefix
+os.environ['JHBUILD_SOURCE'] = checkoutroot
+
+# Some packages go off and find /usr/lib/gm4, which is broken Note the
+# use of _exec_prefix here. By default it's prefix, but you can
+# override it to somewhere else in jhbuildrc-custom if you like.
+#os.environ["M4"] = _exec_prefix + "/bin/m4"
+#os.environ['LIBTOOLIZE'] = _exec_prefix + '/bin/libtoolize'
+#Some autogens detect that it's a Mac and use glibtoolize if it's
+#available. Override this behavior.
+if not ("LIBTOOLIZE" in os.environ and os.environ["LIBTOOLIZE"]):
+ environ_append('LIBTOOLIZE', os.path.join(prefix, "bin", "libtoolize"))
+
+
+# The option "headerpad_max_install_names" is there to leave some room for
+# changing the library locations with install_name_tool. Note that GNU
+# libtool seems to drop the option if we don't use -W here.
+#
+environ_append('LDFLAGS', '-Wl,-headerpad_max_install_names')
+#environ_append('LDFLAGS', '-Wl,-no_weak_imports')
+
+# Make sure we find our installed modules, and before other versions.
+environ_prepend('LDFLAGS', '-L' + prefix + '/lib')
+environ_prepend('CPPFLAGS', '-I' + prefix + '/include')
+
+# Make sure that ltdl can find our libraries
+addpath("LTDL_LIBRARY_PATH", prefix + "/lib")
+
+# Add additional Perl paths so that our modules can be found.
+
+prependpath('PERL5LIB', prefix + '/lib/perl5/vendor_perl')
+prependpath('PERL5LIB', prefix + '/lib/perl5/site_perl')
+
+# Point gtk-doc and other xsltproc users to our XML catalog.
+#
+_pfx_cat_file = os.path.join(prefix, 'share', 'xml', 'catalog')
+if not os.path.exists(_pfx_cat_file):
+ os.makedirs(os.path.dirname(_pfx_cat_file))
+ open(_pfx_cat_file, "w").close()
+if 'XML_CATALOG_FILES' in os.environ:
+# os.environ['XML_CATALOG_FILES'] += ':' + _pfx_cat_file
+ pass
+else:
+ os.environ['XML_CATALOG_FILES'] = _pfx_cat_file
+
+#GConf needs to be built static, overriding the generic autogenargs,
+#but including it in the module puts it in front of where autogenargs
+#puts --disable-static, so we need the override here.
+#
+append_autogenargs("gconf", "--enable-static")
+
+if _build:
+ if "shell" in sys.argv:
+ print("Build setup: %s, prefix: %s" % (_build, prefix))
+ os.environ["JHBUILD_CONFIG"] = _build
+else:
+ if "shell" in sys.argv:
+ print("Prefix: %s" % (prefix))
+
+if not _ran_recursively and _gtk_osx_prompt_prefix:
+ os.environ["JHBUILD_PROMPT"] = "[" + _gtk_osx_prompt_prefix + "] "
+
+os.environ["PYTHON"] = os.path.join(prefix, 'bin', 'python3')
+module_extra_env['pkg-config'] = {'PYTHON':sys.executable}
+module_extra_env["spidermonkey"] = {'AUTOCONF':'autoconf'}
+# Unset this so we don't mess with the check for not starting
+# recursively.
+os.unsetenv("JHB")
+
+if "shell" in sys.argv:
+ print("Entered jhbuild shell, type 'exit' to return.")
diff --git a/packaging/macos/jhb/etc/modulesets/jhb/bootstrap.modules b/packaging/macos/jhb/etc/modulesets/jhb/bootstrap.modules
new file mode 100644
index 0000000..6cc2ed6
--- /dev/null
+++ b/packaging/macos/jhb/etc/modulesets/jhb/bootstrap.modules
@@ -0,0 +1,158 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: nxml -*-->
+<?xml-stylesheet type="text/xsl" href="moduleset.xsl"?>
+<moduleset>
+ <repository type="tarball" name="ftp.gnu.org"
+ href="https://ftp.gnu.org/gnu/"/>
+ <repository type="tarball" name="pkgconfig"
+ href="http://pkgconfig.freedesktop.org/releases/"/>
+ <repository type="tarball" name="sourceforge"
+ href="http://downloads.sourceforge.net/sourceforge/"/>
+ <repository type="tarball" name="tukaani.org"
+ href="http://tukaani.org/"/>
+ <repository type="tarball" name="cmake"
+ href="https://cmake.org/files/"/>
+ <repository type="tarball" name="cpan" href="http://search.cpan.org/CPAN/" />
+ <repository type="tarball" name="intltool"
+ href="http://launchpad.net/intltool/trunk/"/>
+ <repository type="tarball" name="github" href="https://github.com"/>
+
+ <autotools id="xz" autogen-sh="configure" bootstrap="true">
+ <branch repo="tukaani.org" module="xz/xz-5.2.5.tar.bz2" version="5.2.5"
+ hash="sha256:5117f930900b341493827d63aa910ff5e011e0b994197c3b71c08a20228a42df"/>
+ </autotools>
+
+ <!-- gnu make 4.xx, needed to unbreak parallel builds for the webkit -->
+ <autotools id="gnumake" autogen-sh="configure" bootstrap="true"
+ autogenargs="--disable-dependency-tracking">
+ <branch repo="ftp.gnu.org"
+ module="make/make-4.3.tar.gz" version="4.3"
+ hash="sha256:e05fdde47c5f7ca45cb697e973894ff4f5d79e13b750ed57d7b66d8defc78e19">
+ </branch>
+ </autotools>
+
+ <autotools id="gettext" autogen-sh="configure"
+ autogenargs="--without-emacs --disable-java --disable-native-java --disable-libasprintf --disable-csharp --with-included-glib --with-included-libcroco"
+ hash="sha256:d20fcbb537e02dcf1383197ba05bd0734ef7bf5db06bdb241eb69b7d16b73192">
+ <branch repo="ftp.gnu.org"
+ module="gettext/gettext-0.21.tar.xz" version="0.21">
+ </branch>
+ </autotools>
+
+ <!-- cmakes ./configure is picky about invalid flags so we manually set it -->
+ <autotools id="cmake" autogen-sh="bootstrap" bootstrap="true"
+ autogen-template="%(srcdir)s/%(autogen-sh)s --prefix=%(prefix)s --docdir=share/doc/cmake-3.20">
+ <branch repo="cmake" module="v3.20/cmake-3.20.0.tar.gz" version="3.20.0">
+ </branch>
+ </autotools>
+ <!-- The version of m4 provided with Xcode is now too old, see
+ https://savannah.gnu.org/support/index.php?110397 -->
+ <autotools id="m4" autogen-sh="configure" bootstrap="true">
+ <branch repo="ftp.gnu.org"
+ module="m4/m4-1.4.18.tar.xz" version="1.4.18"
+ hash="sha256:f2c1e86ca0a404ff281631bdc8377638992744b175afb806e25871a24a934e07">
+ <patch file="vasnprintf.patch" strip="1"/>
+ </branch>
+ </autotools>
+
+ <autotools id="autoconf" autogen-sh="configure" bootstrap="true">
+ <branch repo="ftp.gnu.org"
+ module="autoconf/autoconf-2.71.tar.xz" version="2.71"
+ hash="shas56:f14c83cfebcc9427f2c3cea7258bd90df972d92eb26752da4ddad81c87a0faa4"/>
+ <dependencies>
+ <dep package="m4"/>
+ <dep package="xz"/>
+ </dependencies>
+ </autotools>
+
+ <autotools id="autoconf-archive" autogen-sh="configure" bootstrap="true">
+ <branch repo="ftp.gnu.org"
+ module="autoconf-archive/autoconf-archive-2021.02.19.tar.xz"
+ version="2021-02-19"
+ hash="sha256:e8a6eb9d28ddcba8ffef3fa211653239e9bf239aba6a01a6b7cfc7ceaec69cbd"/>
+ </autotools>
+
+ <autotools id="libtool" autogen-sh="configure" bootstrap="true">
+ <branch repo="ftp.gnu.org"
+ module="libtool/libtool-2.4.6.tar.gz" version="2.4.6"
+ hash="sha256:e3bd4d5d3d025a36c21dd6af7ea818a2afcd4dfc1ea5a17b39d7854bcd0c06e3">
+ <patch file="libtool-apple-sort.patch" strip="1"/>
+ </branch>
+ </autotools>
+
+
+ <autotools id="automake" autogen-sh="configure" bootstrap="true">
+ <branch repo="ftp.gnu.org" version="1.16.3"
+ module="automake/automake-1.16.3.tar.xz"
+ hash="sha256:ff2bf7656c4d1c6fdda3b8bebb21f09153a736bcba169aaf65eab25fa113bf3a"/>
+ <dependencies>
+ <dep package="autoconf"/>
+ </dependencies>
+ </autotools>
+
+ <autotools id="pkg-config" autogen-sh="configure" bootstrap="true"
+ autogenargs="--with-internal-glib">
+ <branch repo="pkgconfig"
+ module="pkg-config-0.29.2.tar.gz" version="0.29.2"
+ hash="sha256:6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591"/>
+ </autotools>
+
+ <!-- MacOS provides 2.3 (presumably the last GPL2 version, gstreamer
+ requires 2.4. -->
+ <autotools id="bison" autogen-sh="configure">
+ <branch repo="ftp.gnu.org" module="bison/bison-3.7.6.tar.xz"
+ version="3.7.6"
+ hash="sha256:67d68ce1e22192050525643fc0a7a22297576682bef6a5c51446903f5aeef3cf">
+ </branch>
+ <dependencies>
+ <dep package='flex'/>
+ </dependencies>
+ </autotools>
+
+ <!-- As of 29 March 2021 Flex hasn't had an update since May 2017. -->
+ <autotools id="flex" autogen-sh="configure" autogenargs="--disable-libfl">
+ <branch module="westes/flex/releases/download/v2.6.4/flex-2.6.4.tar.gz"
+ repo="github" version="2.6.4"
+ hash="sha256:e87aae032bf07c26f85ac0ed3250998c37621d95f8bd748b31f15b33c45ee995"/>
+ </autotools>
+
+ <!-- This is generated by tarring up the needed docbook stylesheets
+ for gtk-doc to work. If someone wants to work on a setup that
+ uses the real docbook source from upstream, feel free to do so,
+ it used to be a huge amount of work, but might be easier these
+ days.
+
+ -->
+ <autotools id="gtk-osx-docbook" autogen-sh="configure"
+ supports-non-srcdir-builds="no" >
+ <branch repo="github" module="jralls/gtk-osx-docbook/releases/download/gtk-osx-docbook-1.3/gtk-osx-docbook-1.3.tar.xz"
+ version="1.3"
+ hash="sha256:fcf497688a1d531b192301bd09c55adefda5a662729a58eb8a895166e38ef219"/>
+ </autotools>
+
+ <autotools id="intltool" autogen-sh="configure">
+ <branch repo="intltool" module="0.51.0/+download/intltool-0.51.0.tar.gz"
+ version="0.51.0"
+ hash="sha256:67c74d94196b153b774ab9f89b2fa6c6ba79352407037c8c14d5aeb334e959cd"/>
+ <!--dependencies>
+ <dep package="perl-xml-parser"/>
+ </dependencies-->
+ </autotools>
+
+ <metamodule id="meta-bootstrap">
+ <dependencies>
+ <dep package="xz"/>
+ <dep package="gettext" /> <!-- Needed for 64-bit -->
+ <dep package="cmake"/>
+ <dep package="autoconf-archive" />
+ <dep package="libtool" />
+ <dep package="automake"/>
+ <dep package="pkg-config" />
+ <dep package="bison"/>
+ <dep package="flex"/>
+ <dep package="gtk-osx-docbook"/>
+ <dep package="intltool"/>
+ <dep package="gnumake"/>
+ </dependencies>
+ </metamodule>
+
+</moduleset>
diff --git a/packaging/macos/jhb/etc/modulesets/jhb/jhb.modules b/packaging/macos/jhb/etc/modulesets/jhb/jhb.modules
new file mode 100644
index 0000000..f2fc9e3
--- /dev/null
+++ b/packaging/macos/jhb/etc/modulesets/jhb/jhb.modules
@@ -0,0 +1,60 @@
+<?xml version="1.0"?>
+<!DOCTYPE moduleset SYSTEM "moduleset.dtd">
+<?xml-stylesheet type="text/xsl" href="moduleset.xsl"?>
+<moduleset>
+
+ <repository name="gnu" type="tarball" href="http://ftp.halifax.rwth-aachen.de/gnu/"/>
+
+ <!-- GNU core utilities https://www.gnu.org/software/coreutils/ -->
+ <autotools
+ id="coreutils"
+ autogen-sh="configure"
+ autogenargs="--prefix=$JHBUILD_PREFIX/usr --program-prefix=g">
+ <branch
+ module="coreutils/coreutils-9.1.tar.xz"
+ version="9.1"
+ hash="sha256:61a1f410d78ba7e7f37a5a4f50e6d1320aca33375484a3255eddf17a38580423"
+ repo="gnu">
+ </branch>
+ </autotools>
+
+ <!-- GNU Find Utilities https://www.gnu.org/software/findutils/ -->
+ <autotools
+ id="findutils"
+ autogen-sh="configure"
+ autogenargs="--prefix=$JHBUILD_PREFIX/usr --program-prefix=g">
+ <branch
+ module="findutils/findutils-4.9.0.tar.xz"
+ version="4.9.0"
+ hash="sha256:a2bfb8c09d436770edc59f50fa483e785b161a3b7b9d547573cb08065fd462fe"
+ repo="gnu">
+ </branch>
+ </autotools>
+
+ <!-- GNU sed https://www.gnu.org/software/sed/ -->
+ <autotools
+ id="sed"
+ autogen-sh="configure"
+ autogenargs="--prefix=$JHBUILD_PREFIX/usr --program-prefix=g">
+ <branch
+ module="sed/sed-4.8.tar.xz"
+ version="4.8"
+ hash="sha256:f79b0cfea71b37a8eeec8490db6c5f7ae7719c35587f21edb0617f370eeff633"
+ repo="gnu">
+ </branch>
+ </autotools>
+
+ <!-- GNU Tar https://www.gnu.org/software/tar/ -->
+ <autotools
+ id="tar"
+ autogen-sh="configure"
+ autogenargs="--prefix=$JHBUILD_PREFIX/usr --program-prefix=g">
+ <branch
+ module="tar/tar-1.34.tar.xz"
+ version="1.34"
+ hash="sha256:63bebd26879c5e1eea4352f0d03c991f966aeb3ddeb3c7445c902568d5411d28"
+ repo="gnu">
+ </branch>
+ </autotools>
+
+</moduleset>
diff --git a/packaging/macos/jhb/etc/modulesets/jhb/moduleset.dtd b/packaging/macos/jhb/etc/modulesets/jhb/moduleset.dtd
new file mode 100644
index 0000000..d9c392a
--- /dev/null
+++ b/packaging/macos/jhb/etc/modulesets/jhb/moduleset.dtd
@@ -0,0 +1,240 @@
+<!ELEMENT moduleset (if|redirect|repository|include|autotools|metamodule|tarball|distutils|perl|linux|testmodule|cvsroot|cvsmodule|waf|cmake|meson|systemmodule)+>
+<!ATTLIST moduleset
+ name CDATA #IMPLIED>
+
+<!-- DTD is incapable of allowing different children of an element
+ of a given name depending on the context in which it appears so
+ this is more permissive than it ought to be. The RNG version
+ of the schema gets this correct.
+
+ DTD also appears to be incapable of describing the fact that
+ exactly one of condition-set='' and condition-unset='' is required.
+-->
+<!ELEMENT if (if|autotools|dep|autogenargs|cmakeargs|mesonargs|makeargs|ninjaargs|makeinstallargs)+>
+<!ATTLIST if
+ condition-set CDATA #IMPLIED
+ condition-unset CDATA #IMPLIED>
+
+<!ELEMENT repository (mirror*)>
+<!ATTLIST repository
+ name CDATA #REQUIRED
+ type (arch|bzr|cvs|darcs|fossil|git|hg|mtn|svn|system|tarball) #REQUIRED
+ default (yes|no) "no"
+ password CDATA #IMPLIED
+ cvsroot CDATA #IMPLIED
+ archive CDATA #IMPLIED
+ href CDATA #IMPLIED
+ server CDATA #IMPLIED
+ database CDATA #IMPLIED
+ defbranch CDATA #IMPLIED
+ developer-href-example CDATA #IMPLIED
+ trunk-template CDATA #IMPLIED
+ branches-template CDATA #IMPLIED
+ tags-template CDATA #IMPLIED>
+<!-- note the following attributes are specific to some repository types:
+ - CVS: password & cvsroot
+ - Arch: archive & href
+ - Monotone: server, database, defbranch
+ - Subversion: *-template -->
+
+<!ELEMENT mirror EMPTY>
+<!ATTLIST mirror
+ type (arch|bzr|cvs|darcs|fossil|git|hg|svn|tarball) #REQUIRED
+ trunk-template CDATA #IMPLIED
+ branches-template CDATA #IMPLIED
+ href CDATA #IMPLIED>
+
+<!ELEMENT include EMPTY>
+<!ATTLIST include href CDATA #REQUIRED>
+
+<!ELEMENT redirect EMPTY>
+<!ATTLIST redirect href CDATA #REQUIRED>
+
+<!ELEMENT autotools (if*,autogenargs*,makeargs*,makeinstallargs*,pkg-config?,branch,dependencies?,suggests?,after?)>
+<!-- Note: Here the ID type is not used as some existing IDs in modsets are not
+ valid XML ID types - instead CDATA is used -->
+<!ATTLIST autotools
+ id CDATA #REQUIRED
+ autogenargs CDATA #IMPLIED
+ makeargs CDATA #IMPLIED
+ makeinstallargs CDATA #IMPLIED
+ autogen-sh CDATA #IMPLIED
+ makefile CDATA #IMPLIED
+ bootstrap (true|false) "false"
+ skip-autogen (true|false|never) "false"
+ skip-install (yes|no) "no"
+ uninstall-before-install (true|false) "false"
+ supports-non-srcdir-builds (yes|no) "yes"
+ force-non-srcdir-builds (yes|no) "no"
+ supports-parallel-builds (yes|no) "yes"
+ supports-unknown-configure-options (yes|no) "yes"
+ autogen-template CDATA #IMPLIED
+ check-target (true|false) "true">
+
+<!ELEMENT autogenargs EMPTY>
+<!ATTLIST autogenargs value CDATA #REQUIRED>
+<!ELEMENT makeargs EMPTY>
+<!ATTLIST makeargs value CDATA #REQUIRED>
+<!ELEMENT makeinstallargs EMPTY>
+<!ATTLIST makeinstallargs value CDATA #REQUIRED>
+
+<!ELEMENT waf (pkg-config?,branch,dependencies?,suggests?,after?)>
+<!-- Note: Here the ID type is not used as some existing IDs in modsets are not
+ valid XML ID types - instead CDATA is used -->
+<!ATTLIST waf
+ id CDATA #REQUIRED
+ waf-command CDATA #IMPLIED>
+
+<!ELEMENT metamodule (dependencies,suggests?,after?)>
+<!ATTLIST metamodule
+ id CDATA #REQUIRED>
+
+<!-- tarball module type is deprecated, a tarball repository inside the
+ appropriate modtype should be used instead -->
+<!ELEMENT tarball (pkg-config?,source,branch?,dependencies?,suggests?,after?,patches?)>
+<!ATTLIST tarball
+ id CDATA #REQUIRED
+ version CDATA #REQUIRED
+ checkoutdir CDATA #IMPLIED
+ autogenargs CDATA #IMPLIED
+ makeargs CDATA #IMPLIED
+ autogen-sh CDATA #IMPLIED
+ supports-non-srcdir-builds (yes|no) "yes">
+
+<!ELEMENT distutils (pkg-config?,branch?,dependencies?,after?)>
+<!ATTLIST distutils
+ id ID #REQUIRED
+ python3 CDATA #FIXED "1"
+ supports-non-srcdir-builds (yes|no) "yes">
+
+<!ELEMENT ninjaargs EMPTY>
+<!ATTLIST ninjaargs value CDATA #REQUIRED>
+
+<!ELEMENT cmake (if*,cmakeargs*,makeargs*,ninjaargs*,pkg-config?,branch?,dependencies?,suggests?,after?)>
+<!ATTLIST cmake
+ id CDATA #REQUIRED
+ cmakeargs CDATA #IMPLIED
+ makeargs CDATA #IMPLIED
+ ninjaargs CDATA #IMPLIED
+ use-ninja (yes|no) "yes"
+ supports-non-srcdir-builds (yes|no) "yes"
+ force-non-srcdir-builds (yes|no) "no">
+
+<!ELEMENT cmakeargs EMPTY>
+<!ATTLIST cmakeargs value CDATA #REQUIRED>
+
+<!ELEMENT meson (if*,mesonargs*,ninjaargs*,pkg-config?,branch?,dependencies?,suggests?,after?)>
+<!ATTLIST meson
+ id CDATA #REQUIRED
+ mesonargs CDATA #IMPLIED
+ ninjaargs CDATA #IMPLIED>
+
+<!ELEMENT mesonargs EMPTY>
+<!ATTLIST mesonargs value CDATA #REQUIRED>
+
+<!ELEMENT perl (pkg-config?,branch?,dependencies?,after?)>
+<!ATTLIST perl
+ id CDATA #REQUIRED
+ makeargs CDATA #IMPLIED>
+
+<!ELEMENT linux (pkg-config?,branch?,dependencies?,after?,kconfig+)>
+<!ATTLIST linux
+ id CDATA #REQUIRED>
+
+<!ELEMENT systemmodule (pkg-config?,branch,dependencies?,suggests?,after?,systemdependencies?)>
+<!ATTLIST systemmodule
+ id CDATA #REQUIRED
+ supports-parallel-builds (yes|no) "yes">
+
+<!ELEMENT testmodule (pkg-config?,branch?,dependencies?,after?,testedmodules?)>
+<!ATTLIST testmodule
+ id CDATA #REQUIRED
+ type CDATA #REQUIRED>
+
+<!ELEMENT cvsroot EMPTY>
+<!ATTLIST cvsroot
+ name CDATA #REQUIRED
+ root CDATA #REQUIRED
+ password CDATA "">
+
+
+<!ELEMENT cvsmodule (suggests?,dependencies?,after?)>
+<!ATTLIST cvsmodule
+ id CDATA #REQUIRED
+ cvsroot CDATA #REQUIRED
+ supports-non-srcdir-builds (yes|no) "yes">
+
+<!-- Tarball's children -->
+<!ELEMENT source EMPTY>
+<!ATTLIST source
+ href CDATA #REQUIRED
+ size CDATA #IMPLIED
+ md5sum CDATA #IMPLIED
+ hash CDATA #IMPLIED>
+
+<!ELEMENT patches (patch*)>
+<!ELEMENT patch EMPTY>
+<!ATTLIST patch
+ file CDATA #REQUIRED
+ strip CDATA "0">
+
+
+<!-- Linux's children -->
+<!ELEMENT kconfig EMPTY>
+<!ATTLIST kconfig
+ repo CDATA #IMPLIED
+ version CDATA #REQUIRED
+ module CDATA #IMPLIED
+ config CDATA #IMPLIED>
+
+
+<!-- Testmodule's children -->
+<!ELEMENT testedmodules (tested)>
+<!ELEMENT tested EMPTY>
+<!ATTLIST tested
+ package CDATA #REQUIRED>
+
+<!-- Other children -->
+<!ELEMENT pkg-config (#PCDATA)>
+<!ELEMENT dependencies (dep|if)*>
+<!ELEMENT suggests (dep|if)*>
+<!ELEMENT after (dep|if)*>
+<!ELEMENT systemdependencies (dep*)>
+<!ELEMENT dep (altdep*)>
+<!-- This is actually 2 different types of element: <dep package=""/> as used in <dependencies>
+ and <dep type="" name=""/> as used in <systemdependencies>. The DTD can't specify both
+ separately since they have the same element name. -->
+<!ATTLIST dep
+ package CDATA #IMPLIED
+ type CDATA #IMPLIED
+ name CDATA #IMPLIED>
+<!-- <altdep> is only used in <systemdependencies> to specify alternative dependencies. -->
+<!ELEMENT altdep EMPTY>
+<!ATTLIST altdep
+ type CDATA #IMPLIED
+ name CDATA #IMPLIED>
+
+<!ELEMENT branch (patch*,quilt*)>
+<!ATTLIST branch
+ repo CDATA #IMPLIED
+ module CDATA #IMPLIED
+ checkoutdir CDATA #IMPLIED
+ override-checkoutdir (yes|no) "yes"
+ update-new-dirs (yes|no) "yes"
+ source-subdir CDATA #IMPLIED
+ revision CDATA #IMPLIED
+ tag CDATA #IMPLIED
+ user CDATA #IMPLIED
+ revspec CDATA #IMPLIED
+ branch CDATA #IMPLIED
+ version CDATA #IMPLIED
+ size CDATA #IMPLIED
+ md5sum CDATA #IMPLIED
+ hash CDATA #IMPLIED
+ rename-tarball CDATA #IMPLIED>
+ <!-- override-checkoutdir and update-new-dirs are CVS only
+ source-subdir is tarballs only -->
+
+<!ELEMENT quilt (branch)>
+<!ATTLIST quilt
+ id CDATA #REQUIRED>
diff --git a/packaging/macos/jhb/etc/modulesets/jhb/moduleset.xsl b/packaging/macos/jhb/etc/modulesets/jhb/moduleset.xsl
new file mode 100644
index 0000000..c2e7f7a
--- /dev/null
+++ b/packaging/macos/jhb/etc/modulesets/jhb/moduleset.xsl
@@ -0,0 +1,196 @@
+<?xml version='1.0'?> <!--*- mode: nxml -*-->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+
+ <xsl:output method="html" encoding="ISO-8859-1" indent="yes" />
+ <xsl:key name="module-id" match="moduleset/*" use="@id" />
+
+ <xsl:template match="/">
+ <html>
+ <head>
+ <title>Module Set</title>
+ <style type="text/css">
+ <xsl:text>
+ dl {
+ -moz-column-width: 40em;
+ -moz-column-gap: 2em;
+ }
+ dt {
+ font-weight: bold;
+ background: #8f8;
+ display: inline;
+ padding: 0 1ex;
+ }
+ dt.metamodule {
+ background: #F08080;
+ }
+ dt.tarball {
+ background: #EEDD82;
+ }
+ dd {
+ font-size: smaller;
+ }
+ dd {
+ margin-bottom: 0.5em;
+ }
+ th {
+ text-align: left;
+ vertical-align: top;
+ }
+ ul.patches {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ }
+ </xsl:text>
+ </style>
+ </head>
+ <body>
+ <xsl:apply-templates />
+ </body>
+ </html>
+ </xsl:template>
+
+ <xsl:template match="moduleset">
+ <h1>JHBuild Module Set</h1>
+ <dl>
+ <xsl:apply-templates />
+ </dl>
+ </xsl:template>
+
+ <xsl:template match="dependencies|suggests|after">
+ <xsl:variable name="deps" select="dep/@package" />
+ <xsl:for-each select="$deps">
+ <a href="#{generate-id(key('module-id', .))}">
+ <xsl:value-of select="." />
+ </a>
+ <xsl:if test="not($deps[last()] = .)">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template match="moduleset/*">
+ <xsl:param name="reponame">
+ <xsl:choose>
+ <xsl:when test="branch/@repo"><xsl:value-of select="branch/@repo"/></xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="//repository[@default = 'yes']/@name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:param>
+
+ <dt id="{generate-id(.)}">
+ <xsl:attribute name="class">module
+ <xsl:if test="name(.) = 'tarball' or
+ //repository[@name = $reponame]/@type = 'tarball'">tarball</xsl:if>
+ </xsl:attribute>
+ <xsl:value-of select="@id" />
+ </dt>
+
+ <dd>
+ <table>
+ <tr>
+ <th>Module:</th>
+ <td>
+ <xsl:choose>
+ <xsl:when test="@module">
+ <xsl:value-of select="@module" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@id" />
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="branch/@revision">
+ <xsl:text> revision: </xsl:text>
+ <xsl:value-of select="branch/@revision" />
+ </xsl:if>
+ </td>
+ </tr>
+ <xsl:if test="name(.) = 'tarball' or //repository[@name = $reponame]/@type = 'tarball'">
+ <tr>
+ <th>URL:</th>
+ <td>
+ <xsl:variable name="url">
+ <xsl:choose>
+ <xsl:when test="name(.) = 'tarball'">
+ <xsl:value-of select="source/@href"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="//repository[@name=$reponame]/@href"
+ /><xsl:value-of select="branch/@module"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <a href="{$url}"><xsl:value-of select="$url"/></a>
+ <xsl:if test="branch/@size"> (<xsl:value-of select="branch/@size"/> bytes)</xsl:if>
+ <xsl:if test="source/@size"> (<xsl:value-of select="source/@size"/> bytes)</xsl:if>
+ </td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="branch/patch">
+ <tr>
+ <th>Patches:</th>
+ <td>
+ <ul class="patches">
+ <xsl:apply-templates select="branch/patch"/>
+ </ul>
+ </td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="@checkoutdir">
+ <tr>
+ <th>Checkout directory:</th>
+ <td><xsl:value-of select="@checkoutdir" /></td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="@autogenargs">
+ <tr>
+ <th>Autogen args:</th>
+ <td><xsl:value-of select="@autogenargs" /></td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="dependencies/dep">
+ <tr>
+ <th>Dependencies:</th>
+ <td><xsl:apply-templates select="dependencies" /></td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="suggests">
+ <tr>
+ <th>Suggests:</th>
+ <td><xsl:apply-templates select="suggests" /></td>
+ </tr>
+ </xsl:if>
+ <xsl:if test="after">
+ <tr>
+ <th>After:</th>
+ <td><xsl:apply-templates select="after" /></td>
+ </tr>
+ </xsl:if>
+ </table>
+ </dd>
+ </xsl:template>
+
+ <xsl:template match="moduleset/repository|moduleset/include">
+ </xsl:template>
+
+ <xsl:template match="moduleset/metamodule">
+ <dt id="{generate-id(.)}" class="metamodule"><xsl:value-of select="@id" /></dt>
+ <dd>
+ <table>
+ <xsl:if test="dependencies/dep">
+ <tr>
+ <th>Dependencies:</th>
+ <td><xsl:apply-templates select="dependencies" /></td>
+ </tr>
+ </xsl:if>
+ </table>
+ </dd>
+ </xsl:template>
+
+ <xsl:template match="patch">
+ <li><xsl:value-of select="@file" /></li>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/packaging/macos/jhb/etc/modulesets/jhb/patches/libtool-apple-sort.patch b/packaging/macos/jhb/etc/modulesets/jhb/patches/libtool-apple-sort.patch
new file mode 100644
index 0000000..8c880ef
--- /dev/null
+++ b/packaging/macos/jhb/etc/modulesets/jhb/patches/libtool-apple-sort.patch
@@ -0,0 +1,38 @@
+--- a/Makefile.am 2015-01-20 07:34:33.000000000 -0800
++++ b/Makefile.am 2021-11-12 10:18:23.000000000 -0800
+@@ -416,8 +416,8 @@
+ # files created in the build tree, so instead we regenerate the
+ # manual pages if the sources for the build-tree files we want to
+ # run have changed.
+-$(libtool_1): $(ltmain_sh)
+- $(AM_V_GEN)$(update_mans) --help-option=--help-all libtool
++#$(libtool_1): $(ltmain_sh)
++# $(AM_V_GEN)$(update_mans) --help-option=--help-all libtool
+ $(libtoolize_1): $(libtoolize_in)
+ $(AM_V_GEN)$(update_mans) libtoolize
+
+--- s/Makefile.in 2015-02-15 08:14:14.000000000 -0800
++++ b/Makefile.in 2021-11-12 10:26:26.000000000 -0800
+@@ -2324,8 +2324,8 @@
+ # files created in the build tree, so instead we regenerate the
+ # manual pages if the sources for the build-tree files we want to
+ # run have changed.
+-$(libtool_1): $(ltmain_sh)
+- $(AM_V_GEN)$(update_mans) --help-option=--help-all libtool
++#$(libtool_1): $(ltmain_sh)
++# $(AM_V_GEN)$(update_mans) --help-option=--help-all libtool
+ $(libtoolize_1): $(libtoolize_in)
+ $(AM_V_GEN)$(update_mans) libtoolize
+
+--- a/build-aux/ltmain.in 2015-02-06 04:57:56.000000000 -0800
++++ b/build-aux/ltmain.in 2021-11-08 14:58:33.000000000 -0800
+@@ -3188,7 +3188,7 @@
+ if test yes = "$lock_old_archive_extraction"; then
+ $opt_dry_run || rm -f "$lockfile"
+ fi
+- if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
++ if ($AR t "$f_ex_an_ar_oldlib" | sort -u | sort -c >/dev/null 2>&1); then
+ :
+ else
+ func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
+
diff --git a/packaging/macos/jhb/etc/modulesets/jhb/patches/vasnprintf.patch b/packaging/macos/jhb/etc/modulesets/jhb/patches/vasnprintf.patch
new file mode 100644
index 0000000..995e1e3
--- /dev/null
+++ b/packaging/macos/jhb/etc/modulesets/jhb/patches/vasnprintf.patch
@@ -0,0 +1,11 @@
+--- a/lib/vasnprintf.c 2017-09-29 11:10:29.000000000 +0200
++++ b/lib/vasnprintf.c 2017-09-29 11:15:06.000000000 +0200
+@@ -4858,7 +4858,7 @@
+ #endif
+ *fbp = dp->conversion;
+ #if USE_SNPRINTF
+-# if !(((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined __UCLIBC__) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
++# if !(((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined __UCLIBC__) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) || defined __APPLE__)
+ fbp[1] = '%';
+ fbp[2] = 'n';
+ fbp[3] = '\0';
diff --git a/packaging/macos/jhb/usr/bin/archive b/packaging/macos/jhb/usr/bin/archive
new file mode 100755
index 0000000..f84f0c8
--- /dev/null
+++ b/packaging/macos/jhb/usr/bin/archive
@@ -0,0 +1,205 @@
+#!/usr/bin/env bash
+#
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# This is a helper to create release archives and mount them.
+
+### shellcheck #################################################################
+
+# Nothing here.
+
+### dependencies ###############################################################
+
+#------------------------------------------------------ source jhb configuration
+
+source "$(dirname "${BASH_SOURCE[0]}")"/../../etc/jhb.conf.sh
+
+#------------------------------------------- source common functions from bash_d
+
+# bash_d is already available (it's part of jhb configuration)
+
+bash_d_include error
+
+### variables ##################################################################
+
+# Nothing here.
+
+### functions ##################################################################
+
+function create_tar
+{
+ local file=$ARTIFACT_DIR/$RELEASE_ARCHIVE
+
+ echo_i "creating $file"
+
+ tar -C "$WRK_DIR" -cp "$(basename "$VER_DIR")" |
+ XZ_OPT=-T0 "$BIN_DIR"/xz > "$file"
+
+ shasum -a 256 "$file" > "$file".sha256
+ cat "$file".sha256
+}
+
+function create_dmg
+{
+ local file=$ARTIFACT_DIR/$RELEASE_ARCHIVE
+
+ ( # create dmg
+ local vol_name
+ vol_name=$(basename "$VER_DIR")
+
+ cd "$WRK_DIR" || exit 1
+ hdiutil create -fs HFS+ -ov -format UDBZ \
+ -srcfolder "$vol_name" \
+ -volname "$vol_name" \
+ "$file"
+ )
+
+ ( # create and print checksum
+ cd "$(dirname "$file")" || exit 1
+ shasum -a 256 "$(basename "$file")" > "$file".sha256
+ cat "$file".sha256
+ )
+}
+
+function mount_dmg
+{
+ local file=$REP_DIR/$RELEASE_ARCHIVE
+ local mountpoint=$VER_DIR
+
+ if [ ! -d "$mountpoint" ]; then
+ mkdir -p "$mountpoint"
+ fi
+
+ echo_i "mounting $(basename "$file") may take some time"
+ local device
+ device=$(hdiutil attach -nomount "$file" | grep "^/dev/disk" |
+ grep "Apple_HFS" | awk '{ print $1 }')
+ echo_i "$file attached to $device"
+ mount -o nobrowse,noowners,noquarantine,ro -t hfs "$device" "$mountpoint"
+ echo_i "$device mounted to $mountpoint"
+}
+
+function unmount_dmg
+{
+ local mountpoint=$VER_DIR
+
+ while : ; do # unmount everything (in reverse order)
+ local disk
+ disk=$(mount | grep "$mountpoint" | tail -n1 | awk '{ print $1 }')
+ disk=${disk%s[0-9]} # cut off slice specification
+
+ if [ ${#disk} -eq 0 ]; then
+ break # nothing to do here
+ else
+ # We loop over the 'eject' since it occasionally timeouts.
+ while ! diskutil eject "$disk" > /dev/null; do
+ echo_w "retrying to eject $disk in 5 seconds"
+ sleep 5
+ done
+
+ echo_i "ejected $disk"
+ fi
+ done
+}
+
+function download_dmg
+{
+ if [ ! -d "$REP_DIR" ]; then
+ mkdir -p "$REP_DIR"
+ fi
+
+ for url in "${RELEASE_URLS[@]}"; do
+ local partial_download=$REP_DIR/${FUNCNAME[0]} # TMP_DIR not available yet
+ # download (at least) 100 kb of data
+ curl -L "$url" 2>/dev/null | head -c 100000 > "$partial_download"
+ # if we got 100 kb, it's not a "404 file not found"
+ if [ "$(stat -f%z "$partial_download")" -eq 100000 ]; then
+ echo_i "downloading $url"
+ curl -o "$REP_DIR/$RELEASE_ARCHIVE" -L -C - "$url"
+ break
+ fi
+ done
+
+ rm "$partial_download"
+}
+
+function install_dmg
+{
+ local overlay_size=${1:-1} # unit GiB, default 1
+
+ local file=$REP_DIR/$RELEASE_ARCHIVE
+
+ # download and mount read-only disk image
+ if [ -f "$file" ]; then
+ echo_i "using $file"
+ else
+ download_dmg
+ fi
+ mount_dmg
+
+ # create writable overlay
+ local device
+ device=$(hdiutil attach -nomount ram://$((overlay_size * 1024 * 2048)) | xargs)
+ newfs_hfs -v "$RELEASE_OVERLAY" "$device" >/dev/null
+ echo_i "$overlay_size GiB ram attached to $device"
+ mount -o nobrowse,rw,union -t hfs "$device" "$VER_DIR"
+ echo_i "$device union-mounted at $VER_DIR"
+
+ # Sadly, there are some limitations involved with union-mounting:
+ # - Files are not visible to macOS' versions of 'ls' or 'find'.
+ # (The GNU versions do work though.)
+ # - You cannot write in a location without having written to its
+ # parent location first. That's why we need to pre-create all directories
+ # below.
+ #
+ # (Shadow-mounting a dmg is not a feasible alternative due to its
+ # bad write-performance.)
+
+ # Create and run a script for mass-creating directories.
+ echo_i "setting up directories in overlay"
+ gfind "$VER_DIR" -mindepth 1 -type d \
+ ! -path "$BLD_DIR/*" ! -path "$SRC_DIR/*" \
+ -exec echo "mkdir {}" \; > "$VER_DIR"/create_dirs.sh
+ chmod 755 "$VER_DIR"/create_dirs.sh
+ "$VER_DIR"/create_dirs.sh
+ rm "$VER_DIR"/create_dirs.sh
+}
+
+function uninstall_dmg
+{
+ unmount_dmg
+}
+
+function main
+{
+ local command=$1
+ local option=$2
+
+ case "$command" in
+ create_dmg)
+ create_dmg
+ ;;
+ create_tar)
+ create_tar
+ ;;
+ install_dmg)
+ install_dmg "$option" # option: overlay size in GiB, defaul is 1
+ ;;
+ uninstall_dmg)
+ uninstall_dmg
+ ;;
+ *)
+ echo_e "usage: $0 {create_dmg|create_tar|install_dmg|uninstall_dmg}"
+ ;;
+ esac
+}
+
+### main #######################################################################
+
+error_trace_enable
+
+main "$@"
diff --git a/packaging/macos/jhb/usr/bin/bootstrap b/packaging/macos/jhb/usr/bin/bootstrap
new file mode 100755
index 0000000..3d46dbb
--- /dev/null
+++ b/packaging/macos/jhb/usr/bin/bootstrap
@@ -0,0 +1,135 @@
+#!/usr/bin/env bash
+#
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# This script bootstraps JHBuild so it's ready to build any module.
+
+### shellcheck #################################################################
+
+# Nothing here.
+
+### dependencies ###############################################################
+
+#------------------------------------------------------ source jhb configuration
+
+# You can install a custom configuration file by passing it as first
+# argument. It has to be named '*.conf.sh'.
+
+source "$(dirname "${BASH_SOURCE[0]}")"/../../etc/jhb.conf.sh "$1"
+
+#------------------------------------------- source common functions from bash_d
+
+# bash_d is already available (it's part of jhb configuration)
+
+bash_d_include error
+
+### variables ##################################################################
+
+SELF_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" || exit 1; pwd)
+
+FORCE_BUILD_FROM_SOURCE=${FORCE_BUILD_FROM_SOURCE:-false}
+
+### functions ##################################################################
+
+function is_release_usable
+{
+ local url=$1
+
+ local partial_download="$TMP_DIR/${FUNCNAME[0]}".tar.xz
+ local rc=1
+
+ # download at least 100 kb of data
+ curl -L "$url" 2>/dev/null | head -c 100000 > "$partial_download"
+ # if we got 100 kb, it's not a "404 file not found"
+ if [ "$(stat -f%z "$partial_download")" -eq 100000 ]; then
+ # look inside: dir needs to match our VER_DIR to be usable
+ local dir
+ dir=$(basename "$(tar -tvJf "$partial_download" 2>/dev/null |
+ head -n 1 | awk '{ print $NF }')")
+ if [ "$dir" = "$(basename "$VER_DIR")" ]; then
+ rc=0
+ fi
+ fi
+
+ rm "$partial_download"
+
+ return $rc
+}
+
+### main #######################################################################
+
+error_trace_enable
+
+#-------------------------------------------------------- print main directories
+
+echo_i "WRK_DIR = $WRK_DIR"
+echo_i "VER_DIR = $VER_DIR"
+
+#--------------------------------------------------------- perform system checks
+
+if sys_wrkdir_is_usable &&
+ sdkroot_exists &&
+ sys_usrlocal_is_clean; then
+
+ # these checks may issue warnings but have have no consequences otherwise
+ sys_macos_is_recommended || true
+ sys_sdk_is_recommended || true
+else
+ exit 1 # cannot continue
+fi
+
+#--------------------------------------------------- initialize directory layout
+
+if [ "$SELF_DIR" = "$USR_DIR"/bin ]; then
+ : # we are already running inside target directory layout
+else
+ # sync repository into target structure, remove everything git-related
+ rsync -a "$SELF_DIR"/../../../jhb/ "$VER_DIR"/
+ find "$VER_DIR" -type f -name ".gitignore" -delete
+ rm -rf "$VER_DIR"/.git
+ rm "$VER_DIR"/.gitmodules
+fi
+
+#------------------------------------------- check if binary release can be used
+
+for URL in "${RELEASE_URLS[@]}"; do
+ if is_release_usable "$URL" && ! $FORCE_BUILD_FROM_SOURCE; then
+ echo_i "using $URL"
+ curl -L "$URL" | tar -C "$WRK_DIR" -xJ
+ exit $? # we can quit here and now, nothing further to do
+ fi
+done
+
+echo_i "building everything from scratch"
+
+#---------------------------------------------------------------- install ccache
+
+ccache_install
+ccache_configure
+
+#------------------------------------------ log relevant versions to release.log
+
+sys_create_log
+
+#------------------------------------------------- install and configure JHBuild
+
+jhbuild_install
+jhbuild_configure
+
+#------------------------------------------------------- run bootstrap procedure
+
+jhbuild bootstrap-gtk-osx
+
+#--------------------------------------------------------- install GNU utilities
+
+# GNU versions of various utilites make life significantly easier on macOS.
+
+jhbuild build coreutils findutils sed tar
+
+#-------------------------------------------------------------- install dmgbuild
+
+dmgbuild_install
diff --git a/packaging/macos/jhb/usr/bin/jhb b/packaging/macos/jhb/usr/bin/jhb
new file mode 100755
index 0000000..b268339
--- /dev/null
+++ b/packaging/macos/jhb/usr/bin/jhb
@@ -0,0 +1,63 @@
+#!/usr/bin/env bash
+#
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# This script is a wrapper around the jhbuild binary to run it in our
+# configured environment (etc/jhb.conf).
+
+### shellcheck #################################################################
+
+# Nothing here.
+
+### dependencies ###############################################################
+
+#---------------------------------------------------------- source configuration
+
+source "$(dirname "${BASH_SOURCE[0]}")"/../../etc/jhb.conf.sh
+
+#------------------------------------------- source common functions from bash_d
+
+# bash_d is already available (it's part of etc/jhb.conf)
+
+bash_d_include error
+
+### variables ##################################################################
+
+# Nothing here.
+
+### functions ##################################################################
+
+# Nothing here.
+
+### main #######################################################################
+
+if $CI; then # break in CI, otherwise we get interactive prompt by JHBuild
+ error_trace_enable
+fi
+
+case "$1" in
+ debug)
+ echo_d "doing nothing"
+ ;;
+ configure)
+ jhbuild_configure "$2" # e.g. 'jhbuild/myapp.modules'
+ ccache_configure
+ ;;
+ *)
+ if sys_wrkdir_is_usable &&
+ sdkroot_exists &&
+ sys_usrlocal_is_clean; then
+
+ # these checks may issue warnings but have have no consequences otherwise
+ sys_macos_is_recommended || true
+ sys_sdk_is_recommended || true
+ else
+ exit 1 # cannot continue
+ fi
+ "$USR_DIR"/bin/jhbuild "$@"
+ ;;
+esac \ No newline at end of file
diff --git a/packaging/macos/jhb/usr/bin/run-parts b/packaging/macos/jhb/usr/bin/run-parts
new file mode 100755
index 0000000..ff0470c
--- /dev/null
+++ b/packaging/macos/jhb/usr/bin/run-parts
@@ -0,0 +1,73 @@
+#!/usr/bin/env bash
+
+### description ################################################################
+
+# A partial replacement for Debian's "run-parts" tool. Execute files in a
+# directory in their lexical order with the specialty of being able to
+# use symlinks to create an order without executing the files twice.
+
+### shellcheck #################################################################
+
+# Nothing here.
+
+### dependencies ###############################################################
+
+# Nothing here.
+
+### variables ##################################################################
+
+# Nothing here.
+
+### functions ##################################################################
+
+function main
+{
+ local mode=$1
+ local dir=$2
+
+ local file_pattern
+
+ if [ -d "$dir" ]; then
+ # reconstruct to make it proper (e.g. remove superfluous slashes)
+ dir=$(dirname "$dir")/$(basename "$dir")
+ else
+ # split into directory and file
+ file_pattern=$(basename "$dir")
+ dir=$(dirname "$dir")
+ fi
+
+ file_pattern=${file_pattern:-*} # default pattern is "*"
+
+ local linked_files
+ linked_files=$(find "$dir" -type l -exec readlink {} +)
+
+ for file in "$dir"/$file_pattern; do # requires 'shopt -s nullglob'
+ # Only process files that have no symlinks (in that same directory) pointing
+ # at them.
+ if [[ "$linked_files" != *$(basename "$file")* ]]; then
+ case "$mode" in
+ list)
+ echo "$file"
+ ;;
+ run)
+ $file
+ ;;
+ esac
+ fi
+ done
+}
+
+### main #######################################################################
+
+set -e
+
+shopt -s nullglob # in case no files are found
+
+case "$1" in
+ list)
+ main "list" "$2"
+ ;;
+ *)
+ main "run" "$1"
+ ;;
+esac
diff --git a/packaging/macos/jhb/usr/src/bash_d/README.md b/packaging/macos/jhb/usr/src/bash_d/README.md
new file mode 100644
index 0000000..fc97cc4
--- /dev/null
+++ b/packaging/macos/jhb/usr/src/bash_d/README.md
@@ -0,0 +1,9 @@
+# `bash_d`
+
+Conceived as part of my (unpublished) dotfiles on macOS, this collection of functions outgrew its originally limited scope and I began developing this into the spiritual successor of [bashlib](https://github.com/dehesselle/bashlib).
+
+This is far from finished and comes with no support and without documentation at this point, but I need to put this online now so I can start using this in other projects.
+
+## License
+
+[GPL](LICENSE) \ No newline at end of file
diff --git a/packaging/macos/jhb/usr/src/bash_d/ansi.sh b/packaging/macos/jhb/usr/src/bash_d/ansi.sh
new file mode 100644
index 0000000..5ecc5ff
--- /dev/null
+++ b/packaging/macos/jhb/usr/src/bash_d/ansi.sh
@@ -0,0 +1,76 @@
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# This file contains ANSI control codes to control terminal output.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+# shellcheck disable=SC2034 # there are a lot of unexported vars here
+
+### includes ###################################################################
+
+# Nothing here.
+
+### variables ##################################################################
+
+ANSI_ENABLED=${ANSI_ENABLED:-true} # allow ANSI escape sequences...
+ANSI_TERM_ONLY=${ANSI_TERM_ONLY:-true} # ...but only when running in a terminal
+
+ANSI_CURSOR_LEFT="\033[1D"
+
+# 0: normal
+# 1: bold
+# 2: faint
+# |
+# \033[1;32m
+# |
+# color
+ANSI_FG_BLACK="\033[0;30m"
+ANSI_FG_BLACK_BOLD="\033[1;30m"
+ANSI_FG_BLACK_BRIGHT="\033[0;90m"
+ANSI_FG_BLUE="\033[0;34m"
+ANSI_FG_BLUE_BOLD="\033[1;34m"
+ANSI_FG_BLUE_BRIGHT="\033[0;94m"
+ANSI_FG_CYAN="\033[0;36m"
+ANSI_FG_CYAN_BOLD="\033[1;36m"
+ANSI_FG_CYAN_BRIGHT="\033[0;96m"
+ANSI_FG_GREEN="\033[0;32m"
+ANSI_FG_GREEN_BOLD="\033[1;32m"
+ANSI_FG_GREEN_BRIGHT="\033[0;92m"
+ANSI_FG_MAGENTA="\033[0;35m"
+ANSI_FG_MAGENTA_BOLD="\033[1;35m"
+ANSI_FG_MAGENTA_BRIGHT="\033[0;95m"
+ANSI_FG_RED="\033[0;31m"
+ANSI_FG_RED_BOLD="\033[1;31m"
+ANSI_FG_RED_BRIGHT="\033[0;91m"
+ANSI_FG_RESET="\033[0;0m"
+ANSI_FG_WHITE="\033[0;37m"
+ANSI_FG_WHITE_BOLD="\033[1;37m"
+ANSI_FG_WHITE_BRIGHT="\033[0;97m"
+ANSI_FG_YELLOW="\033[0;33m"
+ANSI_FG_YELLOW_BOLD="\033[1;33m"
+ANSI_FG_YELLOW_BRIGHT="\033[0;93m"
+
+### functions ##################################################################
+
+function ansi_test_colors
+{
+ for color in ${!ANSI_FG_*}; do
+ echo -e "${!color}This is $color"
+ done
+}
+
+### aliases ####################################################################
+
+# This performs the following check:
+# - usage of ANSI is generally enabled AND
+# - we are either running in a terminal OR we don't care at all
+alias ansi_is_usable='$ANSI_ENABLED && ([ -t 1 ] || ! $ANSI_TERM_ONLY)'
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/usr/src/bash_d/assert.sh b/packaging/macos/jhb/usr/src/bash_d/assert.sh
new file mode 100644
index 0000000..6b65138
--- /dev/null
+++ b/packaging/macos/jhb/usr/src/bash_d/assert.sh
@@ -0,0 +1,42 @@
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# This file provides a mechanism to restrict sourcing a script to specific
+# platforms.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+
+### dependencies ###############################################################
+
+bash_d_include echo
+
+### variables ##################################################################
+
+ASSERT_RC=0
+
+### functions ##################################################################
+
+# Nothing here.
+
+### aliases ####################################################################
+
+# Bash version
+alias assert_bash4_or_above='[ ${BASH_VERSINFO[0]} -lt 4 ] && echo_e "$(basename ${BASH_SOURCE[0]}) will be unavailable (depends on bash >= 4)" && return $LINENO || true'
+
+# Git
+alias assert_git='[ ! -x "$(command -v git)" ] && echo_e "$(basename ${BASH_SOURCE[0]}) will be unavailable (depends on git)" && return $LINENO || true'
+
+# Unix platforms
+alias assert_darwin='[ "$(uname)" != "Darwin" ] && echo_e "Darwin required" && return $LINENO || true'
+alias assert_linux='[ "$(uname)" != "Linux" ] && echo_e "Linux required" && return $LINENO || true'
+
+alias assert_ok='ASSERT_RC=$?; [ $ASSERT_RC -ne 0 ] && echo_e "assert_ok rc=$ASSERT_RC" && return $LINENO'
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/usr/src/bash_d/bash_d.sh b/packaging/macos/jhb/usr/src/bash_d/bash_d.sh
new file mode 100644
index 0000000..e0715b4
--- /dev/null
+++ b/packaging/macos/jhb/usr/src/bash_d/bash_d.sh
@@ -0,0 +1,98 @@
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# Provide an include guard to be used in every script to protect them from
+# being sourced multiple times.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+
+### dependencies ###############################################################
+
+# All of these need to be "or true" because they fail on the first run.
+
+bash_d_include echo 2>/dev/null || true
+bash_d_include assert 2>/dev/null || true
+
+### variables ##################################################################
+
+BASH_D_DIR=${BASH_D_DIR:-$(dirname "${BASH_SOURCE[0]}")}
+
+if [ "$BASH_D_FAIL_ON_INCLUDE_ERROR" != "false" ]; then
+ BASH_D_FAIL_ON_INCLUDE_ERROR=true
+fi
+
+### functions ##################################################################
+
+function bash_d_include_all
+{
+ local includes
+ includes=$(mktemp "$TMP/${FUNCNAME[0]}".XXXXXX)
+
+ echo "BASH_D_FAIL_ON_INCLUDE_ERROR=false" >> "$includes"
+ for file in "$BASH_D_DIR"/*.sh; do
+ echo "bash_d_include $(basename "$file")" >> "$includes"
+ done
+ echo "BASH_D_FAIL_ON_INCLUDE_ERROR=true" >> "$includes"
+
+ # shellcheck disable=SC1090 # dynamic sourcing on purpose
+ source "$includes"
+ rm "$includes"
+}
+
+function bash_d_is_included
+{
+ local file=$1
+
+ #shellcheck disable=SC2076 # we want literal match, not regex
+ if [[ " ${BASH_D_INCLUDE_FILES[*]} " =~ \
+ " $BASH_D_DIR/$(basename -s .sh "$file").sh " ]]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+### aliases ####################################################################
+
+# shellcheck disable=SC2142 # too much trickery for shellcheck to digest
+alias bash_d_include=\
+'declare -a BASH_D_INCLUDE_FILES; '\
+'BASH_D_INCLUDE_FILE=$(sed -n ${LINENO}p ${BASH_SOURCE[0]} | awk '"'"'{ print $2 }'"'"'); '\
+'BASH_D_INCLUDE_FILE=$BASH_D_DIR/$(basename -s .sh $BASH_D_INCLUDE_FILE).sh; '\
+'if [[ " ${BASH_D_INCLUDE_FILES[@]} " =~ " ${BASH_D_INCLUDE_FILE} " ]]; then '\
+' : ; '\
+'else '\
+' if [ "$BASH_D_INCLUDE_FILE" = "$BASH_D_DIR/bash_d.sh" ] && '\
+' [ ${#BASH_D_INCLUDE_FILES[@]} -gt 0 ] || '\
+' source $BASH_D_INCLUDE_FILE; then '\
+' BASH_D_INCLUDE_FILE=$(sed -n ${LINENO}p ${BASH_SOURCE[0]} | awk '"'"'{ print $2 }'"'"'); '\
+' BASH_D_INCLUDE_FILE=$BASH_D_DIR/$(basename -s .sh $BASH_D_INCLUDE_FILE).sh; '\
+' BASH_D_INCLUDE_FILES+=("$BASH_D_INCLUDE_FILE"); '\
+' else '\
+' if alias | grep "echo_e" >/dev/null; then '\
+' echo_e "$BASH_D_INCLUDE_FILE will be unavailable"; '\
+' else '\
+' >&2 echo "error: $BASH_D_INCLUDE_FILE will be unavailable"; '\
+' fi; '\
+' if [ "$BASH_D_INCLUDE_FILE" != "$BASH_D_DIR/bash_d.sh" ] && $BASH_D_FAIL_ON_INCLUDE_ERROR; then '\
+' exit 1; '\
+' fi '\
+' fi '\
+'fi '\
+'# '
+
+### main #######################################################################
+
+if [ ! -d "$BASH_D_DIR" ]; then
+ echo "error: BASH_D_DIR=$BASH_D_DIR is invalid [${BASH_SOURCE[0]}]"
+ exit 1
+fi
+
+shopt -s expand_aliases
+
+bash_d_include bash_d # Need to rerun so complete setting us up.
diff --git a/packaging/macos/jhb/usr/src/bash_d/echo.sh b/packaging/macos/jhb/usr/src/bash_d/echo.sh
new file mode 100644
index 0000000..d160db0
--- /dev/null
+++ b/packaging/macos/jhb/usr/src/bash_d/echo.sh
@@ -0,0 +1,52 @@
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# Provide colorful convenience functions for echo.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+
+### includes ###################################################################
+
+bash_d_include ansi
+
+### variables ##################################################################
+
+# Nothing here.
+
+### functions ##################################################################
+
+function echo_message__
+{
+ local funcname=$1 # empty if outside function
+ local filename=$2
+ local type=$3
+ local color=$4
+ local args=${*:5}
+
+ if [ -z "$funcname" ] || [ "$funcname" = "source" ]; then
+ funcname=$(basename "$filename")
+ fi
+
+ if ansi_is_usable; then
+ echo -e "${color}$type:$ANSI_FG_RESET $args ${ANSI_FG_BLACK_BRIGHT}[$funcname]$ANSI_FG_RESET"
+ else
+ echo "$type: $args [$funcname]"
+ fi
+}
+
+### aliases ####################################################################
+
+alias echo_d='>&2 echo_message__ "$FUNCNAME" "${BASH_SOURCE[0]}" "debug" "$ANSI_FG_BLUE_BOLD"'
+alias echo_e='>&2 echo_message__ "$FUNCNAME" "${BASH_SOURCE[0]}" "error" "$ANSI_FG_RED_BRIGHT"'
+alias echo_i='>&2 echo_message__ "$FUNCNAME" "${BASH_SOURCE[0]}" "info" "$ANSI_FG_BLUE_BRIGHT"'
+alias echo_o='>&2 echo_message__ "$FUNCNAME" "${BASH_SOURCE[0]}" "ok" "$ANSI_FG_GREEN_BRIGHT"'
+alias echo_w='>&2 echo_message__ "$FUNCNAME" "${BASH_SOURCE[0]}" "warning" "$ANSI_FG_YELLOW_BRIGHT"'
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/usr/src/bash_d/error.sh b/packaging/macos/jhb/usr/src/bash_d/error.sh
new file mode 100644
index 0000000..69ec0be
--- /dev/null
+++ b/packaging/macos/jhb/usr/src/bash_d/error.sh
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# https://github.com/dehesselle/bash_d
+
+### includes ###################################################################
+
+bash_d_include ansi.sh
+bash_d_include echo.sh
+
+### variables ##################################################################
+
+# Nothing here.
+
+### functions ##################################################################
+
+function error_catch
+{
+ local rc=$1
+
+ local index=0
+ local output
+
+ while output=$(caller $index); do
+ if [ $index -eq 0 ]; then
+ if ansi_is_usable; then
+ echo_e "rc=$rc $ANSI_FG_YELLOW_BRIGHT$BASH_COMMAND$ANSI_FG_RESET"
+ else
+ echo "rc=$rc $BASH_COMMAND"
+ fi
+ fi
+
+ echo_e $output
+ ((index+=1))
+ done
+
+ exit $rc
+}
+
+### aliases ####################################################################
+
+alias error_trace_enable='set -o errtrace; trap '\''error_catch ${?}'\'' ERR'
+alias error_trace_disable='trap - ERR'
+
+### main #######################################################################
+
+# Nothing here. \ No newline at end of file
diff --git a/packaging/macos/jhb/usr/src/bash_d/lib.sh b/packaging/macos/jhb/usr/src/bash_d/lib.sh
new file mode 100644
index 0000000..c1f385e
--- /dev/null
+++ b/packaging/macos/jhb/usr/src/bash_d/lib.sh
@@ -0,0 +1,174 @@
+# SPDX-FileCopyrightText: 2021 René de Hesselle <dehesselle@web.de>
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+### description ################################################################
+
+# Provide convenience wrappers for install_name_tool.
+
+### shellcheck #################################################################
+
+# shellcheck shell=bash # no shebang as this file is intended to be sourced
+
+### dependencies ###############################################################
+
+assert_darwin
+bash_d_include echo
+bash_d_include readlinkf
+
+### variables ##################################################################
+
+LIB_RESET_ID=keep # options: basename, canonical, keep
+
+### functions ##################################################################
+
+function lib_change_path
+{
+ # Compared to install_name_tool, this function
+ # - requires less arguments as 'source' can be deducted from 'target'
+ # - can apply the requested changes to multiple binaries at once
+
+ local target=$1 # new path to dynamically linked library
+ local binaries=${*:2} # binaries to modify
+
+ local source_lib=${target##*/} # get library filename from target location
+
+ for binary in $binaries; do # won't work if spaces in paths
+ if [[ $binary == *.so ]] ||
+ [[ $binary == *.dylib ]] ||
+ [ $(file $binary | grep "shared library" | wc -l) -eq 1 ]; then
+ lib_reset_id $binary
+ fi
+
+ local source=$(otool -L $binary | grep "$source_lib " | awk '{ print $1 }')
+ if [ -z $source ]; then
+ echo_w "no $source_lib in $binary"
+ else
+ # Reconstructing 'target' as it might have been specified as regex.
+ target=$(dirname $target)/$(basename $source)
+
+ install_name_tool -change $source $target $binary
+ fi
+ done
+}
+
+function lib_change_paths
+{
+ # This is a wrapper ontop lib_change_path: given a directory 'lib_dir' that
+ # contains the libraries, all (matching) libraries linked in 'binary' can be
+ # changed at once to a specified 'target' path.
+
+ local target=$1 # new path to dynamically linked library
+ local lib_dir=$2
+ local binaries=${*:3}
+
+ for binary in $binaries; do
+ for linked_lib in $(otool -L $binary | tail -n +2 | awk '{ print $1 }'); do
+ if [ "$(basename $binary)" != "$(basename $linked_lib)" ] &&
+ [ -f $lib_dir/$(basename $linked_lib) ]; then
+ lib_change_path $target/$(basename $linked_lib) $binary
+ fi
+ done
+ done
+}
+
+function lib_change_siblings
+{
+ # This is a wrapper ontop lib_change_path: all libraries inside a given
+ # 'lib_dir' that are linked to libraries located in that same 'lib_dir' can
+ # be automatically adjusted.
+
+ local lib_dir=$1
+
+ for lib in $lib_dir/*.dylib; do
+ lib_reset_id $lib
+ for linked_lib in $(otool -L $lib | tail -n +2 | awk '{ print $1 }'); do
+ if [ "$(basename $lib)" != "$(basename $linked_lib)" ] &&
+ [ -f $lib_dir/$(basename $linked_lib) ]; then
+ lib_change_path @loader_path/$(basename $linked_lib) $lib
+ fi
+ done
+ done
+}
+
+function lib_reset_id
+{
+ local lib=$1
+
+ case "$LIB_RESET_ID" in
+ basename)
+ install_name_tool -id $(basename $lib) $lib
+ ;;
+ canonical)
+ install_name_tool -id $(readlinkf $lib) $lib
+ ;;
+ keep)
+ : # don't do anything
+ ;;
+ *)
+ echo_e "invalid value for LIB_RESET_ID: $LIB_RESET_ID"
+ ;;
+ esac
+}
+
+function lib_add_rpath
+{
+ local rpath=$1
+ local binary=$2
+
+ install_name_tool -add_rpath "$rpath" "$binary"
+}
+
+function lib_clear_rpath
+{
+ local binary=$1
+
+ for rpath in $(otool -l $binary | grep -A2 LC_RPATH | grep -E "^[ ]+path" | awk '{ print $2 }'); do
+ install_name_tool -delete_rpath $rpath $binary
+ done
+}
+
+function lib_replace_path
+{
+ local source=$1
+ local target=$2
+ local binary=$3
+
+ for lib in $(lib_get_linked $binary); do
+ if [[ $lib =~ $source ]]; then
+ lib_change_path @rpath/$(basename $lib) $binary
+ fi
+ done
+}
+
+function lib_get_linked
+{
+ local binary=$1 # can be executable or library
+
+ #echo_d "binary: $binary"
+
+ local filter # we need to distinguish between executable and library
+
+ local file_type
+ file_type=$(file "$binary")
+ if [[ $file_type = *"shared library"* ]]; then
+ filter="-v $(otool -D "$binary" | tail -n 1)" # exclude library id
+ elif [[ $file_type = *"executable"* ]]; then
+ filter="-E [.]+" # include everything
+ else
+ echo_w "neither shared library nor executable: $binary"
+ return 1
+ fi
+
+ # since we're not echoing this, output will be newline-separated
+ # shellcheck disable=SC2086 # need word splitting for arguments
+ otool -L "$binary" | grep " " | grep $filter | awk '{ print $1 }'
+}
+
+### aliases ####################################################################
+
+# Nothing here.
+
+### main #######################################################################
+
+# Nothing here.
diff --git a/packaging/macos/jhb/usr/src/bash_d/readlinkf.sh b/packaging/macos/jhb/usr/src/bash_d/readlinkf.sh
new file mode 100644
index 0000000..135a886
--- /dev/null
+++ b/packaging/macos/jhb/usr/src/bash_d/readlinkf.sh
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# https://github.com/dehesselle/bash_d
+
+### description ################################################################
+
+# This is a replacement for GNU's '-f' extension to 'readlink' which is not
+# part of the BSD version.
+
+### includes ###################################################################
+
+# Nothing here.
+
+### variables ##################################################################
+
+# Nothing here.
+
+### functions ##################################################################
+
+# Nothing here.
+
+### aliases ####################################################################
+
+alias readlinkf='perl -e '"'"'use Cwd "abs_path"; print abs_path(@ARGV[0])'"'"' --'
+
+### main #######################################################################
+
+# Nothing here.