I am fairly unfamiliar with static linking in any language, but I'm trying to statically link a Haskell program for usage on other macs. I've managed to statically link on Linux and confirm it to be working on other Linux boxes by using these options: -O2 -static -optl-static -optl-pthread
When I try to use those options on OS X, I get the following error:
ld: library not found for -lcrt0.o
collect2: ld returned 1 exit status
Any idea what is up? Am I doing something completely nuts?
Community-wiki answer for posterity, derived from the comments:
Typically OS X executables dynamically link against the system-provided libraries; static linking is far less common than on Linux. You can run otool -Lv on your executable to see what libraries it dynamically loads. If they're all in /usr/lib or /System/Frameworks and they're not things you installed, then you're probably already OK.
In fact, as per this answer, static linking of mac system libraries is simply disallowed.
Related
In Windows, the dynamic loader always looks for modules in the path of the loaded executable first, making it possible to have private libraries without affecting system libraries.
The dynamic loader on Linux only looks for libraries in a fixed path, in the sense that it is independent on the chosen binary. I needed GCC 5 for its overflow checked arithmetic functions, but since the C++ ABI changed between 4.9 and 5, some applications became unstable and recompiling them solved the issue. While waiting for my distro [kubuntu] to upgrade the default compiler, is it possible to have newly compiled application linking to the new runtime, while packaged application still links to the old library, either by static linkage, or something that mimics the Windows behavior?
One way of emulating it would be to create a wrapper script
#!/bin/bash
LD_LIBRARY_PATH=$(dirname $(which your_file)) your_file
And after the linking step copy the affected library but it is sort of a hack.
You can use rpath.
Let's say your "new ABI" shared libraries are in /usr/local/newapi-libs.
gcc -L/usr/local/newapi-libs
-Wl,-rpath,/usr/local/newapi-libs
program.cpp -o program -lsomething`
The -rpath option of the linker is the runtime counterpart to -L. When a program compiled this way is run, the linker will first look in /usr/local/newapi-libs before searching the system library paths.
More information here and here.
You can emulate the Windows behavior of looking in the executable's directory by specifying -Wl,-rpath,.
[edit] added missing -L parameter and dashes before rpath.
Ok, so I want to link against a lower version of libc / glibc, for compatibility. I noticed this answer about how to do this, on a case-by-case basis:
How can I link to a specific glibc version?
https://stackoverflow.com/a/2858996/920545
However, when I tried to apply this myself, I ran into problems, because I can't figure out what lower-version-number I should use to link against. Using the example in the answer, if I use "nm" to inspect the symbols provided by my /lib/libc.so.6 (which, in my case, is a link to libc-2.17.so), I see that it seems to provide versions 2.0 and 2.3 of realpath:
> nm /lib/libc.so.6 | grep realpath#
4878d610 T realpath##GLIBC_2.3
48885c20 T realpath#GLIBC_2.0
However, if I try to link against realpath#GLIBC_2.0:
__asm__(".symver realpath,realpath#GLIBC_2.0");
...i get an error:
> gcc -o test_glibc test_glibc.c
/tmp/ccMfnLmS.o: In function `main':
test_glibc.c:(.text+0x25): undefined reference to `realpath#GLIBC_2.0'
collect2: error: ld returned 1 exit status
However, using realpath#GLIBC_2.3 works... and the code from the example, realpath#GLIBC_2.2.5 works - even though, according to nm, no such symbol exists. (FYI, if I compile without any __asm__ instruction, then inspect with nm, I see that it linked against realpath#GLIBC_2.3, which makes sense; and I confirmed that linking to realpath#GLIBC_2.2.5 works.)
So, my question is, how the heck to I know which version of the various functions I can link against? Or even which are available? Are there some other kwargs I should be feeding to nm? Am I inspecting the wrong library?
Thanks!
It seems to me that you have mixed up your libraries and binaries a bit...
/lib/libc.so.6 on most Linux distributions is a 32-bit shared object and should contain the *#GLIBC_2.0 symbols. If you are on an x86_64 platform, though, I would expect GCC to produce an 64-bit binary by default. 64-bit binaries are generally linked against /lib64/libc.so.6, which would not contain compatibility symbols for an old glibc version like 2.0 - the x86_64 architecture did not even exist back then...
Try compiling your *#GLIBC_2.0 program with the -m32 GCC flag to force linking against the 32-bit C library.
Context: I'm using a linux toolchain (includes g++, other build tools, libs, headers, etc) to build my code with statically linked libraries. I want to ensure that I'm using ONLY libraries/headers from my toolchain, not the default ones on the build machine. I can use strace to see what g++ is doing (which libraries it is using) while it is compiling which would be helpful in a normal scenario - but my build system has many wrappers around g++ that hide all of the output.
Question: is there a way to obtain from a statically-linked binary any useful information regarding the library and header files which were used to create the binary? I've taken a look at the objdump tool but I'm not sure if it will help much.
Just pass -v to g++ or gcc at link time. It will show all the linked libraries. Perhaps try make CC='gcc -v' CXX='g++ -v'
More generally, -v passed g++ or gcc shows you the underlying command with its arguments because gcc or g++ is just a driver program (starting cc1, ld or collect2, as, ...)
By passing the -H flag to GCC (i.e. g++ or gcc) you can see every included header. So you can check that only the heanders you expect are included.
You cannot see what static library has been linked, because linking a static library just means linking the relevant object file members in it, so a static library can (and usually is) linked in only partly.
You could use the nm command to find names from such libraries.
If you can simply recompile, then there are ways (using some of the techniques that Basile explained) to get the headers and libraries (static or dynamic) but, unfortunately, there is no way to know which libraries were used after the compilation is complete.
I'm trying to use the 64-bit MinGW from http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Automated%20Builds/ but when I compile a program with it, the resulting executable fails when a DLL isn't available.
How do I get this compiler to do static linking with the standard library?
Or is there another distribution of 64-bit MinGW that I should be using instead?
The g++ switch is supposed to be
-static
See
http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html.
-static
On systems that support dynamic linking, this prevents linking with
the shared libraries. On other systems, this option has no effect.
You should post the command line, that you use in order to compile/link, in order to get more help if this does not work for you.
How can I link a shared library function statically in gcc?
Refer to:
http://www.linuxquestions.org/questions/linux-newbie-8/forcing-static-linking-of-shared-libraries-696714/
You need the static version of the library to link it.
A shared library is actually an executable in a special format
with entry points specified (and some sticky addressing issues
included). It does not have all the information needed to
link statically.
You can't statically link a shared library (or dynamically link a static one).
The flag -static will force the linker to use static libraries (.a) instead of shared (.so) ones. But static libraries aren't always installed by default, so you may have to install the static library yourself.
Another possible approach is to use statifier or Ermine. Both tools take as input a dynamically linked executable and as output create a self-contained executable with all shared libraries embedded.
If you want to link, say, libapplejuice statically, but not, say, liborangejuice, you can link like this:
gcc object1.o object2.o -Wl,-Bstatic -lapplejuice -Wl,-Bdynamic -lorangejuice -o binary
There's a caveat -- if liborangejuice uses libapplejuice, then libapplejuice will be dynamically linked too.
You'll have to link liborangejuice statically alongside with libapplejuice to get libapplejuice static.
And don't forget to keep -Wl,-Bdynamic else you'll end up linking everything static, including libc (which isn't a good thing to do).
Yeah, I know this is an 8 year-old question, but I was told that it was possible to statically link against a shared-object library and this was literally the top hit when I searched for more information about it.
To actually demonstrate that statically linking a shared-object library is not possible with ld (gcc's linker) -- as opposed to just a bunch of people insisting that it's not possible -- use the following gcc command:
gcc -o executablename objectname.o -Wl,-Bstatic -l:libnamespec.so
(Of course you'll have to compile objectname.o from sourcename.c, and you should probably make up your own shared-object library as well. If you do, use -Wl,--library-path,. so that ld can find your library in the local directory.)
The actual error you receive is:
/usr/bin/ld: attempted static link of dynamic object `libnamespec.so'
collect2: error: ld returned 1 exit status
Hope that helps.
If you have the .a file of your shared library (.so) you can simply include it with its full path as if it was an object file, like this:
This generates main.o by just compiling:
gcc -c main.c
This links that object file with the corresponding static library and creates the executable (named "main"):
gcc main.o mylibrary.a -o main
Or in a single command:
gcc main.c mylibrary.a -o main
It could also be an absolute or relative path:
gcc main.c /usr/local/mylibs/mylibrary.a -o main
A bit late but ... I found a link that I saved a couple of years ago and I thought it might be useful for you guys:
CDE: Automatically create portable Linux applications
http://www.pgbovine.net/cde.html
Just download the program
Execute the binary passing as a argument the name of the binary you want make portable, for example: nmap
./cde_2011-08-15_64bit nmap
The program will read all of libs linked to nmap and its dependencias and it will save all of them in a folder called cde-package/ (in the same directory that you are).
Finally, you can compress the folder and deploy the portable binary in whatever system.
Remember, to launch the portable program you have to exec the binary located in cde-package/nmap.cde
Best regards
In gcc, this isn't supported. In fact, this isn't supported in any existing compiler/linker i'm aware of.