假设有如三个源代码文件:

$ cat a.cpp

void a()

{

}

$ cat b.cpp

extern void a();

void b()

{

a(); // 调用a.cpp中的a()

}

$ cat x.cpp

extern void b();

int main()

{

b(); // 调用b.cpp中的b()

return 0;

}

对应的Makefile文件:

all: x

liba.a: a.o

libb.a: b.o

x: x.o liba.a libb.a # 问题出在这儿

g++ -g -o $@ $^

a.o: a.cpp

g++ -g -c $^

b.o: b.cpp

g++ -g -c $^

x.o: x.cpp

g++ -g -c $^

clean:

rm -f a.o b.o x.o x

使用上面的Makefile编译,将会遇到如下所示的“undefined reference”问题:

g++ -g -c x.cpp

g++ -g -c a.cpp

g++ -g -c b.cpp

g++ -g -o x x.o liba.a libb.a # 改成“g++ -g -o x x.o libb.a liba.a”即可解决

libb.a(b.o): In function `b()':

/tmp/b.cpp:2: undefined reference to `a()'

collect2: ld returned 1 exit status

make: *** [x] Error 1

这个问题的原因是b.cpp依赖a.cpp,gcc要求(实际是ld要求)libb.a须放在liba.a前面,即需要改成:g++ -g -o x x.o libb.a liba.a,也就是被依赖的库需要放在后头。

这是最常规的解决办法,除此之外,只需要加入--start-group和--end-group两个链接参数,即可保持被依赖的库放在前头,也就是改成如下即可:g++ -g -o $@ -Wl,--start-group $^ -Wl,--end-group。

这里的“-Wl,”表示后面跟着的参数是传递给链接器ld的,gcc不关心具体是啥。“--start-group”表示范围的开始;“--end-group”表示范围的结束,是可选的。位于“--end-group”之后的仍然要求被依赖的库放在后头。注意“--start-group”不能重复,相关链接参数:--whole-archive
和 --no-whole-archive。

再议GCC编译时的静态库依赖次顺问题的更多相关文章

  1. 再议GCC编译时的静态库依赖顺序问题

    相关博文1:http://blog.chinaunix.net/uid-20682147-id-76330.html相关博文:http://blog.chinaunix.net/uid-2068214 ...

  2. gcc编译时指定链接库的查找目录

    gcc编译时,如果需要链接的库的目录不在标准目录,则需要通过将保护库的目录/aa/bb/cc通过-L/aa/bb/cc 添加到搜索路径中,如: gcc -o xmltest xml_test.cpp ...

  3. Linux下Gcc生成和使用静态库和动态库详解(转)

    一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同( ...

  4. Linux下Gcc生成和使用静态库和动态库详解

    参考文章:http://blog.chinaunix.net/uid-23592843-id-223539.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库 ...

  5. 在Linux使用GCC编译C语言共享库

    在Linux使用GCC编译C语言共享库 对任何程序员来说库都是必不可少的.所谓的库是指已经编译好的供你使用的代码.它们常常提供一些通用功能,例如链表和二叉树可以用来保存任何数据,或者是一个特定的功能例 ...

  6. 【转】Linux下gcc生成和使用静态库和动态库详解

    一.基本概念 1.1 什么是库 在Windows平台和Linux平台下都大量存在着库. 本质上来说,库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不 ...

  7. Linux下GCC生成和使用静态库和动态库【转】

    本文转载自:http://www.cppblog.com/deane/articles/165216.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本 ...

  8. gcc编译时对'xxxx'未定义的引用问题

    gcc编译时对’xxxx’未定义的引用问题 gcc编译时对’xxxx’未定义的引用问题 原因 解决办法 gcc 依赖顺序问题 在使用gcc编译的时候有时候会碰到这样的问题,编译为.o(obj) 文件没 ...

  9. gcc使用及动静态库制作

    一. GCC的使用 1. GCC的编译过程 (1)预处理(cpp)gcc -E(输出问价通常以 .i 结尾),将头文件展开,宏替换等操作: (2)编译器(gcc)gcc -S(输出问价以 .s 结尾) ...

随机推荐

  1. 【转】VC++ 也有 Refactoring 功能了

    原文网址:http://blog.csdn.net/yapingxin/article/details/18923095 分类: C++2014-02-04 14:00 2688人阅读 评论(0) 收 ...

  2. CentOS 6.5 下HeartBeat的安装与配置

    CentOS 6.5 下HeartBeat的安装与配置 参考网站: http://wenku.baidu.com/link?url=BvqJatdx1m12PLil-7YA1zkM0yUOEO8OnN ...

  3. WinForm各浏览器内核控件

    WebKit.NET webkit-sharp CefSharp awesomium OpenWebKitSharp geckofx MozNet Web Component

  4. 给iOS开发新手送点福利,简述UISegment的属性和用法

    UISegment属性 1.segmentedControlStyle 设置segment的显示样式. typedef NS_ENUM(NSInteger, UISegmentedControlSty ...

  5. httpclient pool帮助类

    摘自爬虫类  用于频繁请求减少网络消耗 import java.io.IOException; import java.io.InterruptedIOException; import java.i ...

  6. Oracle 查询历史数据(转帖)

    回复误删除数据信息. 1.执行 alter table table_name enable row movement; 2.执行 FlashBack table table_name to times ...

  7. ES6系列_12之map数据结构

    1.map数据结构出现的原因? JavaScript 的对象(Object),本质上是键值对的集合(Hash 结构),但是传统上只能用字符串当作键.这给它的使用带来了很大的限制.为了能实现将对象作为键 ...

  8. fabric本地一键部署LAMP

    一.添加普通用户jeff执行sudo时无需输入密码 $ sudo vim /etc/sudoers ---------------------------------------> ## All ...

  9. spring security+cas(cas proxy配置)

    什么时候会用到代理proxy模式? 举一个例子:有两个应用App1和App2,它们都是受Cas服务器保护的,即请求它们时都需要通过Cas 服务器的认证.现在需要在App1中通过Http请求访问App2 ...

  10. SpringMvc配置拦截器

    SpringMVC可以通过配置拦截器,进行url过滤等处理. 在spring-mvc.xml的配置文件中,如下示: 其中,在<mvc:interceptors>中可以配置多个拦截器< ...