cross work
Some checks failed
CI / checks (push) Failing after 3s

This commit is contained in:
Robin Appelman 2024-09-26 18:09:03 +02:00
commit f4380e5341
4 changed files with 180 additions and 1 deletions

38
crossArgs.nix Normal file
View file

@ -0,0 +1,38 @@
{ callPackage, pkgsCross, stdenv, lib }:
let
inherit (lib) mapAttrs hasInfix replaceStrings toUpper concatStrings recursiveUpdate;
isMusl = hasInfix "-musl";
crossOpts = callPackage ./crossOpts.nix { };
buildCrossArgs = target: { targetDeps ? [ ]
, rustFlags ? (if isMusl target then "-C target-feature=+crt-static" else "")
, cFlags ? ""
, targetStdenv
, ...
} @ args:
let
isHostTarget = targetStdenv.targetPlatform.config == stdenv.targetPlatform.config;
# don't use the pkgsCross cc if the target is the host platform
targetCc = if isHostTarget then stdenv.cc else targetStdenv.cc;
targetUnderscore = replaceStrings [ "-" ] [ "_" ] target;
targetUpperCase = toUpper targetUnderscore;
rest = removeAttrs args [ "rustFlags" "cc" "cFlags" "targetDeps" "targetStdenv" "nativeBuildInputs" ];
# by adding the dependency in the (target specific) linker args instead of buildInputs
# we can prevent it trying to link to it for host build dependencies
rustFlagsWithDeps = rustFlags + concatStrings (map (targetDep: " -Clink-arg=-L${targetDep}/lib") targetDeps);
in
(
{
nativeBuildInputs = (args.nativeBuildInputs or [ ]) ++ [ targetCc stdenv.cc ];
"CARGO_TARGET_${targetUpperCase}_RUSTFLAGS" = rustFlagsWithDeps;
"CARGO_TARGET_${targetUpperCase}_LINKER" = "${targetCc.targetPrefix}cc";
"AR_${targetUnderscore}" = "${targetCc.targetPrefix}ar";
"CC_${targetUnderscore}" = "${targetCc.targetPrefix}cc";
"CCX_${targetUnderscore}" = "${targetCc.targetPrefix}ccx";
"HOST_CC" = "${stdenv.cc.targetPrefix}cc";
"CFLAGS_${targetUnderscore}" = cFlags;
} //
rest
);
in
target: buildCrossArgs target crossOpts.${target}

53
crossOpts.nix Normal file
View file

