库也就是我们常说的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. UVa 12712 && UVaLive 6653 Pattern Locker (排列组合)

    题意:给定 一个n * n 的宫格,就是图案解锁,然后问你在区间 [l, r] 内的所有的个数进行组合,有多少种. 析:本来以为是数位DP,后来仔细一想是排列组合,因为怎么组合都行,不用考虑实际要考虑 ...

  2. idea简单使用

    注意 错误: 找不到或无法加载主类 main.scala03.WordCountDemo 上面解决方法:

  3. bzoj 5277: [Usaco2018 Open]Out of Sorts【冒泡排序瞎搞】

    首先考虑快排的递归什么时候停下,显然是当前段只剩下一个数了,也就是一个数两边出现分隔符 然后再考虑计算冒泡长度这个操作,因为有分割,所以我们可以把这些放到一起冒泡,这和递归每个区间冒泡是等价的 所以答 ...

  4. pyinstaller打包.py程序为.exe操作指南

    pyinstaller打包.py程序为.exe操作指南 20190526内容纲要: 1.pyinstaller安装 2.程序封装 3.可执行程序 0 前言 今天第一次试试将一个py程序封装成一个.ex ...

  5. php安装的扩展php -m可以看到,但是phpinfo()看不到,php-fpm关闭了重新打开还是不行?

    问答 问答详情   php安装的扩展php -m可以看到,但是phpinfo()看不到,php-fpm关闭了重新打开还是不行? centos apache linux html php 3.2k 次浏 ...

  6. [转]广义正交匹配追踪(gOMP)

    广义正交匹配追踪(Generalized OMP, gOMP)算法可以看作为OMP算法的一种推广,由文献[1]提出,第1作者本硕为哈工大毕业,发表此论文时在Korea University攻读博士学位 ...

  7. 题解报告:hdu 1114 Piggy-Bank(完全背包恰好装满)

    Problem Description Before ACM can do anything, a budget must be prepared and the necessary financia ...

  8. jQuery幸运大转盘_jQuery+PHP抽奖程序

    http://www.thinkphp.cn/code/1153.html 网上转盘抽奖程序大多是flash完成的,而本文使用jQuery和PHP来实现转盘抽奖程序. 若是想看更多js特效.网站源码. ...

  9. LN : leetcode 70 Climbing Stairs

    lc 70 Climbing Stairs 70 Climbing Stairs You are climbing a stair case. It takes n steps to reach to ...

  10. Hadoop YARN学习之Hadoop框架演进历史简述

    Hadoop YARN学习之Hadoop框架演进历史简述(1) 1. Hadoop在其发展的过程中经历了多个阶段: 阶段0:Ad Hoc集群时代 标志着Hadoop的起源,集群以Ad Hoc.单用户方 ...