Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reproduce guix pack -RR #18

Open
SomeoneSerge opened this issue Mar 21, 2024 · 3 comments
Open

Reproduce guix pack -RR #18

SomeoneSerge opened this issue Mar 21, 2024 · 3 comments

Comments

@SomeoneSerge
Copy link

SomeoneSerge commented Mar 21, 2024

Provide a flake "bundler" recovering the approach described in https://hpc.guix.info/blog/2020/05/faster-relocatable-packs-with-fakechroot/:

@tomberek
Copy link
Collaborator

@SomeoneSerge Put this together a few days ago. Patchelf and replaceDependency a new glibc into place that will read $PREFIX/etc/ld.so.cache that is pre-populated using the contents of writeClosure.

with import <nixpkgs> { };
let
  wrap =
    drv:
    let
      # Remove rpath from all binaries and set new interpreter with cache
      new_drv = runCommand "${drv.name}-wrapped" { nativeBuildInputs = [ pkgs.patchelfUnstable ]; } ''
        mkdir $out
        ln -st $out ${drv}/*
        rm -rf $out/bin
        mkdir -p $out/bin
        cp -r ${drv}/bin/* $out/bin/.
        chmod +w $out/bin/*
        for f in $out/bin/*; do
          patchelf --remove-rpath $f || true
          patchelf --set-interpreter ${new_glibc}/lib/${
            if drv.system == "x86_64-linux"
            then "ld-linux-x86-64.so.2"
            else "ld-linux-aarch64.so.1" } $f || true
        done
      '';

      # Replace self-references in glibc
      new_glibc = replaceDependency {
        drv = new_glibc_pre;
        oldDependency = glibc.out;
        newDependency = new_glibc_pre;
      };

      # Create a new glibc derivation that has a targetet ld.so.cache
      new_glibc_pre = buildEnv {
        name = pkgs.glibc.out.name;
        paths = [
          (pkgs.runCommand "something" { nativeBuildInputs = [ pkgs.glibc.bin ]; } ''
            mkdir $out
            mkdir -p $out/etc
            mkdir -p $out/lib
            cp -R ${glibc.out}/* $out/

            chmod +w $out/etc

            cat ${pkgs.writeClosure drv} \
            | xargs printf "%s\n" \
            | xargs -I{} find {} -iname "lib*.so*" -execdir pwd \; \
            | sort -u > $out/etc/ld.so.conf

            ldconfig -f $out/etc/ld.so.conf -C $out/etc/ld.so.cache
          '')
        ];
      };
    in
    new_drv;
in
builtins.mapAttrs (name: drv: wrap (pkgs.lib.getBin drv)) pkgs

@tomberek
Copy link
Collaborator

the loader supporting a "LD_CACHE_FILE" or similar would allow this to not require a such a wrapping

@SomeoneSerge
Copy link
Author

AFAIU this implements a per-dso cache while reusing cache.nixos.org. How does this help with relocatability however?

P.S. Side note: I had struggled to figure out how to properly use replaceDependency and this is the first working example that I see. I expect transitive/propagated dependencies are still linking to the unwrapped interpreters?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants