库也就是我们常说的library,一个库是若干个已经编译过的目标文件(.obj)的集合,它可以被链接到程序里。那么我们最常见的使用就是,我们在编程时会调用一些函数,这些函数别人已经写好了,它就放在库里面。比如C的数学库里的sqrt开根号函数,这个函数在libm.a里。

库通常存放在专门的档文件里,以".a"为文件后缀,也即linux下的静态库。使用GNU的归档命令ar就可以从目标文件(.obj)构建档文件。链接工具linker会在编译时解决函数引用问题。本文将只介绍静态库。需要使用共享库的动态链接可期待我接下来的文章。

在linux下,一般的系统库都放在"/usr/lib"和"/lib"下。例如,在类Unix系统下,C的数学库一般存放在"/usr/lib/libm.a"。而相应的函数原型声明则在"/usr/include/math.h"给出。C的标准库则存在"/usr/lib/libc.a',这里面有ANSI/ISO C标准中指定的函数,比如"printf",这个库默认被所有C程序自动链接。

接下来给一个例程,在这个例程(calc.c)里,需要调用数学库(libm.a)中的一个函数sqrt。

#include <math.h>
#include <stdio.h> int
main (void)
{
double x = sqrt (2.0);
printf ("The square root of 2.0 is %f\n", x);
return ;
}

当我们尝试创建一个可执行文件时,compiler在链接阶段发出error。

$ gcc -Wall calc.c -o calc
/tmp/ccbR6Ojm.o: In function `main':
/tmp/ccbR6Ojm.o(.text+0x19): undefined reference
to `sqrt'

这个问题产生的原因是链接时无法解析sqrt函数(这个calc.c里并没有对sqrt函数的定义,默认链接的库libc.a里也找不到相关解析。而真正定义声明了这个函数的外部库libm.a没有被链接到,所以不能从这个库里找)。顺便说一下,报错里提到的这个“/tmp/ccbR60jm.o”是一个用于链接进程的临时目标文件。那么应该如何解决这个问题呢?

我们需要想办法提供"libm.a"这个库给编译器。一个很容易想到但是十分笨拙的方法就是在编译命令里显式地提到这个库:

$ gcc -Wall calc.c /usr/lib/libm.a -o calc

"ilbm.a"这个库包含了所有数学公式的目标文件,例如sin,cos,exp,log以及sqrt。链接器linker会去搜索这个库去找包含sqrt这个函数的目标文件。

一旦找到了那个目标文件,刚才的代码就可以顺利地生成完整的可执行文件:

$ ./calc
The square root of 2.0 is 1.414214

生成的这个可执行文件将会含括main函数的机器码和sqrt函数的机器码(从libm.a中拷贝相应的目标文件)。也就是运行的时候已经不需要libm.a了。

但是我们不会希望每次都要在编译的命令里放辣么长的path吧。因此gcc编译器提供了短的选项命令符"-l" 一遍链接时触及你想要的库。下面的命令可以替换之前的编译命令。

$ gcc - Wall calc.c -lm -o calc

使用编译器选项 -lNAME 可以让编译器尝试链接  "libNAME.a"(一般来说这个库必须处于标准库目录)里的目标文件。至于其他目录里的库文件如何链接(使用编译器选项指明环境变量)请期待后续文章。所以一般大型的项目将会用到很多-l 选项去链接各种能够各样的库:数学库、图形库还有网络库等等。

参考资源:

1  gcc入门

2  An Introduction to GCC - for the GNU compilers gcc and g++

3  Linux下的tar压缩解压缩命令详解

4  linux下的find文件查找命令与grep文件内容查找命令

