Rajesh
Rajesh

Reputation: 1135

multiple inclusion of static library in C

I have libTimer.a, lib2.a, lib3.a and application code. lib2.a created by linking libTimer.a (created from timer.o) with other object files a.o and b.o. Even lib3.a also created by linking libTimer.a and other object files such as c.o and d.o.

Now application main.o is linked with libraries lib2.a and lib3.a. I understand that size of the application does not increase (multiple inclusion does not happen) by this method. I just tested and found no change in application size when application is built by linking libraries or by adding individual source files a.o, b.o, c.o, d.o and timer.o.

But are there any guidelines in nesting libraries in this way?

Given below is the command summary:

libTimer.a

Compilation Command:

avr-gcc.exe -Os -Wextra -Wall -mmcu=atmega328p -std=gnu99 \
    -fshort-enums -ffunction-sections -fdata-sections -DF_CPU=16000000UL \
    -g -Os -Wmain -Wextra -Wall -c CL_Timer.c -o Debug\CL_Timer.o

Linking Command:

avr-g++.exe -o Debug\Timer.elf Debug\Timer.o -mmcu=atmega328p \
    -Wl,-Map=Debug\timer.map -Wl,--gc-sections 

Post Build Command:

avr-ar rcs libTimer.a Debug\timer.o
ranlib libTimer.a

Lib2.a

Linking Command:

avr-g++.exe -o Debug\library2.elf Debug\a.o Debug\b.o -mmcu=atmega328p \
    -Wl,-Map=Debug\library2.map -Wl,--gc-sections .\libTimer.a

Post Build:

avr-ar rcs lib2.a Debug\a.o Debug\b.o
ranlib lib2.a

lib3.a

Linking Command:

avr-g++.exe -o Debug\library3.elf Debug\c.o Debug\c.o -mmcu=atmega328p \
    -Wl,-Map=Debug\library3.map -Wl,--gc-sections .\libTimer.a

Post Build Command:

avr-ar rcs lib3.a Debug\c.o Debug\d.o
ranlib lib3.a

Main Application Linking:

avr-g++.exe -o Debug\main.elf Debug\main.o -mmcu=atmega328p \
    -Wl,-Map=Debug\main.map -Wl,--gc-sections .\liba.a .\liba.b

Upvotes: 1

Views: 460

Answers (1)

user2371524
user2371524

Reputation:

What you show as "linking commands" is unnecessary except for your main application. I'm actually surprised that it doesn't throw errors, as your library code shouldn't contain main().

The commands creating the static library are the ar commands (in your case the cross-compiler avr-ar commands). The only thing they do is to place all object files for the library in an archive file (*.a).

With shared libraries, you would have some dependency information, so a shared library can link against another shared library. With static libraries, no such thing exists, they are just archives of object files and in your final linking step of your main application, you have to make sure to link all required libraries. Therefore, with liba and libb both depending on libTimer as you describe, the final linking step is wrong, it should look like this:

avr-g++.exe -o Debug\main.elf Debug\main.o -mmcu=atmega328p \
    -Wl,-Map=Debug\main.map -Wl,--gc-sections .\liba.a .\libb.a .\libTimer.a

This assumes they are actually named liba.a and libb.a -- you have some confusion in your question with libraries called lib2.a and lib3.a as well.

Important thing to note: In your linking command, always list libraries and object files before their dependencies. The linker works by maintaining unresolved symbols and can only resove them from libraries and object files coming later at the command line.

Upvotes: 2

Related Questions