7

I have a requirement that I link all my libraries statically including libstdc++, libc, pthread etc. There is one omniorb library which I want to link dynamically.

Currently I have dynamically linked all the libraries. ldd shows the following

linux-vdso.so.1 =>  (0x00007fff251ff000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f291cc47000)
libomniDynamic4.so.1 (0x00007f291c842000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f291c536000)
libm.so.6 => /lib64/libm.so.6 (0x00007f291c2e0000)
libgomp.so.1 => /usr/lib64/libgomp.so.1 (0x00007f291c0d7000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f291bebf000)
libc.so.6 => /lib64/libc.so.6 (0x00007f291bb66000)
/lib64/ld-linux-x86-64.so.2 (0x00007f291ce63000)
librt.so.1 => /lib64/librt.so.1 (0x00007f291b95d000)
libomniORB4.so.1 (0x00007f291b6aa000)
libomnithread.so.3 (0x00007f291cf35000

I need ldd to show libomniDynamic4.so.1 as the only dynamically linked library.

How do I achieve this?

4 Answers4

10

Trying to make a linux executable that runs on all distros eh? Good luck...But I digress...

You want to look at the -v flag output for g++. It shows the internal link commands executed by g++/ld. Specifically, you'll want to inspect the the final link command collect2 and all of its arguments. You can then specify the exact paths to the .a libs you want to link against. You'll also have to track down static libs of everything. My libstdc++.a is in /usr/lib/gcc/x86_64-linux-gnu/4.4/libstdc++.a

rant on: My biggest complaint about linux is the fractured state of executables. Why cant I compile a binary on one machine and copy it to another and run it!? Even the Ubuntu distros one release apart will produce binary files that cannot be run on the other due to libc/libstdc++ ABI incompatibilites

edit #1 I just wanted to add that The script on this page produces a .png of an executables .so dependencies. This is very useful when attempting to do what you describe.

Be aware ldd <exename> will list all dependencies down the chain, not just immediate dependencies of the executable. So even if your executable only depended upon omniorb.so, but omniorb.so depended upon, libphread.so, ldd's output would list that. Look up the manpage of readelf to find only the immediate dependencies of a binary.

One other item that to be aware of. if omniorb.so depends upon libstdc++.so, you'll have no choice but to be dependant on that same lib. Otherwise ABI incompatibilities will break RTTI between your code and omniorb's code.

McKay.CPP
  • 440
  • 1
  • 3
  • 11
  • 1
    Frustratingly I don't have enough rep to comment on anybody's post. But I'd like to ask @EmployedRussian why is the belife that "mostly static" binaries are not more portable. Why is the opposite true? I've been able to produce binaries that were not able to run whatsoever without the "mostly static" route.... – McKay.CPP May 31 '11 at 03:52
  • 1
    You now have the rep necessary to comment everywhere. Please use your newly acquired power wisely. – sbi May 31 '11 at 10:05
6

I need ldd to show libomniDynamic4.so.1 as the only dynamically linked library.

That is impossible.

First, ldd will always show ld-linux-x86-64.so.2 for any (x86_64) binary that requires dynamic linking. If you use dynamic linking (which you would with libomniDynamic4.so.1), then you will get ld-linux-x86-64.so.2.

Second, linux-vdso.so.1 is "injected" into your process by the kernel. You can't get rid of that either.

Next, the question is why you want to minimize use of dynamic libraries. The most common reason is usually mistaken belief that "mostly static" binaries are more portable, and will run on more systems. On Linux this is the opposite of true.

If in fact you are trying to achieve a portable binary, several methods exist. The best one so far (in my experience) has been to use apgcc.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • 3
    Can you please elaborate on your comment "*The most common reason is usually mistaken belief that "mostly static" binaries are not more portable, and will run on more systems. On Linux this is the opposite of true."* I've been able to produce binaries that were not able to run whatsoever on other machines without the "mostly static" route... – McKay.CPP May 31 '11 at 11:09
0

It is very difficult to build a single binary that runs on a lot of Linux distros and linking statically is not the key point.

Please note that a binary built with an older glibc version--i.e., an old Linux distro--may run on newer Linux distros as well. This works because glibc is back-compatible.

A possible way to attain the desired result is:

  • compile the binary on an old Linux OS

  • find out all the required libraries for your compiled binary using the command ldd or lsof (when running) on the binary, details here

  • copy the required libraries of the old Linux OS in a 'custom-lib' folder

  • always bundle/release this custom-lib folder with your binary

  • create a bash script that puts the custom-lib folder on top of the folders list in LD_LIBRARY_PATH environment variable, and then invokes your binary.

In this way, by executing the binary with the bash script, I was able to execute binaries on a wide range of embedded devices with very different Linux versions. But there are always problematic cases where this fails.

Please note, I always tested this with cli applications/binaries.

Other possible ways..

There also seems to be elegant ways to compile glibc-back-compatible binaries, for example this that seems to compile binaries compatible with older ABI. But I have not checked this route.

Fabiano Tarlao
  • 3,024
  • 33
  • 40
  • Some debian updates today tell the opposite story, libstdc++-6 is missing, libstdc++-7 is installed, apps need to be recompiled. – Gizmo Jul 08 '19 at 00:21
  • I wonder if, copying libstdc++ from older release could solve the issue, as mentioned, copying the "dependencies" is a way which solved my issues... time ago. – Fabiano Tarlao Jul 09 '19 at 07:05
  • Also sometimes, backcompatibility packages are provided in distros.e.g., https://packages.debian.org/buster/libstdc++6 – Fabiano Tarlao Jul 09 '19 at 07:32
-4

when linking, use -static before specifying the libraries you want to link statically to, and use -dynamic before the libraries you want to link dynamically to. You should end up with a command line looking like this:

g++ <other options here> -dynamic -lomniDynamic4 -static -lpthread -lm -lgomp <etc>

Of course, you'll need .a versions of the libraries you want to link statically (duh).

ZeRemz
  • 1,770
  • 1
  • 13
  • 16