f8d67ec135
One issue with cargoSha256 is that it's hard to detect when it needs to be updated or not. It's possible to upgrade a package and forget to update cargoSha256 and run with old versions of the program or libraries. This commit introduces `verifyCargoDeps` which, when enabled, will check that the Cargo.lock is not out of date in the cargoDeps by comparing it with the package source.
185 lines
5.3 KiB
Nix
185 lines
5.3 KiB
Nix
{ stdenv, cacert, git, cargo, rustc, fetchcargo, buildPackages, windows }:
|
|
|
|
{ name ? "${args.pname}-${args.version}"
|
|
, cargoSha256 ? "unset"
|
|
, src ? null
|
|
, srcs ? null
|
|
, cargoPatches ? []
|
|
, patches ? []
|
|
, sourceRoot ? null
|
|
, logLevel ? ""
|
|
, buildInputs ? []
|
|
, nativeBuildInputs ? []
|
|
, cargoUpdateHook ? ""
|
|
, cargoDepsHook ? ""
|
|
, cargoBuildFlags ? []
|
|
, # Set to true to verify if the cargo dependencies are up to date.
|
|
# This will change the value of cargoSha256.
|
|
verifyCargoDeps ? false
|
|
, buildType ? "release"
|
|
, meta ? {}
|
|
|
|
, cargoVendorDir ? null
|
|
, ... } @ args:
|
|
|
|
assert cargoVendorDir == null -> cargoSha256 != "unset";
|
|
assert buildType == "release" || buildType == "debug";
|
|
|
|
let
|
|
cargoDeps = if cargoVendorDir == null
|
|
then fetchcargo {
|
|
inherit name src srcs sourceRoot cargoUpdateHook;
|
|
copyLockfile = verifyCargoDeps;
|
|
patches = cargoPatches;
|
|
sha256 = cargoSha256;
|
|
}
|
|
else null;
|
|
|
|
setupVendorDir = if cargoVendorDir == null
|
|
then ''
|
|
unpackFile "$cargoDeps"
|
|
cargoDepsCopy=$(stripHash $(basename $cargoDeps))
|
|
chmod -R +w "$cargoDepsCopy"
|
|
''
|
|
else ''
|
|
cargoDepsCopy="$sourceRoot/${cargoVendorDir}"
|
|
'';
|
|
|
|
hostConfig = stdenv.hostPlatform.config;
|
|
|
|
rustHostConfig = {
|
|
x86_64-pc-mingw32 = "x86_64-pc-windows-gnu";
|
|
}.${hostConfig} or hostConfig;
|
|
|
|
ccForBuild="${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}cc";
|
|
cxxForBuild="${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}c++";
|
|
ccForHost="${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
|
|
cxxForHost="${stdenv.cc}/bin/${stdenv.cc.targetPrefix}c++";
|
|
releaseDir = "target/${rustHostConfig}/${buildType}";
|
|
in
|
|
|
|
stdenv.mkDerivation (args // {
|
|
inherit cargoDeps;
|
|
|
|
patchRegistryDeps = ./patch-registry-deps;
|
|
|
|
nativeBuildInputs = nativeBuildInputs ++ [ cacert git cargo rustc ];
|
|
buildInputs = buildInputs ++ stdenv.lib.optional stdenv.hostPlatform.isMinGW windows.pthreads;
|
|
|
|
patches = cargoPatches ++ patches;
|
|
|
|
PKG_CONFIG_ALLOW_CROSS =
|
|
if stdenv.buildPlatform != stdenv.hostPlatform then 1 else 0;
|
|
|
|
postUnpack = ''
|
|
eval "$cargoDepsHook"
|
|
|
|
${setupVendorDir}
|
|
|
|
mkdir .cargo
|
|
config="$(pwd)/$cargoDepsCopy/.cargo/config";
|
|
if [[ ! -e $config ]]; then
|
|
config=${./fetchcargo-default-config.toml};
|
|
fi;
|
|
substitute $config .cargo/config \
|
|
--subst-var-by vendor "$(pwd)/$cargoDepsCopy"
|
|
|
|
cat >> .cargo/config <<'EOF'
|
|
[target."${stdenv.buildPlatform.config}"]
|
|
"linker" = "${ccForBuild}"
|
|
${stdenv.lib.optionalString (stdenv.buildPlatform.config != stdenv.hostPlatform.config) ''
|
|
[target."${rustHostConfig}"]
|
|
"linker" = "${ccForHost}"
|
|
${# https://github.com/rust-lang/rust/issues/46651#issuecomment-433611633
|
|
stdenv.lib.optionalString (stdenv.hostPlatform.isMusl && stdenv.hostPlatform.isAarch64) ''
|
|
"rustflags" = [ "-C", "target-feature=+crt-static", "-C", "link-arg=-lgcc" ]
|
|
''}
|
|
''}
|
|
EOF
|
|
|
|
unset cargoDepsCopy
|
|
export RUST_LOG=${logLevel}
|
|
'' + stdenv.lib.optionalString verifyCargoDeps ''
|
|
if ! diff source/Cargo.lock $cargoDeps/Cargo.lock ; then
|
|
echo
|
|
echo "ERROR: cargoSha256 is out of date."
|
|
echo
|
|
echo "Cargo.lock is not the same in $cargoDeps."
|
|
echo
|
|
echo "To fix the issue:"
|
|
echo '1. Use "1111111111111111111111111111111111111111111111111111" as the cargoSha256 value'
|
|
echo "2. Build the derivation and wait it to fail with a hash mismatch"
|
|
echo "3. Copy the 'got: sha256:' value back into the cargoSha256 field"
|
|
echo
|
|
|
|
exit 1
|
|
fi
|
|
'' + (args.postUnpack or "");
|
|
|
|
configurePhase = args.configurePhase or ''
|
|
runHook preConfigure
|
|
runHook postConfigure
|
|
'';
|
|
|
|
buildPhase = with builtins; args.buildPhase or ''
|
|
runHook preBuild
|
|
|
|
(
|
|
set -x
|
|
env \
|
|
"CC_${stdenv.buildPlatform.config}"="${ccForBuild}" \
|
|
"CXX_${stdenv.buildPlatform.config}"="${cxxForBuild}" \
|
|
"CC_${stdenv.hostPlatform.config}"="${ccForHost}" \
|
|
"CXX_${stdenv.hostPlatform.config}"="${cxxForHost}" \
|
|
cargo build \
|
|
${stdenv.lib.optionalString (buildType == "release") "--release"} \
|
|
--target ${rustHostConfig} \
|
|
--frozen ${concatStringsSep " " cargoBuildFlags}
|
|
)
|
|
|
|
# rename the output dir to a architecture independent one
|
|
mapfile -t targets < <(find "$NIX_BUILD_TOP" -type d | grep '${releaseDir}$')
|
|
for target in "''${targets[@]}"; do
|
|
rm -rf "$target/../../${buildType}"
|
|
ln -srf "$target" "$target/../../"
|
|
done
|
|
|
|
runHook postBuild
|
|
'';
|
|
|
|
checkPhase = args.checkPhase or ''
|
|
runHook preCheck
|
|
echo "Running cargo test"
|
|
cargo test
|
|
runHook postCheck
|
|
'';
|
|
|
|
doCheck = args.doCheck or true;
|
|
|
|
inherit releaseDir;
|
|
|
|
installPhase = args.installPhase or ''
|
|
runHook preInstall
|
|
mkdir -p $out/bin $out/lib
|
|
|
|
find $releaseDir \
|
|
-maxdepth 1 \
|
|
-type f \
|
|
-executable ! \( -regex ".*\.\(so.[0-9.]+\|so\|a\|dylib\)" \) \
|
|
-print0 | xargs -r -0 cp -t $out/bin
|
|
find $releaseDir \
|
|
-maxdepth 1 \
|
|
-regex ".*\.\(so.[0-9.]+\|so\|a\|dylib\)" \
|
|
-print0 | xargs -r -0 cp -t $out/lib
|
|
rmdir --ignore-fail-on-non-empty $out/lib $out/bin
|
|
runHook postInstall
|
|
'';
|
|
|
|
passthru = { inherit cargoDeps; } // (args.passthru or {});
|
|
|
|
meta = {
|
|
# default to Rust's platforms
|
|
platforms = rustc.meta.platforms;
|
|
} // meta;
|
|
})
|