Thanks for explaining what your thought process was here. I didn’t realise we were speaking essentially different languages/jargon, so I see how my response was unfair. I’ve deleted it as it didn’t add to the discussion.
Some background: practically all compileable code is built from some sort of source files - text files that humans can understand (source code) that are compiled into some machine-readable format (binaries). In open-source communities, however, when we say “built from source” we mean that we used the source code and our own tools to build the binary, instead of trusting whatever binaries the people on MyProgram dot com decided to post.
Building the binary from source ourselves confers some benefits; aside from the security benefits of being able to know what source code was used to build it, we also get the convenience of having the binary actually point directly at its dependencies. Oversimplifying and limiting to Linux, normally binaries that depend on some dependency called blah will declare that dependency on blah.so or maybe a specific version blah.so.1.2.3. When you run that binary, a special program called a dynamic loader (ld-linux.so) will check common directories like /usr/lib/ for this .so file. Of course most of these paths will not exist on NixOS, so when we build stuff using stdenv from nixpkgs, we will encode a more specific requirement in the binary, like “hey find the dependency at /nix/store/.../blah.so instead of trying to guess where it is”.
On the other hand, there is autoPatchelfHook - it runs patchelf, a really helpful hack for closed-source software where we are forced to trust MyProgram dot com to send us some program that does what it claims. Since basically nobody (%-wise) uses NixOS (and even if they did, distributing a binary like this would be unhelpful), they are going to assume a generic Linux, where stuff like /usr/lib will exist - and so we have to use this hacky scalpel to cut into the machine-readable code and replace some references to ensure they point into /nix/store/.... Unfortunately this process is not perfect, so once this is done, (rarely) some binaries will no longer run at all. Hence, we consider patchelf a very last resort, when building from source isn’t an option.
Also, if you actually did build a program from source, and you still somehow needed autoPatchelfHook, I would assume there is something really weird with the source code or with your build - so already a red flag to me.
In this case, the VMD people provide a tarball (that .tar.gz file) that contains some kind of source code, as well as the binary program vmd_LINUXAMD64. I verified that it is some binary (ELF executable) by running file on it:
$ file ~/Downloads/vmd-2.0.0/LINUXAMD64/vmd_LINUXAMD64
~/Downloads/vmd-2.0.0/LINUXAMD64/vmd_LINUXAMD64: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=0bc3a63618fd345529bd51dac57adedd63276c71, with debug_info, not stripped, too many notes (256)
I can also inspect this file and see that it was not built using nixpkgs’ stdenv (readelf is from toybox package here):
$ readelf ~/Downloads/vmd-2.0.0/LINUXAMD64/vmd_LINUXAMD64 -d
Dynamic section at offset 0x2dd89a0 contains 67 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libGL.so.1]
0x0000000000000001 (NEEDED) Shared library: [libX11.so.6]
0x0000000000000001 (NEEDED) Shared library: [librt.so.1]
0x0000000000000001 (NEEDED) Shared library: [libXinerama.so.1]
0x0000000000000001 (NEEDED) Shared library: [libXi.so.6]
0x0000000000000001 (NEEDED) Shared library: [liboptixu.so.6.5.0]
0x0000000000000001 (NEEDED) Shared library: [liboptix.so.6.5.0]
0x0000000000000001 (NEEDED) Shared library: [libpng16.so.16]
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libz.so.1]
0x0000000000000001 (NEEDED) Shared library: [libXft.so.2]
0x0000000000000001 (NEEDED) Shared library: [libfontconfig.so.1]
0x0000000000000001 (NEEDED) Shared library: [libfreetype.so.6]
0x0000000000000001 (NEEDED) Shared library: [libdl.so.2]
0x0000000000000001 (NEEDED) Shared library: [libwayland-cursor.so.0]
0x0000000000000001 (NEEDED) Shared library: [libwayland-client.so.0]
0x0000000000000001 (NEEDED) Shared library: [libxkbcommon.so.0]
0x0000000000000001 (NEEDED) Shared library: [libpangocairo-1.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libpango-1.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libgobject-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libglib-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libcairo.so.2]
0x0000000000000001 (NEEDED) Shared library: [libdbus-1.so.3]
0x0000000000000001 (NEEDED) Shared library: [libgtk-3.so.0]
0x0000000000000001 (NEEDED) Shared library: [libgdk-3.so.0]
0x0000000000000001 (NEEDED) Shared library: [libatk-1.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libcairo-gobject.so.2]
0x0000000000000001 (NEEDED) Shared library: [libgdk_pixbuf-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libgio-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libXcursor.so.1]
0x0000000000000001 (NEEDED) Shared library: [libXfixes.so.3]
0x0000000000000001 (NEEDED) Shared library: [libXrender.so.1]
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libmvec.so.1]
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [ld-linux-x86-64.so.2]
0x000000000000000f (RPATH) Library runpath: [/]
This looks a lot different from something that is built with nixpkgs’ stdenv (the hello binary in the hello package, for example):
$ readelf -d result/bin/hello
Dynamic section at offset 0xcbd8 contains 29 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000001d (RUNPATH) Library runpath: [/nix/store/fjkx1l5cnskzrqacf08z7i8z17256w0j-glibc-2.42-61/lib]
You can see the library runpath DT_RUNPATH actually mentions /nix/store here.
So, when I see your build code that puts this vmd_LINUXAMD64 file into $out/bin, I think, why did you spend CPU cycles building some other code, discarding it, and afterwards putting this vmd_LINUXAMD64 file that wasn’t built with nix in $out/bin when the file was there from the start? In other words, it’s as if you didn’t build anything from source at all.
The main reason this may matter to you is that you can spend time debugging only one thing (autoPatchelfHook failing) rather than two things (that + all the configure/install phase stuff) and you can therefore cut out most of the configure/install phases since your installPhase essentially becomes
install -Dm555 vmd_LINUXAMD64 $out/bin/vmd
(install is just a command to copy files around, -D creates $out and $out/bin here, then copies vmd_LINUXAMD64 to $out/bin/vmd, and -m 555 just marks the program runnable.)
Ultimately I still believe the code can be a lot shorter here if you don’t want to package the thing from source (which I understand can be a hassle in many cases). And if you do want to package the thing from source, you would need to check where the binary that you build is actually getting put and copy that to $out/bin/vmd (instead of trying to copy over the existing vmd_LINUXAMD64), and then you (hopefully) wouldn’t need autoPatchelfHook.
Feel free to ask for clarification if any point is unclear.