Ubuntu 12.04 Compile link library order problem
1. Description of the phenomenon
In the process of compiling Ubuntu 12.04, it is often found that the ubuntu9.10 can compile the program in the 12.04 compiler does not pass, reported "undefined reference toxxxxx" error, as shown in the following figure:
2. Problem analysis
After a simple attempt, you can compile the past using the following methods:
Gcc-o XPointer xpointer.c-lx11
So: What's the difference between "Gcc-lx11-o xpointer xpointer.c" and "Gcc-o xpointer xpointer.c-lx11"? From the following two diagrams you can see:
Compiled with but, basically see "collect2" This program's parameter order,
"Collect2 ...-lx11xxx.o-lgcc ..." will not pass, "Collect2 ... xxx.o-lx11-lgcc ..." can be compiled.
So what is the role of the COLLECT2 program?
Various parts of GCC installation:
|
g++ |
C + + compiler, using C + + library when linking |
|
gcc |
C compiler, using C-Library |
in link
|
CC1 |
The actual C compiler |
|
Cc1plus |
Actual C + + compiler |
|
Collect2 |
uses collect2 to produce a specific global initialization code, which is passed parameters to the LD to complete the actual link work. |
|
crt0.o |
Initialize and end code |
|
LIBGCC |
Platform-related libraries |
In other words, the background is really dealing with ld,collect2 is only a passing parameter. From <anintroduction to GCC > (http://www.network-theory.co.uk/docs/gccintro/gccintro_18.html) There is a phrase " Thetraditional behavior of linkers is to search for external functions from LeftTo right in the libraries specified on the Command line. This means which alibrary containing the definition of a function should appear after any SourceFiles or object files which Use it. "
From the above description we can more clearly understand the order of the library to the impact of the link, but left a problem, is why the Ubuntu 9.10 on the compiler is no problem. Is there any way to remove the effect of the sequence of libraries on the connection? Of course, eventually it has to go back to the LD to solve the problem, from the man LD can be seen several options affect this:
--as-needed --no-as-needed This option affects ELF dt_needed tags for dynamic libraries mentioned on the command line after the--as-needed option. Normally, the linker'll add a dt_needed tag for each dynamic The library mentioned on the command line, regardless of whether the library is actually needed. --as-needed causes a dt_needed tag to is emitted for a library that satisfies a symbol Reference from regular objects which are undefined at the "point" of this library was linked, or, if the library isn't not Foun D in the dt_needed lists of the "other libraries linked" to "point, A reference from another dynamic library. --no-as-needed restores the default behaviour. --add-needed --no-add-needed This option affects the treatment of dynamic libraries to ELF dt_needed tags in dynamic libraries mentioned on the comma nd line after the--no-add-needed option. Normally, the linker would Add a dt_needed tag for each dynamic library from dt_needed tags. --no-add-needed causes dt_needed tags would never be emitted for those libraries from dt_needed tags. --add-needed Restores The default behaviour. |
The General meaning is:
--add-needed Set dt_needed tags fordt_needed entries in following dynamiclibs
--no-add-needed Don't set dt_needed tags fordt_needed entries in following dynamiclibs
--as-needed only set dt_needed forfollowing dynamic libs if used
--no-as-needed Always set dt_needed forfollowing dynamic Libs
The key to see--as-needed, meaning said: only to use the dynamic library set dt_needed. (Detailed analysis can refer to: http://blog.csdn.net/littlegrizzly/article/details/7599868)
Back to our previous question, "Collect2 ...-lx11 xxx.o-lgcc ..." will not pass, "Collect2 ... xxx.o-lx11-lgcc ..." can be compiled? Because GCC's order requirements and--as-needed for libraries (because libx11.so is on the left side of XXX.O, so GCC doesn't think it is used,--as-needed ignore it), LD ignores libx11.so, and when it locates XXX.O symbols, of course, it can't find the definition of the symbol. So the error of ' undefined reference to ' is normal. To verify the above ideas, we need to look at the way Ubuntu 9.10 and 12.04 uses the--as-needed:
Ubuntu9.10
/usr/lib/gcc/i486-linux-gnu/4.4.1/collect2--build-id--eh-frame-hdr-m elf_i386--hash-style=both-dynamic-linker/ Lib/ld-linux.so.2-o xpointer-z RELRO/USR/LIB/GCC/I486-LINUX-GNU/4.4.1/. /.. /.. /.. /LIB/CRT1.O/USR/LIB/GCC/I486-LINUX-GNU/4.4.1/.. /.. /.. /.. /lib/crti.o/usr/lib/gcc/i486-linux-gnu/4.4.1/crtbegin.o-l/usr/lib/gcc/i486-linux-gnu/4.4.1-l/usr/lib/gcc/ I486-LINUX-GNU/4.4.1-L/USR/LIB/GCC/I486-LINUX-GNU/4.4.1/.. /.. /.. /.. /lib-l/lib/.. /lib-l/usr/lib/.. /LIB-L/USR/LIB/GCC/I486-LINUX-GNU/4.4.1/.. /.. /.. -L/USR/LIB/I486-LINUX-GNU-LX11/TMP/CCUZ403F.O-LGCC--AS-NEEDED-LGCC_S--NO-AS-NEEDED-LC-LGCC--as-needed-lgcc_s-- NO-AS-NEEDED/USR/LIB/GCC/I486-LINUX-GNU/4.4.1/CRTEND.O/USR/LIB/GCC/I486-LINUX-GNU/4.4.1/.. /.. /.. /.. /lib/crtn.o
Ubuntu12.04
/usr/lib/gcc/i686-linux-gnu/4.6/collect2--sysroot=/--build-id --no-add-needed--as-needed --EH-FRAME-HDR -melf_i386--hash-style=gnu-dynamic-linker/lib/ld-linux.so.2-z relro-oxpointer/usr/lib/gcc/i686-linux-gnu/4.6/. /.. /.. /i386-linux-gnu/crt1.o/usr/lib/gcc/i686-linux-gnu/4.6/.. /.. /.. /i386-linux-gnu/crti.o/usr/lib/gcc/i686-linux-gnu/4.6/crtbegin.o-l/usr/lib/gcc/i686-linux-gnu/4.6-l/usr/lib/ gcc/i686-linux-gnu/4.6/.. /.. /.. /i386-linux-gnu-l/usr/lib/gcc/i686-linux-gnu/4.6/.. /.. /.. /.. /lib-l/lib/i386-linux-gnu-l/lib/.. /lib-l/usr/lib/i386-linux-gnu-l/usr/lib/.. /lib-l/usr/lib/gcc/i686-linux-gnu/4.6/.. /.. /.. -lx11/tmp/ccvh7bld.o-lgcc--as-needed-lgcc_s--NO-AS-NEEDED-LC-LGCC--as-needed-lgcc_s--no-as-needed/usr/lib/gcc/ i686-linux-gnu/4.6/crtend.o/usr/lib/gcc/i686-linux-gnu/4.6/.. /.. /.. /i386-linux-gnu/crtn.o
As you can see, the order of the Ubuntu 12.04 links is required because GCC adds --no-add-needed--as-needed two parameters by default when passing parameters to LD.
The analysis here has basically finished, but there is a problem, that is there is no way to remove the Ubuntu 12.04 gcc This default behavior, that is, the LD can pass parameters, plus --no-as-needed . Google will soon be able to find the answer: