Pianoteq 7 - No display available

Hey Nix Community,

I am really new to Nix and NixOS and so far it is quite a ride.

Today (actually the last couple days) I tried to create a package for the proprietary
programm pianoteq by Modartt (https://www.modartt.com/). It took me quite a while to
figure stuff out but in the end it finally built. (Unfortunately, I only discovered NUR
and the package for pianoteq-stage after I was done with my package… Could’ve saved me
quite some time… nur-combined/default.nix at b7417c71d6b8d4789b3b091c839cb0c64476c9f3 · nix-community/nur-combined · GitHub)
I also checked PKGBUILD - aur.git - AUR Package Repositories for anything I might have forgotten.
Further, I found these two posts mentioning that pianoteq might work on their machine:
SOLVED: One audio plugin seems to be getting low priority
Pianoteq exits with "No display available" on Linux (NixOS) (Page 1) - Pianoteq user forum - Modartt user forum (Even with the same error)

The problem is, that when I try to run the patched executable the following message pops up:

No display available. Use the --headless option in order to run without a GUI.

My env shows DISPLAY=:0 so that should be set correctly.

My flake.nix which describes my derivation looks like this (Probably not optimal):

{
  inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";


  outputs = { self, nixpkgs }@inputs: {

    defaultPackage.x86_64-linux =

      with import nixpkgs { system = "x86_64-linux"; };

      stdenv.mkDerivation rec {
        pname = "pianoteq";
        version = "7.5.4";

        # Downloaded manually
        src = ./pianoteq_linux_v754.7z;

        nativeBuildInputs = [
          autoPatchelfHook
          p7zip
        ];

        buildInputs = [
          alsa-lib
          freetype
          xorg.libX11
          xorg.libXext
          stdenv.cc.cc.lib
          libjack2
          lv2
        ];

        unpackCmd = "7z x ${src}";

        installPhase = ''
          install -Dm 755 x86-64bit/Pianoteq\ 7 $out/bin/pianoteq7
          install -Dm 755 x86-64bit/Pianoteq\ 7.lv2/Pianoteq_7.so \
                          $out/lib/lv2/Pianoteq\ 7.lv2/Pianoteq_7.so
          cd x86-64bit/Pianoteq\ 7.lv2/
          for i in *.ttl; do
              install -D "$i" "$out/lib/lv2/Pianoteq 7.lv2/$i"
          done
        '';

        meta = {
          homepage = "https://www.modartt.com/";
          description = "Pianoteq is a virtual instrument which in contrast to other virtual instruments is physically modelled and thus can simulate the playability and complex behaviour of real acoustic instruments. Because there are no samples, the file size is just a tiny fraction of that required by other virtual instruments.";
          platforms = lib.platforms.linux;
        };
      };
  };
}

The build output seems fine and shows this:

pianoteq> unpacking sources
pianoteq> unpacking source archive /nix/store/43dcikdh9waqxzfx0hmmkq9bj9dbwbd0-pianoteq_linux_v754.7z
pianoteq> 7-Zip [64] 17.04 : Copyright (c) 1999-2021 Igor Pavlov : 2017-08-28
pianoteq> p7zip Version 17.04 (locale=C,Utf16=off,HugeFiles=on,64 bits,12 CPUs x64)
pianoteq> Scanning the drive for archives:
pianoteq> 1 file, 33120217 bytes (32 MiB)
pianoteq> Extracting archive: /nix/store/43dcikdh9waqxzfx0hmmkq9bj9dbwbd0-pianoteq_linux_v754.7z
pianoteq> --
pianoteq> Path = /nix/store/43dcikdh9waqxzfx0hmmkq9bj9dbwbd0-pianoteq_linux_v754.7z
pianoteq> Type = 7z
pianoteq> Physical Size = 33120217
pianoteq> Headers Size = 669
pianoteq> Method = LZMA:27
pianoteq> Solid = +
pianoteq> Blocks = 1
pianoteq> Everything is Ok
pianoteq> Folders: 11
pianoteq> Files: 24
pianoteq> Size:       231404515
pianoteq> Compressed: 33120217
pianoteq> source root is Pianoteq 7
pianoteq> setting SOURCE_DATE_EPOCH to timestamp 1644593263 of file Pianoteq
pianoteq> patching sources
pianoteq> configuring
pianoteq> no configure script, doing nothing
pianoteq> building
pianoteq> no Makefile, doing nothing
pianoteq> installing
pianoteq> beep
pianoteq> post-installation fixup
pianoteq> shrinking RPATHs of ELF executables and libraries in /nix/store/cjljwikrfnqkqpfrzn3lrmjrlnlk63q9-pianoteq-7.5.4
pianoteq> shrinking /nix/store/cjljwikrfnqkqpfrzn3lrmjrlnlk63q9-pianoteq-7.5.4/lib/lv2/Pianoteq 7.lv2/Pianoteq_7.so
pianoteq> shrinking /nix/store/cjljwikrfnqkqpfrzn3lrmjrlnlk63q9-pianoteq-7.5.4/bin/pianoteq7
pianoteq> strip is /nix/store/wsxm2bwsjai4nbsxxacdfabriiqsmdk1-binutils-wrapper-2.39/bin/strip
pianoteq> stripping (with command strip and flags -S) in  /nix/store/cjljwikrfnqkqpfrzn3lrmjrlnlk63q9-pianoteq-7.5.4/lib /nix/store/cjljwikrfnqkqpfrzn3lrmjrlnlk63q9-pianoteq-7.5.4/bin
pianoteq> patching script interpreter paths in /nix/store/cjljwikrfnqkqpfrzn3lrmjrlnlk63q9-pianoteq-7.5.4
pianoteq> checking for references to /build/ in /nix/store/cjljwikrfnqkqpfrzn3lrmjrlnlk63q9-pianoteq-7.5.4...
pianoteq> automatically fixing dependencies for ELF files
pianoteq> {'ignore_missing': [],
pianoteq>  'libs': [PosixPath('/nix/store/sw5m94nrg6r643arrsl55ihyi19ldh54-auto-patchelf-hook/lib'),
pianoteq>           PosixPath('/nix/store/wsxm2bwsjai4nbsxxacdfabriiqsmdk1-binutils-wrapper-2.39/lib'),
pianoteq>           PosixPath('/nix/store/gyzc8qrz7l11b18519wafn0zc8y0pdss-p7zip-17.04/lib'),
pianoteq>           PosixPath('/nix/store/0arxxg8ggpr3fc5i37hkfpsd7bya61c6-patchelf-0.15.0/lib'),
pianoteq>           PosixPath('/nix/store/59jmzisg8fkm9c125fw384dqq1np602l-move-docs.sh/lib'),
pianoteq>           PosixPath('/nix/store/kxw6q8v6isaqjm702d71n2421cxamq68-make-symlinks-relative.sh/lib'),
pianoteq>           PosixPath('/nix/store/m54bmrhj6fqz8nds5zcj97w9s9bckc9v-compress-man-pages.sh/lib'),
pianoteq>           PosixPath('/nix/store/g8xg0i02aqwhgxwd2vnp5ax3d6lrkg1v-strip.sh/lib'),
pianoteq>           PosixPath('/nix/store/bnj8d7mvbkg3vdb07yz74yhl3g107qq5-patch-shebangs.sh/lib'),
pianoteq>           PosixPath('/nix/store/cickvswrvann041nqxb0rxilc46svw1n-prune-libtool-files.sh/lib'),
pianoteq>           PosixPath('/nix/store/8zxndz5ag0p6s526c2xyllhk1nrn4c3i-audit-tmpdir.sh/lib'),
pianoteq>           PosixPath('/nix/store/c8n9kcdddp9np665xz6ri61b383nxvz8-move-systemd-user-units.sh/lib'),
pianoteq>           PosixPath('/nix/store/1i5y55x4b4m9qkx5dqbmr1r6bvrqbanw-multiple-outputs.sh/lib'),
pianoteq>           PosixPath('/nix/store/kd4xwxjpjxi71jkm6ka0np72if9rm3y0-move-sbin.sh/lib'),
pianoteq>           PosixPath('/nix/store/fyaryjvghbkpfnsyw97hb3lyb37s1pd6-move-lib64.sh/lib'),
pianoteq>           PosixPath('/nix/store/ngg1cv31c8c7bcm2n8ww4g06nq7s4zhm-set-source-date-epoch-to-latest.sh/lib'),
pianoteq>           PosixPath('/nix/store/wlwcf1nw2b21m4gghj70hbg1v7x53ld8-reproducible-builds.sh/lib'),
pianoteq>           PosixPath('/nix/store/j061mvdxw70xz20r2r0lr5lk0rcsjf9i-gcc-wrapper-11.3.0/lib'),
pianoteq>           PosixPath('/nix/store/hk75004j435l09ij4gawlkzg4wfs839w-binutils-wrapper-2.39/lib'),
pianoteq>           PosixPath('/nix/store/xxlhlnhvmgq87q3rr7py91rmc07ip9vd-alsa-lib-1.2.7.2-dev/lib'),
pianoteq>           PosixPath('/nix/store/ngnrwp3b4zc1jha4zpfcj6gknn1x27ml-alsa-lib-1.2.7.2/lib'),
pianoteq>           PosixPath('/nix/store/vx31vg1dxs49gwf25lk4rna57kgyz7y9-freetype-2.12.1-dev/lib'),
pianoteq>           PosixPath('/nix/store/ilr6sa1pzik3xdssrp6h92bb1mcisw2s-zlib-1.2.12-dev/lib'),
pianoteq>           PosixPath('/nix/store/7pjbsjdpycjn62326663p1qi8d4jk92n-zlib-1.2.12/lib'),
pianoteq>           PosixPath('/nix/store/icvgv2jkyfadm0y8ddvbdcdk7xhvhipn-bzip2-1.0.8-dev/lib'),
pianoteq>           PosixPath('/nix/store/9q56fhpyx870wilk7358wn9pyzkyxw40-bzip2-1.0.8-bin/lib'),
pianoteq>           PosixPath('/nix/store/lh7i8vfpqzs2if7yq8xg44r4qv8ypgfh-bzip2-1.0.8/lib'),
pianoteq>           PosixPath('/nix/store/20rc37wjs1ahgawpv6yfc72nfxrklsxc-libpng-apng-1.6.37-dev/lib'),
pianoteq>           PosixPath('/nix/store/wmv2k3736qdja8a0pkp9bfrj852r48hy-libpng-apng-1.6.37/lib'),
pianoteq>           PosixPath('/nix/store/md56q0amhj1q9h4s9swx1g7y38lzr46a-freetype-2.12.1/lib'),
pianoteq>           PosixPath('/nix/store/zv018d2541kyxdsy08vhvkk3gi3sgxin-libX11-1.8.1-dev/lib'),
pianoteq>           PosixPath('/nix/store/f61zxzmq6dikmrzvj44ivd8wmk85s8i4-xorgproto-2021.5/lib'),
pianoteq>           PosixPath('/nix/store/k73rnz4qh2v7xnz2cdhwpyy6s2h16cfk-libxcb-1.14-dev/lib'),
pianoteq>           PosixPath('/nix/store/2wabjgmbhgir772732dbnrqaz5cww100-libxcb-1.14/lib'),
pianoteq>           PosixPath('/nix/store/9ckz4x424lrsypkqfpfk432sa75yjsx7-libX11-1.8.1/lib'),
pianoteq>           PosixPath('/nix/store/ay7nsa6l67lw2y45l4mmaxmji43fpd9p-libXext-1.3.4-dev/lib'),
pianoteq>           PosixPath('/nix/store/gw394q0zg5wdksxphpm2swi8nagpzdl6-libXau-1.0.9-dev/lib'),
pianoteq>           PosixPath('/nix/store/v611hwz7kszryv105wz9vdr34c2qj53n-libXau-1.0.9/lib'),
pianoteq>           PosixPath('/nix/store/cjqp3wirsafkpwaxyc8b0k15l9rsp78r-libXext-1.3.4/lib'),
pianoteq>           PosixPath('/nix/store/glnknyx742009d61mrg0dccd0nlhchsr-gcc-11.3.0-lib/lib'),
pianoteq>           PosixPath('/nix/store/gh7i4277n8w8y5r1s7834h4slh4dwg1l-libjack2-1.9.19/lib'),
pianoteq>           PosixPath('/nix/store/11v8i3qxqdrzrnf8nnh8d5wfbv3v4f8x-lv2-1.18.2-dev/lib'),
pianoteq>           PosixPath('/nix/store/c1q71s349x227capdkpdv05fanx4wlk2-lv2-1.18.2/lib'),
pianoteq>           PosixPath('/nix/store/sw5m94nrg6r643arrsl55ihyi19ldh54-auto-patchelf-hook/lib'),
pianoteq>           PosixPath('/nix/store/wsxm2bwsjai4nbsxxacdfabriiqsmdk1-binutils-wrapper-2.39/lib'),
pianoteq>           PosixPath('/nix/store/gyzc8qrz7l11b18519wafn0zc8y0pdss-p7zip-17.04/lib'),
pianoteq>           PosixPath('/nix/store/0arxxg8ggpr3fc5i37hkfpsd7bya61c6-patchelf-0.15.0/lib'),
pianoteq>           PosixPath('/nix/store/59jmzisg8fkm9c125fw384dqq1np602l-move-docs.sh/lib'),
pianoteq>           PosixPath('/nix/store/kxw6q8v6isaqjm702d71n2421cxamq68-make-symlinks-relative.sh/lib'),
pianoteq>           PosixPath('/nix/store/m54bmrhj6fqz8nds5zcj97w9s9bckc9v-compress-man-pages.sh/lib'),
pianoteq>           PosixPath('/nix/store/g8xg0i02aqwhgxwd2vnp5ax3d6lrkg1v-strip.sh/lib'),
pianoteq>           PosixPath('/nix/store/bnj8d7mvbkg3vdb07yz74yhl3g107qq5-patch-shebangs.sh/lib'),
pianoteq>           PosixPath('/nix/store/cickvswrvann041nqxb0rxilc46svw1n-prune-libtool-files.sh/lib'),
pianoteq>           PosixPath('/nix/store/8zxndz5ag0p6s526c2xyllhk1nrn4c3i-audit-tmpdir.sh/lib'),
pianoteq>           PosixPath('/nix/store/c8n9kcdddp9np665xz6ri61b383nxvz8-move-systemd-user-units.sh/lib'),
pianoteq>           PosixPath('/nix/store/1i5y55x4b4m9qkx5dqbmr1r6bvrqbanw-multiple-outputs.sh/lib'),
pianoteq>           PosixPath('/nix/store/kd4xwxjpjxi71jkm6ka0np72if9rm3y0-move-sbin.sh/lib'),
pianoteq>           PosixPath('/nix/store/fyaryjvghbkpfnsyw97hb3lyb37s1pd6-move-lib64.sh/lib'),
pianoteq>           PosixPath('/nix/store/ngg1cv31c8c7bcm2n8ww4g06nq7s4zhm-set-source-date-epoch-to-latest.sh/lib'),
pianoteq>           PosixPath('/nix/store/wlwcf1nw2b21m4gghj70hbg1v7x53ld8-reproducible-builds.sh/lib'),
pianoteq>           PosixPath('/nix/store/j061mvdxw70xz20r2r0lr5lk0rcsjf9i-gcc-wrapper-11.3.0/lib'),
pianoteq>           PosixPath('/nix/store/hk75004j435l09ij4gawlkzg4wfs839w-binutils-wrapper-2.39/lib'),
pianoteq>           PosixPath('/nix/store/xxlhlnhvmgq87q3rr7py91rmc07ip9vd-alsa-lib-1.2.7.2-dev/lib'),
pianoteq>           PosixPath('/nix/store/ngnrwp3b4zc1jha4zpfcj6gknn1x27ml-alsa-lib-1.2.7.2/lib'),
pianoteq>           PosixPath('/nix/store/vx31vg1dxs49gwf25lk4rna57kgyz7y9-freetype-2.12.1-dev/lib'),
pianoteq>           PosixPath('/nix/store/ilr6sa1pzik3xdssrp6h92bb1mcisw2s-zlib-1.2.12-dev/lib'),
pianoteq>           PosixPath('/nix/store/7pjbsjdpycjn62326663p1qi8d4jk92n-zlib-1.2.12/lib'),
pianoteq>           PosixPath('/nix/store/icvgv2jkyfadm0y8ddvbdcdk7xhvhipn-bzip2-1.0.8-dev/lib'),
pianoteq>           PosixPath('/nix/store/9q56fhpyx870wilk7358wn9pyzkyxw40-bzip2-1.0.8-bin/lib'),
pianoteq>           PosixPath('/nix/store/lh7i8vfpqzs2if7yq8xg44r4qv8ypgfh-bzip2-1.0.8/lib'),
pianoteq>           PosixPath('/nix/store/20rc37wjs1ahgawpv6yfc72nfxrklsxc-libpng-apng-1.6.37-dev/lib'),
pianoteq>           PosixPath('/nix/store/wmv2k3736qdja8a0pkp9bfrj852r48hy-libpng-apng-1.6.37/lib'),
pianoteq>           PosixPath('/nix/store/md56q0amhj1q9h4s9swx1g7y38lzr46a-freetype-2.12.1/lib'),
pianoteq>           PosixPath('/nix/store/zv018d2541kyxdsy08vhvkk3gi3sgxin-libX11-1.8.1-dev/lib'),
pianoteq>           PosixPath('/nix/store/f61zxzmq6dikmrzvj44ivd8wmk85s8i4-xorgproto-2021.5/lib'),
pianoteq>           PosixPath('/nix/store/k73rnz4qh2v7xnz2cdhwpyy6s2h16cfk-libxcb-1.14-dev/lib'),
pianoteq>           PosixPath('/nix/store/2wabjgmbhgir772732dbnrqaz5cww100-libxcb-1.14/lib'),
pianoteq>           PosixPath('/nix/store/9ckz4x424lrsypkqfpfk432sa75yjsx7-libX11-1.8.1/lib'),
pianoteq>           PosixPath('/nix/store/ay7nsa6l67lw2y45l4mmaxmji43fpd9p-libXext-1.3.4-dev/lib'),
pianoteq>           PosixPath('/nix/store/gw394q0zg5wdksxphpm2swi8nagpzdl6-libXau-1.0.9-dev/lib'),
pianoteq>           PosixPath('/nix/store/v611hwz7kszryv105wz9vdr34c2qj53n-libXau-1.0.9/lib'),
pianoteq>           PosixPath('/nix/store/cjqp3wirsafkpwaxyc8b0k15l9rsp78r-libXext-1.3.4/lib'),
pianoteq>           PosixPath('/nix/store/glnknyx742009d61mrg0dccd0nlhchsr-gcc-11.3.0-lib/lib'),
pianoteq>           PosixPath('/nix/store/gh7i4277n8w8y5r1s7834h4slh4dwg1l-libjack2-1.9.19/lib'),
pianoteq>           PosixPath('/nix/store/11v8i3qxqdrzrnf8nnh8d5wfbv3v4f8x-lv2-1.18.2-dev/lib'),
pianoteq>           PosixPath('/nix/store/c1q71s349x227capdkpdv05fanx4wlk2-lv2-1.18.2/lib')],
pianoteq>  'paths': [PosixPath('/nix/store/cjljwikrfnqkqpfrzn3lrmjrlnlk63q9-pianoteq-7.5.4')],
pianoteq>  'recursive': True,
pianoteq>  'runtime_dependencies': []}
pianoteq> searching for dependencies of /nix/store/cjljwikrfnqkqpfrzn3lrmjrlnlk63q9-pianoteq-7.5.4/lib/lv2/Pianoteq 7.lv2/Pianoteq_7.so
pianoteq>     libX11.so.6 -> found: /nix/store/9ckz4x424lrsypkqfpfk432sa75yjsx7-libX11-1.8.1/lib
pianoteq>     libfreetype.so.6 -> found: /nix/store/md56q0amhj1q9h4s9swx1g7y38lzr46a-freetype-2.12.1/lib
pianoteq>     libstdc++.so.6 -> found: /nix/store/glnknyx742009d61mrg0dccd0nlhchsr-gcc-11.3.0-lib/lib
pianoteq> setting RPATH to: /nix/store/9ckz4x424lrsypkqfpfk432sa75yjsx7-libX11-1.8.1/lib:/nix/store/md56q0amhj1q9h4s9swx1g7y38lzr46a-freetype-2.12.1/lib:/nix/store/glnknyx742009d61mrg0dccd0nlhchsr-gcc-11.3.0-lib/lib
pianoteq> setting interpreter of /nix/store/cjljwikrfnqkqpfrzn3lrmjrlnlk63q9-pianoteq-7.5.4/bin/pianoteq7
pianoteq> searching for dependencies of /nix/store/cjljwikrfnqkqpfrzn3lrmjrlnlk63q9-pianoteq-7.5.4/bin/pianoteq7
pianoteq>     libasound.so.2 -> found: /nix/store/ngnrwp3b4zc1jha4zpfcj6gknn1x27ml-alsa-lib-1.2.7.2/lib
pianoteq>     libfreetype.so.6 -> found: /nix/store/md56q0amhj1q9h4s9swx1g7y38lzr46a-freetype-2.12.1/lib
pianoteq> setting RPATH to: /nix/store/ngnrwp3b4zc1jha4zpfcj6gknn1x27ml-alsa-lib-1.2.7.2/lib:/nix/store/md56q0amhj1q9h4s9swx1g7y38lzr46a-freetype-2.12.1/lib
pianoteq> auto-patchelf: 0 dependencies could not be satisfied

I also tried the manual patchelf approach from the NUR package which yielded the same result.
I am also not quite sure, why the actual binary for pianoteq does not depend on libX11

I also checked the resulting binary for missing libs with:

ldd result/bin/pianoteq7 | rg 'not found'
patchelf --print-needed result/bin/pianoteq7

Which looked fine imo, but I am not too familiar with this whole process yet.

Any help or hints to documentation or other examples is appreciated.

Thanks!

Just to check, do you actually have an X display set up? If you’re running a wayland session this isn’t a forgone conclusion…

Sorry I did not mention that: I am using X with bspwm as window manager. Relevant part of my configuration:

xserver = {
      enable = true;
      layout = "us";
      xkbVariant = "altgr-intl";
      xkbOptions = "caps:escape";
      videoDrivers = [ "nvidia" ];
      displayManager = {
        defaultSession = "none+bspwm";
        lightdm.enable = true;
        lightdm.greeters = {
          mini.enable = true;
          mini.user = "phga";
          gtk.cursorTheme = {
            name = "Bibata-Original-Amber";
            package = pkgs.bibata-cursors;
            size = 16;
          };
        };
      };
      windowManager.bspwm.enable = true;
      wacom.enable = true;
    };

Hmm, depending on how it’s programmed, you may need to add some explicit lib paths. autoPatchelfHook only automatically handles libraries linked by the loader itself. If they’re looked up and linked after loading, which seems to be the case here given the existence of the --headless option, you probably need to either force patchelf to add entries for things not linked at load time, or else wrap the program with an LD_LIBRARY_PATH to find those libs. I’m not sure what the idiomatic solution to that is, but I suspect at least that that’s the problem.

Hey, thanks for your fast replies, much appreciated!

As soon as I am at home, I’ll give your suggestions a try and report back!

Okey, I got time trying out your recommendations. (At least I hope I did the correct things)

Scroll down for the working solution

I kept this part so others can maybe use it in their own troubleshooting

After a bit of research I tried basically the same approach as in the NUR derivation:

{
  inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";


  outputs = { self, nixpkgs }@inputs: {

    defaultPackage.x86_64-linux =

      with import nixpkgs { system = "x86_64-linux"; };

      stdenv.mkDerivation rec {
        pname = "pianoteq";
        version = "7.5.4";

        # Downloaded manually
        src = ./pianoteq_linux_v754.7z;

        nativeBuildInputs = [
          p7zip
        ];

        libPath = lib.makeLibraryPath [
          alsa-lib
          freetype
          xorg.libX11
          xorg.libXext
          stdenv.cc.cc.lib
          libjack2
          lv2
        ];

        unpackCmd = "7z x ${src}";

        installPhase = ''
          install -Dm 755 x86-64bit/Pianoteq\ 7 $out/bin/pianoteq7
          install -Dm 755 x86-64bit/Pianoteq\ 7.lv2/Pianoteq_7.so \
                          $out/lib/lv2/Pianoteq\ 7.lv2/Pianoteq_7.so
          patchelf --set-interpreter "$(< $NIX_CC/nix-support/dynamic-linker)" \
                   --set-rpath $libPath "$out/bin/pianoteq7"
          cd x86-64bit/Pianoteq\ 7.lv2/
          for i in *.ttl; do
              install -D "$i" "$out/lib/lv2/Pianoteq 7.lv2/$i"
          done
        '';

        meta = {
          homepage = "https://www.modartt.com/";
          description = "Pianoteq is a virtual instrument which in contrast to other virtual instruments is physically modelled and thus can simulate the playability and complex behaviour of real acoustic instruments. Because there are no samples, the file size is just a tiny fraction of that required by other virtual instruments.";
          platforms = lib.platforms.linux;
        };
      };
  };
}

I also tried to combine this with the autoPatchelfHook and the buildInputs from before.

Both attempts led to the following output when running the executable:

./result/bin/pianoteq7 
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: ./result/bin/pianoteq7: no version information available (required by ./result/b
in/pianoteq7)
./result/bin/pianoteq7: symbol lookup error: ./result/bin/pianoteq7: undefined symbol: , version 

After that I looked at the symbols and dynamic symbols (filtered out the “already satisfied” library outputs) table to maybe get a hint of the missing library (idk if that is the correct way of doing things):

nm ./result/bin/pianoteq7 
nm: ./result/bin/pianoteq7: no symbols

nm -D ./result/bin/pianoteq7 | rg -v -e '@(GLIB|GCC|ALSA).*'
                 U FT_Done_Face
                 U FT_Done_FreeType
                 U FT_Get_Char_Index
                 U FT_Get_First_Char
                 U FT_Get_Kerning
                 U FT_Get_Next_Char
                 U FT_Init_FreeType
                 U FT_Load_Glyph
                 U FT_New_Face
                 U FT_Select_Charmap
                 U FT_Set_Charmap
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w jack_port_get_latency_range
                 w _Jv_RegisterClasses

I did not see any symbols (function calls?) related to X11.

The next thing I tried was to add the following to the installPase:

install -Dm 755 x86-64bit/Pianoteq\ 7 $out/bin/pianoteq7
          install -Dm 755 x86-64bit/Pianoteq\ 7.lv2/Pianoteq_7.so \
                          $out/lib/lv2/Pianoteq\ 7.lv2/Pianoteq_7.so
          patchelf --set-interpreter "$(< $NIX_CC/nix-support/dynamic-linker)" \

                   --add-needed "libX11.so.6" \

                   --set-rpath $libPath "$out/bin/pianoteq7"
          cd x86-64bit/Pianoteq\ 7.lv2/
          for i in *.ttl; do
              install -D "$i" "$out/lib/lv2/Pianoteq 7.lv2/$i"
          done

I hope this is what you meant by

you probably need to either force patchelf to add entries for things not linked at load time

This led to:

[nix-shell:~/git/code/nix/pianoteq]$ ./result/bin/pianoteq7 
Segmentation fault (core dumped)

WORKING SOLUTION

Your second suggestion

wrap the program with an LD_LIBRARY_PATH to find those libs

would in my understanding work in a way that I would set the LD_LIBRARY_PATH with the makeWrapper script. With this appoach I came up with this cleaned up AND WORKING flake.nix file:

{
  inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";


  outputs = { self, nixpkgs }@inputs: {

    defaultPackage.x86_64-linux =

      with import nixpkgs { system = "x86_64-linux"; };

      stdenv.mkDerivation rec {
        pname = "pianoteq";
        version = "7.5.4";

        # Downloaded manually
        src = ./pianoteq_linux_v754.7z;

        nativeBuildInputs = [
          makeWrapper
          p7zip
        ];

        libPath = lib.makeLibraryPath [
          alsa-lib
          freetype
          xorg.libX11
          xorg.libXext
          stdenv.cc.cc.lib
          libjack2
          lv2
        ];

        unpackCmd = "7z x ${src}";

        installPhase = ''
          install -Dm 755 x86-64bit/Pianoteq\ 7 $out/bin/pianoteq7
          install -Dm 755 x86-64bit/Pianoteq\ 7.lv2/Pianoteq_7.so \
                          $out/lib/lv2/Pianoteq\ 7.lv2/Pianoteq_7.so
          patchelf --set-interpreter "$(< $NIX_CC/nix-support/dynamic-linker)" \
                   --set-rpath $libPath "$out/bin/pianoteq7"
          cd x86-64bit/Pianoteq\ 7.lv2/
          for i in *.ttl; do
              install -D "$i" "$out/lib/lv2/Pianoteq 7.lv2/$i"
          done
        '';

        fixupPhase = ''
          makeWrapper $out/bin/pianoteq7 $out/bin/pianoteq7_wrapped --set LD_LIBRARY_PATH "$libPath:$LD_LIBRARY_PATH"
        '';

        meta = {
          homepage = "https://www.modartt.com/";
          description = "Pianoteq is a virtual instrument which in contrast to other virtual instruments is physically modelled and thus can simulate the playability and complex behaviour of real acoustic instruments. Because there are no samples, the file size is just a tiny fraction of that required by other virtual instruments.";
          platforms = lib.platforms.linux;
        };
      };
  };
}

I tested as I wrote this answer and decided to keep the two failed approaches so maybe others can use the information in their own troubleshooting scenarios.

Thanks @tejing for the hints which led to the working example above!

1 Like

I still kind of suspect there’s a way to do this with patchelf, but I’m not actually familiar enough with glibc to be certain, nor do I know enough about patchelf to know how to do it properly. Regardless, if LD_LIBRARY_PATH works for you, then good enough.

One note: --set LD_LIBRARY_PATH "$libPath:$LD_LIBRARY_PATH" is definitely wrong. You’re injecting the build environment’s LD_LIBRARY_PATH into the wrapper. You should use --prefix LD_LIBRARY_PATH : "$libPath" instead.

1 Like

Thanks for this additional hint. I cleaned up the code a bit further and noticed the following:

If I change

fixupPhase = ''
         makeWrapper $out/bin/pianoteq7 $out/bin/pianoteq7_wrapped --prefix LD_LIBRARY_PATH : "$libPath"
''

to

fixupPhase = '':'';

It works without the wrapper. So maybe the fixupPhase just has to run in order to fix the dynamic linking?

Anyways I added a bit of instructions to this flake and published it here for anyone interested:

Here the final working flake.nix:

{
  inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";

  outputs = { self, nixpkgs }@inputs: {

    packages.x86_64-linux.default =

      with import nixpkgs { system = "x86_64-linux"; };
      stdenv.mkDerivation rec {
        pname = "pianoteq";
        version = "7.5.4";

        icon = fetchurl {
          name = "pianoteq_icon_128";
          url = "https://www.pianoteq.com/images/logo/pianoteq_icon_128.png";
          sha256 = "sha256-lO5kz2aIpJ108L9w2BHnRmq6wQP+6rF0lqifgor8xtM=";
        };

        # IMPORTANT: Use the following command to retrive the correct hash.
        # Otherwise the file is not found in the nix store (Add it first ofc)
        # nix hash to-sri --type sha256 `sha256sum pianoteq_linux_v754.7z`
        src = requireFile {
          name = "pianoteq_linux_v754.7z";
          message = "Download the file from: https://www.modartt.com/download?file=pianoteq_linux_v754.7z and add it to the nix store manually: nix-store --add-fixed sha256 ./pianoteq_linux_v754.7z";
          sha256 = "sha256-TA9CiuT21fQedlMUGz7bNNxYun5ArmRjvIxjOGqXDCs=";
        };

        # Alternative: Downloaded manually and place in this directory
        # src = ./pianoteq_linux_v754.7z;

        desktopItems = [
          (makeDesktopItem {
            name = "pianoteq7";
            desktopName = "Pianoteq 7";
            exec = "pianoteq7";
            icon = "pianoteq_icon_128";
          })
        ];

        nativeBuildInputs = [
          p7zip
          copyDesktopItems
        ];

        libPath = lib.makeLibraryPath [
          alsa-lib
          freetype
          xorg.libX11
          xorg.libXext
          stdenv.cc.cc.lib
          libjack2
          lv2
        ];

        unpackCmd = "7z x ${src}";

        # `runHook postInstall` is mandatory otherwise postInstall won't run
        installPhase = ''
          install -Dm 755 x86-64bit/Pianoteq\ 7 $out/bin/pianoteq7
          install -Dm 755 x86-64bit/Pianoteq\ 7.lv2/Pianoteq_7.so \
                          $out/lib/lv2/Pianoteq\ 7.lv2/Pianoteq_7.so
          patchelf --set-interpreter "$(< $NIX_CC/nix-support/dynamic-linker)" \
                   --set-rpath $libPath "$out/bin/pianoteq7"
          cd x86-64bit/Pianoteq\ 7.lv2/
          for i in *.ttl; do
              install -D "$i" "$out/lib/lv2/Pianoteq 7.lv2/$i"
          done
          runHook postInstall
        '';

        # This also works instead of the following
        # makeWrapper $out/bin/pianoteq7 $out/bin/pianoteq7_wrapped --prefix LD_LIBRARY_PATH : "$libPath"
        fixupPhase = '':'';

        # Runs copyDesktopItems hook.
        # Alternatively call copyDesktopItems manually in installPhase/fixupPhase
        postInstall = ''
          install -Dm 444 ${icon} $out/share/icons/hicolor/128x128/apps/pianoteq_icon_128.png
        '';

        meta = {
          homepage = "https://www.modartt.com/";
          description = "Pianoteq is a virtual instrument which in contrast to other virtual instruments is physically modelled and thus can simulate the playability and complex behaviour of real acoustic instruments. Because there are no samples, the file size is just a tiny fraction of that required by other virtual instruments.";
          platforms = lib.platforms.linux;
        };
      };
  };
}

Which can be used like this:

Main flake.nix for your installation

inputs = {
    #...
    pianoteq.url = "github:qhga/nix-pianoteq7";
};
#...

Some module in your nixosConfigurations

#...
  environment.systemPackages = [
    pkgs.pianoteq.packages.x86_64-linux.default
  ];
#...
1 Like

Great that it works! By the way, if you want to use autoPatchelfHook the documentation specifies that you can still force libraries to be added using runtimeDependencies:

You can also specify a runtimeDependencies variable which lists dependencies to be unconditionally added to rpath of all executables. This is useful for programs that use dlopen 3 to load libraries at runtim

2 Likes