Linux: Weak link an entire library, like OS X ld -weak-lfoo - linux

On OS X, ld has a handy option -weak-l, which is like -l, but the library is linked 'weakly'. If the lib can't be found when the executable is loaded, no errors are raised until the program actually encounters a symbol it can't find.
g++ -L. -weak-lfoo -o main.out main.cpp
Is there an equivalent feature in the Linux ld command? I can't find it.
I'm trying to avoid this error:
./main.out: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
...even if libfoo.so is not available. (I happen to know that -- for my use case -- main.out won't be calling any functions that require symbols from libfoo.so.)

afaik, there is no such thing.
At least some recent (2017-03-22) discussion in the Debian-devel mailinglist suggests that this would be a nice-to-have feature (thus implying that it doesn't exist)

Related

Shared library name in executable is different than the filename

A cleaned up version of my compile command looks like gcc -o semantic_seg -Wl,-rpath,... -l:libnvrtc-5e8a26c9.so.10.1 ... and I have a dynamic library file named exactly libnvrtc-5e8a26c9.so.10.1 in the directory specified by the -rpath flag. The command succeeds.
When I go to run my program, it says semantic_seg: error while loading shared libraries: libnvrtc.so.10.1: cannot open shared object file: No such file or directory and when I do ldd it shows libnvrtc.so.10.1 => not found.
So the problem looks like the name of the shared library in the executable is not the same as the filename. Could that be true? Did the 5e8a26c9 part of the name somehow get stripped off?
Update: Creating a symbolic link libnvrtc-5e8a26c9.so.10.1 -> libnvrtc.so.10.1 allows the executable to run. But I'm still not sure the mechanism that causes this name modification to happen. It seems a bit magic.
Could that be true?
This is often true.
On ELF systems, the linker uses SONAME of the library (if it has one) and not its filename to record a runtime dependency.
Running readelf -d libnvrtc-5e8a26c9.so.10.1 | grep SONAME will likely show that in fact that library does have SONAME, and the value of SONAME is libnvrtc.so.10.1.
This used to be very convenient for external library versioning.
Update:
it allows you to link against a library which will be different than the one which will used at run time, but why would I ever want that?
Like I said, it's useful for external library versioning and ABI evolution.
Suppose you ship version 1.0 of libfoo.so. You provide libfoo.so as a symlink to libfoo.so.1, and you use libfoo.so.1 as SONAME.
Any program that links with gcc main.c -lfoo (note: no funny -l:libfoo.so.1 syntax required) will record libfoo.so.1 as its external dependency, and will use that name at runtime.
Time passes, and you are ready to ship version 2, which is not ABI-compatible.
You don't want to cause all your end-users to change their link line, and you don't want to break any existing binaries.
With the SONAME, this is trivial: new package will include libfoo.so.2 with SONAME of libfoo.so.2, and a symlink libfoo.so now pointing to libfoo.so.2.
Voila: both requirements are achieved: existing binaries continue to use libfoo.so.1, newly-linked binaries use libfoo.so.2, no Makefile changes required.

linking fortran code to library

I'm trying to link my main code to a library
main code:
program main1
call test1
end program main1
library:
subroutine test1
print*,'ok'
end subroutine test1
then I create library :
gfortran -shared -fPIC -o lib1.so 1.f90
and compile main code
gfortran -c main.f90
and link
gfortran main.o lib1.so
but I've got this error :
./a.out: error while loading shared libraries: lib1.so: cannot open shared object file: No such file or directory
what am I doing wrong?
your example does work, but you are just missing a small thing: When using a shared library, your program (main.f90 / a.out) will try to find the linked library in one of the library folders (such as /lib*, /usr/lib* or /usr/local/lib*).
If you want to specify another folder for your shared library (for example for testing/debugging), you can use the enviroment variable LD_LIBRARY_PATH to "tell" linux another place to look for shared libraries.
So, assuming you wrote your program in the folder /home/mojijoon/fortran you can get the correct output after setting the library path by:
$: export LD_LIBRARY_PATH=LD_LIBRARY_PATH:/home/mojijoon/fortran
$: ./a.out
ok
You can find more information on shared libraries (and the LD_LIBRARY_PATH enviromental variable) here:
tldp.org - shared libraries

Is it possible to statically link a Haskell application on OS X?

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.

Does linker include libc.so.6 in statically linked file?

When I link executable elf file dynamically it needs libc.so.6 shared library.
When I link executable elf file statically it doesn't need libc.so.6 shared library (it's not surprise).
Does it mean, that to assemble executable file with --static, linker includes libc.so.6 in it?
If not - what file does linker include? where can I search it?
As far as I know, linker includes static libraries in statically assembled file.
If you link as static, the linker will link all the needed object (.o) files from the static libraries (.a). For example, the following command lists the object files which are included in the libc6 library:
ar t /usr/lib/libc.a
(the exact path to libc.a of course differs from system to system)
So answer to your question is no, it will not link the whole libc6 library, but only the needed object files. And also, it doesn't do anything with libc.so.6, since this is only for dynamic linking. It works with the libc.a - static version of the library.
According to #janneb comment, the smallest unit to be linked is "section", so it might not even need to link the whole object files.
The linker is the ld command. If you use that command, it does what you ask. Notice that GNU ld can accept scripts
However, most people are using the gcc command. This is a compiler from the Gnu Compiler Collection suite. Actually, the gcc command is just a driver program, which will run cc1 (the proper C compiler), as, ld and collect2 (which deals with initializations, etc. then invoke the linker).
To understand what exact command[s] gcc is running, pass it the -v program flag.
When you pass -static to gcc it will probably link with e.g. /usr/lib/x86_64-linux-gnu/libc.a or some other static form of the GNU Libc library.

Static link of shared library function in gcc

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.

Resources