commit 37d34b3a262cea358fd4c6927676f0c1727bea5c
parent d358770be147ec76b406b0cce36d207fbfa54df5
Author: Florian Dold <florian@dold.me>
Date: Tue, 25 Nov 2025 15:54:30 +0100
cross-arch builds
Diffstat:
2 files changed, 104 insertions(+), 82 deletions(-)
diff --git a/packaging/ng/buildscripts/generic b/packaging/ng/buildscripts/generic
@@ -36,17 +36,17 @@ def make_version(deb_version, build_codename):
def main():
- # unset LD_LIBRARY_PATH
if 'LD_LIBRARY_PATH' in os.environ:
del os.environ['LD_LIBRARY_PATH']
# Arguments
- if len(sys.argv) < 2:
- print("Usage: script.py <PACKAGE> [CODENAME]", file=sys.stderr)
+ if len(sys.argv) < 3:
+ print("Usage: script.py <PACKAGE> <CODENAME> <ARCH>", file=sys.stderr)
sys.exit(1)
PACKAGE = sys.argv[1]
- CODENAME = sys.argv[2] if len(sys.argv) > 2 else ""
+ CODENAME = sys.argv[3]
+ ARCH = sys.argv[3]
# Path of the debian/ folder in the repository
DEBIANPATH = ""
@@ -156,8 +156,8 @@ def main():
shutil.copy(f, "/pkgdir/")
# Save built filenames
- built_current_path = f"/pkgdir/{PACKAGE}.built.current"
- with open(built_current_path, 'w') as f: # 'w' mimics truncate -s0
+ built_current_path = f"/pkgdir/{PACKAGE}@{ARCH}.built.current"
+ with open(built_current_path, 'w') as f:
for deb in deb_files:
f.write(os.path.basename(deb) + "\n")
for ddeb in ddeb_files:
@@ -217,7 +217,7 @@ def main():
sys.exit(2)
# Finalize tag
- with open(f"/pkgdir/{PACKAGE}.built.tag", "w") as f:
+ with open(f"/pkgdir/{PACKAGE}@{ARCH}.built.tag", "w") as f:
f.write(TAG + "\n")
if __name__ == "__main__":
diff --git a/packaging/ng/taler-pkg b/packaging/ng/taler-pkg
@@ -6,7 +6,7 @@
import argparse
import subprocess
-from dataclasses import dataclass
+import platform
import os
import sys
from pathlib import Path
@@ -20,7 +20,9 @@ from util import Dpkg
mydir = os.path.dirname(os.path.realpath(__file__))
+archs = ["arm64", "amd64"]
host = "taler.net"
+native_arch = "amd64" if platform.machine().lower() in ("x86_64", "amd64") else "arm64"
components = [
"gnunet",
@@ -33,7 +35,7 @@ components = [
"taler-rust",
"robocop",
"taler-wallet-cli",
- "depolymerization",
+ #"depolymerization",
# These two packages don't have good debs yet,
# Debian complains "No section given for ..., skipping.
# "taler-directory",
@@ -108,12 +110,12 @@ def propagate_outdated(outdated):
return closure
-def find_outdated(pkgdir, roots):
+def find_outdated(pkgdir, arch, roots):
"""Find outdated components based on tag files"""
outdated = set()
for component in roots:
ver_requested = open(f"buildconfig/{component}.tag").read().strip()
- built_tag_file = pkgdir / f"{component}.built.tag"
+ built_tag_file = pkgdir / f"{component}@{arch}.built.tag"
ver_built = None
if built_tag_file.exists():
ver_built = open(built_tag_file).read().strip()
@@ -131,7 +133,7 @@ def build(cfg):
vendor, codename = distro.split("-", 1)
print("building", distro)
dockerfile = f"distros/Dockerfile.{distro}"
- image_tag = f"taler-packaging-{distro}:latest"
+ image_tag = f"localhost/taler-packaging-{distro}:latest"
pkgdir = Path(f"packages/{distro}").absolute()
cachedir = Path(f"cache").absolute()
cachedir.mkdir(exist_ok=True)
@@ -141,78 +143,90 @@ def build(cfg):
(cachedir / distro / "apt-archives").mkdir(parents=True, exist_ok=True)
(cachedir / distro / "apt-lists").mkdir(parents=True, exist_ok=True)
+ if cfg.arch is None:
+ arch_list = [native_arch]
+ else:
+ arch_list = cfg.arch.split(",")
+
if not cfg.dry:
- subprocess.run(
- [
- "podman",
- "build",
- "-v",
- f"{cachedir}/{distro}/apt-archives:/var/cache/apt/archives:z",
- "-v",
- f"{cachedir}/{distro}/apt-lists:/var/lib/apt/lists:z",
- "-t",
- image_tag,
- "-f",
- dockerfile,
- ],
- check=True,
- )
+ for arch in arch_list:
+ subprocess.run(
+ [
+ "podman",
+ "build",
+ "--arch",
+ arch,
+ "-v",
+ f"{cachedir}/{distro}/apt-archives:/var/cache/apt/archives:z",
+ "-v",
+ f"{cachedir}/{distro}/apt-lists:/var/lib/apt/lists:z",
+ "-t",
+ image_tag,
+ "-f",
+ dockerfile,
+ ],
+ check=True,
+ )
# Sort components by their dependencies
buildorder = buildsort(components)
print("build order:", buildorder)
- outdated = find_outdated(pkgdir, buildorder)
+ for arch in arch_list:
+ outdated = find_outdated(pkgdir, arch, buildorder)
- # Propagate outdatedness to dependees
- closure = propagate_outdated(outdated)
+ # Propagate outdatedness to dependees
+ closure = propagate_outdated(outdated)
- print("outdated closure", closure)
+ print("outdated closure", closure)
- for component in buildorder:
- if transitive:
- if component not in closure:
- continue
- else:
- if component not in outdated:
- continue
- print("building", component)
- pkgdir.mkdir(parents=True, exist_ok=True)
- cmd = [
- "podman",
- "run",
- "-it",
- "--entrypoint=/bin/python3",
- "--security-opt",
- "label=disable",
- "--mount",
- f"type=bind,source={cachedir}/cargo-registry,target=/root/.cargo/registry",
- "--mount",
- f"type=bind,source={cachedir}/cargo-git,target=/root/.cargo/git",
- "--mount",
- f"type=bind,source={cachedir}/cargo-build,target=/root/.cargo-build",
- "--env",
- "CARGO_BUILD_BUILD_DIR=/root/.cargo-build",
- "--mount",
- f"type=bind,source={cachedir}/{distro}/apt-archives,target=/var/cache/apt/archives,relabel=shared",
- "--mount",
- f"type=bind,source={cachedir}/{distro}/apt-lists,target=/var/lib/apt/lists,relabel=shared",
- "--mount",
- f"type=bind,source={mydir}/buildscripts,target=/buildscripts,readonly",
- "--mount",
- f"type=bind,source={mydir}/buildconfig,target=/buildconfig,readonly",
- "--mount",
- f"type=bind,source={pkgdir},target=/pkgdir",
- image_tag,
- "/buildscripts/generic",
- component,
- codename,
- ]
- if not cfg.dry:
- subprocess.run(
- cmd,
- check=True,
- )
+ for component in buildorder:
+ if transitive:
+ if component not in closure:
+ continue
+ else:
+ if component not in outdated:
+ continue
+ print("building", component)
+ pkgdir.mkdir(parents=True, exist_ok=True)
+ cmd = [
+ "podman",
+ "run",
+ "-it",
+ "--arch",
+ arch,
+ "--entrypoint=/bin/python3",
+ "--security-opt",
+ "label=disable",
+ "--mount",
+ f"type=bind,source={cachedir}/cargo-registry,target=/root/.cargo/registry",
+ "--mount",
+ f"type=bind,source={cachedir}/cargo-git,target=/root/.cargo/git",
+ "--mount",
+ f"type=bind,source={cachedir}/cargo-build,target=/root/.cargo-build",
+ "--env",
+ "CARGO_BUILD_BUILD_DIR=/root/.cargo-build",
+ "--mount",
+ f"type=bind,source={cachedir}/{distro}/apt-archives,target=/var/cache/apt/archives,relabel=shared",
+ "--mount",
+ f"type=bind,source={cachedir}/{distro}/apt-lists,target=/var/lib/apt/lists,relabel=shared",
+ "--mount",
+ f"type=bind,source={mydir}/buildscripts,target=/buildscripts,readonly",
+ "--mount",
+ f"type=bind,source={mydir}/buildconfig,target=/buildconfig,readonly",
+ "--mount",
+ f"type=bind,source={pkgdir},target=/pkgdir",
+ image_tag,
+ "/buildscripts/generic",
+ component,
+ codename,
+ arch,
+ ]
+ if not cfg.dry:
+ subprocess.run(
+ cmd,
+ check=True,
+ )
def show_order(cfg):
@@ -291,13 +305,14 @@ def publish(cfg):
)
server_debs = server_debs_str.split()
for component in components:
- current = None
- cf = Path(f"./packages/{distro}/{component}.built.current")
- if not cf.exists():
- print(f"component {component} has no current packages")
- continue
- with open(f"./packages/{distro}/{component}.built.current") as f:
- current = f.read().split()
+ current = []
+ for arch in archs + ["all"]:
+ cf = Path(f"./packages/{distro}/{component}@{arch}.built.current")
+ if not cf.exists():
+ print(f"component {component}@{arch} has no current packages")
+ continue
+ with open(cf) as f:
+ current = current + f.read().split()
print("current", current)
for deb in current:
if deb.endswith(".deb"):
@@ -478,6 +493,13 @@ def main():
default=None,
)
parser_build.add_argument(
+ "--arch",
+ help="Architecture(s) to build for",
+ action="store",
+ dest="arch",
+ default=None,
+ )
+ parser_build.add_argument(
"--dry", help="Dry run", action="store_true", default=False
)