Merge pull request #4 from nmattia/nm-wip-3

Avoid IFD as much as possible
This commit is contained in:
Nicolas Mattia 2019-08-02 11:00:30 +02:00 committed by GitHub
commit 5834403f4f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 209 additions and 80 deletions

View file

@ -17,8 +17,8 @@ src:
, buildInputs ? [] , buildInputs ? []
, nativeBuildInputs ? [] , nativeBuildInputs ? []
, builtDependencies ? [] , builtDependencies ? []
, cargolockPath ? null , cargolock ? null
, cargotomlPath ? null , cargotoml ? null
, release ? true , release ? true
, stdenv , stdenv
, lib , lib
@ -37,23 +37,34 @@ src:
with with
{ builtinz = { builtinz =
builtins // builtins //
import ./builtins.nix import ./builtins
{ inherit lib writeText remarshal runCommand ; }; { inherit lib writeText remarshal runCommand ; };
}; };
with rec with rec
{ {
drv = stdenv.mkDerivation drv = stdenv.mkDerivation (
{ inherit { inherit
src src
doCheck doCheck
nativeBuildInputs nativeBuildInputs
cargolockPath
cargotomlPath
cratePaths cratePaths
name name
version; version;
cargoconfig = builtinz.toTOML
{ source =
{ crates-io = { replace-with = "nix-sources"; } ;
nix-sources =
{ directory = symlinkJoin
{ name = "crates-io";
paths = map (v: unpackCrate v.name v.version v.sha256)
crateDependencies;
};
};
};
};
outputs = [ "out" ] ++ lib.optional doDoc "doc"; outputs = [ "out" ] ++ lib.optional doDoc "doc";
preInstallPhases = lib.optional doDoc [ "docPhase" ]; preInstallPhases = lib.optional doDoc [ "docPhase" ];
@ -88,24 +99,24 @@ with rec
'' ''
runHook preConfigure runHook preConfigure
if [ -n "$cargolockPath" ] if [ -n "$cargolock" ]
then then
echo "Setting Cargo.lock" echo "Setting Cargo.lock"
if [ -f "Cargo.lock" ] if [ -f "Cargo.lock" ]
then then
echo "WARNING: replacing existing Cargo.lock" echo "WARNING: replacing existing Cargo.lock"
fi fi
cp --no-preserve mode "$cargolockPath" Cargo.lock echo "$cargolock" > Cargo.lock
fi fi
if [ -n "$cargotomlPath" ] if [ -n "$cargotoml" ]
then then
echo "Setting Cargo.toml" echo "Setting Cargo.toml"
if [ -f "Cargo.toml" ] if [ -f "Cargo.toml" ]
then then
echo "WARNING: replacing existing Cargo.toml" echo "WARNING: replacing existing Cargo.toml"
fi fi
cp "$cargotomlPath" Cargo.toml echo "$cargotoml" > Cargo.toml
fi fi
mkdir -p target mkdir -p target
@ -127,7 +138,7 @@ with rec
export CARGO_HOME=''${CARGO_HOME:-$PWD/.cargo-home} export CARGO_HOME=''${CARGO_HOME:-$PWD/.cargo-home}
mkdir -p $CARGO_HOME mkdir -p $CARGO_HOME
cp --no-preserve mode ${cargoconfig} $CARGO_HOME/config echo "$cargoconfig" > $CARGO_HOME/config
# TODO: figure out why "1" works whereas "0" doesn't # TODO: figure out why "1" works whereas "0" doesn't
find . -type f -exec touch --date=@1 {} + find . -type f -exec touch --date=@1 {} +
@ -209,7 +220,13 @@ with rec
runHook postInstall runHook postInstall
''; '';
}; } //
lib.optionalAttrs (! isNull cargolock )
{ cargolock = builtinz.toTOML cargolock; } //
lib.optionalAttrs (! isNull cargotoml )
{ cargotoml = builtinz.toTOML cargotoml; }
)
;
# XXX: the actual crate format is not documented but in practice is a # XXX: the actual crate format is not documented but in practice is a
# gzipped tar; we simply unpack it and introduce a ".cargo-checksum.json" # gzipped tar; we simply unpack it and introduce a ".cargo-checksum.json"
@ -227,18 +244,5 @@ with rec
tar -xvzf ${crate} -C $out tar -xvzf ${crate} -C $out
echo '{"package":"${sha256}","files":{}}' > $out/${name}-${version}/.cargo-checksum.json echo '{"package":"${sha256}","files":{}}' > $out/${name}-${version}/.cargo-checksum.json
''; '';
cargoconfig = builtinz.writeTOML
{ source =
{ crates-io = { replace-with = "nix-sources"; } ;
nix-sources =
{ directory = symlinkJoin
{ name = "crates-io";
paths = map (v: unpackCrate v.name v.version v.sha256)
crateDependencies;
};
};
};
};
}; };
if isNull override then drv else drv.overrideAttrs override if isNull override then drv else drv.overrideAttrs override

