GNU编译器学习 --> 如何链接外部库【Linking with external libraries】
库也就是我们常说的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++
4 linux下的find文件查找命令与grep文件内容查找命令
GNU编译器学习 --> 如何链接外部库【Linking with external libraries】的更多相关文章
- Keil5.15使用GCC编译器链接.a库文件
		
我们知道,当使用第三方的代码时,人家有可能会扔个Lib文件给你.这时候,别人仅仅要提供header文件给你,则你就能够通过Lib文件及header的函数声明,对Lib中的函数进行调用.在Keil中假设 ...
 - vc如何编译链接opengl库
		
强烈推荐的一篇强大的OpenGl学习博文OpenGL入门学习 vc2012如何链接opengl库? 首先,我们需要下载opengl的库文件,http://pan.baidu.com/s/1kTsjkZ ...
 - linux下 GCC编译链接静态库&动态库
		
静态库 有时候需要把一组代码编译成一个库,这个库在很多项目中都要用到,例如libc就是这样一个库, 我们在不同的程序中都会用到libc中的库函数(例如printf),也会用到libc中的变量(例如以后 ...
 - Linux gcc链接动态库出错:LIBRARY_PATH和LD_LIBRARY_PATH的区别
		
昨天在自己的CentOs7.1上写makefile的时候,发现在一个C程序在编译并链接一个已生成好的lib动态库的时候出错.链接命令大概是这样的: [root@typecodes tcpmsg]# g ...
 - Linux下Qt创建共享库与链接共享库详解
		
随着程序写的逐渐变多,或多或少的我们都会使用别人写好的库:或者我们不想让别人看到我们的一些核心程序,可以将核心程序封装成库.本次和大家分享的是在Ubuntu下使用Qt生成共享库以及在Qt中链接共享库的 ...
 - vs2010静态链接MFC库报链接错误
		
由于需要将MFC程序在其它电脑上运行,所以需要将动态链接的MFC改成静态链接,本以为很简单,没想到链接的时候出现下面的链接错误: uafxcw.lib(afxmem.obj) : error LNK2 ...
 - C++学习笔记23:库
		
静态库(Archives) 后缀一般为"*.a" 使用两个目标文件创建单一静态库的编译与链接命令:ar cr libtest.a test1.o test2.o 链接器搜索静态库 ...
 - 从Theano到Lasagne:基于Python的深度学习的框架和库
		
从Theano到Lasagne:基于Python的深度学习的框架和库 摘要:最近,深度神经网络以“Deep Dreams”形式在网站中如雨后春笋般出现,或是像谷歌研究原创论文中描述的那样:Incept ...
 - Unix环境链接静态库
		
静态库 请点评 有时候需要把一组代码编译成一个库,这个库在很多项目中都要用到,例如libc就是这样一个库,我们在不同的程序中都会用到libc中的库函数(例如printf),也会用到libc中的变量(例 ...
 
随机推荐
- 真正认识 realloc 的工作方式(转载)
			
转自:http://www.cnblogs.com/ren54/archive/2008/11/20/1337545.html realloc 用过很多次了.无非就是将已经存在的一块内存扩大. cha ...
 - Rebel 6 破解版及使用方法
			
下载地址:http://www.zeroturnaround.com/jrebel/download/ 下载下来的是一个Zip压缩包,打开之后会发现一个jrebel.jar,这就是其最重要的运 ...
 - bzoj 4195: [Noi2015]程序自动分析【并查集】
			
等于有传递性,所以hash一下把等于用并查集连起来,然后再判断不等于是否合法即可 #include<iostream> #include<cstdio> #include< ...
 - js 几秒之后就不断的执行
			
function url() { $.ajax({ url: "AA.ashx", data: { ID: "gggg ...
 - $Edmonds-Karp$[网络流]
			
\(原题戳这里\) >最大流最小割定理$(Maximum Flow, Minimum Cut Theorem): $ 网络的最大流等于最小割 具体的证明分三部分 1.任意一个流都小于等于任意一个 ...
 - SimpleDateForma类
			
package Format_daqo; import java.text.SimpleDateFormat; import java.util.Date; public class SimpleDa ...
 - Oracle 用到的服务
			
1.Oracle ORCL VSS Writer Service Oracle卷映射拷贝写入服务,VSS(Volume ShadowCopy Service)能够让存储基础设备(比如磁盘,阵列等)创建 ...
 - VMware虚拟机中涉及的3种常见网络模式
			
桥接模式.这种模式下,虚拟机和物理机连的是同一个网络,虚拟机和物理机是并列关系,地位是相当的.比如你家如果有用路由器,那么你的电脑和你的手机同时连接这个路由器提供的Wi-Fi,那么它们的关系就是这种模 ...
 - 12.1Java-构造方法
			
一.构造方法 作用:在new的同时对成员变量赋值,给对象的属性初始化赋值格式:权限 方法名(参数列表){}方法的名字,必须和类的名字完全一致,大小写一致构造方法不许写返回值类型,如void,int 构 ...
 - poj2718 Smallest Difference
			
思路: 暴力乱搞. 实现: #include <iostream> #include <cstdio> #include <sstream> #include &l ...