最近几天一直在没网的情况下往服务器上安装软件,针对一些软件,简单的解压一下或者make编译完就可以运行,复杂一点的配置下环境变量也还可以,但有一些软件,依赖比较多时,就连编译过程就要去对编译文件进行一些改动,之前都是靠着点一些经验根据报错信息进行改动,昨天遇见一个软件,Augustus,再编译过程中,遇见下图这个问题,/usr/bin/ld: cannot find -lhts ,第一次遇见,反复修改了下编译文件始终没有解决,昨晚睡觉前拿起《鸟哥的Linux私房菜-基础篇》翻了翻,发现我这个软件基于c语言编译来进行的,有必要好好学习一下,其它概念也温故而知新。
一.什么是开放源码、编译程序
Linux系统真正认识的可执行文件其实是二进制文件 ( binary program)。那么这些binary 的程序咋来的呢?之前我都是用vim/vi来写一些小程序,写完的程序都是纯文本文档,对于软件开发者,这些文本文档就是源代码。完成源代码工作后,就需要将这个文件[编译]成为操作系统看的懂得binary program。这个编译过程就需要『编译程序』来完成,经过编译程序的编译与连结之后,就会产生一支可以执行的 binary program 了。很多软件会提供我们编译好的binary program,这类软件,通常我们解压后就可以使用了。
二.GCC编译程序进行程序编译
Linux 上面最标准的程序语言为C,标准的 C 语言编译程序是 gcc 这支程序来编译,整个的流程借助鸟哥的图片如下图:
C 语言的原始码文件通常以 *.c 作为扩展名,而在编译的过程当中还会产生所谓的目标文件 (Object file),这些文件是以 *.o 的扩展名样式存在的。此外,有的时候,我们会在程序当中『引用、呼叫』 其他的外部子程序,或者是利用其他软件提供的『函数功能』,这个时候,我们就必须要在编译的过程当中, 将该函式库给他加进去,如此一来,编译程序就可以将所有的程序代码与函
式库作一个连结 (Link) 以产生正确的执行档。
小结:
开放源码:就是程序代码,写给人类看的程序语言,但机器并不认识,所以无法执行;
编译程序:将程序代码转译成为机器看的懂得语言,就类似翻译者的角色;
可执行文件:经过编译程序变成二进制程序后,机器看的懂的可以执行的文件。
三.函式库
什么叫函式库呢,举个例子,Linux 系统有一个可以进行身份验证的模块,PAM 模块。这个 PAM 提供的功能可以让很多的程序在被执行的时候,除了可以验证用户登入的信息外, 还可以将身份确认的数据记录在登录档里面,以方便系统管理员的追踪!那么其它人在编写具有身份认证功能的程序时,直接引用该 PAM 的功能就可以了,不需要再重新设计认证机制,也就是说,只要在写的程序代码里面,设定去呼叫 PAM 的函式功能,这个程序就可以利用 Linux 原本就有的身份认证的程序!除此之外,Linux 核心也提供了很多的函式库来给硬件开发者利用。
函式库在Linux中是一个非常重要的项目,因为很多软件都会调用彼此的函式库来进行特殊功能的运作,函式库依据是否被编译到程序内部而分为动态和静态函式库 ,后面再进行讲述,函式库的调用用个简单的流程图来示意:
如果程序里面加入引用的函式库,就需要如图 21.1.1 所示,在编译的过程当中,加入函式库的相关设定。Linux 的核心提供很多的核心相关函式库与外部参数,这些核心功能在设计硬件的驱动程序的时候是相当有用的信息,这些核心相关信息大多放置/usr/include, /usr/lib, /usr/lib64 目录下。
小结:
函式库:就类似子程序的角色,可以被呼叫来执行的一段功能函数。
四.make 与configure
估计很多人和我之前一样,会有疑问,为啥有的软件解压就能用,有的直接make,还有的先configure然后再make,看完这段我才理解了。
有一些比较复杂的软件,不仅有一支程序,而是一堆的程序代码文件,在编译过程中,除了每个主程序与子程序均需要写上一笔编译过程的指令外,还需要写上最终的链接程序,这个时候就可以使用 make 这个指令的相关功能来进行编译过程的指令简化了!
当执行 make 时,make 会在当时的目录下搜寻 Makefile (or makefile) 这个文本文件,而 Makefile 里面则记录了原始码如何编译的详细信息!make 会自动的判别原始码是否经过变动了,而自动更新执行档。
make 就是一支程序,会去找 Makefile,那 Makefile 怎么写?通常软件开发商都会写一支侦测程序来侦测用户的作业环境,以及该作业环境是否有软件开发商所需要的其他功能,该侦测程序侦测完毕后,就会主动的建立这个 Makefile 的规则文件啦!通常这支侦测程序的文件名为 configure 或者是 config。
那为什么要侦测作业环境呢?不同环境使用的系统呼叫可能不相同,而且每个软件所需要的相依的函式库也不相同,同时,软件开发商不会仅针对 Linux 开发,而是会针对整个 Unix-Like做开发。所以他也必须要侦测该操作系统平台有没有提供合适的编译程序才行!所以需要要侦测环境。一般来说,侦测程序会侦测的数据大约有底下这些:
1.是否有适合的编译程序可以编译本软件的程序代码;
2.是否已经存在本软件所需要的函式库,或其他需要的相依软件;
3.操作系统平台是否适合本软件,包括 Linux 的核心版本;
4.核心的表头定义档 (header include) 是否存在 (驱动程序必须要的侦测)。
make 与 configure 运作流程的可以使用底下的图示来示意,下图中,先是执行 configure 来建立 Makefile,成功之后再以 make 来呼叫所需要的数据来编译即可。
透过 configure 与 make 进行编译示意图
五.Tarball 的软件
Tarball 文件,就是将软件的所有原始码文件先以 tar 打包,然后再以压缩技术来压缩,通常最常见的就是以 gzip 来压缩了。因为利用了 tar 与 gzip 的功能,所以 tarball 文件一般的扩展名就会写成 *.tar.gz 或者是简写为 *.tgz!不过,近来由于 bzip2 与 xz 的压缩率较佳,所以 Tarball渐渐的以 bzip2 及 xz 的压缩技术来取代 gzip。因此档名也会变成 *.tar.bz2, *.tar.xz 之类的哩。所以说, Tarball 是一个软件包,解压缩之后,里面的文件通常就会有:
1.源代码文件;
2.侦测程序文件 (可能是 configure 或 config);
3.本软件的简易说明与安装说明 (INSTALL 或 README)。
其中最重要的是那个 INSTALL 或者是 README 这两个文件,通常参考这两个文件来进行Tarball 软件的安装(以前都忽视了,都是报错提醒啥解决啥)。那么,一个正确的tar.gz软件安装过程是啥样呢,参考下图:
然后我就是在第4步出错了,学一下咋加入外部函式库。
六.呼叫外部函式库:加入连结的函式库
我们编译一个计算三角函数里面的 sin (90 度角)的函数,先看一下程序:
编译时加入额外函式库连结的方式:
-lm 表示使用 libm.so (或 libm.a) ,这个函式库的意思:到 /lib 或 /lib64 里面搜寻函式库 libm.so。
到这里,总算知道我的报错原因了,没有在/usr/lib目录下找到-lhts库,需要我在makefile文件中通过-L给他指定路径。
再接着往下学习,
sin.c第一行的[#include],这行说的是要将一些定义数据由 stdio.h 这个文件读入,这包括 printf 的相关设定。这个文件其实是放置在 /usr/include/stdio.h 的!那么万一这个文件并非放置在这里呢?那么我们就可以使用底下的方式来定义出要读取的 include 文件放置的目录:
-I/path 后面接的路径( Path )就是设定要去搜寻相关的 include 文件的目录!不过,默认值是放置在 /usr/include 底下。
七.gcc 的简易用法 (编译、参数与链结)
gcc 为 Linux 上面最标准的编译程序,是由 GNU 计划所维护的,列举几个 gcc 常见的参数,
比较重要的大概就是这一些。另外,通常称 -Wall 或者 -O 这些非必要的参数为旗标 (FLAGS),因为我们使用的是 C 程序语言,所以有时候也会简称这些旗标为 CFLAGS ,这些变量偶尔会被使用!尤其是在后头会介绍的 make 相关的用法时,更是重要。
附:大部分内容来自《鸟哥的Linux私房菜-基础篇》,电子版材料可以关注我微信公众号,发送书名,免费提供电子版。
本文使用 文章同步助手 同步