3

I want to combine object files and a static library into a shared library but the static library shall not be exposed, it is only referred in the object files that go into the shared library. I think that in this case, I do not need to compile the static library with -fPIC but I do not know how to tell the linker that the fact that I will not use the symbols from the static library. As an illustration of my problem, take the following files:

File foo.cpp:

#include "static.h"
using namespace std;

string version_info()
{
    return static_version_info();
}

File static.cpp:

#include"static.h"
#include <vector>
using namespace std;
string static_version_info()
{
    std::vector<int> ivec;
    return to_string(ivec.size());
}

File static.h:

#ifndef STATIC_H
#define STATIC_H
#include<iostream>
using namespace std;
std::string static_version_info();
#endif 

Then do

$ g++ -c foo.cpp -o foo.o -fPIC
$ g++ -c static.cpp -o static.o
$ gcc-ar rcs static.a static.o
$ g++ -shared foo.o static.a
/usr/bin/ld: static.a(static.o): relocation R_X86_64_PC32 against symbol `_ZNSt6vectorIiSaIiEEC1Ev' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status

Question: How can I adjust the last command such I do not get an error? Is this possible?

Note that I do not want to compile static.cpp with -fPIC and I do not need the symbols (here return_static_version_info()) in the shared library.

phinz
  • 1,225
  • 10
  • 21
  • I am not following your line of thought. If you `...will not use the symbols from the static library...` why do you need it linked in? – SergeyA Oct 31 '18 at 15:24
  • @SergeyA The static library is only used in an interface defined in the object files that are linked together with the static lib into the shared lib. I only access the static lib via this interface. And the question is if in this case I can avoid `-fPIC` for the static lib. – phinz Oct 31 '18 at 15:28

1 Answers1

12

You cannot (or at least you should not) link a static library into a shared library.

Even if you happen to apparently succeed in linking a non-PIC static library libX.a into a shared library libY.so, the resulting thing won't have position-independent code (so would have a lot of "useless" or "annoying" relocations).

A shared library needs to contain only position-independent code (in practice); but a static library does not contain PIC.

I do not want to compile static.cpp with -fPIC

But you really should.

Read Drepper's How to Write Shared Libraries for details.

BTW, some Linux distributions (e.g. Debian) provide a libc6-pic package giving files such as /usr/lib/x86_64-linux-gnu/libc_pic.a which are a static library of position-independent code. This might be used to extend your system's libc.so.6 with e.g. your own function (or your own malloc, etc...).

In practice, you'll better recompile your static library code with -fPIC; BTW the x86-64 ISA was designed to facilitate PIC.

At last, if you care about optimizations, there are many of them. Did you consider compiling and linking with gcc -O3 -fPIC -flto ? In some cases, you might consider -ffast-math (which enables optimizations against the C standard), or replacing -O3 with -Ofast.

And you surely should use a recent GCC or Clang compiler (or a recent proprietary icc). This old question (mentioned in your comments) is about 4.7. Current GCC in fall 2018 is GCC 8, and GCC 9 is worked upon (so should appear in spring 2019). Current Clang is Clang 7. Compilers are continuously making progress on optimizations.

You might want to download the source tarball of the latest release of GCC or of Clang and build that on your computer. This is a good way to have a recent version of these compilers, since distribution makers often prefer an older variant of them (which is compatible even with non-standard compliant code).

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • Of course I can do with `fPIC` but I did not want to slow down my high-performance code from the static library. I thought it is OK to avoid `-fPIC` if I do not need the position independent code from outside (when using the shared library), only via an interface that is defined in the object files which are compiled with `-fPIC`. So this is not true and I still need it even for the static library whose functions will not be called from the user of the shared lib directly? – phinz Oct 31 '18 at 15:25
  • 3
    Are you sure that `-fPIC` slows down your code on `x86-64` ? Did you benchmark? What is the measured slowdown? The x86-64 ISA was designed to facilitate PIC – Basile Starynkevitch Oct 31 '18 at 15:27
  • No, but I read about `-fPIC` that some optimizations are disabled. Yes, I know that one should not try to optimize without benchmarking... – phinz Oct 31 '18 at 15:30
  • Where did you read that? For what ISA? I tend to believe that your source is wrong. – Basile Starynkevitch Oct 31 '18 at 15:30
  • The second answer of https://stackoverflow.com/questions/15861759/how-much-overhead-can-the-fpic-flag-add – phinz Oct 31 '18 at 15:33