GNU编译器学习 --> 如何链接外部库【Linking with external libraries】的更多相关文章

  1. Keil5.15使用GCC编译器链接.a库文件

    我们知道,当使用第三方的代码时,人家有可能会扔个Lib文件给你.这时候,别人仅仅要提供header文件给你,则你就能够通过Lib文件及header的函数声明,对Lib中的函数进行调用.在Keil中假设 ...

  2. vc如何编译链接opengl库

    强烈推荐的一篇强大的OpenGl学习博文OpenGL入门学习 vc2012如何链接opengl库? 首先,我们需要下载opengl的库文件,http://pan.baidu.com/s/1kTsjkZ ...

  3. linux下 GCC编译链接静态库&动态库

    静态库 有时候需要把一组代码编译成一个库,这个库在很多项目中都要用到,例如libc就是这样一个库, 我们在不同的程序中都会用到libc中的库函数(例如printf),也会用到libc中的变量(例如以后 ...

  4. Linux gcc链接动态库出错:LIBRARY_PATH和LD_LIBRARY_PATH的区别

    昨天在自己的CentOs7.1上写makefile的时候,发现在一个C程序在编译并链接一个已生成好的lib动态库的时候出错.链接命令大概是这样的: [root@typecodes tcpmsg]# g ...

  5. Linux下Qt创建共享库与链接共享库详解

    随着程序写的逐渐变多,或多或少的我们都会使用别人写好的库:或者我们不想让别人看到我们的一些核心程序,可以将核心程序封装成库.本次和大家分享的是在Ubuntu下使用Qt生成共享库以及在Qt中链接共享库的 ...

  6. vs2010静态链接MFC库报链接错误

    由于需要将MFC程序在其它电脑上运行,所以需要将动态链接的MFC改成静态链接,本以为很简单,没想到链接的时候出现下面的链接错误: uafxcw.lib(afxmem.obj) : error LNK2 ...

  7. C++学习笔记23:库

    静态库(Archives) 后缀一般为"*.a" 使用两个目标文件创建单一静态库的编译与链接命令:ar cr libtest.a  test1.o test2.o 链接器搜索静态库 ...

  8. 从Theano到Lasagne:基于Python的深度学习的框架和库

    从Theano到Lasagne:基于Python的深度学习的框架和库 摘要:最近,深度神经网络以“Deep Dreams”形式在网站中如雨后春笋般出现,或是像谷歌研究原创论文中描述的那样:Incept ...

  9. Unix环境链接静态库

    静态库 请点评 有时候需要把一组代码编译成一个库,这个库在很多项目中都要用到,例如libc就是这样一个库,我们在不同的程序中都会用到libc中的库函数(例如printf),也会用到libc中的变量(例 ...

随机推荐

  1. node.js在读取文件时中文乱码问题

    断更很久了........从今天开始会努力的持续更博,积极学习. 言归正传.今天在写node.js的demo时发现一个bug.我在node中读取本地的text文件时,发现英文的内容可以被读取,但是中文 ...

  2. 洛谷P3239 [HNOI2015]亚瑟王(期望dp)

    传送门 stdcall大佬好强 期望的姿势不是很高……据大佬说期望有一个线性性质,也就是说可以把每一张牌的期望伤害算出来然后再加起来就是总的期望伤害 因为每一张牌只能用一次,我们设$dp[i]$表示第 ...

  3. WPF-DataGrid(数据表格)美化

    我们不多哔哔先上图: 数据表格使用背景: 当我们在做二次开发发现我我们的表格无法向WEB的表格一样好看,这时我们就需要对数据表格进行美化和重构 表格美化思维引导: WPF数据表格是由表头和表体(内容) ...

  4. 【SpringCloud构建微服务系列】Feign的使用详解

    一.简介 在微服务中,服务消费者需要请求服务生产者的接口进行消费,可以使用SpringBoot自带的RestTemplate或者HttpClient实现,但是都过于麻烦. 这时,就可以使用Feign了 ...

  5. [POI2009]SLO

    Description 对于一个1-N的排列(ai),每次你可以交换两个数ax与ay(x<>y),代价为W(ax)+W(ay) 若干次交换的代价为每次交换的代价之和.请问将(ai)变为(b ...

  6. 在 c#中 如何 重新激活一个控件

    比如toolBar是一个组合控件 this.toolBar.CaptionHeight =this.toolBar.Items.Count * 60;//重新激活toolBar控件 CaptionHe ...

  7. C. Mahmoud and a Message dp + 暴力

    http://codeforces.com/contest/766/problem/C 关键在于dp,如何计数. 设dp[i]表示前i个字母中,能分成多少份合法的情况.那么答案就是dp[n],其中dp ...

  8. 转】[MySQL优化]为MySQL数据文件ibdata1瘦身

    原博文出自于: http://blog.fens.me/category/%E6%95%B0%E6%8D%AE%E5%BA%93/page/2/ 感谢! [MySQL优化]为MySQL数据文件ibda ...

  9. 工作记录:JS正则表达式 angularjs ng-if ng-show ng-switch

    用了一下JS 正则表达式判断密码,很简单 学习了angularjs的ng-if ng-show ng-switch的区别并使用 https://www.cnblogs.com/54td/p/59743 ...

  10. 10.3 Implementing pointers and objects and 10.4 Representing rooted trees

    Algorithms 10.3 Implementing pointers and  objects  and 10.4 Representing rooted trees Allocating an ...