Linking completely statically

Hi! I know of the command line argument "-static". But this only affects the Haskell libraries. I want to link some programs completely statically, no external libraries needed. When just linking with "-static" I still have those dynamically linked things: desktop ~/bin $ ldd sicherung linux-vdso.so.1 (0x00007ffdab53f000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3633da0000) librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f3633d95000) libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f3633d90000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f3633d8a000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f3633d67000) libgmp.so.10 => /lib/x86_64-linux-gnu/libgmp.so.10 (0x00007f3633ce3000) libatomic.so.1 => /lib/x86_64-linux-gnu/libatomic.so.1 (0x00007f3633cd7000) libffi.so.7 => /lib/x86_64-linux-gnu/libffi.so.7 (0x00007f3633ccb000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3633ad9000) /lib64/ld-linux-x86-64.so.2 (0x00007f3633f0c000) Is it possible to link the remaining libraries statically too? Regards, Volker

Linux is not friendly to static linking, and you would need to either
package or match exact versions of things like the nss and locale libraries
that are dynamically loaded at runtime and don't show up in ldd. This
limitation comes from glibc and is documented in its manual.
On Sun, Aug 9, 2020, 08:50 Volker Wysk
Hi!
I know of the command line argument "-static". But this only affects the Haskell libraries. I want to link some programs completely statically, no external libraries needed.
When just linking with "-static" I still have those dynamically linked things:
desktop ~/bin $ ldd sicherung linux-vdso.so.1 (0x00007ffdab53f000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3633da0000) librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f3633d95000) libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f3633d90000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f3633d8a000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f3633d67000) libgmp.so.10 => /lib/x86_64-linux-gnu/libgmp.so.10 (0x00007f3633ce3000) libatomic.so.1 => /lib/x86_64-linux-gnu/libatomic.so.1 (0x00007f3633cd7000) libffi.so.7 => /lib/x86_64-linux-gnu/libffi.so.7 (0x00007f3633ccb000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3633ad9000) /lib64/ld-linux-x86-64.so.2 (0x00007f3633f0c000)
Is it possible to link the remaining libraries statically too?
Regards, Volker _______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users

Am Sonntag, den 09.08.2020, 08:59 -0400 schrieb Brandon Allbery:
Linux is not friendly to static linking, and you would need to either package or match exact versions of things like the nss and locale libraries that are dynamically loaded at runtime and don't show up in ldd. This limitation comes from glibc and is documented in its manual.
That's bad. But, like you said, it *is* possible. The dar (disk archiver) program comes with a statically linked version "dar_static": % ldd dar_static Das Programm ist nicht dynamisch gelinkt ("The program isn't linked dynamically.") From your answer, I assume that this isn't supported by GHC. Cheers Volker
On Sun, Aug 9, 2020, 08:50 Volker Wysk
wrote: Hi!
I know of the command line argument "-static". But this only affects the Haskell libraries. I want to link some programs completely statically, no external libraries needed.
When just linking with "-static" I still have those dynamically linked things:
desktop ~/bin $ ldd sicherung linux-vdso.so.1 (0x00007ffdab53f000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3633da0000) librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f3633d95000) libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f3633d90000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f3633d8a000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f3633d67000) libgmp.so.10 => /lib/x86_64-linux-gnu/libgmp.so.10 (0x00007f3633ce3000) libatomic.so.1 => /lib/x86_64-linux-gnu/libatomic.so.1 (0x00007f3633cd7000) libffi.so.7 => /lib/x86_64-linux-gnu/libffi.so.7 (0x00007f3633ccb000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3633ad9000) /lib64/ld-linux-x86-64.so.2 (0x00007f3633f0c000)
Is it possible to link the remaining libraries statically too?
Regards, Volker _______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users

