playing FTL on NIXOS

13 apr 2015

motivation

this posting is about how to get a binary only x86/amd64 game called FTL [1] on nixos. the problem to solve is how to tell the game the proper library locations in the /nix/store!

how to make it work

in order to get the FTL binary to work, you can do either of these possibilities:

  • use patchelf without any use of a .nix expression (ad-hoc solution, very hacky)
  • use LD_LIBRARY_PATH (ad-hoc solution, very hacky)
  • use patchelf from a .nix expression (recommended solution)

with this posting i want to document all three solutions for FTL.

fixing binaries

i’ve been using FTL FTL.1.5.13.tar.gz and i extract it like this:

$ tar xzf FTL.1.5.13.tar.gz

the archive contains:

$ du -a FTL
216         FTL/data/amd64/lib/libILU.so.1
1280        FTL/data/amd64/lib/libIL.so.1
224         FTL/data/amd64/lib/libbass.so
2200        FTL/data/amd64/lib/libfreetype.so.6
100         FTL/data/amd64/lib/libz.so.1
40          FTL/data/amd64/lib/libbassmix.so
528         FTL/data/amd64/lib/libpng12.so.0
56          FTL/data/amd64/lib/libILUT.so.1
2104        FTL/data/amd64/lib/libSDL-1.2.so.0
6752        FTL/data/amd64/lib
216         FTL/data/amd64/bin/libILU.so.1
1280        FTL/data/amd64/bin/libIL.so.1
224         FTL/data/amd64/bin/libbass.so
2200        FTL/data/amd64/bin/libfreetype.so.6
100         FTL/data/amd64/bin/libz.so.1
40          FTL/data/amd64/bin/libbassmix.so
528         FTL/data/amd64/bin/libpng12.so.0
56          FTL/data/amd64/bin/libILUT.so.1
2104        FTL/data/amd64/bin/libSDL-1.2.so.0
3500        FTL/data/amd64/bin/FTL
10252       FTL/data/amd64/bin
17008       FTL/data/amd64
196548      FTL/data/resources/resource.dat
1480        FTL/data/resources/data.dat
4           FTL/data/resources/exe_icon.bmp
198036      FTL/data/resources
180         FTL/data/x86/lib/libILU.so.1
1032        FTL/data/x86/lib/libIL.so.1
212         FTL/data/x86/lib/libbass.so
1792        FTL/data/x86/lib/libfreetype.so.6
96          FTL/data/x86/lib/libz.so.1
36          FTL/data/x86/lib/libbassmix.so
456         FTL/data/x86/lib/libpng12.so.0
48          FTL/data/x86/lib/libILUT.so.1
1856        FTL/data/x86/lib/libSDL-1.2.so.0
5712        FTL/data/x86/lib
3396        FTL/data/x86/bin/FTL
3400        FTL/data/x86/bin
9116        FTL/data/x86
28          FTL/data/licenses/LGPL.txt
4           FTL/data/licenses/README-RapidXML.txt
4           FTL/data/licenses/README-zlib.txt
4           FTL/data/licenses/README-SDL.txt
8           FTL/data/licenses/README-FreeType.txt
4           FTL/data/licenses/README-DevIL.txt
56          FTL/data/licenses
20          FTL/data/exe_icon.bmp
4           FTL/data/FTL
224244      FTL/data
12          FTL/FTL_README.html
4           FTL/FTL
224264      FTL

FTL/FTL is a bash script, we skip it and check the FTL/data/amd64/bin/FTL binary:

$ file FTL/data/amd64/bin/FTL
FTL: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.8, stripped

which looks good, now let’s execute it:

$ FTL/data/amd64/bin/./FTL
zsh: no such file or directory: ./FTL

note: this error message is not very helpful!

let’s have a look at the FTL/data/amd64/bin/FTL ELF part (interpreter and RPATH):

$ patchelf --print-interpreter FTL/data/amd64/bin/FTL
/lib64/ld-linux-x86-64.so.2

$ patchelf --print-rpath FTL/data/amd64/bin/FTL
(empty output)

‘/lib64/ld-linux-x86-64.so.2’ won’t be running on nixos, so let’s find a proper interpreter:

