The link to the static library is basically the same as the link to the target file.obj/.o
Same, but there are some differences. This article briefly describes some details of the Linux static library link process.
Static Library File Format
Static databases are far different from dynamic databases, and do not involve issues such as symbol relocation. In essence, static libraries only package a bunch of target files. There is no standard for static libraries, and there will be slight differences in Linux. The approximate format is clearly described on the Wiki:
Global header----------------- +-------------------------------File header 1 ---> | File nameFile content 1 | | File modification timestamp ----------------- | Owner IDFile header 2 | Group IDFile content 2 | File mode----------------- | File size in bytes... | File magic +-------------------------------
File header
Many fields are represented in ASCII code, so they can be opened in a text editor.
Static libraries are essentially usedar
Command Packaging.o
File. We can even usear
Package some files at will:
$ echo 'hello' > a.txt && echo 'world' > b.txt$ ar -r test.a a.txt b.txt$ cat test.a!<arch>a.txt/ 1410628755 60833 100 100644 6 `hellob.txt/ 1410628755 60833 100 100644 6 `world
Link Process
When the linker links to a static library.o
Similar. The link process can be summarized as follows:
Summary:
- All
.o
Will be linked to the final executable program; Link.o
The.o
Inglobal symbol
Andunresolved symbol
Put in a temporary table
- If multiple
.o
The sameglobal symbol
Then, multiple defined link errors will be returned.
- If the link is over,
unresolved symbol
If the table is not empty, an undefined Link error is returned.
.a
Static library processing is essentially processing each of them.o
The difference is that if.o
No symbol inunresolved symbol
Table, that is, the linker suspects that.o
If this is not necessary, it will be ignored.
You can use some code to demonstrate the above process. When developing a C ++ program, you can use the static variable of the file beforemain
Previously, we executed some things that may benefit the program structure. If.o
(Including.o
) Is linked to the program, the static variable in the file will be priormain
Initialization.
// test.cpp#include <stdio.h>class Test {public: Test() { printf("Test ctor\n"); }};static Test s_test;// lib.cpp#include <stdio.h>class Lib {public: Lib() { printf("Lib ctor\n"); }};static Lib s_lib;// main.cpp#include <stdio.h>int main() { printf("main\n"); return 0;}
The above codemain.cpp
Not referencedtest.cpp``lib.cpp
Symbol in:
$ g++ -o test test.o lib.o main.o$ ./testLib ctorTest ctormain
The generated executable program is linked as expected.test.o``lib.o
. Howeverlib.o
Links are made in the form of static libraries, and the situation is different: For comparison, add a file based on the above Code, and modifymain.cpp
:
// libfn.cppint sum(int a, int b) { return a + b;}// main.cpp#include <stdio.h>int main() { printf("main\n"); extern int sum(int, int); printf("sum: %d\n", sum(2, 3)); return 0;}
Setlibfn.o
Andlib.o
Create a static Library:
$ ar -r libfn.a libfn.o lib.o$ g++ -o test main.o test.o -lfn -L.$ ./testTest ctormainsum: 5
Becauselib.o
The file is not linked, and the static variables of the file are not initialized.
Adjust the link order to further test the previous link process:
# Set libfn. the link of A is placed in main. O front $ g ++-O test. o-LFN main. o-l. main. o: In function 'main': Main. CPP :(. text + 0x19): Undefined reference to 'sum (INT, INT) 'collect2: LD returned 1 exit status
This problem has been encountered many times, and it is a bit confusing. The reason is that the linker is linkedlibfn.a
When you findlibfn.o
Still notPreviously linked*.o
Reference, that is, there is no symbol inunresolved symbol table
Medium, Solibfn.o
Is ignored.
Some practices
Some static library problems will also be encountered during actual development.
Link order problems
The preceding example shows the problem.Adjust the database link SequenceMost problems can be solved, but when there is a circular dependency between static databases, the order cannot be adjusted.
-Whole-Archive
-whole-archive
The option tells the linker.o
For the above example:
$ g++ -o test -L. test.o -Wl,--whole-archive -lfn main.o -Wl,--no-whole-archive$ ./testLib ctorTest ctormainsum: 5
Connectionlib.o
It is also linked in.-Wl
The option tells GCC to pass it as a linker parameter; the reason why it is added at the end of the command line--no-whole-archive
To tell the compiler not to link the default GCC Library
It can be seen that this method is still a bit violent.
-Start-group
Format:
--start-group archives --end-group
Located in--start-group
--end-group
All static databases in will be searched repeatedly, instead of searching only once by default until newunresolved symbol
Generated. That is to say,.o
If anyunresolved symbol
, You may return to the previous static library to continue searching.
$ g++ -o test -L. test.o -Wl,--start-group -lfn main.o -Wl,--end-group$ ./testTest ctormainsum: 5
Viewldd
The man page of this parameter can also view the details of the link process:
The specified archives are searched repeatedly until no new undefined references are created. normally, an archive is searched only once in the order that it is specified on the command line. if a symbol in that archive is needed to resolve an undefined symbol referred to by an object in an archive that appears later on the command line, the linker wocould not be able to resolve that reference. by grouping the archives, they all be searched repeatedly until all possible references are resolved.
Nested static library
Becausear
When creating a static library, the file is essentially packaged. Therefore, you can even create a nested static library to test whether the linker will recursively process.o
:
$ ar -r libfn.a libfn.o$ ar -r liboutfn.a libfn.a lib.o$ g++ -o test -L. test.o main.o -loutfnmain.o: In function `main':main.cpp:(.text+0x19): undefined reference to `sum(int, int)'collect2: ld returned 1 exit status
The visible linker does not recursively process files in the static library.
The reason why we need to mention the nested static library is that we often like to link a static library project to other static libraries. Of course, the link here is not a real link (only a package). Of course, this process can be smart.o
Extract it and package it into the new static library.
If we use a higher dependency management tool like scons, will it do this?
Based on the previous example, we use scons to createliboutfn.a
:
# SconstructStaticLibrary('liboutfn.a', ['libfn.a', 'lib.o'])
Open with a text editorliboutfn.a
You can see its content, or use:
$ ar -tv liboutfn.arw-r--r-- 60833/100 1474 Sep 14 02:59 2014 libfn.arw-r--r-- 60833/100 2448 Sep 14 02:16 2014 lib.o
It can be seen that scons is simply packaged.Therefore, when a static library is built in sconsLink
Other static libraries are meaningless.
References
- AR (UNIX)
- Ld man page
- GNU LD
- Library order in static linking
- Linkers and loaders
- Scons building and linking with libraries
Address: http://codemacro.com/2014/09/15/inside-static-library/
Written by Kevin Lynx posted athttp: // codemacro.com
Analysis on the principle of static Library Link