@ -0,0 +1,53 @@
{ pkgsCross, perl, callPackage, freebsdCross }:
let
freebsdSysrootX86 = callPackage ./freebsd-sysroot.nix {
arch = "amd64";
sha256 = "sha256-/XZXt0bPI9bTXrD+TR2KYzhE7wKpVAvKndWL3tqe5cg=";
version = freebsdCross.versionData.revision;
};
in
{
"armv7-unknown-linux-musleabihf" = {
targetStdenv = pkgsCross.muslpi.stdenv;
};
"armv7-unknown-linux-gnueabihf" = {
targetStdenv = pkgsCross.armv7l-hf-multiplatform.stdenv;
};
"aarch64-unknown-linux-gnu" = {
targetStdenv = pkgsCross.aarch64-multiplatform.stdenv;
};
"aarch64-unknown-linux-musl" = {
targetStdenv = pkgsCross.aarch64-multiplatform-musl.stdenv;
cFlags = "-mno-outline-atomics";
};
"i686-unknown-linux-musl" = {
targetStdenv = pkgsCross.musl32.stdenv;
};
"i686-unknown-linux-gnu" = {
targetStdenv = pkgsCross.gnu32.stdenv;
};
"x86_64-pc-windows-gnu" = {
targetStdenv = pkgsCross.mingwW64.stdenv;
# rink wants perl for windows targets
buildInputs = [ perl ];
targetDeps = [ pkgsCross.mingwW64.windows.pthreads ];
rustFlags = "-C target-feature=+crt-static";
BINARY_SUFFIX = ".exe";
};
"x86_64-unknown-freebsd" = {
targetStdenv = pkgsCross.x86_64-freebsd.stdenv;
targetDeps = [ freebsdSysrootX86 ];
dontPatchELF = true;
postInstall = ''
patchelf --set-interpreter /libexec/ld-elf.so.1 $out/bin/*
'';
X86_64_UNKNOWN_FREEBSD_OPENSSL_DIR = freebsdSysrootX86;
BINDGEN_EXTRA_CLANG_ARGS_x86_64_unknown_freebsd = "--sysroot=${freebsdSysrootX86}";
};
"x86_64-unknown-linux-musl" = {
targetStdenv = pkgsCross.musl64.stdenv;
};
"x86_64-unknown-linux-gnu" = {
targetStdenv = pkgsCross.gnu64.stdenv;
};
}

58
freebsd-sysroot.nix Normal file
View file

@ -0,0 +1,58 @@
{ stdenv
, fetchzip
, arch
, version
, sha256
,
}:
stdenv.mkDerivation {
pname = "freebsd-sysroot";
version = "${version}-${arch}";
src = fetchzip {
url = "https://download.freebsd.org/ftp/releases/${arch}/${version}-RELEASE/base.txz";
stripRoot = false;
inherit sha256;
};
doBuild = false;
dontFixup = true;
installPhase = ''
# adapted from https://github.com/cross-rs/cross/blob/main/docker/freebsd.sh#L184
ls -l
mkdir -p $out/lib/
cp -r "usr/include" "$out"
cp -r "lib/"* "$out/lib"
cp "usr/lib/libc++.so" "$out/lib"
cp "usr/lib/libc++.a" "$out/lib"
cp "usr/lib/libcxxrt.a" "$out/lib"
cp "usr/lib/libcompiler_rt.a" "$out/lib"
cp "usr/lib"/lib{c,util,m,ssp_nonshared,memstat}.a "$out/lib"
cp "usr/lib/librt.so" "$out/lib"
cp "usr/lib"/lib{execinfo,procstat}.so.1 "$out/lib"
cp "usr/lib"/libmemstat.so.3 "$out/lib"
cp "usr/lib"/{crt1,Scrt1,crti,crtn}.o "$out/lib"
cp "usr/lib"/libkvm.a "$out/lib"
local lib=
local base=
local link=
for lib in "''${out}/lib/"*.so.*; do
base=$(basename "''${lib}")
link="''${base}"
# not strictly necessary since this will always work, but good fallback
while [[ "''${link}" == *.so.* ]]; do
link="''${link%.*}"
done
# just extra insurance that we won't try to overwrite an existing file
local dstlink="''${out}/lib/''${link}"
if [[ -n "''${link}" ]] && [[ "''${link}" != "''${base}" ]] && [[ ! -f "''${dstlink}" ]]; then
ln -s "''${base}" "''${dstlink}"
fi
done
ln -s libthr.so.3 "''${out}/lib/libpthread.so"
'';
}

View file

@ -5,7 +5,7 @@
{ lib, src, config, flakelight, inputs, ... }:
let
inherit (builtins) elem readFile pathExists isAttrs attrNames;
inherit (lib) mkDefault mkIf mkMerge mkOption warnIf assertMsg optionalAttrs types optionalString;
inherit (lib) map mkDefault mkIf mkMerge mkOption warnIf assertMsg optionalAttrs types optionalString genAttrs hasInfix;
inherit (lib.fileset) fileFilter toSource;
inherit (flakelight.types) fileset;
@ -32,6 +32,10 @@ warnIf (! builtins ? readFileType) "Unsupported Nix version in use."
(file: file.hasExt "rs" || elem file.name ([ "Cargo.toml" "Cargo.lock" ] ++ config.extraFiles))
src;
};
crossTargets = mkOption {
type = with types; listOf str;
default = [ ];
};
};
config = mkMerge [
@ -41,6 +45,7 @@ warnIf (! builtins ? readFileType) "Unsupported Nix version in use."
(final: { inputs, rust-bin, writeShellApplication, stdenvNoCC, ... } @ prev: rec {
crateName = (craneLib.crateNameFromCargoToml { inherit src; }).pname;
craneLib = (inputs.crane.mkLib final).overrideToolchain (p: p.latestRustToolchain);
craneLibForTargets = targets: (inputs.crane.mkLib final).overrideToolchain (p: p.latestRustToolchain.override { inherit targets; });
craneLibMsrv = (inputs.crane.mkLib final).overrideToolchain (p: p.msrvRustToolchain);
cargoArtifacts = craneLib.buildDepsOnly
{
@ -107,6 +112,31 @@ warnIf (! builtins ? readFileType) "Unsupported Nix version in use."
strictDeps = true;
meta = defaultMeta;
};
} // (genAttrs config.crossTargets (
target: { craneLibForTargets, cargoArtifacts, defaultMeta, callPackage, crateName }:
let
targetCraneLib = craneLibForTargets [ target ];
crossArgs = callPackage ./crossArgs.nix {} target;
in
targetCraneLib.buildPackage
({
src = toSource { root = src; inherit (config) fileset; };
doCheck = false;
strictDeps = true;
meta = defaultMeta // {
targetPlatform = target;
binarySuffix = crossArgs.BINARY_SUFFIX or "";
};
pname = "${crateName}-${target}";
cargoExtraArgs = "--target ${target}";
} // crossArgs)
));
outputs = {
crossMatrix = map (target: {
inherit target;
binary-suffix = optionalString (hasInfix "windows" target) ".exe";
}) config.crossTargets;
};
checks =