$ du -a /nix/store | grep ld-linux-x86-64.so.2
0       /nix/store/93zfs0zzndi7pkjkjxawlafdj8m90kg5-glibc-2.20/lib/ld-linux-x86-64.so.2
0       /nix/store/94n64qy99ja0vgbkf675nyk39g9b978n-glibc-2.19/lib/ld-linux-x86-64.so.2
0       /nix/store/i11d0d4015p0vbdnjq7lb509v9pwp049-glibc-2.19/lib/ld-linux-x86-64.so.2
0       /nix/store/cj7a81wsm1ijwwpkks3725661h3263p5-glibc-2.13/lib/ld-linux-x86-64.so.2
4       /nix/store/kp4m5d52ljhb2fyxvnm6jgkbaf3hkdkv-glibc-multi-2.20/lib/ld-linux-x86-64.so.2
0       /nix/store/la5imi1602jxhpds9675n2n2d0683lbq-glibc-2.20/lib/ld-linux-x86-64.so.2
144     /nix/store/gakif09g14jybn6vkgnzb0kn46kqg1w6-extra-utils/lib/ld-linux-x86-64.so.2
4       /nix/store/g9y2f5awcw9jdgirlv7163k3g5hjak0a-system-path/lib/ld-linux-x86-64.so.2
0       /nix/store/nrxyygy0wqski1klq0305d3h523k41ps-glibc-2.20/lib/ld-linux-x86-64.so.2
0       /nix/store/zm4bhsm8lprkzvrjgqr0klfkvr21als4-glibc-2.17/lib/ld-linux-x86-64.so.2
0       /nix/store/c8lg3m5mr246fvlx6xsrxa0sykv4l9pg-bootstrap-tools/lib/ld-linux-x86-64.so.2
0       /nix/store/ywxpkmy9kagcsvbjjhi46pr4xwpd6sfm-glibc-2.19/lib/ld-linux-x86-64.so.2
0       /nix/store/r2nzgy23qzfn273n9mbqngyidm05670f-glibc-2.19/lib/ld-linux-x86-64.so.2
4       /nix/store/i4bqvffrh47rlbc42dkqhzgmrw40zfvy-system-path/lib/ld-linux-x86-64.so.2
4       /nix/store/qdd4ypr32j1d373779ggnqqmgqm29xyb-system-path/lib/ld-linux-x86-64.so.2
4       /nix/store/vi4r0vw7jipwzfxhrqghzny74jsgxv5c-system-path/lib/ld-linux-x86-64.so.2
0       /nix/store/pdskwizjw8ar31hql2wjnnx6g0s6xc50-glibc-2.19/lib/ld-linux-x86-64.so.2
0       /nix/store/7yvf54nxwmaslcgyqfghqsqr1dwmr8ld-glibc-2.20/lib/ld-linux-x86-64.so.2
4       /nix/store/ggz4x9azga18bs2n2n5ap9qq1m088694-system-path/lib/ld-linux-x86-64.so.2
0       /nix/store/k0vqprjmxybr7clvfljk13zsdjwklcch-bootstrap-tools/lib/ld-linux-x86-64.so.2
0       /nix/store/q784x64hp3nwdxx7lbgb16f74i2bhxxk-glibc-2.18/lib/ld-linux-x86-64.so.2
0       /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/ld-linux-x86-64.so.2
144     /nix/store/nvxln8cf8aprddpvz5zpx8xgn34w9mz3-extra-utils/lib/ld-linux-x86-64.so.2
4       /nix/store/5rr3d51im48n5y3sx0kr9l61z0b9i5bs-system-path/lib/ld-linux-x86-64.so.2
0       /nix/store/6k9z1sfl7kghmagwd205k3i81pbcw57s-glibc-2.21/lib/ld-linux-x86-64.so.2

now just pick a ‘random’ one and issue:

$ patchelf --set-interpreter /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/ld-linux-x86-64.so.2 FTL/data/amd64/bin/FTL

and run it again:

$ FTL/data/amd64/bin/FTL
./FTL: error while loading shared libraries: libGL.so.1: cannot open shared object file: No such file or directory

looks much better now, let’s see the library (DSOs - dynamic shared objects) status:

$ ldd FTL/data/amd64/bin/FTL
    linux-vdso.so.1 (0x00007fff495e2000)
    libSDL-1.2.so.0 => ../lib/libSDL-1.2.so.0 (0x00007f7d2cdc5000)
    libGL.so.1 => not found
    libfreetype.so.6 => ../lib/libfreetype.so.6 (0x00007f7d2cb42000)
    libIL.so.1 => ../lib/libIL.so.1 (0x00007f7d2c827000)
    libILU.so.1 => ../lib/libILU.so.1 (0x00007f7d2c612000)
    libILUT.so.1 => ../lib/libILUT.so.1 (0x00007f7d2c40c000)
    libbass.so => ../lib/libbass.so (0x00007f7d2d127000)
    libbassmix.so => ../lib/libbassmix.so (0x00007f7d2c303000)
    librt.so.1 => /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/librt.so.1 (0x00007f7d2c0fb000)
    libstdc++.so.6 => not found
    libm.so.6 => /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libm.so.6 (0x00007f7d2bdf8000)
    libc.so.6 => /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libc.so.6 (0x00007f7d2ba49000)
    libpthread.so.0 => /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libpthread.so.0 (0x00007f7d2b82b000)
    libdl.so.2 => /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libdl.so.2 (0x00007f7d2b627000)
    libpng12.so.0 => ../lib/libpng12.so.0 (0x00007f7d2b402000)
    /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/ld-linux-x86-64.so.2 (0x00007f7d2d056000)
    libstdc++.so.6 => not found
    libgcc_s.so.1 => not found
    libGLU.so.1 => not found
    libGL.so.1 => not found
    libz.so.1 => ../lib/libz.so.1 (0x00007f7d2b1ec000)

wonderful, so all the libraries coming with FTL are already in the RPATH of the binary (as libSDL-1.2.so.0, …), so we have to find the missing ones:

