Skip to content

Support bazel-central-registry's rules_perl on nixos #80

@shixiong-jiang

Description

@shixiong-jiang

Hello rules_perl owner,

I have a question about rule_perl .
(I did post this question under bazelbuild/bazel-central-registry#3565 too)
We are using bazel to compile cc under nix system.
However, the rule_perl is broken.

You can reproduce it with a nix docker container.

1. Launch a nix docker container on Linux

mkdir /tmp/example; cd /tmp/example

## 1.1. Create a nix config.
## I installed the `pkgs.libcrypt` at first. 
## However, it only has `libcrypt.so.2`, but `rule_perl` built perl wants `libcrypto.so.1`. Only `libxcrypt-legacy` includes it.
## See https://search.nixos.org/packages?channel=unstable&show=libxcrypt-legacy&from=0&size=50&sort=relevance&type=packages&query=libxcrypt

## Here, I also ask nix to install perl by itself. So, we can compare nix install perl vs rule_perl.

cat <<EOF > default.nix
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
  buildInputs = [
    pkgs.vim
    pkgs.bazel_7
    pkgs.libxcrypt-legacy
    pkgs.perl
  ];
}
EOF

## 1.2. create an example
cat <<EOF > MODULE.bazel
bazel_dep(name = "rules_perl", version = "0.2.5")
bazel_dep(name = "openssl", version = "3.3.1.bcr.1")
EOF

## 1.3. Start a nix docker container

sudo docker run --rm \
  -v /tmp/example:/tmp/example \
  --name my-nix-container -it nixos/nix bash

2. Within the nix, bazel build

cd /tmp/example
nix-channel --update
nix-shell
bazel build --sandbox_debug  @openssl//:all

It fails with this error

/nix/store/fd118hwh7d1ncib4mdw56ylv3g9k0iyj-bash-5.2p37/bin/bash: line 3: external/rules_perl~~perl_repositories~perl_linux_amd64/bin/perl: cannot execute: required file not found

3. Debug

3.1. Run perl directly. It fails too.

## Path is copied from `bazel build --sandbox_debug`'s output 
/root/.cache/bazel/_bazel_root/89a35363ec8de7131a16c2ed7419999a/sandbox/processwrapper-sandbox/48/execroot/_main/external/rules_perl~~perl_repositories~perl_linux_amd64/bin/perl

ldd the perl, libcrypt.so.1 is not found.

ldd /root/.cache/bazel/_bazel_root/89a35363ec8de7131a16c2ed7419999a/sandbox/processwrapper-sandbox/48/execroot/_main/external/rules_perl~~perl_repositories~perl_linux_amd64/bin/perl
	linux-vdso.so.1 (0x00007f508cbdf000)
	libpthread.so.0 => /nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib/libpthread.so.0 (0x00007f508cbd4000)
	libdl.so.2 => /nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib/libdl.so.2 (0x00007f508cbcf000)
	libm.so.6 => /nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib/libm.so.6 (0x00007f508cae6000)
	libcrypt.so.1 => not found
	libutil.so.1 => /nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib/libutil.so.1 (0x00007f508cadf000)
	libc.so.6 => /nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib/libc.so.6 (0x00007f508c800000)
	/lib64/ld-linux-x86-64.so.2 => /nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib64/ld-linux-x86-64.so.2 (0x00007f508cbe1000)

3.2. set LD_LIBRARY_PATH to include libcrypt.so.1

ls /nix/store/*libxcrypt*/lib

Output

/nix/store/d550hx0zzirlbww967k0d0xs8asrb3ia-libxcrypt-4.4.38/lib:
libcrypt.la  libcrypt.so  libcrypt.so.2  libcrypt.so.2.0.0  pkgconfig

/nix/store/flvyd9qpx5gk6pr9l7ki0s841cx717ny-libxcrypt-4.4.36/lib:
libcrypt.la  libcrypt.so  libcrypt.so.2  libcrypt.so.2.0.0  pkgconfig

/nix/store/hcsh4083lvy8sim1ry04r83czfz1r1h6-libxcrypt-4.4.38/lib:
libcrypt.la  libcrypt.so  libcrypt.so.1  libcrypt.so.1.1.0  libxcrypt.so  pkgconfig

