75 lines
2.7 KiB
Nix
75 lines
2.7 KiB
Nix
buildArgs@{ nixpkgs ? <nixpkgs>, pkgs ? import nixpkgs {}, lib ? import ./lib.nix { inherit pkgs; }, root, filter ? [] }:
|
|
let
|
|
inherit (lib) searchPath whichdo d1 d2 getSrc;
|
|
|
|
resolve = path: let
|
|
builder = (whichdo path);
|
|
in if builder == "" then throw "No rule to build ${path}"
|
|
else runBuilder (d1 path builder) (d2 path builder) builder;
|
|
|
|
runBuilder = d1: d2: builder:
|
|
with pkgs.lib;
|
|
with builtins;
|
|
let
|
|
|
|
# CWD relative to source root
|
|
rcwd = dirOf (removePrefix (root + "/") builder);
|
|
|
|
# Funktionalise pkgs; our main entry point to resolve default*nix build
|
|
# scripts.
|
|
funcPkgs = {
|
|
__functor = self: arg: resolve arg;
|
|
src = getSrc root rcwd filter resolve id;
|
|
inherit pkgs rcwd d1 d2;
|
|
# Convenience function that calculates the source tree, links it to src
|
|
# and cd's to the location of the current builder.
|
|
S = getSrc root rcwd filter resolve (src: ''
|
|
ln -s ${src} src
|
|
cd src/${rcwd}
|
|
'');
|
|
};
|
|
|
|
_builder = let
|
|
imported = (tryEval (let
|
|
# Needs to be done as nix chokes on empty files rn.
|
|
# Potential source of memory exhaustion for untrusted very large *.do files!
|
|
content = readFile builder;
|
|
in assert content != "" && (! (hasPrefix "#!" content)); import builder));
|
|
in if imported.success
|
|
then imported.value
|
|
else {
|
|
src = getSrc (/. + root);
|
|
builder = ''
|
|
#!/bin/sh
|
|
set -e
|
|
pout=$(mktemp -u -p $PWD)
|
|
cp -r --reflink=auto --no-preserve=mode "$src/" src
|
|
cd src/${rcwd}
|
|
${/. + builder} "$d1" "$d2" "$out" >$pout
|
|
if [ -e "$out" -a -s "$pout" ]; then
|
|
printf "Error: %s wrote to stdout and created \$3\n" "${baseNameOf builder}" >&2
|
|
exit 207
|
|
elif [ -s $pout ]; then
|
|
mv $pout $out
|
|
fi
|
|
'';
|
|
};
|
|
__builder = if isFunction _builder then _builder funcPkgs
|
|
else _builder;
|
|
|
|
args = { stdenv = pkgs.stdenvNoCC; } // (if isString __builder
|
|
then { builder = __builder; }
|
|
else __builder);
|
|
|
|
drv = (args.deriver or args.stdenv.mkDerivation) ({
|
|
name = pkgs.lib.strings.sanitizeDerivationName d1;
|
|
buildCommand = args.builder;
|
|
passAsFile = [ "buildCommand" ];
|
|
preferLocalBuild = true;
|
|
allowSubstitutes = false;
|
|
outputs = [ "out" ];
|
|
inherit d1 d2;
|
|
} // (removeAttrs args [ "builder" "system" "deriver" "stdenv" "outputs" ]));
|
|
in drv; # myself
|
|
in resolve
|