TODO: patchelf for these libraries:

  • libGL.so.1
  • libstdc++.so.6
  • libstdc++.so.6
  • libgcc_s.so.1
  • libGLU.so.1

again, use this command to find candidates:

$ du -a /nix/store | grep libGL.so.1

note: DSOs might introduce other DSOs and thus you might have to add even more libraries than shown here. hint: later we are about to find out that we require libasound.so which is not listed just yet!

and again, pick one:

i picked this one: /nix/store/0sgyyrml3j55nx4mmb3v099n7g1fidr4-mesa-10.2.9/lib/libGL.so.1

so the command goes like this:

$ patchelf --set-rpath FTL/data/amd64/lib:/nix/store/0sgyyrml3j55nx4mmb3v099n7g1fidr4-mesa-10.2.9/lib/ FTL/data/amd64/bin/FTL

note: FTL/data/amd64/lib contains the bundled libraries! you should run ‘patchelf –set-rpath’ from the location you want to start the binary later on. in case of FTL this would be ‘FTL/’ but in this example i was using the parent directory of ‘FTL/’. also note that you can set the RPATH to an absolute directory which is good until you move the FTL program into a different location or use relative path names which is good until you decided to run the program from any other directory as the one you issued the ‘patchelf –set-rpath’ from. sigh

and afterwards the ldd output has changed a lot:

$ ldd FTL/data/amd64/bin/FTL
    linux-vdso.so.1 (0x00007fff04dcd000)
    libSDL-1.2.so.0 => FTL/data/amd64/lib/libSDL-1.2.so.0 (0x00007f512a1c8000)
    libGL.so.1 => /nix/store/fiz0mz982n1m03qzbpvl40n51bvr4b0m-mesa-10.4.5/lib/libGL.so.1 (0x00007f5129f3c000)
    libfreetype.so.6 => FTL/data/amd64/lib/libfreetype.so.6 (0x00007f5129cb9000)
    libIL.so.1 => FTL/data/amd64/lib/libIL.so.1 (0x00007f512999e000)
    libILU.so.1 => FTL/data/amd64/lib/libILU.so.1 (0x00007f5129788000)
    libILUT.so.1 => FTL/data/amd64/lib/libILUT.so.1 (0x00007f5129582000)
    libbass.so => FTL/data/amd64/lib/libbass.so (0x00007f512a52a000)
    libbassmix.so => FTL/data/amd64/lib/libbassmix.so (0x00007f5129479000)
    librt.so.1 => /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/librt.so.1 (0x00007ff8f3d18000)
    libstdc++.so.6 => /nix/store/jrhjp66sdfv0pc95dwgdz2sly9hima23-gcc-4.8.4/lib/libstdc++.so.6 (0x00007ff8f3a15000)
    libm.so.6 => /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libm.so.6 (0x00007ff8f3712000)
    libc.so.6 => /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libc.so.6 (0x00007ff8f3363000)
    libpthread.so.0 => /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libpthread.so.0 (0x00007ff8f3145000)
    libdl.so.2 => /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libdl.so.2 (0x00007ff8f2f41000)
    libexpat.so.1 => /nix/store/vydr1x0s2lpw2id04388azad7xaw4m8w-expat-2.1.0/lib/libexpat.so.1 (0x00007ff8f2d18000)
    libglapi.so.0 => /nix/store/fiz0mz982n1m03qzbpvl40n51bvr4b0m-mesa-10.4.5/lib/libglapi.so.0 (0x00007ff8f2aef000)
    libXdamage.so.1 => /nix/store/j292kvvwsfyqx73a6zyn81ykmrbkcf31-libXdamage-1.1.4/lib/libXdamage.so.1 (0x00007ff8f28ed000)
    libXfixes.so.3 => /nix/store/98gi4m67cr1cgrw6c1g2r51wyd6x8nld-libXfixes-5.0.1/lib/libXfixes.so.3 (0x00007ff8f26e8000)
    libX11-xcb.so.1 => /nix/store/vsk28b0riggcmigbgkzahf93xj3hw7gx-libX11-1.6.2/lib/libX11-xcb.so.1 (0x00007ff8f24e7000)
    libxcb-glx.so.0 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-glx.so.0 (0x00007ff8f22d1000)
    libxcb-dri2.so.0 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-dri2.so.0 (0x00007ff8f20cd000)
    libxcb-dri3.so.0 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-dri3.so.0 (0x00007ff8f1ecb000)
    libxcb-present.so.0 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-present.so.0 (0x00007ff8f1cc9000)
    libxcb-randr.so.0 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-randr.so.0 (0x00007ff8f1abd000)
    libxcb-xfixes.so.0 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-xfixes.so.0 (0x00007ff8f18b7000)
    libxcb-render.so.0 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-render.so.0 (0x00007ff8f16ae000)
    libxcb-shape.so.0 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-shape.so.0 (0x00007ff8f14ab000)
    libxcb-sync.so.1 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-sync.so.1 (0x00007ff8f12a6000)
    libxshmfence.so.1 => /nix/store/mib83k6wfp6dg7rffk2k3zrr1vhpdm90-libxshmfence-1.2/lib/libxshmfence.so.1 (0x00007ff8f10a4000)
    libXxf86vm.so.1 => /nix/store/alfnyr2zf1y2y348lrrv9r0b7lhamlz2-libXxf86vm-1.1.3/lib/libXxf86vm.so.1 (0x00007ff8f0e9f000)
    libXext.so.6 => /nix/store/iaaijiqdji1bhjgpa4rdvdw1a1z9rpn3-libXext-1.3.3/lib/libXext.so.6 (0x00007ff8f0c8d000)
    libX11.so.6 => /nix/store/vsk28b0riggcmigbgkzahf93xj3hw7gx-libX11-1.6.2/lib/libX11.so.6 (0x00007ff8f0953000)
    libxcb.so.1 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb.so.1 (0x00007ff8f0735000)
    libXau.so.6 => /nix/store/4fk2pcy9nwyhsipin43r1svh2h02hk5a-libXau-1.0.8/lib/libXau.so.6 (0x00007ff8f0532000)
    libXdmcp.so.6 => /nix/store/khd2573yk3v3d8jspf0m9ad2hma64sc0-libXdmcp-1.1.1/lib/libXdmcp.so.6 (0x00007ff8f032d000)
    libdrm.so.2 => /nix/store/zci3rhzh24s6zwfxdysb9mqwrzbn7lyb-libdrm-2.4.59/lib/libdrm.so.2 (0x00007ff8f0121000)
    libpng12.so.0 => not found
    libgcc_s.so.1 => /nix/store/jrhjp66sdfv0pc95dwgdz2sly9hima23-gcc-4.8.4/lib/libgcc_s.so.1 (0x00007ff8eff0b000)
    libpng12.so.0 => /nix/store/i7ifkqarb8m0w58vs96mqvj0giwll2km-libpng-1.2.51/lib/libpng12.so.0 (0x00007ff8efce5000)
    libGLU.so.1 => /nix/store/fiz0mz982n1m03qzbpvl40n51bvr4b0m-mesa-10.4.5/lib/libGLU.so.1 (0x00007ff8efa66000)
    /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/ld-linux-x86-64.so.2 (0x00007ff8f4f00000)
    libz.so.1 => /nix/store/mvjf7dvnpqz9zlvnq4yi86xbc5k9j94r-zlib-1.2.8/lib/libz.so.1 (0x00007ff8ef84e000)

