mirror of
https://github.com/ilyakooo0/nixpkgs.git
synced 2024-11-11 04:02:55 +03:00
Add the replace-dependency build support function.
The use case is to do a deep replacement of a dependency without rebuilding the entire tree. For example, suppose a security hole is found in glibc and a patch released. Ideally, you'd just rebuild everything, but that takes time, space, and CPU that you might not have, so in the mean time you could build a safe version of, say, firefox with: firefox-safe = replace-dependency { drv = firefox; old-dependency = glibc; new-dependency = patched-glibc; }; Building firefox-safe will rebuild glibc, but only do a simple copy/string replacement on all other dependencies of firefox. On my system (MBP 13" mid-2012), after a new glibc had been build building firefox took around 11 seconds. See the comments in the file for more details.
This commit is contained in:
parent
2dd59fc4cf
commit
d1662d7155
80
pkgs/build-support/replace-dependency.nix
Normal file
80
pkgs/build-support/replace-dependency.nix
Normal file
@ -0,0 +1,80 @@
|
||||
{ runCommand, nix, lib }:
|
||||
|
||||
# Replace a single dependency in the requisites tree of drv, propagating
|
||||
# the change all the way up the tree, without a full rebuild. This can be
|
||||
# useful, for example, to patch a security hole in libc and still use your
|
||||
# system safely without rebuilding the world. This should be a short term
|
||||
# solution, as soon as a rebuild can be done the properly rebuild derivation
|
||||
# should be used. The old dependency and new dependency MUST have the same-length
|
||||
# name, and ideally should have close-to-identical directory layout.
|
||||
#
|
||||
# Example: safe-firefox = replace-dependency {
|
||||
# drv = firefox;
|
||||
# old-dependency = glibc;
|
||||
# new-dependency = overrideDerivation glibc (attrs: {
|
||||
# patches = attrs.patches ++ [ ./fix-glibc-hole.patch ];
|
||||
# });
|
||||
# };
|
||||
# This will rebuild glibc with your security patch, then copy over firefox
|
||||
# (and all of its dependencies) without rebuilding further.
|
||||
{ drv, old-dependency, new-dependency }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
references = import (runCommand "references.nix" { exportReferencesGraph = [ "graph" drv ]; } ''
|
||||
(echo {
|
||||
while read path
|
||||
do
|
||||
echo " \"$path\" = ["
|
||||
read count
|
||||
read count
|
||||
while [ "0" != "$count" ]
|
||||
do
|
||||
read ref_path
|
||||
if [ "$ref_path" != "$path" ]
|
||||
then
|
||||
echo " (builtins.storePath $ref_path)"
|
||||
fi
|
||||
count=$(($count - 1))
|
||||
done
|
||||
echo " ];"
|
||||
done < graph
|
||||
echo }) > $out
|
||||
'').outPath;
|
||||
|
||||
discard = builtins.unsafeDiscardStringContext;
|
||||
|
||||
old-storepath = builtins.storePath (discard old-dependency.outPath);
|
||||
|
||||
references-of = drv: getAttr (discard (toString drv)) references;
|
||||
|
||||
depends-on-old = drv: elem old-storepath (references-of drv) ||
|
||||
any depends-on-old (references-of drv);
|
||||
|
||||
drv-name = drv:
|
||||
discard (substring 33 (stringLength (builtins.baseNameOf drv)) (builtins.baseNameOf drv));
|
||||
|
||||
replace-strings = drv: rewritten-drvs: runCommand (drv-name drv) { nixStore = "${nix}/bin/nix-store"; } ''
|
||||
$nixStore --dump ${drv} | sed 's|${baseNameOf drv}|'$(basename $out)'|g' | sed -e ${
|
||||
concatStringsSep " -e " (mapAttrsToList (name: value:
|
||||
"'s|${baseNameOf name}|${baseNameOf value}|g'"
|
||||
) rewritten-drvs)
|
||||
} | $nixStore --restore $out
|
||||
'';
|
||||
|
||||
fn = { drv, rewritten-drvs }: rewritten-drvs // (
|
||||
if depends-on-old drv
|
||||
then listToAttrs [ {
|
||||
name = discard (toString drv);
|
||||
|
||||
value = replace-strings drv (rewritten-drvs // (fold (drv: acc:
|
||||
(fn { inherit drv rewritten-drvs; }) // acc
|
||||
) {} (references-of drv)));
|
||||
} ]
|
||||
else {}
|
||||
);
|
||||
in assert (stringLength old-dependency.name == stringLength new-dependency.name); getAttr (discard drv.outPath) (fn {
|
||||
inherit drv;
|
||||
rewritten-drvs = listToAttrs [ {name = discard old-dependency.outPath; value = new-dependency;} ];
|
||||
})
|
@ -344,6 +344,10 @@ let
|
||||
inherit stdenv;
|
||||
};
|
||||
|
||||
"replace-dependency" = import ../build-support/replace-dependency.nix {
|
||||
inherit runCommand nix lib;
|
||||
};
|
||||
|
||||
nukeReferences = callPackage ../build-support/nuke-references/default.nix { };
|
||||
|
||||
vmTools = import ../build-support/vm/default.nix {
|
||||
|
Loading…
Reference in New Issue
Block a user