I am using Debian/MIPS+QEMU to build MIPS ports of PortFusion (a TCP tunneling solution). The resulting binaries are linked against GNU libc. Thus, they cannot be just copied over and used on vanilla OpenWrt which ships with uclibc instead of eglibc (which seems binary-compatible with GNU libc).
-static
ignored on MIPS:
root@debian:~# cat hello.hs
main = print 2
root@debian:~# ghc --make hello.hs
[1 of 1] Compiling Main ( hello.hs, hello.o )
Linking hello ...
root@debian:~# ldd ./hello
libgmp.so.10 => /usr/lib/mips-linux-gnu/libgmp.so.10 (0x77908000)
libffi.so.5 => /usr/lib/mips-linux-gnu/libffi.so.5 (0x778ea000)
libm.so.6 => /lib/mips-linux-gnu/libm.so.6 (0x77855000)
librt.so.1 => /lib/mips-linux-gnu/librt.so.1 (0x7783c000)
libdl.so.2 => /lib/mips-linux-gnu/libdl.so.2 (0x77827000)
libc.so.6 => /lib/mips-linux-gnu/libc.so.6 (0x776a0000)
libpthread.so.0 => /lib/mips-linux-gnu/libpthread.so.0 (0x77675000)
/lib/ld.so.1 (0x55550000)
root@debian:~# rm hello
root@debian:~# ghc --make -static hello.hs
Linking hello ...
root@debian:~# ldd ./hello
libgmp.so.10 => /usr/lib/mips-linux-gnu/libgmp.so.10 (0x76f98000)
libffi.so.5 => /usr/lib/mips-linux-gnu/libffi.so.5 (0x76f7a000)
libm.so.6 => /lib/mips-linux-gnu/libm.so.6 (0x76ee5000)
librt.so.1 => /lib/mips-linux-gnu/librt.so.1 (0x76ecc000)
libdl.so.2 => /lib/mips-linux-gnu/libdl.so.2 (0x76eb7000)
libc.so.6 => /lib/mips-linux-gnu/libc.so.6 (0x76d30000)
libpthread.so.0 => /lib/mips-linux-gnu/libpthread.so.0 (0x76d05000)
/lib/ld.so.1 (0x55550000)
info on GHC:
root@debian:~# ghc --info
[("Project name","The Glorious Glasgow Haskell Compilation System")
,("GCC extra via C opts"," -fwrapv")
,("C compiler command","/usr/bin/gcc")
,("C compiler flags"," -fno-stack-protector -Wl,--hash-size=31 -Wl,--reduce-memory-overheads")
,("ar command","/usr/bin/ar")
,("ar flags","q")
,("ar supports at file","YES")
,("touch command","touch")
,("dllwrap command","/bin/false")
,("windres command","/bin/false")
,("perl command","/usr/bin/perl")
,("target os","OSLinux")
,("target arch","ArchUnknown")
,("target word size","4")
,("target has GNU nonexec stack","True")
,("target has subsections via symbols","False")
,("Project version","7.4.1")
,("Booter version","7.4.1")
,("Stage","2")
,("Build platform","mips-unknown-linux")
,("Host platform","mips-unknown-linux")
,("Target platform","mips-unknown-linux")
,("Have interpreter","NO")
,("Object splitting supported","NO")
,("Have native code generator","NO")
,("Support SMP","NO")
,("Unregisterised","YES")
,("Tables next to code","YES")
,("RTS ways","l debug ")
,("Leading underscore","NO")
,("Debug on","False")
,("LibDir","/usr/lib/ghc")
,("Global Package DB","/usr/lib/ghc/package.conf.d")
,("Gcc Linker flags","[\"-Wl,--hash-size=31\",\"-Wl,--reduce-memory-overheads\"]")
,("Ld Linker flags","[\"--hash-size=31\",\"--reduce-memory-overheads\"]")
]
See also: Can GHC link binaries against a libc implementation such as uclibc (used in OpenWrt by default)?
Statically link C++ programs. First, install the package needed: # yum install glibc-static libstdc++-static. Under GCC 4.4, you can use the -static option as for C programs: $ g++ -static. After GCC 4.5, gcc supports the -static-libstdc++ option: $ gcc -static -static-libstdc++ -static-libgcc. Also note the library order.
TL;DR: I made some GHC binaries for linux that rely on musl instead of glibc for easier static linking. Scroll down for the link. As most of you know, musl is a linux only C standard library that is optimized for static linking.
It's a little more complicated than that. glibc has certain function calls which cause dynamic libraries to be loaded, for things like iconv or NSS - glibc NSS includes getpwuid for example, which needs to load pam_unix.so at runtime for account information. Your application is built with glibc X.Y, statically. You give it to a customer.
You can even use other libc implementation like uClibc or musl libc which are more friendly for static linking. A comparison of C/POSIX standard library implementations for Linux can be found here. Linux binaries are not portable if they are built in normal way even with full static linking.
In fact, the -static
flag simply tells GHC to avoid dynamic linking to Haskell libraries. To statically link also to the C libraries, you need to pass -optl-pthread -optl-static
as well. The latter tells the linker to statically link to the C libraries, while the former is (AFAIK) needed due to some ordering of the linked libraries being messed up when doing this.
You need the same flags for a fully static binary on x86 as well, so this isn't specific to ARM and MIPS.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With