note: it is common that DSOs depend on other DSOs, just use ‘ldd’ to find out.

patchelf –set-rpath FTL/data/amd64/lib:/nix/store/0sgyyrml3j55nx4mmb3v099n7g1fidr4-mesa-10.2.9/lib/:/nix/store/ds3k0yci9swgglvjmn78p7fcz02ma4vr-gcc-4.8.4/lib64 FTL/data/amd64/bin/FTL

note: sometimes there are folders called /lib and lib64, do NOT mix them as you only want 64bit libraries! but other times also 64bit libraries are in a /lib folder, so happy guessing!

$ ldd FTL/data/amd64/bin/FTL
    linux-vdso.so.1 (0x00007fff017d4000)
    libSDL-1.2.so.0 => FTL/data/amd64/lib/libSDL-1.2.so.0 (0x00007f8617b76000)
    libGL.so.1 => /nix/store/fiz0mz982n1m03qzbpvl40n51bvr4b0m-mesa-10.4.5/lib/libGL.so.1 (0x00007f86178ea000)
    libfreetype.so.6 => FTL/data/amd64/lib/libfreetype.so.6 (0x00007f8617667000)
    libIL.so.1 => FTL/data/amd64/lib/libIL.so.1 (0x00007f861734c000)
    libILU.so.1 => FTL/data/amd64/lib/libILU.so.1 (0x00007f8617137000)
    libILUT.so.1 => FTL/data/amd64/lib/libILUT.so.1 (0x00007f8616f31000)
    libbass.so => FTL/data/amd64/lib/libbass.so (0x00007f8617ed8000)
    libbassmix.so => FTL/data/amd64/lib/libbassmix.so (0x00007f8616e28000)
    librt.so.1 => /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/librt.so.1 (0x00007f8616c20000)
    libstdc++.so.6 => /nix/store/jrhjp66sdfv0pc95dwgdz2sly9hima23-gcc-4.8.4/lib/libstdc++.so.6 (0x00007f861691d000)
    libm.so.6 => /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libm.so.6 (0x00007f861661a000)
    libc.so.6 => /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libc.so.6 (0x00007f861626b000)
    libpthread.so.0 => /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libpthread.so.0 (0x00007f861604d000)
    libdl.so.2 => /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libdl.so.2 (0x00007f8615e49000)
    libexpat.so.1 => /nix/store/vydr1x0s2lpw2id04388azad7xaw4m8w-expat-2.1.0/lib/libexpat.so.1 (0x00007f8615c20000)
    libglapi.so.0 => /nix/store/fiz0mz982n1m03qzbpvl40n51bvr4b0m-mesa-10.4.5/lib/libglapi.so.0 (0x00007f86159f7000)
    libXdamage.so.1 => /nix/store/j292kvvwsfyqx73a6zyn81ykmrbkcf31-libXdamage-1.1.4/lib/libXdamage.so.1 (0x00007f86157f5000)
    libXfixes.so.3 => /nix/store/98gi4m67cr1cgrw6c1g2r51wyd6x8nld-libXfixes-5.0.1/lib/libXfixes.so.3 (0x00007f86155f0000)
    libX11-xcb.so.1 => /nix/store/vsk28b0riggcmigbgkzahf93xj3hw7gx-libX11-1.6.2/lib/libX11-xcb.so.1 (0x00007f86153ef000)
    libxcb-glx.so.0 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-glx.so.0 (0x00007f86151d9000)
    libxcb-dri2.so.0 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-dri2.so.0 (0x00007f8614fd5000)
    libxcb-dri3.so.0 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-dri3.so.0 (0x00007f8614dd3000)
    libxcb-present.so.0 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-present.so.0 (0x00007f8614bd1000)
    libxcb-randr.so.0 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-randr.so.0 (0x00007f86149c5000)
    libxcb-xfixes.so.0 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-xfixes.so.0 (0x00007f86147bf000)
    libxcb-render.so.0 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-render.so.0 (0x00007f86145b6000)
    libxcb-shape.so.0 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-shape.so.0 (0x00007f86143b3000)
    libxcb-sync.so.1 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb-sync.so.1 (0x00007f86141ae000)
    libxshmfence.so.1 => /nix/store/mib83k6wfp6dg7rffk2k3zrr1vhpdm90-libxshmfence-1.2/lib/libxshmfence.so.1 (0x00007f8613fac000)
    libXxf86vm.so.1 => /nix/store/alfnyr2zf1y2y348lrrv9r0b7lhamlz2-libXxf86vm-1.1.3/lib/libXxf86vm.so.1 (0x00007f8613da7000)
    libXext.so.6 => /nix/store/iaaijiqdji1bhjgpa4rdvdw1a1z9rpn3-libXext-1.3.3/lib/libXext.so.6 (0x00007f8613b95000)
    libX11.so.6 => /nix/store/vsk28b0riggcmigbgkzahf93xj3hw7gx-libX11-1.6.2/lib/libX11.so.6 (0x00007f861385b000)
    libxcb.so.1 => /nix/store/16g3p2596fjvkiwlzxgs6qrc0fmj0dnk-libxcb-1.11/lib/libxcb.so.1 (0x00007f861363d000)
    libXau.so.6 => /nix/store/4fk2pcy9nwyhsipin43r1svh2h02hk5a-libXau-1.0.8/lib/libXau.so.6 (0x00007f861343a000)
    libXdmcp.so.6 => /nix/store/khd2573yk3v3d8jspf0m9ad2hma64sc0-libXdmcp-1.1.1/lib/libXdmcp.so.6 (0x00007f8613235000)
    libdrm.so.2 => /nix/store/zci3rhzh24s6zwfxdysb9mqwrzbn7lyb-libdrm-2.4.59/lib/libdrm.so.2 (0x00007f8613029000)
    libpng12.so.0 => not found
    libgcc_s.so.1 => /nix/store/jrhjp66sdfv0pc95dwgdz2sly9hima23-gcc-4.8.4/lib/libgcc_s.so.1 (0x00007f8612e13000)
    libpng12.so.0 => not found
    libGLU.so.1 => /nix/store/fiz0mz982n1m03qzbpvl40n51bvr4b0m-mesa-10.4.5/lib/libGLU.so.1 (0x00007f8612b94000)
    /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/ld-linux-x86-64.so.2 (0x00007f8617e07000)

