From 147a0f5c4d42bad2453afe984c494b78bcaa436f Mon Sep 17 00:00:00 2001 From: Oliver Smith Date: Sun, 6 Aug 2023 20:43:31 +0200 Subject: [PATCH] build: use sccache for rust Cache the compiler output of rust code with sccache, like we use ccache for c code. I've considered using sccache to completely replace ccache since it can cache output of C/C++ code too. But let's not do it for now since ccache doesn't need to run a daemon in the background that needs to be stopped when shutting down / zapping. Also it would need more refactoring. Reviewed-by: Luca Weiss Link: https://lists.sr.ht/~postmarketos/pmbootstrap-devel/%3C20230806184729.4891-5-ollieparanoid@postmarketos.org%3E --- pmb/build/_package.py | 9 ++++++++- pmb/build/init.py | 2 ++ pmb/chroot/shutdown.py | 14 +++++++++++++- pmb/config/__init__.py | 8 +++++--- test/test_build_package.py | 2 ++ 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/pmb/build/_package.py b/pmb/build/_package.py index c5eb151a..486aa127 100644 --- a/pmb/build/_package.py +++ b/pmb/build/_package.py @@ -213,7 +213,10 @@ def init_buildenv(args, apkbuild, arch, strict=False, force=False, cross=None, if not skip_init_buildenv: pmb.build.init(args, suffix) pmb.build.other.configure_abuild(args, suffix) - pmb.build.other.configure_ccache(args, suffix) + if args.ccache: + pmb.build.other.configure_ccache(args, suffix) + if "rust" in depends or "cargo" in depends: + pmb.chroot.apk.install(args, ["sccache"], suffix) if not strict and "pmb:strict" not in apkbuild["options"] and len(depends): pmb.chroot.apk.install(args, depends, suffix) if src: @@ -400,6 +403,10 @@ def run_abuild(args, apkbuild, arch, strict=False, force=False, cross=None, if not args.ccache: env["CCACHE_DISABLE"] = "1" + # Use sccache without crossdirect (crossdirect uses it via rustc.sh) + if args.ccache and cross != "crossdirect": + env["RUSTC_WRAPPER"] = "/usr/bin/sccache" + # Cache binary objects from go in this path (like ccache) env["GOCACHE"] = "/home/pmos/.cache/go-build" diff --git a/pmb/build/init.py b/pmb/build/init.py index 38bfae5f..5de698bb 100644 --- a/pmb/build/init.py +++ b/pmb/build/init.py @@ -108,6 +108,8 @@ def init_compiler(args, depends, cross, arch): if cross == "crossdirect": cross_pkgs += ["crossdirect"] if "rust" in depends or "cargo" in depends: + if args.ccache: + cross_pkgs += ["sccache"] # crossdirect for rust installs all build dependencies in the # native chroot too, as some of them can be required for building # native macros / build scripts diff --git a/pmb/chroot/shutdown.py b/pmb/chroot/shutdown.py index 23d115ad..20f90604 100644 --- a/pmb/chroot/shutdown.py +++ b/pmb/chroot/shutdown.py @@ -22,6 +22,17 @@ def kill_adb(args): pmb.chroot.root(args, ["adb", "-P", str(port), "kill-server"]) +def kill_sccache(args): + """ + Kill sccache daemon if it's running. Unlike ccache it automatically spawns + a daemon when you call it and exits after some time of inactivity. + """ + port = 4226 + with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock: + if sock.connect_ex(("127.0.0.1", port)) == 0: + pmb.chroot.root(args, ["sccache", "--stop-server"]) + + def shutdown_cryptsetup_device(args, name): """ :param name: cryptsetup device name, usually "pm_crypt" in pmbootstrap @@ -48,8 +59,9 @@ def shutdown_cryptsetup_device(args, name): def shutdown(args, only_install_related=False): - # Stop adb server + # Stop daemons kill_adb(args) + kill_sccache(args) # Umount installation-related paths (order is important!) pmb.helpers.mount.umount_all(args, args.work + diff --git a/pmb/config/__init__.py b/pmb/config/__init__.py index 12be7b1a..098b86ea 100644 --- a/pmb/config/__init__.py +++ b/pmb/config/__init__.py @@ -218,6 +218,7 @@ chroot_mount_bind = { "$WORK/cache_rust": "/mnt/pmbootstrap/rust", "$WORK/config_abuild": "/mnt/pmbootstrap/abuild-config", "$WORK/config_apk_keys": "/etc/apk/keys", + "$WORK/cache_sccache": "/mnt/pmbootstrap/sccache", "$WORK/images_netboot": "/mnt/pmbootstrap/netboot", "$WORK/packages/$CHANNEL": "/mnt/pmbootstrap/packages", } @@ -237,12 +238,13 @@ chroot_mount_bind = { chroot_home_symlinks = { "/mnt/pmbootstrap/abuild-config": "/home/pmos/.abuild", "/mnt/pmbootstrap/ccache": "/home/pmos/.ccache", - "/mnt/pmbootstrap/packages": "/home/pmos/packages/pmos", "/mnt/pmbootstrap/go/gocache": "/home/pmos/.cache/go-build", "/mnt/pmbootstrap/go/gomodcache": "/home/pmos/go/pkg/mod", - "/mnt/pmbootstrap/rust/registry/index": "/home/pmos/.cargo/registry/index", - "/mnt/pmbootstrap/rust/registry/cache": "/home/pmos/.cargo/registry/cache", + "/mnt/pmbootstrap/packages": "/home/pmos/packages/pmos", "/mnt/pmbootstrap/rust/git/db": "/home/pmos/.cargo/git/db", + "/mnt/pmbootstrap/rust/registry/cache": "/home/pmos/.cargo/registry/cache", + "/mnt/pmbootstrap/rust/registry/index": "/home/pmos/.cargo/registry/index", + "/mnt/pmbootstrap/sccache": "/home/pmos/.cache/sccache", } # Device nodes to be created in each chroot. Syntax for each entry: diff --git a/test/test_build_package.py b/test/test_build_package.py index 800ff609..f9cc73c5 100644 --- a/test/test_build_package.py +++ b/test/test_build_package.py @@ -274,6 +274,7 @@ def test_run_abuild(args, monkeypatch): output = "armhf/test-1-r2.apk" env = {"CARCH": "armhf", "GOCACHE": "/home/pmos/.cache/go-build", + "RUSTC_WRAPPER": "/usr/bin/sccache", "SUDO_APK": "abuild-apk --no-progress"} cmd = ["abuild", "-D", "postmarketOS", "-d"] assert func(args, apkbuild, "armhf") == (output, cmd, env) @@ -285,6 +286,7 @@ def test_run_abuild(args, monkeypatch): # cross=native env = {"CARCH": "armhf", "GOCACHE": "/home/pmos/.cache/go-build", + "RUSTC_WRAPPER": "/usr/bin/sccache", "SUDO_APK": "abuild-apk --no-progress", "CROSS_COMPILE": "armv6-alpine-linux-musleabihf-", "CC": "armv6-alpine-linux-musleabihf-gcc"}