Statically linking a library - linker

I have a library say libX.a I am creating one more library myLib2.a i want to statically link libX.a with myLib2.a
The problem is when i use myLib2.a it complaints asking for libX.a but i want libX.a to be part of myLib2.a so that I can directly use myLib2.a
I have already tried to generate myLib2.a and was successful in doing so but when I try to use it i get error.
Can you please suggest is this is possible? and if possible how can we achieve this using a makefile.
Thanks and regards,
Rohit

I want to link the two libraries to make one library.
You don't want to link the two libraries; you want to combine them. A recipe is here.

Extract the object files from libX.a (using ar -x), then add them to myLib2.a (using ar -r).
In a makefile:
CONTENTS := $(filter %.o,$(shell ar -t libX.a))
libMy2.a: libX.a
ar -x libX.a
ar -r $# $(CONTENTS)
rm $(CONTENTS)

Related

C : How to link all o file into one file

I try to integrate a C library into my project. The custom makefile of this project try to compile all source files, each file into one object file (*.o).
I need to link all of those *.o files into one file, for example so file, for easily to use it. Do I need this ? And if yes, how can I link all of *.o files into one library file. Which lines I will add to Makefile ?
(Notes that, this C library include many sub-directory, and a big makefile will go into all sub directories, and use Makefile in each directory to run it)
Thanks :)
see this is best document.
Lets see i have 2 .o files. ctest1.o ctest2.o
so i will make static library as follows way.
ar -cvq libctest.a ctest1.o ctest2.o
For dynamic .so file
gcc -Wall -fPIC -c *.c
gcc -shared -Wl,-soname,libctest.so.1 -o libctest.so.1.0 *.o
mv libctest.so.1.0 /opt/lib
ln -sf /opt/lib/libctest.so.1.0 /opt/lib/libctest.so.1
ln -sf /opt/lib/libctest.so.1.0 /opt/lib/libctest.so
This creates the library libctest.so.1.0 and symbolic links to it.

Makefile for a system

I'm trying to build an application where there are two different systems interacting with each other and most of their functionalities are common. So I'm planning a directory structure like this.
Xxx
|_sys1
|
|_sys2
|
|_common
Each have a separate include and src directories.
Learned from a little browsing that keeping the compilation of common as libcmn.so will be efficient and can be linked for compiling xxx and yyy.
Though I understand how to create a .so, using them in a makefile with variables and linking header files are new to me.
Can someone guide me on how the Makefile for each should be and how linking should be done for a proper build?
In a make(1) control file, sequencing is important. Here is the general rule:
Targets placed on the same prerequisites line may be build concurrently. Order is preserved between different <code>Makefile</code> targets. So something like this:
all:: a b
a:: a.o lib/libfoo.so
${CC} ${LDFLAGS} -o $# a.o -Llib -rpath=lib -lfoo.so ${LDLIBS}
b:: b.o lib/libfoo.so
${CC} ${LDFLAGS} -o $# b.o -Llib -rpath=lib -lfoo.so ${LDLIBS}
lib/libfoo.so:
${MAKE} -C lib all
Now, on a big server you can do this:
$ make -j10 all
and everything will be built in the right order. Just be sure there is a Makefile in the lib directory that knows how to build the library.
Unless libfoo.so is significantly large, I'd make it a static libary, then you would not have to pre-program where to find it later at runtime.
To compile xxx and yyy that use your libcmn.so, they just need to include the library interface header.
To link with the library just add a -lcmn and -Lpath/to/your/lib to your LDFLAGS
To be noted that using this method, you will need to :
Add the library path to LD_LIBRARY_PATH
or add the library path to ldconfig
or move the library to a place where ldconfig looks already (/usr/lib for example)
You can also use the dlopen and dlsym functions to map your libcmn functions to function pointers at runtime. This will allow you to specify the path and name of the library to load at runtime and avoid the LD_LIBRARY_PATH problem.
You will need to add the -ldl flag to compile using this technique

Kernel module makefile - How to make a static library from objects and then link with another object to make the final module