now repeat the same procedure time and again to get all the DSOs found.

note: sometimes this does not work as you simply don’t have the required libraries installed in the store! then either install them directly or any software which might use them (indirectly). however, when using libraries like this one will have a problem if the libraries are GCed (garbage collected) but the GC does not know that the libraries are still in use (in this case through FTL, by our patchelf hack).

interestinly, using patchelf on the FTL binary with the store paths to libpng12.so.0 seems to have no effect, the outcome is always:

$  ldd FTL/data/amd64/lib/libIL.so.1
    linux-vdso.so.1 (0x00007fff3cbcf000)
    libpng12.so.0 => not found
    libstdc++.so.6 => /nix/store/jrhjp66sdfv0pc95dwgdz2sly9hima23-gcc-4.8.4/lib/libstdc++.so.6 (0x00007f7e2d949000)
    libm.so.6 => /nix/store/93zfs0zzndi7pkjkjxawlafdj8m90kg5-glibc-2.20/lib/libm.so.6 (0x00007f7e2d646000)
    libc.so.6 => /nix/store/93zfs0zzndi7pkjkjxawlafdj8m90kg5-glibc-2.20/lib/libc.so.6 (0x00007f7e2d2a9000)
    libgcc_s.so.1 => /nix/store/jrhjp66sdfv0pc95dwgdz2sly9hima23-gcc-4.8.4/lib/libgcc_s.so.1 (0x00007f7e2d092000)
    /nix/store/93zfs0zzndi7pkjkjxawlafdj8m90kg5-glibc-2.20/lib64/ld-linux-x86-64.so.2 (0x00007f7e2df6a000)

