I am working in a big project. And now encounter a link error.
This error can be avoided by a workaround but I can not figure out why it works.
Here is the file structure related to my problem:
project |-package_a |--a.cpp |--... |-package_b |--b.cpp |--c.cpp |--... |-package_others
All the *.o in package_a will be packed in to aa and *.o in package_b will be packed into ba
is used to generate the binary. 用于生成二进制文件。
In package_b/b.cpp, I added a function foo().
And in package_a/a.cpp, I used this function.
But here I will get a link error saying undefined reference of foo() in ao
I can verify (by objdump) that foo() is already in bo
By changing the link command into , the binary can be built successfully. ,可以成功构建二进制文件。 I now understand that the linker do care about the order in linkage list. But please understand this is a big project I have no permission to change the project configuration so the original link order must be kept.
Then I added a dummy function bar() in package_b/c.cpp, which do nothing but just calling foo(), then original will run through without any link error. 会在没有任何链接错误的情况下运行。
Can anybody show me some light why just adding a dummy function in the same package will work in this case?
I'm using g++ 4.4.4 and linux 2.6.18-194.el5
Any comment will be appreciated
This is normal. When linking, the linker goes through the list of object files, finding undefined references which are then satisfied by other object files/libraries coming after it.
You can change this behaviour by either
including one of the archives twice, as in
g++ -o exec aa ba aa
using the -(
construct
g++ -o exec -( aa ba -)
But please understand this is a big project I have no permission to change the project configuration so the original link order must be kept.
Tough luck... Maybe the manager or whoever just doesn't want you to use functions in b
from a
.
Then I added a dummy function bar() in package_b/c.cpp, which do nothing but just calling foo(), then original "g++ -o exec -Bstatic ba aa ..." will run through without any link error.
Could be that another function of package_b/c.cpp
was already referenced, and the linker took bar()
with it (because they are in the same file) and this referenced foo()
, which was subsequently included in the output, too. It succeeded, because foo
was in ba
too.
You may like to read up on how linkers work . BTW, -Bstatic
flag is unnecessary because .a.
object file archives link statically only (as if the list of object files contained in .a
was specified on the command line instead of .a
).
Alternatively, you can always wrap a list of archives to link with --start-group
/ --end-group
options to make the linker scan the list of archives multiple times, so that no ordering of archives is required (like MS VC++ does):
g++ -o exec -Wl,--start-group a.a b.a -Wl,--end-group
See man ld
:
-( archives -)
--start-group archives --end-group
The archives should be a list of archive files. They may be either
explicit file names, or -l options.
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 would not be able to resolve that
reference. By grouping the archives, they all be searched
repeatedly until all possible references are resolved.
Using this option has a significant performance cost. It is best
to use it only when there are unavoidable circular references
between two or more archives.
GCC, unlike the Visual-C++-linker, requires static libraries to be supplied in an order so that references are defined before they are used. Don't ask me why, but you will always have to check that you are listing the files to be linked in the correct order with GCC.
There is an in-depth explanation here .
When you are using a function from a static library, you must on the command line first place the file from which the function is used, then the library where the function is defined. Otherwise, if you place the definition first, gcc (or more specifically, ld) discards the "unused" function. That's how gcc works, sorry.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.