70

I have a third-party library which consists mainly of a large number of static (.a) library files. I can compile this into a single .a library file, but I really need it to be a single .so shared library file.

Is there any way to convert a static .a file into a shared .so file? Or more generally is there a good way to combine a huge number of static .a files with a few .o object files into a single .so file?

Eli Courtwright
  • 186,300
  • 67
  • 213
  • 256

5 Answers5

55

Does this (with appropriate -L's of course)

gcc -shared -o megalib.so foo.o bar.o -la_static_lib -lb_static_lib

Not do it?

Shahbaz
  • 46,337
  • 19
  • 116
  • 182
dicroce
  • 45,396
  • 28
  • 101
  • 140
  • 7
    Using gcc -shared did the trick, but only after I recompiled with -fPIC. Thanks for pointing me in the right direction! – Eli Courtwright Mar 17 '09 at 17:30
  • 1
    I know this is an old answert but it... doesn't work? With every static library I have tried this the resulting shared object does not export any of the original symbols anymore. – Peter Aug 12 '20 at 12:09
  • I encountered the same issue @Peter – André Cruz Jul 29 '21 at 13:18
  • @Peter: I'm guessing you're not using any `.o` files at all, and just trying to directly convert from static lib to dynamic lib providing all the same symbols. If so, there's [a trick to telling the linker to include all the unused names from the archive](https://stackoverflow.com/q/7935421/364696) you'll need to use. – ShadowRanger May 10 '22 at 17:40
30

You can't do this if objects within static library was compiled without -fPIC or like.

vitaly.v.ch
  • 2,485
  • 4
  • 26
  • 36
  • 3
    On well-supported targets, `PIC` is not essential for shared library code. It just results in much more efficient use of memory (the majority, instead of a minority, of pages can be shared) at the expense of some performance. – R.. GitHub STOP HELPING ICE Oct 04 '10 at 16:42
  • 4
    Missing of -fPIC or like at some conditions result in SegFault – vitaly.v.ch Nov 01 '10 at 09:33
  • @R..GitHubSTOPHELPINGICE I belive you, but source? :-) – Ciro Santilli OurBigBook.com Oct 13 '22 at 13:37
  • @CiroSantilliOurBigBook.com: That comment is from 12 years ago and probably reflected the state of things at the time, but now it's pretty much outdated. The modern consensus is that TEXTREL support is a legacy feature that modern targets aren't really expected to support well or even at all, and indeed many don't. – R.. GitHub STOP HELPING ICE Oct 14 '22 at 13:04
  • @R..GitHubSTOPHELPINGICE no-PIC code still is faster on all major platforms, because of better use of cache – vitaly.v.ch Oct 14 '22 at 14:29
  • @vitaly.v.ch: That's not the topic at hand, and no, it's not even true - modern architectures have completely-free PC-relative addressing. But the topic was whether non-PIC code in shared libraries is supported, and nowadays, the answer is "no, except when it is" (i.e. not in general). – R.. GitHub STOP HELPING ICE Oct 14 '22 at 14:32
20
g++ -shared -o megalib.so foo.o bar.o -Wl,--whole-archive -la_static_lib -lb_static_lib -Wl,--no-whole-archive -lc_static_lib -lother_shared_object

I'm not sure about gcc, but for g++ I had to add the --whole-archive linker option to include the objects from the static libraries in the shared object. The --no-whole-archive option is necessary if you want to link to libc_static_lib.a and libother_shared_object.so, but not include them as a whole in megalib.so.

thkala
  • 84,049
  • 23
  • 157
  • 201
Calm
  • 341
  • 3
  • 4
  • 6
    `-Wl--no-whole-archive` is necessary at the end of the command line. See [the question edit, here](http://stackoverflow.com/questions/7935421/linking-archives-a-into-shared-object-so). – ofavre Aug 07 '12 at 20:52
12

ar -x can be also useful if you want to focus on specific objects from your .as and you don't want to add anything on your own.

Examples:

ar -x lib***.a
gcc -shared *.o -o lib***.so
Anastasios Andronidis
  • 6,310
  • 4
  • 30
  • 53
  • `ar -x` doesn't support unpacking a list of archives, so `ar -x lib1.a lib2.a ...` will print `no entry lib2.a in archive`. The solution is to : `mk extracted; parallel ar --output extracted -x ::: *.a` and then run `gcc` in `extracted` – Samuel Prevost Mar 27 '21 at 17:13
7
ar -x lib***.a
gcc -shared *.o -o lib***.so
  • 1
    Wasn't this just taken from another earlier answer, and posted with less context / explanation? – Dan Sep 11 '19 at 17:34
  • No, there was not such answer by that time. See history. – Artur Shaikhullin Sep 13 '19 at 00:19
  • I could've sworn in the web browser it showed the date for the other one was earlier, but in the phone app it's showing this one was first. My apologies! – Dan Sep 13 '19 at 09:06