the reason is that one of the bundled DSOs are actually depending on libpng12.so.0 (amd64/lib/libIL.so.1), so now one has to patchelf the DSO instead…

fixing DSOs

the FTL binary is a nice example that patchelf does not work for libGLU.so.1 and libpng12.so.0 because you even though you can try to add a RPATH for either to the FTL binary, it will never work as the problem is not the FTL binary but the bundled libraries as ‘lib/libILUT.so.1’ or ‘libILU.so.1’. here an example:

$ patchelf --set-rpath /nix/store/i7ifkqarb8m0w58vs96mqvj0giwll2km-libpng-1.2.51/lib/:/nix/store/93zfs0zzndi7pkjkjxawlafdj8m90kg5-glibc-2.20/lib/:/nix/store/jrhjp66sdfv0pc95dwgdz2sly9hima23-gcc-4.8.4/lib/ FTL/data/amd64/lib/libIL.so.1

$ ldd FTL/data/amd64/lib/libIL.so.1
    linux-vdso.so.1 (0x00007fff207df000)
    libpng12.so.0 => /nix/store/i7ifkqarb8m0w58vs96mqvj0giwll2km-libpng-1.2.51/lib/libpng12.so.0 (0x00007f5113b04000)
    libstdc++.so.6 => /nix/store/jrhjp66sdfv0pc95dwgdz2sly9hima23-gcc-4.8.4/lib/libstdc++.so.6 (0x00007f5113800000)
    libm.so.6 => /nix/store/93zfs0zzndi7pkjkjxawlafdj8m90kg5-glibc-2.20/lib/libm.so.6 (0x00007f51134fd000)
    libc.so.6 => /nix/store/93zfs0zzndi7pkjkjxawlafdj8m90kg5-glibc-2.20/lib/libc.so.6 (0x00007f5113160000)
    libgcc_s.so.1 => /nix/store/jrhjp66sdfv0pc95dwgdz2sly9hima23-gcc-4.8.4/lib/libgcc_s.so.1 (0x00007f5112f49000)
    libz.so.1 => /nix/store/mvjf7dvnpqz9zlvnq4yi86xbc5k9j94r-zlib-1.2.8/lib/libz.so.1 (0x00007f5112d31000)
    /nix/store/93zfs0zzndi7pkjkjxawlafdj8m90kg5-glibc-2.20/lib64/ld-linux-x86-64.so.2 (0x00007f511404b000)

note: beware of ELF 32-bit libs as ‘ldd’ will just silently fail and tell you there is no lib, altough you added a RPATH pointing to one:

file /nix/store/55nsmmx7jzpm8i664pbj0adik4z6klcv-glu-9.0.0/lib/libGLU.so.1.3.1
/nix/store/55nsmmx7jzpm8i664pbj0adik4z6klcv-glu-9.0.0/lib/libGLU.so.1.3.1: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped

note: you need to patch the RPATH from the ‘FTL/’ directory as the binary expects the the ‘data’ directory to be residing there so you have to patch the RPATH for the bundled libraries again as we were doing that wrong in the first place.

finally running the FTL binary:

$ FTL/data/amd64/bin/FTL
Initializing Crash Catcher...
Initializing Video
Video Initialized
Opengl version = 3.0 Mesa 10.2.9
File or path name not found
Error opening resource file
File or path name not found
Error opening resource file
Starting audio library...
BASS_Init: Failed to init BASS Library!
BAS_INIT: 39
File or path name not found
Error opening resource file
Resource Loading Failure (or voluntary quit)!

so we need to make a hack here:

$ ln -s FTL/data/resources
$ FTL/data/amd64/bin/FTL
Initializing Crash Catcher...
Initializing Video
Video Initialized
Opengl version = 3.0 Mesa 10.2.9
Starting audio library...
BASS_Init: Failed to init BASS Library!
BAS_INIT: 39
Resource Preload: 2.530
Loading text....
Initializing animations...
Animations Initialized!
Loading Ship Blueprints....
Blueprints Loaded!
Initializing Sound Data....
Generating world...
Loading achievements...
Loading score file...
Running Game!

and it is working! except that it lacks audio ;P

fixing audio

there seems to be some problem with a BASS_Init thingy:

$ ./FTL
Loading Arch = amd64
Initializing Crash Catcher...
Initializing Video
Video Initialized
Opengl version = 3.0 Mesa 10.2.9
Starting audio library...
BASS_Init: Failed to init BASS Library!
BAS_INIT: 39
Resource Preload: 2.607
Loading text....
Initializing animations...
Animations Initialized!
Loading Ship Blueprints....
Blueprints Loaded!
Initializing Sound Data....
Generating world...
Loading achievements...
Loading score file...
Running Game!

no clue what is going on, let’s try ‘’strace’’ on the binary (not on the FTL shell script):