View file

@ -1,36 +1,33 @@
# some extra "builtins" # some extra "builtins"
{ lib, writeText, runCommand, remarshal }: { lib
, writeText
, runCommand
, remarshal
}:
rec
{ {
# Nix < 2.3 cannot parse all TOML files toTOML = import ./to-toml.nix { inherit lib; };
# https://github.com/NixOS/nix/issues/2901 writeTOML = attrs: writeText "write-toml" (toTOML attrs);
# can then be replaced with:
# readTOML = f: builtins.fromTOML (builtins.readFile f);
readTOML = f: builtins.fromJSON (builtins.readFile (runCommand "read-toml"
{ buildInputs = [ remarshal ];
allowSubstitutes = false;
preferLocalBuild = true;
}
''
remarshal \
-if toml \
-i ${f} \
-of json \
-o $out
''));
writeTOML = attrs: runCommand "write-toml" readTOML = usePure: f:
{ buildInputs = [ remarshal ]; if usePure then
allowSubstitutes = false; builtins.fromTOML (builtins.readFile f)
preferLocalBuild = true; else
} builtins.fromJSON (builtins.readFile (
'' runCommand "from-toml"
remarshal \ { buildInputs = [ remarshal ];
-if json \ allowSubstitutes = false;
-i ${writeText "toml-json" (builtins.toJSON attrs)} \ preferLocalBuild = true;
-of toml \ }
-o $out ''
''; echo "$from_toml_in" > in.toml
remarshal \
-if toml \
-i ${f} \
-of json \
-o $out
''));
writeJSON = name: attrs: writeText name writeJSON = name: attrs: writeText name
(builtins.toJSON attrs); (builtins.toJSON attrs);

130
builtins/to-toml.nix Normal file
View file

@ -0,0 +1,130 @@
{ lib }:
let
inherit (lib)
length
elemAt
concatMap
all
concatLists
concatStringsSep
concatMapStringsSep
mapAttrsToList
;
inherit (builtins)
abort
match
toJSON
typeOf
;
quoteKey = k:
if match "[a-zA-Z]+" k == []
then k
else quoteString k;
quoteString = builtins.toJSON;
outputValInner = v:
let ty = tomlTy v; in
if ty == "set" then
let
vals = mapAttrsToList
(k': v': "${quoteKey k'} = ${outputValInner v'}") v;
valsStr = concatStringsSep ", " vals;
in
"{ ${valsStr} }" else
outputVal v;
outputVal = v:
let ty = tomlTy v; in
if ty == "bool" then
builtins.toJSON v
else
if ty == "string" then
quoteString v
else
if ty == "list" || ty == "list_of_attrs" then
let
vals = map quoteString v;
valsStr = concatStringsSep ", " vals;
in
"[ ${valsStr} ]" else
if ty == "set" then
abort "unsupported set for not-inner value"
else abort "Not implemented: type ${ty}"
;
outputKeyValInner = k: v:
let ty = tomlTy v; in
if ty == "set" then
let
vals = mapAttrsToList
(k': v': "${quoteKey k'} = ${outputValInner v'}") v;
valsStr = concatStringsSep ", " vals;
in
[ "${quoteKey k} = { ${valsStr} }" ] else
outputKeyVal k v;
# Returns a list of strings; one string per line
outputKeyVal = k: v:
let ty = tomlTy v; in
if ty == "bool" then
[ "${quoteKey k} = ${outputValInner v}" ]
else
if ty == "string" then
[ "${quoteKey k} = ${quoteString v}" ]
else
if ty == "list_of_attrs" then
concatMap (inner:
[ "[[${k}]]" ] ++
(concatLists (mapAttrsToList outputKeyValInner inner))) v
else
if ty == "list" then
let
vals = map quoteString v;
valsStr = concatStringsSep ", " vals;
in
[ "${quoteKey k} = [ ${valsStr} ]" ] else
if ty == "set" then
[ "[${k}]" ] ++
(concatLists (mapAttrsToList outputKeyValInner v))
else abort "Not implemented: type ${ty} for key ${k}"
;
tomlTy = x:
if typeOf x == "string" then "string" else
if typeOf x == "bool" then "bool" else
if typeOf x == "int" then "int" else
if typeOf x == "float" then "float" else
if typeOf x == "set" then
if lib.isDerivation x then "string" else "set" else
if typeOf x == "list" then
if length x == 0 then "list"
else
let ty = typeOf (elemAt x 0); in
#assert (all (v: typeOf v == ty) x);
if ty == "set" then "list_of_attrs" else "list"
else abort "Not implemented: toml type for ${typeOf x}";
toTOML = attrs:
assert (typeOf attrs == "set");
let
byTy = lib.foldl
(acc: x:
let ty = tomlTy x.v; in
acc // { "${ty}" = (acc.${ty} or []) ++ [ x ]; }
)
{} (mapAttrsToList (k: v: { inherit k v ; }) attrs);
in
concatMapStringsSep "\n"
(kv: concatStringsSep "\n" (outputKeyVal kv.k kv.v))
( (byTy.string or []) ++
(byTy.int or []) ++
(byTy.float or []) ++
(byTy.list or []) ++
(byTy.list_of_attrs or []) ++
(byTy.set or [])
)
;
in
toTOML

View file

@ -36,7 +36,7 @@ with
with with
{ builtinz = { builtinz =
builtins // builtins //
import ./builtins.nix import ./builtins
{ inherit lib writeText remarshal runCommand ; }; { inherit lib writeText remarshal runCommand ; };
}; };
@ -44,18 +44,17 @@ with
with rec with rec
{ {
commonAttrs = src: attrs: rec commonAttrs = src: attrs: rec
{ cargolockPath = attrs.cargolockPath or null; { usePureFromTOML = attrs.usePureFromTOML or true;
cargotomlPath = attrs.cargotomlPath or null; cargolock = attrs.cargolock or null;
cargolock = cargotoml = attrs.cargotoml or null;
if isNull cargolockPath then cargolock' =
builtinz.readTOML "${src}/Cargo.lock" if isNull cargolock then
else builtinz.readTOML usePureFromTOML "${src}/Cargo.lock"
builtinz.readTOML cargolockPath; else cargolock;
rootCargotoml = rootCargotoml =
if isNull cargotomlPath then if isNull cargotoml then
builtinz.readTOML "${src}/Cargo.toml" builtinz.readTOML usePureFromTOML "${src}/Cargo.toml"
else else cargotoml;
builtinz.readTOML cargotomlPath;
# All the Cargo.tomls, including the top-level one # All the Cargo.tomls, including the top-level one
cargotomls = cargotomls =
@ -68,7 +67,7 @@ with rec
lib.elem cargotoml.package.name attrs.targets lib.elem cargotoml.package.name attrs.targets
else true else true
) ( map ) ( map
(member: (builtinz.readTOML "${src}/${member}/Cargo.toml")) (member: (builtinz.readTOML usePureFromTOML "${src}/${member}/Cargo.toml"))
members ); members );
# The list of paths to Cargo.tomls. If this is a workspace, the paths # The list of paths to Cargo.tomls. If this is a workspace, the paths
@ -80,7 +79,7 @@ with rec
if isNull workspaceMembers then "." if isNull workspaceMembers then "."
else lib.concatStringsSep "\n" workspaceMembers; else lib.concatStringsSep "\n" workspaceMembers;
crateDependencies = libb.mkVersions cargolock; crateDependencies = libb.mkVersions cargolock';
targetInstructions = targetInstructions =
if builtins.hasAttr "targets" attrs then if builtins.hasAttr "targets" attrs then
lib.concatMapStringsSep " " (target: "-p ${target}") attrs.targets lib.concatMapStringsSep " " (target: "-p ${target}") attrs.targets
@ -102,7 +101,7 @@ with rec
version = (lib.head cargotomls).package.version; version = (lib.head cargotomls).package.version;
inherit cratePaths crateDependencies cargoBuild; inherit cratePaths crateDependencies cargoBuild;
} // } //
(removeAttrs attrs [ "targets"]) (removeAttrs attrs [ "targets" "usePureFromTOML" ])
); );
buildPackageIncremental = src: attrs: buildPackageIncremental = src: attrs:
@ -163,12 +162,10 @@ with rec
{ cargoBuild = "source ${buildDepsScript}"; { cargoBuild = "source ${buildDepsScript}";
doCheck = false; doCheck = false;
copyBuildArtifacts = true; copyBuildArtifacts = true;
cargolockPath = builtinz.writeTOML cargolock; cargolock = cargolock';
cargotomlPath = builtinz.writeTOML cargotoml =
(
{ package = { name = "dummy"; version = "0.0.0"; }; } // { package = { name = "dummy"; version = "0.0.0"; }; } //
{ dependencies = directDependencies; } { dependencies = directDependencies; }
)
; ;
name = name =
if lib.length cargotomls == 0 then if lib.length cargotomls == 0 then

View file

@ -2,7 +2,7 @@
with with
{ builtinz = { builtinz =
builtins // builtins //
import ./builtins.nix import ./builtins
{ inherit lib writeText remarshal runCommand ; }; { inherit lib writeText remarshal runCommand ; };
}; };
rec rec

View file

@ -15,7 +15,7 @@ with rec
}; };
with with
{ builtinz = builtins // pkgs.callPackage ./builtins.nix {}; }; { builtinz = builtins // pkgs.callPackage ./builtins {}; };
rec rec
{ rustfmt = naersk.buildPackage sources.rustfmt {}; { rustfmt = naersk.buildPackage sources.rustfmt {};
@ -23,7 +23,7 @@ rec
{ buildInputs = [ rustfmt ]; } { buildInputs = [ rustfmt ]; }
"rustfmt --help && cargo-fmt --help && touch $out"; "rustfmt --help && cargo-fmt --help && touch $out";
ripgrep = naersk.buildPackage sources.ripgrep {}; ripgrep = naersk.buildPackage sources.ripgrep { usePureFromTOML = false; };
# XXX: executables are missing # XXX: executables are missing
#ripgrep_test = pkgs.runCommand "ripgrep-test" #ripgrep_test = pkgs.runCommand "ripgrep-test"
#{ buildInputs = [ ripgrep ]; } #{ buildInputs = [ ripgrep ]; }
@ -98,7 +98,8 @@ rec
cargo = cargo =
with rec with rec
{ cargoSrc = sources.cargo; { cargoSrc = sources.cargo;
cargoCargoToml = builtinz.readTOML "${cargoSrc}/Cargo.toml"; # cannot use the pure readTOML
cargoCargoToml = builtinz.readTOML false "${cargoSrc}/Cargo.toml";
# XXX: this works around some hack that breaks the build. For more info # XXX: this works around some hack that breaks the build. For more info
# on the hack, see # on the hack, see
@ -109,11 +110,11 @@ rec
cargoCargoToml.dependencies; cargoCargoToml.dependencies;
}; };
cargoCargoLock = "${sources.rust}/Cargo.lock"; cargoCargoLock = builtinz.readTOML true "${sources.rust}/Cargo.lock";
}; };
naersk.buildPackage cargoSrc naersk.buildPackage cargoSrc
{ cargolockPath = cargoCargoLock; { cargolock = cargoCargoLock;
cargotomlPath = builtinz.writeTOML cargoCargoToml'; cargotoml = cargoCargoToml';
# Tests fail, although cargo seems to operate normally # Tests fail, although cargo seems to operate normally
doCheck = false; doCheck = false;