1{
2 lib,
3 stdenv,
4 bintools-unwrapped,
5 llvmPackages,
6 coreutils,
7}:
8
9if stdenv.hostPlatform.isStatic then
10 throw ''
11 libredirect is not available on static builds.
12
13 Please fix your derivation to not depend on libredirect on static
14 builds, using something like following:
15
16 nativeBuildInputs =
17 lib.optional (!stdenv.buildPlatform.isStatic) libredirect;
18
19 and disable tests as necessary, although fixing tests to work without
20 libredirect is even better.
21
22 libredirect uses LD_PRELOAD feature of dynamic loader and does not
23 work on static builds where dynamic loader is not used.
24 ''
25else
26 stdenv.mkDerivation {
27 pname = "libredirect";
28 version = "0";
29
30 unpackPhase = ''
31 cp ${./libredirect.c} libredirect.c
32 cp ${./test.c} test.c
33 '';
34
35 outputs = [
36 "out"
37 "hook"
38 ];
39
40 libName = "libredirect" + stdenv.hostPlatform.extensions.sharedLibrary;
41
42 buildPhase = ''
43 runHook preBuild
44
45 ${
46 if stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64 then
47 ''
48 # We need the unwrapped binutils and clang:
49 # We also want to build a fat library with x86_64, arm64, arm64e in there.
50 # Because we use the unwrapped tools, we need to provide -isystem for headers
51 # and the library search directory for libdl.
52 # We can't build this on x86_64, because the libSystem we point to doesn't
53 # like arm64(e).
54 PATH=${bintools-unwrapped}/bin:${llvmPackages.clang-unwrapped}/bin:$PATH \
55 clang -arch x86_64 -arch arm64 -arch arm64e \
56 -isystem "$SDKROOT/usr/include" \
57 -isystem ${lib.getLib llvmPackages.libclang}/lib/clang/*/include \
58 "-L$SDKROOT/usr/lib" \
59 -Wl,-install_name,$out/lib/$libName \
60 -Wall -std=c99 -O3 -fPIC libredirect.c \
61 -shared -o "$libName"
62 ''
63 else if stdenv.hostPlatform.isDarwin then
64 ''
65 $CC -Wall -std=c99 -O3 -fPIC libredirect.c \
66 -Wl,-install_name,$out/lib/$libName \
67 -shared -o "$libName"
68 ''
69 else
70 ''
71 $CC -Wall -std=c99 -O3 -fPIC libredirect.c \
72 -shared -o "$libName"
73 ''
74 }
75
76 if [ -n "$doInstallCheck" ]; then
77 $CC -Wall -std=c99 \
78 ${lib.optionalString (!stdenv.hostPlatform.isDarwin) "-D_GNU_SOURCE"} \
79 -O3 test.c -o test
80 fi
81
82 runHook postBuild
83 '';
84
85 # We want to retain debugging info to be able to use GDB on libredirect.so
86 # to more easily investigate which function overrides are missing or why
87 # existing ones do not have the intended effect.
88 dontStrip = true;
89
90 installPhase = ''
91 runHook preInstall
92
93 install -vD "$libName" "$out/lib/$libName"
94
95 ''
96 + lib.optionalString (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64) ''
97 # dylib will be rejected unless dylib rpath gets explicitly set
98 install_name_tool \
99 -change $libName $out/lib/$libName \
100 $out/lib/$libName
101 ''
102 + ''
103 # Provide a setup hook that injects our library into every process.
104 mkdir -p "$hook/nix-support"
105 cat <<SETUP_HOOK > "$hook/nix-support/setup-hook"
106 echo "Setting up libredirect"
107 ${
108 if stdenv.hostPlatform.isDarwin then
109 ''
110 export DYLD_INSERT_LIBRARIES="$out/lib/$libName"
111 ''
112 else
113 ''
114 export LD_PRELOAD="$out/lib/$libName"
115 ''
116 }
117 SETUP_HOOK
118
119 runHook postInstall
120 '';
121
122 doInstallCheck = true;
123
124 installCheckPhase = ''
125 (
126 source "$hook/nix-support/setup-hook"
127 NIX_REDIRECTS="/foo/bar/test=${coreutils}/bin/true:/bar/baz=$(mktemp -d)" ./test
128 )
129 '';
130
131 meta = with lib; {
132 platforms = platforms.unix;
133 description = "LD_PRELOAD library to intercept and rewrite the paths in glibc calls";
134 longDescription = ''
135 libredirect is an LD_PRELOAD library to intercept and rewrite the paths in
136 glibc calls based on the value of $NIX_REDIRECTS, a colon-separated list
137 of path prefixes to be rewritten, e.g. "/src=/dst:/usr/=/nix/store/".
138 '';
139 };
140 }