naersk/default.nix
2019-07-31 15:53:30 +02:00

184 lines
6.1 KiB
Nix

{ lib
, runCommand
, symlinkJoin
, stdenv
, writeText
, llvmPackages
, jq
, rsync
, darwin
, remarshal
, cargo
, rustc
}:
with
{ libb = import ./lib.nix { inherit lib writeText runCommand remarshal; }; };
with
{ defaultBuildAttrs =
{ inherit
llvmPackages
jq
runCommand
lib
darwin
writeText
stdenv
rsync
remarshal
symlinkJoin
cargo
rustc;
};
};
with
{ builtinz =
builtins //
import ./builtins
{ inherit lib writeText remarshal runCommand ; };
};
# Crate building
with rec
{
commonAttrs = src: attrs: rec
{ usePureFromTOML = attrs.usePureFromTOML or true;
cargolock = attrs.cargolock or null;
cargotoml = attrs.cargotoml or null;
cargolock' =
if isNull cargolock then
builtinz.readTOML usePureFromTOML "${src}/Cargo.lock"
else cargolock;
rootCargotoml =
if isNull cargotoml then
builtinz.readTOML usePureFromTOML "${src}/Cargo.toml"
else cargotoml;
# All the Cargo.tomls, including the top-level one
cargotomls =
if builtins.hasAttr "package" rootCargotoml then
[rootCargotoml]
else
with { members = rootCargotoml.workspace.members or []; };
lib.filter (cargotoml:
if builtins.hasAttr "targets" attrs then
lib.elem cargotoml.package.name attrs.targets
else true
) ( map
(member: (builtinz.readTOML usePureFromTOML "${src}/${member}/Cargo.toml"))
members );
# The list of paths to Cargo.tomls. If this is a workspace, the paths
# are the members. Otherwise, there is a single path, ".".
cratePaths =
with rec
{ workspaceMembers = rootCargotoml.workspace.members or null;
};
if isNull workspaceMembers then "."
else lib.concatStringsSep "\n" workspaceMembers;
crateDependencies = libb.mkVersions cargolock';
targetInstructions =
if builtins.hasAttr "targets" attrs then
lib.concatMapStringsSep " " (target: "-p ${target}") attrs.targets
else "";
cargoBuild = attrs.cargoBuild or
"cargo build ${targetInstructions} --$CARGO_BUILD_PROFILE -j $NIX_BUILD_CORES";
};
buildPackageSingleStep = src: attrs:
with (commonAttrs src attrs);
import ./build.nix src
( defaultBuildAttrs //
{ name =
if lib.length cargotomls == 0 then
abort "Found no cargotomls"
else if lib.length cargotomls == 1 then
(lib.head cargotomls).package.name
else
"${(lib.head cargotomls).package.name}-and-others";
version = (lib.head cargotomls).package.version;
inherit cratePaths crateDependencies cargoBuild;
} //
(removeAttrs attrs [ "targets" "usePureFromTOML" ])
);
buildPackageIncremental = src: attrs:
with (commonAttrs src attrs);
with rec
# FIXME: directDependencies should be built on a per-cargotoml basis.
# All dependencies are not available in every member.
# Also, if a dependency is shared between two cargotomls, there's
# (most of the time) no point recompiling it
{ buildDepsScript = writeText "prebuild-script"
''
cat ${builtinz.writeJSON "crates" ((directDependenciesList))} |\
jq -r \
--arg cbp $CARGO_BUILD_PROFILE \
--arg nbc $NIX_BUILD_CORES \
'.[] | "cargo build --\($cbp) -j \($nbc) -p \(.name):\(.version)"' |\
while IFS= read -r c
do
echo "Running build command '$c'"
$c || echo "WARNING: one some dependencies failed to build: $c"
done
'';
isMember = name:
lib.elem name (map (ctoml: ctoml.package.name) cargotomls);
isLocal = v:
! builtins.hasAttr "path" v;
versions =
lib.listToAttrs (
map (v: { name = v.name; value = v.version; })
crateDependencies);
directDependenciesList =
lib.filter (c:
builtins.hasAttr c.name directDependencies) crateDependencies;
directDependencies =
lib.filterAttrs (_: v:
lib.isString v ||
(! builtins.hasAttr "path" v)
) (
lib.foldr (x: y: x // y) {}
(map (cargotoml:
(lib.optionalAttrs (builtins.hasAttr "dependencies" cargotoml)
cargotoml.dependencies) //
(lib.optionalAttrs (builtins.hasAttr "dev-dependencies" cargotoml)
cargotoml.dev-dependencies)
) cargotomls
));
};
buildPackageSingleStep src
((attrs) //
{ builtDependencies =
[(
buildPackageSingleStep (libb.dummySrc src)
(attrs //
{ cargoBuild = "source ${buildDepsScript}";
doCheck = false;
copyBuildArtifacts = true;
cargolock = cargolock';
cargotoml =
{ package = { name = "dummy"; version = "0.0.0"; }; } //
{ dependencies = directDependencies; }
;
name =
if lib.length cargotomls == 0 then
abort "Found no cargotomls"
else if lib.length cargotomls == 1 then
"${(lib.head cargotomls).package.name}-deps"
else
"${(lib.head cargotomls).package.name}-and-others-deps";
})
)];
});
};
{ inherit buildPackageSingleStep buildPackageIncremental crates;
buildPackage = buildPackageIncremental;
}