diff --git a/Makefile.am b/Makefile.am
index 52111ad34fdfef2c908d72f5b56bc7f19fe67ac1..22a9386d47372dd392c96d835fbc14e53b627d59 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -53,6 +53,7 @@ EXTRA_DIST = \
 	tools/check-coding-style.mk \
 	tools/check-py-style.sh \
 	tools/check-whitespace.sh \
+	tools/dist.sh \
 	tools/generate-pkginfo.py \
 	$(NULL)
 
@@ -369,23 +370,8 @@ $(patsubst %,%.test,$(test_programs)): %.test: Makefile
 # === Documentation ===
 
 dist-hook:
-	echo $(VERSION) > $(distdir)/.version
-	$(MKDIR_P) $(distdir)/dbus_python.egg-info
-	touch $(distdir)/MANIFEST
-	touch $(distdir)/MANIFEST.in
-	touch $(distdir)/dbus_python.egg-info/SOURCES.txt
-	$(PYTHON) $(distdir)/tools/generate-pkginfo.py $(VERSION) $(distdir)/PKG-INFO
-	echo > $(distdir)/dbus_python.egg-info/dependency_links.txt
-	echo _dbus_bindings > $(distdir)/dbus_python.egg-info/top_level.txt
-	echo _dbus_glib_bindings >> $(distdir)/dbus_python.egg-info/top_level.txt
-	echo dbus >> $(distdir)/dbus_python.egg-info/top_level.txt
-	cp $(distdir)/PKG-INFO $(distdir)/dbus_python.egg-info/PKG-INFO
-	( cd $(distdir) && find -type d -o -print ) | \
-		LC_ALL=C sort | \
-		$(SED) -e 's|^\./||' \
-		> $(distdir)/MANIFEST
-	sed -e 's/.*/include &/' < $(distdir)/MANIFEST > $(distdir)/MANIFEST.in
-	cp $(distdir)/MANIFEST $(distdir)/dbus_python.egg-info/SOURCES.txt
+	MESON_PROJECT_DIST_ROOT="${distdir}" \
+	$(srcdir)/tools/dist.sh "${VERSION}" "${PYTHON}"
 
 maintainer-upload:
 	rsync -tvpP --chmod=ugo=r $(DIST_ARCHIVES) $(DIST_ARCHIVES:%=%.asc) \
diff --git a/meson.build b/meson.build
index 8251880f59b886ac1034a39be4af426d4ab085ee..d5da6fbdea7c7f5c57e5d0eeafbe794b6a93b183 100644
--- a/meson.build
+++ b/meson.build
@@ -238,3 +238,9 @@ gi_dep = py_mod.find_installation(
 if dbus_run_session.found()
     subdir('test')
 endif
+
+meson.add_dist_script(
+    'tools/dist.sh',
+    meson.project_version(),
+    py.full_path(),
+)
diff --git a/tools/dist.sh b/tools/dist.sh
new file mode 100755
index 0000000000000000000000000000000000000000..5f627240e47d9850fc0d8c4833c95f2be16b9d77
--- /dev/null
+++ b/tools/dist.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+# Copyright 2006-2025 Collabora Ltd.
+# SPDX-License-Identifier: MIT
+
+set -eux
+
+distdir="${MESON_PROJECT_DIST_ROOT}"
+
+MKDIR_P="${MKDIR_P-mkdir -p}"
+SED="${SED-sed}"
+
+VERSION="$1"
+PYTHON="$2"
+
+umask 022
+
+echo "${VERSION}" > "${distdir}/.version"
+${MKDIR_P} "${distdir}/dbus_python.egg-info"
+touch "${distdir}/MANIFEST"
+touch "${distdir}/MANIFEST.in"
+touch "${distdir}/dbus_python.egg-info/SOURCES.txt"
+${PYTHON} "${distdir}/tools/generate-pkginfo.py" "${VERSION}" "${distdir}/PKG-INFO"
+echo > "${distdir}/dbus_python.egg-info/dependency_links.txt"
+echo _dbus_bindings > "${distdir}/dbus_python.egg-info/top_level.txt"
+echo _dbus_glib_bindings >> "${distdir}/dbus_python.egg-info/top_level.txt"
+echo dbus >> "${distdir}/dbus_python.egg-info/top_level.txt"
+cp "${distdir}/PKG-INFO" "${distdir}/dbus_python.egg-info/PKG-INFO"
+
+( cd "${distdir}" && find . -type d -o -print ) | \
+        LC_ALL=C sort | \
+        ${SED} -e 's|^\./||' \
+        > "${distdir}/MANIFEST"
+${SED} -e 's/.*/include &/' < "${distdir}/MANIFEST" > "${distdir}/MANIFEST.in"
+cp "${distdir}/MANIFEST" "${distdir}/dbus_python.egg-info/SOURCES.txt"