From 5dcf2a533bb08a63a8f452fd9ad66fabd91c7ab3 Mon Sep 17 00:00:00 2001 From: Colin Date: Thu, 10 Aug 2023 09:45:44 +0000 Subject: [PATCH] WIP: try to cross-compile using proot instead of binfmt but it doesn't seem to be emulating child processes... --- overlays/cross.nix | 57 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/overlays/cross.nix b/overlays/cross.nix index 07b5c595..8dbce127 100644 --- a/overlays/cross.nix +++ b/overlays/cross.nix @@ -84,7 +84,7 @@ let # so hack its components into something which *does* handle cross compilation lib.overrideDerivation pkg ({ builder, args, ... }: { builder = "${final.buildPackages.bash}/bin/sh"; - args = ["-e" (final.buildPackages.vmTools.vmRunCommand qemuCommandLinux)]; + args = [ "-e" (final.buildPackages.vmTools.vmRunCommand qemuCommandLinux) ]; # orig{Builder,Args} gets used by the vmRunCommand script: origBuilder = builder; origArgs = args; @@ -98,12 +98,44 @@ let override = attrs: emulateBuilder (pkg.override attrs); overrideAttrs = mergeFn: emulateBuilder (pkg.overrideAttrs mergeFn); } - # alternatively, `proot` could let us get per-package binfmt: - # - - # - i.e., execute host programs *and* build programs, mixed ; - emulateBuildMachine = + # given a package that's defined for build == host, + # build it from a "proot": a chroot-like environment where `exec` is hooked to invoke qemu instead. + # this is like binfmt, but configured to run *only* the emulated host and not the build machine + # see: + # hinted at by: + emulateBuilderProot = pkg: + lib.overrideDerivation pkg ({ builder, args, ... }: { + builder = "${final.buildPackages.bash}/bin/sh"; + args = [ "-e" prootBuilder ]; + origBuilder = builder; + origArgs = args; + + enableParallelBuilding = true; # TODO: inherit from `pkg`? + NIX_DEBUG = "6"; + + # finally, let nix know that this package should be built by the build system + system = final.stdenv.buildPlatform.system; + }) // { + override = attrs: emulateBuilderProot (pkg.override attrs); + overrideAttrs = mergeFn: emulateBuilderProot (pkg.overrideAttrs mergeFn); + }; + + prootBuilder = let + proot = "${final.buildPackages.proot}/bin/proot"; + # prootFlags = "-r / -b /:/"; + prootFlags = "-b /nix:/nix -b /tmp:/tmp"; + # prootFlags = "-b /:/ -b ${final.bash}/bin/sh:/bin/sh"; # --mixed-mode false + qemu = "${final.buildPackages.qemu}/bin/qemu-aarch64"; + in + final.pkgs.writeText "proot-run" '' + echo "proot: ${proot} -q ${qemu} ${prootFlags} $origBuilder $origArgs" + ${proot} -q ${qemu} ${prootFlags} $origBuilder $origArgs + echo "exited proot" + ''; + + buildOnHost = let # patch packages which can't ordinarily exist in buildPackages preFixPkg = p: @@ -122,7 +154,7 @@ let unsplicePkg = p: p.__spliced.hostTarget or p; unsplicePkgs = ps: map (p: unsplicePkg (preFixPkg p)) ps; in - pkg: emulateBuilder ((pkg.override { + pkg: (pkg.override { inherit (emulated) stdenv; }).overrideAttrs (upstream: { # for this purpose, the naming in `depsAB` is "inputs build for A, used to create packages in B" (i think). @@ -141,7 +173,10 @@ let nativeCheckInputs = unsplicePkgs (upstream.nativeCheckInputs or []); nativeInstallCheckInputs = unsplicePkgs (upstream.nativeInstallCheckInputs or []); - })); + }); + + emulateBuildMachine = pkg: emulateBuilder (buildOnHost pkg); + buildInProot = pkg: emulateBuilderProot (buildOnHost pkg); in { inherit emulated; @@ -352,7 +387,7 @@ in { unwrapped = super.unwrapped // { browserpass-extension = super.unwrapped.browserpass-extension.override { # this overlay is optional for binfmt machines, but non-binfmt can't cross-compile the modules (for use at runtime) - mkYarnModules = args: emulateBuildMachine { + mkYarnModules = args: buildInProot { override = { stdenv }: ( (final.yarn2nix-moretea.override { pkgs = final.pkgs.__splicedPackages // { inherit stdenv; }; @@ -791,7 +826,7 @@ in { koreader = (prev.koreader.override { # fixes runtime error: luajit: ./ffi/util.lua:757: attempt to call field 'pack' (a nil value) # inherit (emulated) luajit; - luajit = emulateBuildMachine (final.luajit.override { + luajit = buildInProot (final.luajit.override { buildPackages.stdenv = emulated.stdenv; # it uses buildPackages.stdenv for HOST_CC }); }).overrideAttrs (upstream: { @@ -802,7 +837,7 @@ in { koreader-from-src = prev.koreader-from-src.override { # fixes runtime error: luajit: ./ffi/util.lua:757: attempt to call field 'pack' (a nil value) # inherit (emulated) luajit; - luajit = emulateBuildMachine (final.luajit.override { + luajit = buildInProot (final.luajit.override { buildPackages.stdenv = emulated.stdenv; # it uses buildPackages.stdenv for HOST_CC }); }; @@ -1651,7 +1686,7 @@ in { tangram = (prev.tangram.override { # N.B. blueprint-compiler is in nativeBuildInputs. # the trick here is to force the aarch64 versions to be used during build (via emulation), - blueprint-compiler = emulateBuildMachine (final.blueprint-compiler.overrideAttrs (upstream: { + blueprint-compiler = buildInProot (final.blueprint-compiler.overrideAttrs (upstream: { # default is to propagate gobject-introspection *as a buildInput*, when it's supposed to be native. propagatedBuildInputs = []; # "Namespace Gtk not available"