Reputation: 2127
I've got a project foo
which depends upon a
, which in turn depends upon b
, in turn depends upon c
. My build script pull/configure
/make
's the three dependencies from source in the correct order, and they compile fine.
Right now, to distribute foo.so
, I also need to distribute all of its dependencies (a.so
, b.so
, and c.so
) alongside. I want to build a foo.so
containing all the objects of both foo
and all of its dependencies; that way I can distribute a single library.
a
, b
, and c
all use autotools, and generate the associated *.o files in the src/ directory, as well as a .libs/ directory containing the usual smattering of *.ar, *.lo, *.lai, and *.so files, all valid. Right now, I'm using this set of gcc flags to build my foo.so
:
gcc -shared ./my/src/*.c \
-I./a/include -I./b/include -I./c/include \
-L ./a/.libs -L./b/.libs -L./c/.libs \
-la -lb -lc \
-o ./foo.so \
-w -fPIC -m64 \
-std=c99
(note that "-la -lb -lc" are just "-l" flags for each dependency, i'm not just messing up the flags).
Using readelf -d
on the resultant foo.so
indeed shows that it has a dependency on a
. Given that I've got all the build files for all the dependencies, it really feels like I'm just missing some flag for "include this path when looking for *.o files to link".
I've tried a variety of things, and honestly can't even remember the different errors and conditions that led to them. The most promising lead was this question, but after removing my "-l" lines in favor of "-Wl,--whole-archive" lines, I get this error (note that "a.a" is just the *.a for a
):
/usr/bin/ld: ./a/.libs/a.a(bands.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
./a/.libs/a.a(bands.o): error adding symbols: Bad value
Which makes no sense to me, since those files need to be PIC in order to build them into a *.so, right? The build process for these dependencies makes a *.so.
I'm on Mint Linux, if it matters.
Upvotes: 1
Views: 1143
Reputation: 2127
With help from the answerers here, I was able to get a working solution. I had fundamentally misunderstood that autotools generates two sets of *.o files, one which is PIC, one which isn't. The location for each one is in the *.lo file. My dependencies (a
, b
, and c
) were all built with autotools, and i needed to link against the PIC versions, not the combined static *.a version.
I also needed to split my build process into two parts with libtool. A compile phase just to build my code, and the linker phase that looked at the PIC versions of the dependencies.
I didn't end up with a pretty script, but if anyone hits the same scenario, my ugly gcc lines look like. Hopefully it will be a jumping point to something less... awful than what I came up with.
find ./my/src -name "*.c" -exec \
libtool --mode=compile gcc -c -O -g \
-I./a/include -I./b/include -I./c/include \
-L./a/.libs/*.lo -L./b/.libs/*.lo -L./c/.libs/*.lo \
-la -lb -lc \
-w -m64 \
-std=c99 \
{} \;
gcc \
-g -O -w -fPIC -m64 -std=c99 -shared \
-o ./foo.so \
$(find . -wholename "*.libs/*.o");
Upvotes: 1
Reputation: 206557
The error message is very clear on what needs to be done.
/usr/bin/ld: ./a/.libs/a.a(bands.o): relocation R_X86_64_32S against
`.rodata' can not be used when making a shared object; recompile with -fPIC
^^^^^^^^^^^^^^^^^^^^^
./a/.libs/a.a(bands.o): error adding symbols: Bad value
The object code that we are part of the static libraries cannot be put in a shared library unless they are compiled with the -fPIC
option.
Upvotes: 3