$ strace -e open FTL/data/amd64/bin/FTL
... (much crap)
write(1, "Starting audio library...\n", 26Starting audio library...
) = 26
open("/nix/store/zwimkmxsgg5h036knq623hzffnpkc7q5-libass-0.11.1/lib/libasound.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/nix/store/nwzpz8lrzry9j223rd84v2r4qs8pc548-libpng-1.2.51/lib/libasound.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/nix/store/0jcjjqm8c4gn2jiklq4f518n8hwlfhml-mesa-9.1.3/lib/libasound.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/home/joachim/Desktop/ftl/FTL/data/amd64/lib/libasound.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/run/opengl-driver/lib/libasound.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/nix/store/93zfs0zzndi7pkjkjxawlafdj8m90kg5-glibc-2.20/lib/libasound.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
write(1, "BASS_Init: Failed to init BASS L"..., 40BASS_Init: Failed to init BASS Library!
) = 40
write(1, "BAS_INIT: 39\n", 13BAS_INIT: 39
... (more crap)

so it seems to not find libasound.so.2 either! so finally i was using this command:

$ LD_LIBRARY_PATH=/nix/store/qhxaivhds8vahb2wzzhcpm820n32acjh-alsa-lib-1.0.28/lib/:$LD_LIBRARY_PATH FTL/data/amd64/bin/FTL
Initializing Crash Catcher...
Initializing Video
Video Initialized
Opengl version = 3.0 Mesa 10.2.9
Starting audio library...
Audio Initialized!
Resource Preload: 3.802
Loading text....
Initializing animations...
Animations Initialized!
Loading Ship Blueprints....
Blueprints Loaded!
Initializing Sound Data....
Generating world...
Loading achievements...
Loading score file...
Running Game!

note: i don’t have an idea where the libasound.so.2 was introduced and thus LD_LIBRARY_PATH is the only working solution so far.

however, FTL seems to be quite unstable and sound does not work, stops working after a while or is just bogus and sounds like noise. after a while FTL crashes, see this:

$ LD_LIBRARY_PATH=/nix/store/qz8wgnwxmw2jwcd83irff3z0l2lbf1s3-alsa-lib-1.0.28/lib/:$LD_LIBRARY_PATH FTL/data/amd64/bin/FTL
Initializing Crash Catcher...
Initializing Video
Video Initialized
Opengl version = 3.0 Mesa 10.2.9
Starting audio library...
Audio Initialized!
Resource Preload: 3.593
Loading text....
Initializing animations...
Animations Initialized!
Loading Ship Blueprints....
Blueprints Loaded!
Initializing Sound Data....
Generating world...
Loading achievements...
Loading score file...
Running Game!
*** Error in `FTL/data/amd64/bin/FTL': double free or corruption (!prev): 0x00000000056e0e40 ***
======= Backtrace: =========
/nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libc.so.6(+0x74866)[0x7f6aaeed8866]
/nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libc.so.6(+0x79c16)[0x7f6aaeeddc16]
/nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libc.so.6(+0x7b3d1)[0x7f6aaeedf3d1]
FTL/data/amd64/lib/libbassmix.so(+0x2f76)[0x7f6aafa23f76]
FTL/data/amd64/lib/libbassmix.so(+0x4603)[0x7f6aafa25603]
FTL/data/amd64/lib/libbassmix.so(+0x5cd5)[0x7f6aafa26cd5]
FTL/data/amd64/lib/libbass.so(+0x2b707)[0x7f6ab0ae1707]
FTL/data/amd64/lib/libbass.so(+0x2819f)[0x7f6ab0ade19f]
FTL/data/amd64/lib/libbass.so(+0x2d052)[0x7f6ab0ae3052]
FTL/data/amd64/lib/libbass.so(+0x2d1e5)[0x7f6ab0ae31e5]
/nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libpthread.so.0(+0x6f4a)[0x7f6aaec4cf4a]
/nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/libc.so.6(clone+0x6d)[0x7f6aaef4ed5d]
======= Memory map: ========
003fe000-00400000 rw-p 00000000 fe:01 22413413                           /home/joachim/Desktop/ftl/FTL/data/amd64/bin/FTL
00400000-00766000 r-xp 00002000 fe:01 22413413                           /home/joachim/Desktop/ftl/FTL/data/amd64/bin/FTL
00966000-00967000 rw-p 00368000 fe:01 22413413                           /home/joachim/Desktop/ftl/FTL/data/amd64/bin/FTL
00967000-0097a000 rw-p 00000000 00:00 0 
00b06000-05718000 rw-p 00000000 00:00 0                                  [heap]
7f6a58000000-7f6a58021000 rw-p 00000000 00:00 0 
7f6a58021000-7f6a5c000000 ---p 00000000 00:00 0 
...

cause unknown but other users seem to have this problem as well ;P

alternatives

LD_LIBRARY_PATH

instead of using patchelf on the FTL binary nor any DSOs, one can also use LD_LIBRARY_PATH like this:

$ cd FTL/data
$ LD_LIBRARY_PATH=/nix/store/jrhjp66sdfv0pc95dwgdz2sly9hima23-gcc-4.8.4/lib/:/nix/store/fiz0mz982n1m03qzbpvl40n51bvr4b0m-mesa-10.4.5/lib/:amd64/lib:$LD_LIBRARY_PATH /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/ld-linux-x86-64.so.2 amd64/bin/./FTL

what does this do?

  1. first we set the LD_LIBRARY_PATH to include the required libraries into the DSO search path,

  2. afterwards it uses /nix/store/6h129q168ahnl2nzw6azr239cba884ng-glibc-2.18/lib/ld-linux-x86-64.so.2, the dynamic linker,

  3. to execute the binary FTL in directory amd64/bin/.

note: this solution is realy a ‘fast forward’ one and requires only little effort!

ftl.nix

  1. copy FTL.1.5.13.tar.gz to /tmp

     $ cp FTL.1.5.13.tar.gz /tmp
  2. the ftl.nix file contains:

     {stdenv, pkgs, lib, makeWrapper, gcc, mesa_glu, path, version }:
     # build this with:
     # 64-bit systems
     #  nix-build -E 'with import <nixpkgs> { }; callPackage ./ftl.nix { path="/tmp/FTL.1.5.13.tar.gz"; version="1.5.13"; }'
     # 32-bit systems
     #  nix-build -E 'with import <nixpkgs> { }; callPackage_i686 ./ftl.nix { path="/tmp/FTL.1.5.13.tar.gz"; version="1.5.13"; }'
     let
       arch = if stdenv.system == "x86_64-linux" then "amd64" else "x86";
       libmapper = val: (map (x: x + "/lib") val ++ map (x: x + "/lib64") val); 
       lib_help = if stdenv.system == "x86_64-linux" then "lib64" else "lib";
     in
     assert (path != null);
     assert (version != null);
     stdenv.mkDerivation rec {
       name = "FTL-${version}";
       src = path;
       libs = with pkgs; [ stdenv.cc.cc mesa_glu alsaLib zlib ];
       buildInputs = [ makeWrapper ];
       phases = [ "unpackPhase" "installPhase" ];
       installPhase = ''
         mkdir -p "$out/opt/FTL"
         cp -r data "$out/opt/FTL"
         chmod +x "$out/opt/FTL/data/${arch}/bin/FTL"
         interpreter=$(echo ${stdenv.glibc}/${lib_help}/ld-linux*.so.2)
         patchelf --set-interpreter $interpreter "$out/opt/FTL/data/${arch}/bin/FTL"
         patchelf --set-rpath "$out/opt/FTL/data/${arch}/lib" "$out/opt/FTL/data/${arch}/bin/FTL"
         mkdir "$out/bin"
         # using makeWrapper to create a wrapper around the wrapper
         #  --run sets the 'working directory'
         #  --prefix adds the LD_LIBRARY_PATH export to the binary
         #  (libmapper libs) generates store location of libraries with lib and lib64 suffixes appended
         makeWrapper "$out/opt/FTL/data/FTL" "$out/bin/ftl" \
             --run "cd $out/opt/FTL/data" \
             --prefix LD_LIBRARY_PATH ':' "${lib.concatStringsSep ":" (libmapper libs)}";
      '';
     }
    1. build this on a 64-bit system:

      nix-build -E ‘with import { }; callPackage ./ftl.nix { path=“/tmp/FTL.1.5.13.tar.gz”; version=“1.5.13”; }’

    2. build this on a 32-bit system:

      nix-build -E ‘with import { }; callPackage_i686 ./ftl.nix { path=“/tmp/FTL.1.5.13.tar.gz”; version=“1.5.13”; }’

    installing it, this will show something like:

     $ nix-build -E 'with import <nixpkgs> { }; callPackage /home/joachim/.nixpkgs/ftl.nix { }' 
     these derivations will be built:
       /nix/store/i0wqnwzdhgdlr2a18v8s8aivivzn9qfj-FTL-1.5.13.drv
     building path(s) ‘/nix/store/20k9ch8wafxf8sg7472p2gq1g3d9kjrq-FTL-1.5.13’
     unpacking sources
     unpacking source archive /tmp/FTL.1.5.13.tar.gz
     source root is FTL
     installing
     /nix/store/20k9ch8wafxf8sg7472p2gq1g3d9kjrq-FTL-1.5.13
  3. now launch the FTL binary with:

     $ /nix/store/20k9ch8wafxf8sg7472p2gq1g3d9kjrq-FTL-1.5.13/bin/ftl
  4. if this works for you, issue this command:

     $ nix-env -i /nix/store/20k9ch8wafxf8sg7472p2gq1g3d9kjrq-FTL-1.5.13

    note: this is very important as it will add /nix/store/20k9ch8wafxf8sg7472p2gq1g3d9kjrq-FTL-1.5.13 to the GCROOTS (garbage collector roots) so it won’t be removed when calling:

     $ nix-collect-garbage -d

    or

     $ nix-store --gc
  5. you can now issue:

     $ rm /tmp/FTL.1.5.13.tar.gz

and from now on you can just type ‘ftl’ in any shell to start FTL!

summary

it can be quite some work to get proprietary software running on nixos but thanks to the wiki documentation [2], the good examples at [3] and nix language features like makeWrapper it gets much better.

still waiting for an automation tough ;-)

article source