Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to optimize size of shared library?

Say we have huge static libraries with lots of unneeded features (in the example below we have libraries lib1.a and lib2.a with unneeded functions g1() and f2()).

We want to build shared library with a few exported methods which use only a few functions/classes from that huge libraries. See example below: we want to export function foo().

QUESTIONS

  1. Can we tell linker (ld) which functions/methods we want to export (like we do it for DLL in Windows)?
  2. Can linker resolve dependecies and remove unneeded functions/methods? Or is there any other way to solve the problem?
  3. If you have a solution, please, write the fixes for the example below.

EXAMPLE

File 1.h:

int f1( int n );
int g1( int n );

File 2.h:

int f2( int n );

File foo.cpp:

#include "1.h"
#include "2.h"

int foo( int n )
{
    return f1( n );
}

File 1.cpp:

int f1( int n ) { return n; }
int g1( int n ) { return n; }

File 2.cpp:

int f2( int n ) { return n; }

File makefile:

CXXFLAGS = -g -I. -Wall -Wno-sign-compare

all: prepare libFoo.so

clean:
    rm -f obj/*.a obj/*.o res/*.so

prepare:
    mkdir -p src
    mkdir -p obj
    mkdir -p res

lib1.a lib2.a: lib%.a: %.o
    ar r obj/$@ obj/$*.o

1.o 2.o foo.o: %.o:
    g++ $(CXXFLAGS) -c -o obj/$@ src/$*.cpp

libFoo.so: lib1.a lib2.a foo.o
    ld -shared -o res/libFoo.so obj/foo.o -Lobj -l1 -l2

And after making target all we have nm res/libFoo.so:

...
000001d8 T _Z2f1i
0000020e T _Z2g1i
000001c4 T _Z3fooi
...

So ld has removed 2.o object file according to dependencies between object files. But didn't remove function g1() from 1.o.

like image 637
artyom.stv Avatar asked Nov 05 '11 16:11

artyom.stv


2 Answers

Perhaps Link Time Optimization (i.e. -flto option to GCC 4.6) could help?

And also the function attribute __attribute__ ((visibility ("hidden"))) and/or __attribute__ ((weak))

And code going into *.so shared objects should be compiled with -fPIC

like image 80
Basile Starynkevitch Avatar answered Dec 16 '22 04:12

Basile Starynkevitch


First, as Basile pointed out, you should add -fPIC flag when building lib{1,2}.a.

Second, you get all of 1.o linked in because that's how UNIX linkers work.

The simplest solution (much simpler than using -flto) is to turn on linker garbage collection by adding -Wl,--gc-sections to libFoo.so link line, and to build lib{1,2}.a with -ffunction-sections -fdata-sections. This will effectively turn each function into its own separate "book".

like image 33
Employed Russian Avatar answered Dec 16 '22 02:12

Employed Russian