了解automake和autoconf(autoreconf)
机器语言,汇编语言与高级语言
机器语言是机器指令的集合。机器指令展开来讲就是一台机器可以正确执行的命令。电子计算机的机器指令是一列二进制数字。计算机将之转变为一列高低电平,以使计算机的电子器件受到驱动,进行运算。
早期的程序设计均使用机器语言。程序员们将用0, 1数字编成的程序代码打在纸带或卡片上,1打孔,0不打孔,再将程序通过纸带机或卡片机输入计算机,进行运算。这样的机器语言由纯粹的0和1构成,十分复杂,不方便阅读和修改,也容易产生错误。
编语言的主体是汇编指令。汇编指令和机器指令的差别在于指令的表示方法上。汇编指令是机器指令便于记忆的书写格式。
1000100111011000 机器指令
mov ax,bx 汇编指令
将汇编指令转换成机器指令的翻译程序,这样的程序我们称其为编译器。程序员用汇编语言写出源程序,再用汇编编译器将其编译为机器码,由计算机最终执行。
由于汇编语言依赖于硬件体系,且助记符量大难记,于是人们又发明了更加易用的所谓高级语言。在这种语言下,其语法和结构更类似普通英文,且由于远离对硬件的直接操作,使得一般人经过学习之后都可以编程。
高级语言: 面向过程-C, 面向对象C++,Java.
所以, 高级语言要执行,最终是要经过编译转化为汇编语言才能被机器执行。
C语言的编译和链接
编译是把源码编译成中间代码文件,
在Windows下是.obj文件, 在Linix下是.o 的文件,即Object File, 目标文件
链接处理的是目标文件之间的调用关系。方式就是把目标文件打个包, 在Windows 下这个包文件爱你叫Library-库文件, 以.lib结尾。
在Linux下叫Archive文件, 以 .a结尾。
源文件首先会生成中间目标文件,再由中间目标文件生成执行文件。在编译时,编译器只检测程序语法,和函数、变量是否被声明。如果函数未被声明,编译器会给出一个警告,但可以生成Object File。而在链接程序时,链接器会在所有的Object File中找寻函数的实现。
没有Makefile的编译
gcc -o myapp main.c func1.c func2.c func3.c
以上编码包括代码:
主程序代码 main.c
三个子函数 : funcx.c
写在Makefile 文件中:
myapp: main.c func1.c func2.c func3.c
gcc -o calc main.c func1.c func2.c func3.c
这是一个基本的Makefile语句,它主要分成了三个部分,
第一部分:第一行冒号之前的myapp,我们称之为目标(target),被认为是这条语句所要处理的对象,具体到这里就是我们所要编译的这个程序myapp。
第二部分:冒号后面的部分(main.c func1.c func2.c func3.c),我们称之为依赖关系表,也就是编译所需要的文件
第三部分: 命令部分,就是一条编译命令
什么是Makefile?
Makefile是一个文件。
makefile定义整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
Makefile文件被 make命令使用。make是如何工作的呢?
在默认的方式下,
1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个文件,并把这个文件作为最终的目标文件。
3. 如果edit文件不存在,或是edit所依赖的后面的 .o 文件的文件修改时间要比edit这个文件新,那么,他就会执行后面所定义的命令来生成edit这个文件。
4. 如果edit所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)
5. make会生成 .o 文件,然后再用 .o 文件声明make的终极任务,也就是执行文件edit了。
这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦
autoconf&automake
Makefile中纪录有文件的信息,在make时会决定在链接的时候需要重新编译哪些文件。
Makefile的宗旨就是:让编译器知道要编译一个文件需要依赖其他的哪些文件。当那些依赖文件有了改变,编译器会自动的发现最终的生成文件已经过时,而重新编译相应的模块。
当系统环境变量或路径发生了变化后,Makefile可能还要跟着修改。这样就造成了手工书写Makefile的诸多问题,automake恰好能很好地帮助我们解决这些问题。
使用automake,程序开发人员只需要写一些简单的含有预定义宏的文件,由autoconf根据一个宏文件生成configure,由automake根据另一个宏文件生成Makefile.in,再使用configure依据Makefile.in来生成一个符合惯例的Makefile
autoconf用来生成configure configure生成makefile make就去调gcc编译源文件
使用autoconf和automake两个工具来帮助我们自动地生成符合自由软件惯例的Makefile.
实例
- 在工作目录下新建testmake目录
mkdir testmake
cd testmake
- 1
- 2
- 3
- 编写源代码 helloworld.c
vi helloworld.c
int main(int argc,char** argv)
{
printf("Hello,My First Linux Make");
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 生成configure.
使用autoscan命令,生成configure.scan的文件
autoscan
重命名为configure.in, 并修改文件内容
mv configure.scan configure.in
-*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_INIT(helloworld.c)
AM_INIT_AUTOMAKE(helloworld,1.0)
# Checks for programs.
AC_PROG_CC
# Checks for libraries.
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_OUTPUT(Makefile)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 执行 aclocal 和autoconf, 产生aclocal.m4及configure
aclocal根据configure.in文件的内容,自动生成aclocal.m4文件。aclocal是一个perl脚本程序,它的定义是:“aclocal - create aclocal.m4 by scanning configure.ac”。
autoconf 是用来生成自动配置软件源代码脚本(configure)的工具。configure脚本能独立于autoconf运行,且在运行的过程中,不需要用户的干预。
autoconf需要GNU m4宏处理器来处理aclocal.m4,生成configure脚本。
m4是一个宏处理器。将输入拷贝到输出,同时将宏展开。宏可以是内嵌的,也可以是用户定义的。除了可以展开宏,m4还有一些内建的函数,用来引用文件,执行命令,整数运算,文本操作,循环等。m4既可以作为编译器的前端,也可以单独作为一个宏处理器.
5.创建Makefile.am
新建Makefile.am文件,命令:$ vi Makefile.am
automake会根据你写的Makefile.am来自动生成Makefile.in。Makefile.am中定义的宏和目标,会指导automake生成指定的代码。例如,宏bin_PROGRAMS将导致编译和连接的目标被生成。
AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS=helloworld
helloworld_SOURCES=helloworld.c
- 1
- 2
- 3
- 4
- 5
6.运行automake –add-missing
automake会根据Makefile.am文件产生一些文件,包含最重要的Makefile.in。
- 执行configure生成Makefile
./configure
- 1
8.使用Makefile编译代码
make
- 1
9.运行
./helloworld