about summary refs log tree commit diff
path: root/pkgs/test/ld-library-path/default.nix
blob: 74c52cef25328c1700ceaf2bbd1bca5001c310ee (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
{ lib, stdenv }:

# This tests that libraries listed in LD_LIBRARY_PATH take precedence over those listed in RPATH.

let
  # A simple test library: libgreeting.so which exports a single function getGreeting() returning the good old hello greeting.
  libgreeting = stdenv.mkDerivation {
    name = "libgreeting";

    code = ''
      const char* getGreeting() { return "Hello, world!"; }
    '';

    unpackPhase = ''
      echo "$code" > libgreeting.c
    '';

    installPhase = ''
      mkdir -p $out/lib
      $CC -c -fpic libgreeting.c
      $CC -shared libgreeting.o -o $out/lib/libgreeting.so
    '';
  };

  # A variant of libgreeting.so that returns a different message.
  libgoodbye = libgreeting.overrideAttrs (_: {
    name = "libgoodbye";
    code = ''
      const char* getGreeting() { return "Goodbye, world!"; }
    '';
  });

  # A simple consumer of libgreeting.so that just prints the greeting to stdout.
  testProgram = stdenv.mkDerivation {
    name = "greeting-test";

    buildInputs = [ libgreeting ];

    code = ''
      #include <stdio.h>

      extern const char* getGreeting(void);

      int main() {
        puts(getGreeting());
      }
    '';

    unpackPhase = ''
      echo "$code" > greeting-test.c
    '';

    installPhase = ''
      mkdir -p $out/bin
      $CC -c greeting-test.c
      $CC greeting-test.o -lgreeting -o $out/bin/greeting-test

      # Now test the installed binaries right after compiling them. In particular,
      # don't do this in installCheckPhase because fixupPhase has been run by then!
      (
        export PATH=$out/bin
        set -x

        # Verify that our unmodified binary works as expected.
        [ "$(greeting-test)" = "Hello, world!" ]

        # And finally, test that a library in LD_LIBRARY_PATH takes precedence over the linked-in library.
        [ "$(LD_LIBRARY_PATH=${libgoodbye}/lib greeting-test)" = "Goodbye, world!" ]
      )
    '';

  };
in stdenv.mkDerivation {
  name = "test-LD_LIBRARY_PATH";
  nativeBuildInputs = [ testProgram ];

  buildCommand = ''
    # And for good measure, repeat the tests again from a separate derivation,
    # as fixupPhase done by the stdenv can (and has!) affect the result.

    [ "$(greeting-test)" = "Hello, world!" ]
    [ "$(LD_LIBRARY_PATH=${libgoodbye}/lib greeting-test)" = "Goodbye, world!" ]

    touch $out
  '';

  meta.platforms = lib.platforms.linux;
}