On 09/08/2020 14.50, Volker Wysk wrote:
Hi!
I know of the command line argument "-static". But this only affects the Haskell libraries. I want to link some programs completely statically, no external libraries needed.
When just linking with "-static" I still have those dynamically linked things:
desktop ~/bin $ ldd sicherung linux-vdso.so.1 (0x00007ffdab53f000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3633da0000) [--snip--] libgmp.so.10 => /lib/x86_64-linux-gnu/libgmp.so.10 (0x00007f3633ce3000) libatomic.so.1 => /lib/x86_64-linux-gnu/libatomic.so.1 (0x00007f3633cd7000) libffi.so.7 => /lib/x86_64-linux-gnu/libffi.so.7 (0x00007f3633ccb000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3633ad9000) /lib64/ld-linux-x86-64.so.2 (0x00007f3633f0c000)
Is it possible to link the remaining libraries statically too?
As Brandon already mentioned, linking glibc statically is not really supported (by glibc!), but what you can do is bundle a few of the .so's together with your binary and use RPATH to help your executable find them at load time (well, dynamic link time). A project of ours where we do this is using Stack, so I can only really provide info on doing it with Stack, but hopefully you can adapt to whatever you're using: We added ld-options: - -Wl,-rpath,$ORIGIN/../lib to the 'executable' portion of the package.yaml. This instructs the dynamic loader to look for libraries in '../lib' relative to the executable's location. You can pick whatever path you want there. Once you have that bit set up, you can copy *most* of the libraries .so's you're using to that folder on the install target and they'll be loaded from there. (Copying libc.so is ill advised, but most of the others will work just fine. I believe ld-linux-... is also never ever loaded from there since that *is* the dynamic loader.) (Of course a possibly more robust version of this is to just bundle everything into a container of some sort, but that may be a bit excessive for your needs.) HTH,

Am Montag, den 10.08.2020, 09:11 +0200 schrieb Bardur Arantsson:
On 09/08/2020 14.50, Volker Wysk wrote:
Hi!
I know of the command line argument "-static". But this only affects the Haskell libraries. I want to link some programs completely statically, no external libraries needed.
When just linking with "-static" I still have those dynamically linked things:
desktop ~/bin $ ldd sicherung linux-vdso.so.1 (0x00007ffdab53f000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3633da0000) [--snip--] libgmp.so.10 => /lib/x86_64-linux-gnu/libgmp.so.10 (0x00007f3633ce3000) libatomic.so.1 => /lib/x86_64-linux-gnu/libatomic.so.1 (0x00007f3633cd7000) libffi.so.7 => /lib/x86_64-linux-gnu/libffi.so.7 (0x00007f3633ccb000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3633ad9000) /lib64/ld-linux-x86-64.so.2 (0x00007f3633f0c000)
Is it possible to link the remaining libraries statically too?
As Brandon already mentioned, linking glibc statically is not really supported (by glibc!), but what you can do is bundle a few of the .so's together with your binary and use RPATH to help your executable find them at load time (well, dynamic link time).
A project of ours where we do this is using Stack, so I can only really provide info on doing it with Stack, but hopefully you can adapt to whatever you're using:
We added
ld-options: - -Wl,-rpath,$ORIGIN/../lib
to the 'executable' portion of the package.yaml. This instructs the dynamic loader to look for libraries in '../lib' relative to the executable's location. You can pick whatever path you want there.
Once you have that bit set up, you can copy *most* of the libraries .so's you're using to that folder on the install target and they'll be loaded from there. (Copying libc.so is ill advised, but most of the others will work just fine. I believe ld-linux-... is also never ever loaded from there since that *is* the dynamic loader.)
(Of course a possibly more robust version of this is to just bundle everything into a container of some sort, but that may be a bit excessive for your needs.)
Thank you for your elaborate explanation. This would be overkill for what I have in mind. I'm just trying to save a statically linked copy of a program of mine, which is involved in my backup, along with the backup, and also on a maintenance USB stick. I've stowed you answer away in my personal wiki, and may get back to it later. Regards, Volker

On Mon, 10 Aug 2020 at 03:12, Bardur Arantsson
Once you have that bit set up, you can copy *most* of the libraries .so's you're using to that folder on the install target and they'll be loaded from there. (Copying libc.so is ill advised, but most of the others will work just fine. I believe ld-linux-... is also never ever loaded from there since that *is* the dynamic loader.)
Not 100% certain, but I think the issue with libc may be that it may be somewhat tied to the ld-linux. You can actually copy everything, including ld-linux, though. You then invoke the program via ld-linux (it's actually an executable -- see the ld.so page) ./ld-linux-x86_64.so.2 --library-path <path to copied libraries> <executable> <args> ... If you wrap your binaries with a shell script it is actually pretty clean (make sure to exec so you don't windup with the shell sitting between parent and childs that can cause some subtle issues) The only real breakage I've seen from this is when you try and run on too old of a kernel for your libc or the remote system has an unusual nsswitch plugin you didn't provide.