Only /nix/store/hcsh4083lvy8sim1ry04r83czfz1r1h6-libxcrypt-4.4.38/lib has libcrypt.so.1. Use it.

(export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/nix/store/hcsh4083lvy8sim1ry04r83czfz1r1h6-libxcrypt-4.4.38/lib; ldd /root/.cache/bazel/_bazel_root/89a35363ec8de7131a16c2ed7419999a/sandbox/processwrapper-sandbox/48/execroot/_main/external/rules_perl~~perl_repositories~perl_linux_amd64/bin/perl)

ldd output looks fine.

	linux-vdso.so.1 (0x00007f5c64300000)
	libpthread.so.0 => /nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib/libpthread.so.0 (0x00007f5c642f5000)
	libdl.so.2 => /nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib/libdl.so.2 (0x00007f5c642f0000)
	libm.so.6 => /nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib/libm.so.6 (0x00007f5c64207000)
	libcrypt.so.1 => /nix/store/hcsh4083lvy8sim1ry04r83czfz1r1h6-libxcrypt-4.4.38/lib/libcrypt.so.1 (0x00007f5c641cb000)
	libutil.so.1 => /nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib/libutil.so.1 (0x00007f5c641c4000)
	libc.so.6 => /nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib/libc.so.6 (0x00007f5c63e00000)
	/lib64/ld-linux-x86-64.so.2 => /nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib64/ld-linux-x86-64.so.2 (0x00007f5c64302000)

3.3. try perl again with LD_LIBRARY_PATH

However, perl still fail

(export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/nix/store/hcsh4083lvy8sim1ry04r83czfz1r1h6-libxcrypt-4.4.38/lib; /root/.cache/bazel/_bazel_root/89a35363ec8de7131a16c2ed7419999a/sandbox/processwrapper-sandbox/48/execroot/_main/external/rules_perl~~perl_repositories~perl_linux_amd64/bin/perl)

Output

bash: /root/.cache/bazel/_bazel_root/89a35363ec8de7131a16c2ed7419999a/sandbox/processwrapper-sandbox/48/execroot/_main/external/rules_perl~~perl_repositories~perl_linux_amd64/bin/perl: cannot execute: required file not found

4. Root cause

readelf -Wl /root/.cache/bazel/_bazel_root/2190073a42434474a8b7f2bcd3c924b6/sandbox/processwrapper-sandbox/48/execroot/_main/external/rules_perl~~perl_repositories~perl_linux_amd64/bin/perl | grep "Requesting program interpreter"

Output

      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

It should be related to the path of the interpreter.
It is supposed to be /nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib64/ld-linux-x86-64.so.2.

Explicitly add the /nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib64/ld-linux-x86-64.so.2 in front of perl, works

/nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib64/ld-linux-x86-64.so.2 /root/.cache/bazel/_bazel_root/2190073a42434474a8b7f2bcd3c924b6/sandbox/processwrapper-sandbox/48/execroot/_main/external/rules_perl~~perl_repositories~perl_linux_amd64/bin/perl -v

Output

This is perl 5, version 36, subversion 0 (v5.36.0) built for x86_64-linux
...

5. Do you have any idea how to fix it?

A tricky workaround

Adding /nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib64/ld-linux-x86-64.so.2 in front of bazel build command doesn't help for sure.

patchelf changes the GLIBC path. It fixes the perl, but this option is too trivial.

patchelf --set-interpreter \
  /nix/store/81mi7m3k3wsiz9rrrg636sx21psj20hc-glibc-2.40-66/lib64/ld-linux-x86-64.so.2 \
  /root/.cache/bazel/_bazel_root/2190073a42434474a8b7f2bcd3c924b6/sandbox/processwrapper-sandbox/48/execroot/_main/external/rules_perl~~perl_repositories~perl_linux_amd64/bin/perl

I think the right way to make perl also load the correct GLIBC when compile.
I went through perl's bazel-central-registry code, but I didn't figure out how to fix it.

Thanks a lot

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions