1{ lib, stdenv }:
2
3# This tests that libraries listed in LD_LIBRARY_PATH take precedence over those listed in RPATH.
4
5let
6 # A simple test library: libgreeting.so which exports a single function getGreeting() returning the good old hello greeting.
7 libgreeting = stdenv.mkDerivation {
8 name = "libgreeting";
9
10 code = ''
11 const char* getGreeting() { return "Hello, world!"; }
12 '';
13
14 unpackPhase = ''
15 echo "$code" > libgreeting.c
16 '';
17
18 installPhase = ''
19 mkdir -p $out/lib
20 $CC -c -fpic libgreeting.c
21 $CC -shared libgreeting.o -o $out/lib/libgreeting.so
22 '';
23 };
24
25 # A variant of libgreeting.so that returns a different message.
26 libgoodbye = libgreeting.overrideAttrs (_: {
27 name = "libgoodbye";
28 code = ''
29 const char* getGreeting() { return "Goodbye, world!"; }
30 '';
31 });
32
33 # A simple consumer of libgreeting.so that just prints the greeting to stdout.
34 testProgram = stdenv.mkDerivation {
35 name = "greeting-test";
36
37 buildInputs = [ libgreeting ];
38
39 code = ''
40 #include <stdio.h>
41
42 extern const char* getGreeting(void);
43
44 int main() {
45 puts(getGreeting());
46 }
47 '';
48
49 unpackPhase = ''
50 echo "$code" > greeting-test.c
51 '';
52
53 installPhase = ''
54 mkdir -p $out/bin
55 $CC -c greeting-test.c
56 $CC greeting-test.o -lgreeting -o $out/bin/greeting-test
57
58 # Now test the installed binaries right after compiling them. In particular,
59 # don't do this in installCheckPhase because fixupPhase has been run by then!
60 (
61 export PATH=$out/bin
62 set -x
63
64 # Verify that our unmodified binary works as expected.
65 [ "$(greeting-test)" = "Hello, world!" ]
66
67 # And finally, test that a library in LD_LIBRARY_PATH takes precedence over the linked-in library.
68 [ "$(LD_LIBRARY_PATH=${libgoodbye}/lib greeting-test)" = "Goodbye, world!" ]
69 )
70 '';
71
72 };
73in
74stdenv.mkDerivation {
75 name = "test-LD_LIBRARY_PATH";
76 nativeBuildInputs = [ testProgram ];
77
78 buildCommand = ''
79 # And for good measure, repeat the tests again from a separate derivation,
80 # as fixupPhase done by the stdenv can (and has!) affect the result.
81
82 [ "$(greeting-test)" = "Hello, world!" ]
83 [ "$(LD_LIBRARY_PATH=${libgoodbye}/lib greeting-test)" = "Goodbye, world!" ]
84
85 touch $out
86 '';
87
88 meta.platforms = lib.platforms.linux;
89}