ubuntu 12.04编译链接库顺序问题

ubuntu 12.04编译链接库顺序问题

1. 现象描述

在ubuntu 12.04的编译程序过程中,经常发现原来在ubuntu9.10可以编译过的程序在12.04编译不通过,报“undefined reference toxxxxx”的错误,如下图所示:



 

2. 问题分析

经过简单尝试,发现使用以下的方式就可以编译过去:

                      gcc -o xpointer xpointer.c  -lX11


那么:“gcc  -lX11 -o  xpointer   xpointer.c”与”gcc -o xpointer xpointer.c -lX11”到底有什么区别呢?从下面两张图可以看出:

 

 

 

编译过与不过,就主要看“collect2”这个程序的参数顺序,

“collect2 … -lX11xxx.o -lgcc…”就不通过,“collect2 …xxx.o -lX11-lgcc…”就可以编译通过。

那么collect2这个程序的作用是什么呢?

gcc安装的各个部分:

 

g++

c++编译器,链接时使用c++库

 

gcc

c编译器,链接时使用c库

 

cc1

实际的c编译器

 

cc1plus

实际的c++编译器

 

collect2

使用collect2产生特定的全局初始化代码,后台处理是传递参数给ld完成实际的链接工作。

 

crt0.o

初始化和结束代码

 

libgcc

平台相关的库

也就是说,后台真正处理的是ld,collect2只是个传递参数的。从<AnIntroduction to GCC >(http://www.network-theory.co.uk/docs/gccintro/gccintro_18.html)中有这样一句话“Thetraditional behavior of linkers is to search for external functions from leftto right in the libraries specified on the command line. This means that alibrary containing the definition of a function should appear after any sourcefiles or object files which use it.”


从上面的描述我们能够比较清晰的了解到库的先后顺序对链接的影响,但遗留一个问题,就是为什么在ubuntu 9.10上编译没有问题呢?有没有办法去掉库的先后顺序对连接的影响呢?当然,最终还得回到ld才能解决问题,从man ld可以看出有几个选项影响这个:

--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 will add a DT_NEEDED tag for each dynamic

library mentioned on the command line, regardless of whether the library is actually needed.  --as-needed causes a DT_NEEDED tag to only be emitted for a library that satisfies a symbol

           reference from regular objects which is undefined at the point that the library was linked, or, if the library is not found in the DT_NEEDED lists of other libraries linked up to that 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 from ELF DT_NEEDED tags in dynamic libraries mentioned on the command line after the --no-add-needed option.  Normally, the linker will

add a DT_NEEDED tag for each dynamic library from DT_NEEDED tags.  --no-add-needed causes DT_NEEDED tags will never be emitted for those libraries from DT_NEEDED tags. --add-needed restores

the default behaviour.

大体的意思是:

--add-needed                Set DT_NEEDED tags forDT_NEEDED entries in   following dynamiclibs

--no-add-needed             Do not 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

关键的看--as-needed,意思是说:只给用到的动态库设置DT_NEEDED。(详细的分析可以参考:http://blog.csdn.net/littlegrizzly/article/details/7599868

回到我们之前的问题,“collect2 …-lX11 xxx.o -lgcc…”就不通过,“collect2 …xxx.o -lX11 -lgcc…”就可以编译通过?因为gcc对库的顺序要求和--as-needed(因为libX11.so在xxx.o的左边,所以gcc认为没有用到它,--as-needed将其忽略),ld忽略libX11.so,定位xxx.o的符号的时候当然会找不到符号的定义!所以‘undefined reference to’这个错误是正常地!为了验证上述的想法,我们需要看一下ubuntu 9.10及12.04对--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

可见,Ubuntu 12.04对链接的顺序有要求是因为gcc在传递参数给ld时,默认加了--no-add-needed --as-needed两个参数。

分析到这里已经基本结束,但是还有一个问题,就是有没有办法去掉ubuntu 12.04 gcc的这种默认行为呢,也就是说能否给ld传递参数,加上--no-as-needed的呢?Google一下很快就能够找到答案:


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值