I have the following Makefile for a kernel module:
EXTRA_CFLAGS+=-DLINUX_DRIVER -mhard-float
obj-m += main.o
other-objs := Obj.o Obj1.o Obj2.o Obj2.o ...
Question:
How can I first make a static lib from all the objects and only then link with the main object with the created static lib?
I know how to make this process manually in two steps. First I call the version above. then I call:
ar rcs libother.a Obj.o Obj1.o ...
And then I change the makefile to:
EXTRA_CFLAGS+=-DLINUX_DRIVER -mhard-float
obj-m += main.o libother.a
Since I don't master Makefiles I wonder if anyone knows a quick and clean solution for this.
Thanks,
Nuno
I will answer to my own question. I found in Kernel Makefile documentation the following:
3.5 Library file goals - lib-y
Objects listed with obj-* are used for modules, or
combined in a built-in.o for that specific directory.
There is also the possibility to list objects that will
be included in a library, lib.a.
All objects listed with lib-y are combined in a single
library for that directory.
So, what I did was to change the make file to look like this:
EXTRA_CFLAGS+=-DLINUX_DRIVER -mhard-float
obj-m += main.o lib.a
lib-y := Obj.o Obj1.o Obj2.o Obj2.o ...
I don't knwo why, but the suggested answers were making the makefile "forget" it was a kernel makefile and all the kernel includes and addition defines in the extra flags were being ignored.
Hope it helps someone in the future,
With my best regards,
Nuno Santos
Add this rule to your Makefile:
libother.a: $(other-objs)
ar cr $# $<
You can do it like this:
#your variable definitions here
all: your_module_name
your_module_name: main.o libother.a
gcc $(YOUR_OPTIONS_HERE) -o your_module_name main.o -L. -lother
libother.a: $(other-objs)
ar rcs $# $^
main.o: main.c
#your .o file dependencies here, if needed
.PHONY: all
This way your module will depend on both main.o and libother.a, while libother.a will be remade whenever any of other-objs is changed
Note that the library is linked via -lother option (as it is usually done with libraries). You will also need to specify that the current directory should be included in library search path with -L.

Getting undefined references when linking against a static library

I made a static library with GCC. Building of the library was OK.
When I use it the linker throws undefined reference errors on some functions. But nm says the functions are defined and exported in the static library (marked with T). I know about the linking order that I need to put the libraries after that module that needs them so this can not be a problem.
The static library was built from 3 C files. A.c B.c and D.c The D module depend on A and B (includes their headers).
No problem when I use functions from A and B but when I try to use any function from D I get undefined reference errors on them.
If I move these functions in A or B it works. But not if they are in the D module.
I'm completely run out of ideas what's going on or what is I'm overlooked.
I'm using Code::Blocks and working with plain C files.
An old trick that many times works: List each static library twice in the linking phase.
i.e., in your makefile (or whatever you're using), put:
gcc -o <outfile> <liba> <libb> <libc> <liba> <libb> <libc>
Anyway, I hope you get the idea.
I found out that I added A .cpp file to my project and I just renamed it to .c. I chose C language instead of C++ when I created the project. I did't think this could cause problems
I thought the file extension decides when the IDE chooses between gcc and g++. But not. In Code::Blocks if you add a file with a .cpp extension it will use g++. If you add a file with a .c extension it will use gcc. But if you rename the file it will use the same compiler. You have to change it explicitly in the project options.
That D module was built using g++ instead of gcc.
I realized this when I set the IDE to show me the entire command line when building not just "Compiling foo.c".
In the master make file I wrote to simplify my application/library builds, the solution I used was to run the link step twice. Using the -u linker option to specify undefined symbols on the second link.
In my make file I have a target like this:
undefined.txt:
#$(generate-undefined-syms)
which calls this macro... the first attempt at linking...
define generate-undefined-syms
$(PRINTF) "$(this_makefile): Generating undefined symbols ... \n"
$(CC) -o rubbish $(LDFLAGS) $(objects) $(LDLIBS) 2>&1 | $(GREP) 'undefined reference' > tmp.txt; \
$(SED) 's/^.*`/-Wl,-u/g' < tmp.txt > undefined.txt; \
rm -f tmp.txt rubbish
endef
As my sed/regexp skills aren't good (and I wrote this stuff in a rush) I end up with undefined.txt containing:
-uSomeSym'
-uSomeOtherSym'
i.e. with a trailing '
I then use this make syntax to strip the 's, and remove duplicates
undefined_references = $(filter-out follow, $(sort $(subst ',,$(shell cat undefined.txt))))
The 'follow' filter is because if an undefined symbol is referenced many times, a message "more references to XXX follow" appears in the output, which leads to a spurious 'follow' in the undefined.txt file e.g.
-Wl, uXXXX' follow
Finally I link the second time (note the dependency on undefined.txt)
$(application): $(library_dependencies) $(objects) undefined.txt
$(CC) -o $# $(LDFLAGS) $(undefined_references) $(objects) $(LDLIBS)
I'd totally recommed the following book by the way, as I was able to write from scratch a simple build system in a couple of days.
Managing Projects with GNU Make, Third Edition
By: Robert Mecklenburg
Perhaps you should use ranlib or the approriate ar option to provide an index to your .a file.

Convert a Static Library to a Shared Library?

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

Resources