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?
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?
You can't do this if objects within static library was compiled without -fPIC or like.
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.
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
ar -x lib***.a
gcc -shared *.o -o lib***.so
Related
Say I have a.so and b.so.
Can I produce c.so as a single shared library with all the functions exported by a and b, of course resolving all intra-dependencies (i.e. all functions of b.so called by a.so and the other way around)?
I tried
gcc -shared -Wl,soname,c.so -o c.so a.so b.so
but it doesn't work.
Same goes if I archive a.o and b.o in a.a and b.a (which shouldn't modify a.o and b.o), and do
gcc -shared -Wl,soname,c.so -o c.so a.a b.a
Thanks
Merging multiple shared libraries into one is indeed practically impossible on all UNIXen, except AIX: the linker considers the .so a "final" product.
But merging archives into .so should not be a problem:
gcc -shared -o c.so -Wl,--whole-archive a.a b.a -Wl,--no-whole-archive
In practice it is not possible.
From linker point of view, a SO library is a final product that does not contain relocation information required for linking.
If you have access to either source or object files for both libraries, it is straightforward to compile/link a combined SO from them.
I have been following these instructions(http://jonisalonen.com/2012/calling-c-from-java-is-easy/) on how to create a shared library, but these instructions only show how to do it with one file. When I use this file, that I made into a shared library, the .so file can't call other .c files in the same place. How do i compile all the c files so that i can make a merged shared library that is accessible through java?
1) Create your object files with -fPIC:
gcc -fPIC -c file1.c
This creates file1.o. (same for file2.c, file3.c and so on).
2) Link it in a shared library.
gcc -shared -o library.so file1.o file2.o file3.o
Adjust accordingly for additional compiler flags, include paths from other stuff you're using etc.
I have created a http library which contains 2 object files (web.o & webssl.o). These two files share some common constants and functions, that must be repeated for each file. Which also means that I need to update both files when changes are made.
I would like to have a webcommon.o file that I can link to the web.o and webssl.o files. It will contain all the common code that both libraries shares.
I created the webcommon.o file with the shared code. I removed the shared code from web.c and webssl.c. When I go to compile web.c and webssl.c with this:
# gcc -Wall -Werror -O3 -c web.c /my/lib/webcommon.o;
gcc: warning: /my/lib/webcommon.o: linker input file unused because linking not done
Through searching, it appears that the -c option ignores the linking of object files.
How do I create a webcommon.o object file that is used with web.o and webssl.o? Right now it looks like my only 2 options are:
Keep the duplicate code in the web.o and webssl.o and update both files when needed.
Make sure I add the webcommon.o file when compiling a program a program with either web.o or webssl.o
If it is acceptable for webssl.o to have a link dependency on web.o, then you can just have webssl.o declare the shared variables extern, without defining them. When you link a program with webssl.o and web.o, webssl.o will share those extern variables, and webssl.o will have access to the functions in web.o.
This sort of thing is usually done by creating a header containing prototypes of all the shared functions and extern declarations of all the shared variables. All source files sharing those things include the header, but each shared entity is defined in only one source file. Defining a file-scope variable means providing a declaration with an initializer; defining a function means providing the function body.
If you applied this approach, putting all the definitions in the 'web' module, then web.o could be used on its own, but webssl.o could only be used together with web.o.
Alternatively, if you only use web.o and webssl.o independently of each other, then you could build a static library for each that includes webcommon.o as well. That is,
one lib (e.g. libweb.a) containing web.o and webcommon.o, and
one lib (e.g. libwebssl.a) containing webssl.o and webcommon.o
You then link the appropriate static library to your programs, instead of linking web.o or webssl.o directly.
The -c tells gcc to compile an object file so you'd want:
gcc -Wall -Werror -O3 -c web.c -o web.o
gcc -Wall -Werror -O3 -c webssl.c -o webssl.o
...
Then you could link them to put your final executable:
gcc web.o webcommon.o -o web
gcc webssl.o webcommon.o -o webssl
When you compile, the symbols defined in webcommon are stubbed out. When you link, your final executable has the functions defined in your common library.
Since I think web and webssl are libraries, you probably want to create a static library:
ar -c web.a web.o webcommon.o
ar -c webssl.a webssl.o webcommon.o
Or just stick it all in one library:
ar -c weblib.a web.o webcommon.o webssl.o
You might want to look up ld -r to link object files that can then be relinked.
ld -r -o libweb.o web.o webcommon.o
ld -r -o libwebssl.o webssl.o webcommon.o
You can then link with libweb.o or libwebssl.o as required.
Or you could create actual libraries, either libweb.a and libwebssl.a (archive libraries) or libweb.so and libwebssl.so (shared objects). That is the old fashioned way of providing libraries; it has much going for it. If the entry points for the 'web' and 'webssl' portions are distinctly named, then you could build a single library with all three object files in it, and simply link with that.
I need to create a .so by linking it to other opensource libraries (some available as .so and some as .a)
Is it possible to create a .so by linking it with combination of .so and .a
E.g. Say I'm trying to create libfinal.so by linking it with liba.so, libb.a
gcc -shared -Wl,-soname,libfinal.so -Wl,--no-undefined -la -lb
The above command is trying to find libb.so which is not available. Any solution?
UPDATE: The problem seems to be libb.a is compiled with out -fPIC option.
Error --> relocation R_MIPS_26 against `libipt_DNAT_init' can not be used when making a shared object; recompile with -fPIC
Below is command syntax to link object files , archives and libraries.
gcc -o <output file> -l<library> objectfiles|archives
E.g. Linking libc.so.6, Ex.o and binary1.a to generate MyEx.so
gcc -o MyEx.so -lc Ex.o binary1.a
Note : An archive (.a) is nothing but a single file holding a collection of other files
I have the following makefile
CXXFILES = pthreads.cpp
CXXFLAGS = -O3 -o prog -rdynamic -D_GNU_SOURCE -L./libmine
LIBS = -lpthread -ldl
all:
$(CXX) $(CXXFILES) $(LIBS) $(CXXFLAGS)
clean:
rm -f prog *.o
I am trying to include the ./libmine library within CXXFLAGS, but it seems like it is not the right way to include a static library, because when I compile the program, I get many undefined references error. So what is actually the right way to include a static library in the makefile?
use
LDFLAGS= -L<Directory where the library resides> -l<library name>
Like :
LDFLAGS = -L. -lmine
for ensuring static compilation you can also add
LDFLAGS = -static
Or you can just get rid of the whole library searching, and link with with it directly.
Say you have main.c, fun.c and a static library libmine.a.
Then you can just do in your final link line of the Makefile
$(CC) $(CFLAGS) main.o fun.o libmine.a
CXXFLAGS = -O3 -o prog -rdynamic -D_GNU_SOURCE -L./libmine
LIBS = libmine.a -lpthread
Make sure that the -L option appears ahead of the -l option; the order of options in linker command lines does matter, especially with static libraries. The -L option specifies a directory to be searched for libraries (static or shared). The -lname option specifies a library which is with libmine.a (static) or libmine.so (shared on most variants of Unix, but Mac OS X uses .dylib and HP-UX used to use .sl). Conventionally, a static library will be in a file libmine.a. This is convention, not mandatory, but if the name is not in the libmine.a format, you cannot use the -lmine notation to find it; you must list it explicitly on the compiler (linker) command line.
The -L./libmine option says "there is a sub-directory called libmine which can be searched to find libraries". I can see three possibilities:
You have such a sub-directory containing libmine.a, in which case you also need to add -lmine to the linker line (after the object files that reference the library).
You have a file libmine that is a static archive, in which case you simply list it as a file ./libmine with no -L in front.
You have a file libmine.a in the current directory that you want to pick up. You can either write ./libmine.a or -L . -lmine and both should find the library.
The -L merely gives the path where to find the .a or .so file. What you're looking for is to add -lmine to the LIBS variable.
Make that -static -lmine to force it to pick the static library (in case both static and dynamic library exist).
Addition: Suppose the path to the file has been conveyed to the linker (or compiler driver) via -L you can also specifically tell it to link libfoo.a by giving -l:libfoo.a. Note that in this case the name includes the conventional lib-prefix. You can also give a full path this way. Sometimes this is the better method to "guide" the linker to the right location.