On 10/08/2020 23.22, Tyson Whitehead wrote:
On Mon, 10 Aug 2020 at 03:12, Bardur Arantsson
mailto:spam@scientician.net> wrote: Once you have that bit set up, you can copy *most* of the libraries ..so's you're using to that folder on the install target and they'll be loaded from there. (Copying libc.so is ill advised, but most of the others will work just fine. I believe ld-linux-... is also never ever loaded from there since that *is* the dynamic loader.)
Not 100% certain, but I think the issue with libc may be that it may be somewhat tied to the ld-linux.
You can actually copy everything, including ld-linux, though. You then invoke the program via ld-linux (it's actually an executable -- see the ld..so page)
./ld-linux-x86_64.so.2 --library-path <path to copied libraries> <executable> <args> ...
Hm, yes I was vaguely aware of this ability to invoke the loader directly, but IIRC the most immediate problem with glibc has always been that the nsswitch.conf plugins (which are always dynamically loaded) are strictly tied to the exact gblic version. I guess if you copy them too, it should work, but the issue is that there may be ones on the user's system which aren't present on the CI/build system...
If you wrap your binaries with a shell script it is actually pretty clean (make sure to exec so you don't windup with the shell sitting between parent and childs that can cause some subtle issues)
Yes, this is also a good way to do it and doesn't require messing with the build setup.
The only real breakage I've seen from this is when you try and run on too old of a kernel for your libc or the remote system has an unusual nsswitch plugin you didn't provide.
Ack Regards,

I was able to get static linking working recently using docker alpine
images and ghcup to install GHC based on the musl library. The details are
in my Stan fork [1]. This borrowed heavily from ShellCheck's static
linking release system except it uses cabal v2-build instead of v1.
[1]
Script:
https://github.com/TomMD/stan/blob/feature/basic-json-output/mkRelease.sh
Dockerfile:
https://github.com/TomMD/stan/blob/feature/basic-json-output/Dockerfile
On Sun, Aug 9, 2020 at 5:51 AM Volker Wysk
Hi!
I know of the command line argument "-static". But this only affects the Haskell libraries. I want to link some programs completely statically, no external libraries needed.
When just linking with "-static" I still have those dynamically linked things:
desktop ~/bin $ ldd sicherung linux-vdso.so.1 (0x00007ffdab53f000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3633da0000) librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f3633d95000) libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007f3633d90000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f3633d8a000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f3633d67000) libgmp.so.10 => /lib/x86_64-linux-gnu/libgmp.so.10 (0x00007f3633ce3000) libatomic.so.1 => /lib/x86_64-linux-gnu/libatomic.so.1 (0x00007f3633cd7000) libffi.so.7 => /lib/x86_64-linux-gnu/libffi.so.7 (0x00007f3633ccb000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3633ad9000) /lib64/ld-linux-x86-64.so.2 (0x00007f3633f0c000)
Is it possible to link the remaining libraries statically too?
Regards, Volker _______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users

Hi Thank you very much to Brandon, Tyson, Bardur, Thomas, Andreas, Aycan for your explanations. I thought that it probably was just another GHC argument or something like that. But it sounds quite complicated. What I have in mind isn't worth the trouble. I just wanted to have a statically linked version for inclusion in my backup and in my maintenance USB stick. Perhaps someone with insight could compile the answers to my post into a page for the Haskell Wiki. When I should really need it, I'll come back to this thread later. Cheers, Volker

On 2020-08-12 10:15 a.m., Volker Wysk wrote:
But it sounds quite complicated. What I have in mind isn't worth the trouble. I just wanted to have a statically linked version for inclusion in my backup and in my maintenance USB stick.
I have an exe built by GHC in January 2014 (that's like GHC 7.6), and it is still running just fine on the latest Ubuntu. (In fact I have a daily cron job that runs it.) This is a data point for how long GHC default linking can last IRL. Historically my recollection of the only one breakage event in this regard was a libgmp version bump. And that was a bygone era, clearly before my vintage 2014 exe.
participants (6)
-
Albert Y. C. Lai
-
Bardur Arantsson
-
Brandon Allbery
-
Thomas DuBuisson
-
Tyson Whitehead
-
Volker Wysk