From cb007e69a140eb990ba9b2856a6ca211da653d27 Mon Sep 17 00:00:00 2001 From: Andreas Rammhold Date: Mon, 25 Nov 2019 13:23:14 +0100 Subject: [PATCH] stdenv: make symlinks that refer to the same output relative While looking at the graph of all the outputs in my personal binary cache it became obvious that we have a lot of self references within the package set. That isn't an isuse by itself. However it increases the size of the binary cache for every (reproducible) build of a package that carries references to itself. You can no longer deduplicate the outputs since they are all unique. One of the ways to get rid of (a few) references is to rewrite all the symlinks that are currently used to be relative symlinks. Two build of something that didn't really change but carries a self-reference can the be store as the same NAR file again. I quickly hacked together this change to see if that would yield and success. My bash scripting skills are probably not great but so far it seem to somewhat work. --- .../setup-hooks/make-symlinks-relative.sh | 28 +++++++++++++++++++ pkgs/stdenv/generic/default.nix | 1 + 2 files changed, 29 insertions(+) create mode 100644 pkgs/build-support/setup-hooks/make-symlinks-relative.sh diff --git a/pkgs/build-support/setup-hooks/make-symlinks-relative.sh b/pkgs/build-support/setup-hooks/make-symlinks-relative.sh new file mode 100644 index 00000000000..0608d3ca81c --- /dev/null +++ b/pkgs/build-support/setup-hooks/make-symlinks-relative.sh @@ -0,0 +1,28 @@ +fixupOutputHooks+=(_makeSymlinksRelative) + +# For every symlink in $output that refers to another file in $output +# ensure that the symlink is relative. This removes references to the output +# has from the resulting store paths and thus the NAR files. +_makeSymlinksRelative() { + local symlinkTarget + + if [ -n "${dontRewriteSymlinks-}" ]; then + return 0 + fi + + while IFS= read -r -d $'\0' f; do + symlinkTarget=$(readlink "$f") + if [[ "$symlinkTarget"/ != "$prefix"/* ]]; then + # skip this symlink as it doesn't point to $prefix + continue + fi + + if [ ! -e "$symlinkTarget" ]; then + echo "the symlink $f is broken, it points to $symlinkTarget (which is missing)" + fi + + echo "rewriting symlink $f to be relative to $prefix" + ln -snrf "$symlinkTarget" "$f" + + done < <(find $prefix -type l -print0) +} diff --git a/pkgs/stdenv/generic/default.nix b/pkgs/stdenv/generic/default.nix index befeb450997..df2d35d541b 100644 --- a/pkgs/stdenv/generic/default.nix +++ b/pkgs/stdenv/generic/default.nix @@ -53,6 +53,7 @@ let lib = import ../../../lib; in lib.makeOverridable ( let defaultNativeBuildInputs = extraNativeBuildInputs ++ [ ../../build-support/setup-hooks/move-docs.sh + ../../build-support/setup-hooks/make-symlinks-relative.sh ../../build-support/setup-hooks/compress-man-pages.sh ../../build-support/setup-hooks/strip.sh ../../build-support/setup-hooks/patch-shebangs.sh