binding .a file with the .so shared library file in linux - c

I have one .a file ( ar command ) which I want to bind it with my .so file during GCC compilation.
How can I do this.
If I run this command :
gcc /usr/local/apr/lib/libapr-1.a ../../ndagentlibc/obj/*.o tideways_xhprof.o tracing.o -shared -o libhello.so
nm libhello.so | grep apr_term
output: U apr_terminate
apr_terminate is not getting its defination

If your .so file needs the .a file, link your .so with the .a file and all of the needed code from the .a archive will be available in the .so file.

Reorder your command and put the .a library at the end...
gcc ../../ndagentlibc/obj/*.o tideways_xhprof.o tracing.o -shared -o libhello.so /usr/local/apr/lib/libapr-1.a
as the ld(1) linker only selects the object modules (*.o) included in a library archive that it knows have unsolved references for at the moment of reading it (as you put it first in your command line, no unsolved references appear by that time, so no library .o component is selected and included at the time of library processing)
In the case of an archive of object modules, the linker tries to do its best, selecting only the ones that appear to be necessary, and putting an archive at first makes the linker to select no files from it to be linked.
note
BTW, the -shared option is used to create a shared object (a .so module) which probably is not what you want. If you want to create a final executable program, don't use -shared. I point at this, because the first time I had to fight with this, I assumed the kind of linking (shared or static) was specified with some option (common mistake, I think) but the kind of linking is actually given, object by object, by the kind of file you feed to the linker, and not with a command line option. Apart of other things, it makes the linker not to comply when some references are missing in the program (it assumes those will be resolved in a later linking)

Related

Is the GCC link option truly necessary when linking to a static library?

I've been playing around with GCC lately and have been experimenting with the linking options. I'm somewhat confused why the link option -l is necessary when statically linking to an archive file. It seems like you can just toss the .a file as if it were an ordinary object file.
For example, take the following make file:
test1 : main.c libfunc.a
gcc main.c -L. -lfunc -o main.out
test2 : main.c libfunc.a
gcc main.c libfunc.a -o main.out
libfunc.a : func1.c func2.c
gcc func1.c -c
gcc func2.c -c
ar cr libfunc.a func1.o func2.o
Make target test1 uses GCC's linking options to link to the archive file. Target test2 instead just includes the archive file direct. Building and running each output seem to result in the same executable.
There are several ways you can tell gcc what file(s) to use. An argument of the form -lname (or the two arguments -l name) says “Search for a library named name”. Per the GCC documentation, this argument is passed to the linker (typically the ld command). The linker looks for a file with a name like libname.extension, where extension is one of the known library files extensions such as .a or .so, and it looks for files with those names in a list of library directories it has. You can add directories to search with the -L switch.
When the linker finds the library, it uses it just as if you had specified the path, so the end result is the same whether you specify the library with -l or with its path.
By using the path, you can specify libraries that are not in the known library directories or that have unusual names.
Note that the linker does not process libraries the same way as object files. When the linker processes an object file, it incorporates everything in the object file into the output file being constructed. When the linker processes a library file, it incorporates only those modules within the library that provide a symbol definition for a symbol referenced by a prior module and not yet resolved. For example, if you write a program that uses sqrt but does not use sin, then, when the linker processes libm.a after reading your object module, it will take the sqrt module from the library but not the sin module.

GCC compiler multiple files issues

I have a compiled C file, called Hello.o. in Hello.o:
I have a main function
and a function called int myfunc().
I wonder if I were to create a new file, hello2.c that contains a main function as well, and declare myfunc at the top of hello2.c,
will i be able to compile hello2.c and link hello.o to it using a gcc command?
Thanks all in advance.
If you want to just use myfunc() in hello2.c you can try linking the two objects files using gcc.Declare the function in a header file Hello.h and include it in hello2.c and generate Hello.o and hello2.c before linking them together by
$ gcc -o output Hello.o hello2.o
I think this should help you
How do I link object files in C? Fails with "Undefined symbols for architecture x86_64"
Object files are linked completely, or not at all. So this won't work.
GCC adds all the files specified in the command line as .o to the binary. Then the libraries (.a) are used to find needed symbols.
If there are duplicate symbols, an error is reported. (It doesn't know which main).
If a library contains more than one .o file, it can ignore the .O files which are not required. These may have duplicates with the binary.

GCC: undefined reference to xxx

I know that have been already asked a lot of time but I can't really solve it...
so I have a src folder where my main.c source is, an srclib where my lib.c file is stored and an include directory where my lib.h file is stored. now the makefile compiles the lib correctly and put the lib.a file in lib folder. the main.cincludes the lib like this:
#include "lib.h"
and it's compiled with -I ../include option, but when i compile it I get the undefined reference to xxx error for every function in the library
so what am I missing?
Nope. -I is for including the header files. You also need to link with the library using -l option.
Note: You may need to provide the path-to-library using -L option.
To quote the online gcc manual
-llibrary
Search the library named library when linking...... The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a. The linker then uses this file as if it had been specified precisely by name.
EDIT:
To quote the remaining part of the same manual
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded.
So, you need to put the -l<libanme> at the last of your compilation statement, as s_echo.c uses functions defined in that particular library.

Link .a library to .o object so only .o needs to be included when building

I'm using a pre-built library called 'libdscud-6.02.a', which includes a lot of low level I/O calls for some specific hardware. From this, I created some wrapper functions which I compiled into an object file called 'io.o'.
Now, I have a few programs which I'm compiling with these I/O functions and instead of having to do this:
gcc libdscud-6.02a io.o -o test test.c
I would like to just have this:
gcc io.o -o test test.c
Is there any way to link the .a file into the .o file so I only need to include the .o file when compiling binaries?
You could do the opposite and add the io.o file to the .a file using ar:
ar q libdscud-6.02.a io.o
One solution would be simply to use a make variable:
IO_STUFF = libdscud-6.02a io.o
...
$(CC) $(IO_STUFF) ...
AFAIK it is not possible to link .a library and .o file to create another intermediate file i.e. file which is not linked like .o file.
The solution provided by Burton Samograd look like a very good option; but in case you are not allowed to modify .a library file then you can follow suggestion provided by DarkDust in case you are building using make.
However you can create a shared library .so file, from a .a library file and .o file (I think that is what Michael Burr is trying to convey). You can use only the shared library instead of both .a & .o file to generate your executable as follows:
Generate shared library gcc io.o libdscud-6.02.a -shared -o io.so (Please note that the order of files passed for linking is important)
Build your source with gcc io.so -o test test.c . To execute your executable path of io.so should be in the look up path of loader (ld) i.e. LD_LIBRARY_PATH.
The right way to work with shared object would be to create a libio.so which is the naming convention and not io.so and build code as gcc test.c -o test -L<path_to_libio.so> -lio and path to libio.so should be in ld's look up path for executing the output executable.
I know creating shared library just to avoid addition of another file for compilation does not seem to be what you want to do ...but it is just for your info in case you didn't already know :)

object file from .a not included in .so

I have created a .c file which is being converted to a .o file along with around 300 other .c files and included in a .a static library. This library, along with many others is being used to create a .so dynamic library. On analyzing both the .a and the .so file with nm, I found that for some reason the symbols defined in the .c file are present in the .a file but not in the .so file. I can think of no reason this should happen. Can somebody please help me out here? The steps used to create the two binaries are:
gcc -fvisibility=hidden -c foo.c -o foo.c.o
ar cr libbar.a foo.c.o ...
gcc -fvisibility=hidden -fPIC -o libfinal.so libbar.a x.o y.a ...
The reason I have specified visibility hidden here is that I want to expose only a few selected symbols. To expose the symbols from foo.c I have specified the visibility attribute so that the functions signatures in the header foo.h look like:
extern int _____attribute_____ ((visibility ("default"))) func();
EDIT: The command nm libbar.a | grep Ctx gives:
000023c5 T CtxAcquireBitmap
000026e9 T CtxAcquireArray
00001e77 T CtxCallMethod
However, nm libfinal.so | grep Ctx does not show anything.
UPDATE: Found another post which discusses the uses of the --whole-archive option. Also, stumbled across the --export-dynamicoption which apparently tells the linker to retain unreferenced symbols. Investigating further.
Try using --whole-archive linker option to include all objects into your shared library when linking
gcc -o libfinal.so -Wl,--whole-archive libbar.a x.o y.a -Wl,--no-whole-archive
From man ld:
--whole-archive
For each archive mentioned on the command line after the --whole-archive option, include every object file in the archive in the
link, rather than searching the archive for the required object files. This is normally used to turn an archive file into a shared
library, forcing every object to be included in the resulting shared library. This option may be used more than once.
Two notes when using this option from gcc: First, gcc doesn't know about this option, so you have to use -Wl,-whole-archive.
Second, don't forget to use -Wl,-no-whole-archive after your list of archives, because gcc will add its own list of archives to your
link and you may not want this flag to affect those as well.
As far as I know, when compiling against a .a, gcc will only pull out the objects that are referenced by the other modules. If your intent is to include the whole content of the .a in the .so, a plain "compile/link x.c into libfinal.so using content in libbar.a" is not what you want.
Creating a dummy reference for the required symbols in my main file did not solve the problem. The referenced symbols appeared in the binary dump (obtained using nm) with a U (= undefined) marker. I managed to solve the problem by linking the object file directly when creating the .so file instead of including it in the .a library first. As these functions were marked extern they were included in the .so even though they were not being referenced within the library. Had they not been marked extern, they would not have been included just like sylvainulg said.
Thanks to Dmitry for pointing out the --whole-archive option. I did not know that such an option exists.

Resources