【MakeFile详解】

GCC编译的四个步骤

预处理-----> 编译 ----> 汇编 ----> 链接

1.预处理(Pre-processing),生成预编译文件(.i文件):
    gcc –E hello.c –o hello.i
2.编译(Compiling),生成汇编代码(.s文件):
    gcc –S hello.i –o hello.s
3.汇编(Assembling),生成目标文件(.o文件):
    gcc –c hello.s –o hello.o
4.链接(Link),生成可执行文件:
    gcc hello.o –o hello

整个过程如果想一步到位:
    gcc hello.c -o hello即可

程序的编译和链接

要得到最后可执行的程序,首先要把源文件编译成中间代码文件,在Windows 下也就是 .obj 文件,UNIX\Linux 下是 .o 文件,即 Object File,编译(compile)。再把大量的Object File 合成执行文件,链接(link)
编译时,编译器需要的是语法正确,函数与变量的声明正确。对于后者,通常是你需要告诉编译器头文件的所在位置,只要所有的语法正确,编译器就可以编译出中间目标文件。一般来说,每个源文件都应该对应于一个中间目标文件(O 文件或是OBJ 文件)。
链接时,主要是链接函数和全局变量。链接器并不管函数所在的源文件,只管函数的中间目标文件(Object File)。
在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便,所以,通常要给中间目标文件打个包,在Windows 下这种包叫“库文件”(Library File),也就是 .lib 文件,在UNIX 下,是Archive File,也就是 .a 文件。

一个软件项目通常包含多个源码文件。每个源代码的编译和可执行文件的链接都要书写大量的命令。

如果用IDE开发环境,这编译和链接一般由IDE自动完成。但绝大部分Linux和开源项目并不使用IDE,而是使用gcc 之类命令行工具来编译。
在一项目里, 代码通常都引用关系.因此需要指定谁先编译,谁后编译.甚至是更复杂的功能操作
Makefile 就为解决上述一系统问题而创造的。可以把Makefile 理解成是一种由make 程序进行解释的一种特殊脚本。
Linux 几乎所有项目都是通过Makefile 方式编译的,如MySQL、Apache和操作系统本身,因此Linux 下开发必须掌握Makefile的编写和使用。
 

gcc 参数

–c  编译成把源文件目标代码,不做连接的动作。 
–d  在执行过程中打印出所有的调试信息
–S 把源文件编译成汇编代码,不做汇编和连接的动作。 
–E 只把源文件进行预处理之后的结果输出来。不做编译,汇编,连接的动作。 
–o file 指明输出文件名是file。
–g 把调试开关打开,让编译的目标文件有调试信息。 
-O1 -O2 -O3 -O0,这些开关分别控制优化的强度,-O3最强。

 

Makefile 是什么

GNU make是一个命令工具,是一个用来控制软件构建过程的自动化管理工具。Make工具通过称为Makefile的文件来完成并自动维护编译工作,由Richard Stallman 与Roland McGrath设计开发 。
Makefile是用于自动编译和链接的,一个工程有很多文件组成,每一个文件的改变都会导致工程的重新链接,但是不是所有的文件都需要重新编译,Makefile中记录有文件的信 息,在make时会决定在链接的时候需要重新编译哪些文件。
make命令格式:make [-f Makefile] [option] [target] 
#make target         #make         #make clean  (伪目标)

Makefile的宗旨就是:让编译器知道要编译一个文件需要依赖其他的哪些文件。当那些依赖文件有了改变,编译器会自动的发现最终的生成文件已经过时,而重新编译相应的模块。 
makefile带来的好处就是—“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

Makefile的文件名

默认的情况下,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件,找到了解释这个文件。在这三个文件名中,最好使用“Makefile”这个文件名,因为,这个文件名第一个字符为大写,这样有一种显目的感觉。最好不要用“GNUmakefile”,这个文件是GNU的make识别的。有另外一些make只对全小写的“makefile”文件名敏感,但是基本上来说,大多数的make都支持“makefile”和“Makefile”这两种默认文件名。

当然,你可以使用别的文件名来书写Makefile,比如:“Make.Linux”,“Make.Solaris”,“Make.AIX”等,如果要指定特定的Makefile,你可以使用make的“-f”和“--file”参数,如:make -f Make.Linux或make --file Make.AIX。  

Makefile与Shell脚本的异同

相同点:
都是文本文件格式的脚本.
都可以执行Shell命令
都可以定义变量,和条件控制语句.(使用格式上有差别)
不同点:
解释器不同,Shell脚本是由对应Shell程序解释.而Makefile是由make程序解释
格式不一样,Shell脚本以命令行为基本单位,而Makefile以规则为基本单位
Shell脚本只要有执行权限即可直接执行,Makefile必须要用make来显式调用才行,本身不需执行权限 

Makefile相对Shell脚本的优点

在开发领域,Makefile还是有相当优势
Makefile具有自动推导,判断源码依赖关系的功能
Makefile有可以使用隐含规则来简化makefile的编写,但这样会带来makefile可阅读性下降 

Makefile里有什么?

Makefile里主要包含了五个东西:显式规则、隐含规则、变量定义、文件指示和注释。 
1、显式规则。显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。
    如: foo.o : foo.c defs.h        依赖关系
         gcc -o foo.o foo.c 生成目标的方法(方式) 
2、隐含规则。由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile,这是由make所支持的。 
     如:    foo.o : foo.c   (.o文件自己推导出同名的依赖文件.c.)
3、变量的定义。在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点像C语言中的宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。
     如:H: =foo.c     gcc -o foo.o $(H) (赋值可以用: =也可以直接用 =)
4、文件指示。其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中的include一样;另一个是指根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一样;还有就是定义一个多行的命令。
5、注释。Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用“#”字符,这个就像C/C++,Java中的“//”一样。

在Makefile中的命令,必须要以[Tab]键开始。 

Make的调用

最常用的make调用形式.就是直接执行make
    它会自动查找当前目录下的名称为Makefile或makefile的文件,并自动从名称为all的target开始执行
象其它GNU工具一样,make有一些命令参数,以便应用在一些特殊场所
如果makefile脚本名称不是缺省名称,则需要用-f参数来通知make
    make –f hello.mk
    表示执行名称叫hello.mk makefile脚本
如果需要make不去查找当前目录,而是查找另外一个目录下的makefile,则使用-C 参数
    make -C /home/hxy
    表示去找查找 /home/hxy下的makefile

指编译特定部分
一个项目可能不同版本或不同部分,在makefile中以target表示
make可以通用在命令行直接写target名称,用于一个或多个target进行编译,
    make install
    make clean
    make target1 target2

Makefile的格式
规则(rule)概念
一个Makefile 可以看作是一系列规则的组合,一个规则也能称为一个目标(target)
规则的格式
    目标名称是需要创建结果一个称呼.可以取任意标识名.一般与创建文件同名
    依赖对象,表示创建这个目标之前,必须预先创建的其它目标,这里的对象可以是另一个规则的名称,也可是基本的文件名称
    命令列表表示为了创建这一个目标,需要执行哪些Shell命令.可以是一行或多行Shell命令.每一行命令行的行首必须是一个跳格字符(即tab),
        注意行首空格是无效,否则执行makefile报错
        如果命令行过长,可用\分行,分行后的新行,无需使用tab打头
整个规则的可做如下解读.”为了创建这个目标,必须先创建依赖对象(或是依赖的对象必须存在),然后再调用命令行列表进行创建”
目标名称 : [依赖对象]
命令列表

在Makefile里,把源代码编译成目标代码一般是一个规则
把所有中间文件链接在一起也是一个规则
#要想生成hello.o目标,必须先有hello.c,
#然后调用命令行gcc编译生成hello.o
#依赖对象hello.c在这里可以省略
hello.o:hello.c
        gcc –c hello.c –o hello.o
#要想生成执行程序hello,必须先执行规则hello.o,
#然后调用命令行gcc链接生成hello
hello:hello.o
        gcc hello.o –o hello

伪目标

一般的目标最终结果都是生成一个文件,但有一些目标可以不生成结果文件.只是为了调用命令或依赖对象.这称为伪目标(Phony target)
make 内置一些常用的伪目标.
    all 缺省的目标入口,如果执行make命令行没有指定目标名称,all目标则会自动被调用.
    clean 清除项目生成的中间文件和最终成文件,如何清除需要开发者自行编写.
    install 项目如何安装, .具体动作要开发者自行编写
    uninstall 项目如何卸载.具体动作要开发者自行编写
为了让make程序不至于产生误解,开发者可以用.PHONY关键字来声明伪目标,但这不是必须做的
    .PHONY clean,install,all #表示三个都是伪目标
    
跟Shell不同,在Makefile里规则的前后顺序不太重要.
实际的调用顺序取决目标之间的依赖关系.
因此make 采用逆推的方式来判断和执行目标
    首先make找到Makefile的入口规则,一般是all,或者是用户在命令行指定的target
    顺着入口规则的依赖对象查找下去,检查一直查找到最终的目标,即只有被依赖而没有依赖其它对象的目标.即终目标
    从最终目标顺着依赖关系依次执行到入口规则,中间只有运行命令出错,才会停止执行.
    如果是依赖文件,make会自动检测最后更新时间,只会去执行已经修改过的文件,以此来减少编译时间

如果你的Makefile需要一口气生成若干个可执行文件,但你只想简单地敲一个make完事,并且,所有的目标文件都写在一个Makefile中,那么你可以使用“伪目标”这个特性:
all : prog1 prog2 prog3
.PHONY : all
 prog1 : prog1.o utils.o
cc -o prog1 prog1.o utils.o
 prog2 : prog2.o
cc -o prog2 prog2.o
 prog3 : prog3.o sort.o utils.o
cc -o prog3 prog3.o sort.o utils.o
我们知道,Makefile中的第一个目标会被作为其默认目标。我们声明了一个“all”的伪目标,其依赖于其它三个目标。执行 make时,目标“all”被作为终极目标。为了完成对它的更新,make会创建(不存在)或者重建(已存在)目标“all”的所有依赖文件(prog1、prog2 和 prog3) 。这就达到了我们一口气生成多个目标的目的。
“.PHONY : all”声明了“all”这个目标为“伪目标”。 

从前面的例子我们可以看出,目标可以成为依赖。伪目标同样也可成为依赖。看下面的例子: 
    .PHONY: cleanall cleanobj cleandiff 
    cleanall : cleanobj cleandiff 
            rm program 
    cleanobj : 
            rm *.o 
    cleandiff : 
            rm *.diff “make clean”将清除所有要被清除的文件。“cleanobj”和“cleandiff”这两个伪目标有点像“子程序”的意思。我们可以输入“make cleanall”和“make cleanobj”和“make cleandiff”命令来达到清除不同种类文件的目的。

 

makefile 基本结构

makefile 中一般包含如下内容 
    需要由 make 工具创建的项目,通常是目标文件和可执行文件。通常使用“目标(target)”一词来表示 要创建的项目 
    要创建的目标依赖于哪些文件 
    创建每个目标时需要运行的命令,每个命令之前必须有tab打头 
    通常都包含一些固定的伪目标,如all,install,clean用作缺省编译,安装和清除文件
    #打头表示注释行

一个makefile实例
编译test_link的makefile
all:test_link

test_link:test_link.o dl_list.o dl_file.o
        gcc test_link.o dl_list.o dl_file.o -o test_link

test_link.o:test_link.c
        gcc -c test_link.c -o test_link.o

dl_list.o:dl_list.c
        gcc -c dl_list.c -o dl_list.o

dl_file.o:dl_file.c
        gcc -c dl_file.c -o dl_file.o

clean:
        rm -f *.o test_link

支持库编译的makefile实例
通过不同target来执行不同编译
    make 表示编译所有程序和库
    make libstr.a 表示编译静态库
    make main_a 表示编译静态版库的测试程序以及静态库

Makefile命令行的特殊用法
命令行前加-表示如果命令出错不中止makefile的执行
    否则执行出错就立刻中止
    如  -rm –f *.o 表示,即便是没有删除文件成功,也要继续执行后面的命令
命令行前加@表示,执行命令时不显示命令行,直接显示命令行结果
    如@echo “123”,如果没有@,则会在屏幕上显示
    echo “123”
    123
    这样明显是多显示一行,为了不干扰输出,这时加上@则只会显示123,

Makefile的扩展用法
在复杂项目里,为了简化makefile的书写.往往会采用扩展写法.这样大大方便开发者的编写
这些方法包括
    变量
    隐含规则
    Makefile的引用
    Makefile的函数

makefile 变量

GNU 的 make 工具除提供有建立目标的基本功能之外,还有许多便于表达依赖性关系以及建立目标的命令的特 色。其中之一就是变量或宏的定义能力。如果你要以相同的编译选项同时编译十几个 C 源文件,而为每个目 标的编译指定冗长的编译选项的话,将是非常乏味的。但利用简单的变量定义,可避免这种乏味的工作: 
# Define macros for name of compiler
CC = gcc

# Define a macr o for the CC flags
CCFLAGS = -D_DEBUG -g -m486

# A rule for building a object file
test.o: test.c test.h
    $(CC) -c $(CCFLAGS) test.c
在上面的例子中,CC 和 CCFLAGS 就是 make 的变量。GNU make 通常称之为变量,而其他 UNIX 的 make 工具称之为宏,实际是同一个东西。在 makefile 中引用变量的值时,只需变量名之前添加 $ 符号,如 上面的 $(CC) 和 $(CCFLAGS)。 

变量的定义和应用与Linux环境变量一样,变量名要大写,变量一旦定义后,就可以通过将变量名用圆括号括起来,并在前面加上“$”符号来进行引用。
变量的主要作用:   
   1、保存文件名列表
   2、保存可执行命令名,如编译器
   3、保存编译器的参数
变量一般都在makefile的头部定义。按照惯例,所有的makefile变量都应该是大写。
 

Makefile变量定义

Makefile变量定义跟Shell变量定义刚好相反!
    Shell变量定义时,=两边不能有空格.
    Makefile 变量定义,=两边一定要有空格
    Shell变量用{}来保护变量名,而Makefile变量用()来保护变量名
Makefile的变量定义要独立于规则之外,
    是有定义先后顺序的要求
    一般要放在所有规则前面进行定义

=与:=区别
两者都用于变量赋值,:=是简单赋值,=带递归引用
    如=后面是变量,则变量本身值可能还要进行运算
    :=只是简单赋值,后面变量只简单取值,没有定义的变量取为空,一般比较安全
    假设CFLAGS预先定义有值,则CFLAGS = $(CFLAGS) -g 变成无限递归调用,最后变成最终堆栈溢出 ,正确写法是 CFLAGS := $(CFLAGS) -g 
#这里foo最终的值为Huh,因为foo后面bar还要做递归调用,而ugh也会做递归调用
foo = $(bar)
bar = $(ugh)
ugh = Huh? 
#这里foo最终的值为空,定义foo时,bar并未定义,这里取空.
foo := $(bar)
bar := $(ugh)
ugh := Huh? 

GNU make 的主要预定义变量
GNU make 有许多预定义的变量,这些变量具有特殊的含义,可在规则中使用。
除这些变量外,GNU make 还将所有的环境变量作为自己的预定义变量。 
预定义变量                      含义
$*              不包含扩展名的目标文件名称。
$+              所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件。
$<              第一个依赖文件的名称。
$?              所有的依赖文件,以空格分开,这些依赖文件的修改日期比目标的创建日期晚。
$@              目标的完整名称。
$^              所有的依赖文件,以空格分开,不包含重复的依赖文件。

$%              如果目标是归档成员,则该变量表示目标的归档成员名称。例如,如果目标名称
                为 mytarget.so(image.o),则 $@ 为 mytarget.so,而 $% 为 image.o。

AR              归档维护程序的名称,默认值为 ar。
ARFLAGS         归档维护程序的选项。
AS              汇编程序的名称,默认值为 as。
ASFLAGS         汇编程序的选项。
CC              C 编译器的名称,默认值为 cc。
CCFLAGS         C 编译器的选项。
CPP             C 预编译器的名称,默认值为 $(CC) -E。
CPPFLAGS        C 预编译的选项。
CXX             C++ 编译器的名称,默认值为 g++。
CXXFLAGS        C++ 编译器的选项。
FC              FORTRAN 编译器的名称,默认值为 f77。
FFLAGS          FORTRAN 编译器的选项。

隐含规则 

GNU make 包含有一些内置的或隐含的规则,这些规则定义了如何从不同的依赖文件建立特定类型的目标。 
GNU make 支持两种类型的隐含规则: * 后缀规则(Suffix Rule)。后缀规则是定义隐含规则的老风格方法。后缀规则定义了将一个具有某个 后缀的文件(例如,.c 文件)转换为具有另外一种后缀的文件(例如,.o 文件)的方法。每个后缀规 则以两个成对出现的后缀名定义,例如,将 .c 文件转换为 .o 文件的后缀规则可定义为: 
.c.o: 
$(CC) $(CCFLAGS) $(CPPFLAGS) -c -o $@ $< 
* 模式规则(pattern rules)。
这种规则更加通用,因为可以利用模式规则定义更加复杂的依赖性规则。 模式规则看起来非常类似于正则规则,但在目标名称的前面多了一个 % 号,同时可用来定义目标和依赖 文件之间的关系,例如下面的模式规则定义了如何将任意一个 X.c 文件转换为 X.o 文件: 
%.o:%.c 
$(CC) $(CCFLAGS) $(CPPFLAGS) -c -o $@ $<

引用其它的Makefile
在Makefile使用include关键字可以把别的Makefile包含进来,这很像C语言的#include,被包含的文件会原模原样的放在当前文件的包含位置。include的语法是: 
    include  
filename可以是当前操作系统Shell的文件模式(可以保含路径和通配符) 在include前面可以有一些空字符,但是绝不能是[Tab]键开始。include和可以用一个或多个空格隔开
    include foo.make a.mk b.mk c.mk e.mk f.mk 
在大一点的项目里通常都会把通用规则做单独的Makefile供其它程度引用

函数 (Functions )

makefile 里的函数跟它的变量很相似——使用的时候,你用一个 $ 符号跟开括号,函数名,空格后跟一列由逗号分隔的参数,最后 用关括号结束。 
GNU Make 里有一个叫 ‘wildcard’ 的函 数,它有一个参数,功能是展开成一列所有符合由其参数描述的文 件名,文件间以空格间隔 
    SOURCES = $(wildcard *.c) 
另一个有用的函数是 patsubst ( patten substitude, 匹配替 换的缩写)函数。它需要3个参数——第一个是一个需要匹配的式样,第二个表示用什么来替换它,第三个是一个需要被处理的 由空格分隔的字列。例如,处理那个经过上面定义后的变量, 
    OBJS = $(patsubst %.c,%.o,$(SOURCES)) 
    这行将处理所有在 SOURCES 字列中的字(一列文件名),如果它的 结尾是 '.c' ,就用 '.o' 把 '.c' 取代。注意这里的 % 符号将匹 配一个或多个字符,而它每次所匹配的字串叫做一个‘柄’(stem) 。 在第二个参数里, % 被解读成用第一参数所匹配的那个柄。 

常见项目Makefile结构

Linux项目的Makefile结构
Linux下各种项目大部分以Makefile的方式进行构建.从Makefile的结构来划分,大体分为三大类
    简单型:只使用一个makefile,直接调用gcc进行编译,没有用上太多技巧
    分级makefile:项目每个子目录下生成makefile,由项层目录的makefile总控
    autoconf生成型.这是绝大部分开源项目采用标准模式,即项目源码包里没有makefile,而且有一个configure 脚本,由configure检测当前环境生成Makefile.
        这一类又有两大类,一种是简单型的
        还有一种LIBTOOL的类型

简单型makefile
直接调用gcc 进行编译,链接,没有用上太多隐含规则.
一般只有一个makefile文件,整个makefile比较清晰易懂.
通常用于非常小的项目之中.
典型例子
    tree,分颜色显示目录树的命令行工具.
    rzsz ,利用串口传输文件的工具.可移植到ARM开发板
    tftp-hpa ,TFTP客户端,可以移植到ARM开发板

GNUmake工作方式总结

GNU的make工作时的执行步骤如下:
    1、读入所有的Makefile。 
    2、读入被include的其它Makefile。 
    3、初始化文件中的变量。 
    4、推导隐晦规则,并分析所有规则。 
    5、为所有的目标文件创建依赖关系链。 
    6、根据依赖关系,决定哪些目标要重新生成。 
    7、执行生成命令。 

tree是一个显示目录树型结构的小工具
最新版本是tree-1.5.1
编译过程
    tar xvzf tree-1.5.1.tar.gz
    cd tree-1.5.1 
    make
执行过程
    ./tree /home/hxy
    显示/home/hxy的目录结构

# $Copyright: $
# Copyright (c) 1996 - 2004 by Steve Baker
# All Rights reserved
#
# This software is provided as is without any express or implied
# warranties, including, without limitation, the implied warranties
# of merchant-ability and fitness for a particular purpose.

CC=gcc
#CFLAGS=-ggdb -Wall -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
CFLAGS=-O2 -Wall -fomit-frame-pointer -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
LDFLAGS=-s

# Uncomment for FreeBSD:
#CC=gcc
#CFLAGS=-O2 -Wall -fomit-frame-pointer
#LDFLAGS=-s

# Uncomment for Cygwin:
#CC=gcc
#CFLAGS=-O2 -Wall -fomit-frame-pointer -DCYGWIN
#LDFLAGS=-s
#TREE_DEST=tree.exe
## Comment out TREE_DEST definition below as well for Cygwin

# Uncomment for OS X:
#CC=cc
#CFLAGS=-O2 -Wall -fomit-frame-pointer -no-cpp-precomp
#LDFLAGS=

# Uncomment for HP/UX:
#CC=cc
#CFLAGS=-Ae +O2 +DAportable -Wall
#LDFLAGS=

# Uncomment for OS/2:
#CC=gcc
#CFLAGS=-02 -Wall -fomit-frame-pointer -Zomf -Zsmall-conv
#LDFLAGS=-s -Zomf -Zsmall-conv

prefix = /usr

VERSION=1.5.1
TREE_DEST=tree
BINDIR=${prefix}/bin
MAN=tree.1
MANDIR=${prefix}/man/man1

all:	tree

tree:	tree.o
	$(CC) $(LDFLAGS) -o $(TREE_DEST) tree.o

tree.o:	tree.c

clean:
	if [ -x $(TREE_DEST) ]; then rm $(TREE_DEST); fi
	if [ -f tree.o ]; then rm *.o; fi
	rm -f *~

install:
	install -d $(BINDIR)
	install -d $(MANDIR)
	if [ -e $(TREE_DEST) ]; then \
		install -s $(TREE_DEST) $(BINDIR)/$(TREE_DEST); \
	fi
	install man/$(MAN) $(MANDIR)/$(MAN)

distclean:
	if [ -f tree.o ]; then rm *.o; fi
	rm -f *~
	

dist:	distclean
	tar zcf ../tree-$(VERSION).tgz -C .. `cat .tarball`

【MakeFile详解】_第1张图片

rzsz 串口收发项目
rzsz是利用串口的Xmode,Zmode协议进行文件收发的工具.如利用串口在开发板与Windows之间传输文件
编译过程
    mkdir rzsz;tar xvzf rzsz-3.48.tar.gz -C rzsz
    cd rzsz/src
    make posix
执行过程
    ./rz 从主机接收文件
    ./sz filename 发送文件到主机上

# Makefile for Unix/Xenix rz and sz programs
# Some targets may not be up to date
CC=cc
OFLAG= -O


nothing:
	@echo
	@echo "Please study the #ifdef's in crctab.c, rbsb.c, rz.c and sz.c,"
	@echo "make any necessary hacks for oddball or merged SYSV/BSD systems,"
	@echo "then type 'make SYSTEM' where SYSTEM is one of:"
	@echo
	@echo "	posix	POSIX compliant systems"
	@echo "	aix	AIX systems"
	@echo "	next	NeXtstep v3.x (POSIX)"
	@echo "	odt	SCO Open Desktop"
	@echo "	everest	SCO Open Desktop (elf, strict)"
	@echo "	sysvr4	SYSTEM 5.4 Unix"
	@echo "	sysvr3	SYSTEM 5.3 Unix with mkdir(2), COHERENT 4.2"
	@echo "	sysv	SYSTEM 3/5 Unix"
	@echo "	sysiii  SYS III/V  Older Unix or Xenix compilers"
	@echo "	xenix	Xenix"
	@echo "	x386	386 Xenix"
	@echo "	bsd	Berkeley 4.x BSD, Ultrix, V7"
	@echo "	tandy	Tandy 6000 Xenix"
	@echo "	dnix	DIAB Dnix 5.2"
	@echo "	dnix5r3	DIAB Dnix 5.3"
	@echo "	amiga	3000UX running SVR4"
	@echo "	POSIX	POSIX compliant systems (SCO Open Desktop, strict)"
	@echo
	@echo "	undos	Make the undos, todos, etc. program."
	@echo "	doc	Format the man pages with nroff"
	@echo

all:doc usenet unixforum sshar shar zoo

usenet:doc
	shar -c -a -n rzsz -o /tmp/rzsz -l64 \
	  COPYING README Makefile undos.c zmodem.h zm.c rz.c rbsb.c \
	 crc.c crctab.c minirb.c mailer.rz zmr.c *.doc gz sz.c *.t 

sshar:doc
	shar -c -a -n rzsz -o /tmp/rzsz -l64 \
	  COPYING README Makefile undos.c zmodem.h zm.c rz.c rbsb.c \
	 crc.c crctab.c mailer.rz zmr.c *.doc gz sz.c

shar:doc
	shar -c COPYING README Makefile zmodem.h zm.c \
	 undos.c zmr.c sz.c rz.c crctab.c \
	 mailer.rz crc.c rbsb.c minirb.c *.doc gz *.t >/tmp/rzsz.sh
	 cp /tmp/rzsz.sh /u/t/yam

unixforum: shar
	rm -f /tmp/rzsz.sh.gz
	gzip -9 /tmp/rzsz.sh
	cp /tmp/rzsz.sh.gz /u/t/yam

doc:rz.doc sz.doc crc.doc minirb.doc undos.doc

clean:
	rm -f *.o *.out sz sb sx zcommand zcommandi rz rb rx rc
	rm -f undos tounix todos unmac tomac tocpm unparity

minirb.doc:minirb.1
	nroff -man minirb.1 | col  >minirb.doc

rz.doc:rz.1 servers.mi
	nroff -man rz.1 | col  >rz.doc

sz.doc:sz.1 servers.mi
	nroff -man sz.1 | col  >sz.doc

crc.doc:crc.1
	nroff -man crc.1 | col  >crc.doc

undos.doc:undos.1
	nroff -man undos.1 | col  >undos.doc

zoo: doc
	-rm -f /tmp/rzsz.zoo
	zoo ah /tmp/rzsz COPYING README Makefile zmodem.h zm.c sz.c rz.c \
	 undos.c mailer.rz crctab.c rbsb.c *.doc \
	 zmr.c crc.c gz *.t minirb.c
	touch /tmp/rzsz.zoo
	chmod og-w /tmp/rzsz.zoo
	mv /tmp/rzsz.zoo /u/t/yam
	-rm -f rzsz.zip
	zip rzsz readme mailer.rz makefile zmodem.h zm.c sz.c rz.c
	zip rzsz undos.c crctab.c rbsb.c *.doc file_id.diz
	zip rzsz zmr.c crc.c gz *.t minirb.c
	mv rzsz.zip /u/t/yam

tag: doc  xenix
	-rm -f /tmp/rzsz
	tar cvf /tmp/rzsz COPYING README Makefile zmodem.h zm.c sz.c rz.c \
	 mailer.rz crctab.c rbsb.c *.doc \
	 undos.c zmr.c crc.c gz *.t minirb.c rz sz crc undos
	gzip -9 /tmp/rzsz
	mv /tmp/rzsz.gz /u/t/yam/rzsz.tag

tar:doc
	tar cvf /tmp/rzsz.tar COPYING README Makefile zmodem.h zm.c sz.c rz.c \
	 undos.c mailer.rz crctab.c rbsb.c \
	 zmr.c crc.c *.1 gz *.t minirb.c

tags:
	ctags sz.c rz.c zm.c zmr.c rbsb.c

.PRECIOUS:rz sz

xenix:
	/usr/ods30/bin/cc \
	-I/usr/ods30/usr/include -I/usr/ods30/usr/include/sys \
	-M2 $(CFLAGS) $(RFLAGS) $(OFLAG) -s -DSMALL -DUSG -DNFGVMIN -DREADCHECK sz.c -lx -o sz
	size sz; file sz
	-rm -f sb sx zcommand zcommandi
	ln sz sb
	ln sz sx
	ln sz zcommand
	ln sz zcommandi
	/usr/ods30/bin/cc \
	 -I/usr/ods30/usr/include -I/usr/ods30/usr/include/sys \
	-M2 $(CFLAGS) $(RFLAGS) $(OFLAG) -s -DUSG -DMD rz.c -o rz
	size rz; file rz
	-rm -f rb rx rc
	ln rz rb
	ln rz rx
	ln rz rc
	/usr/ods30/bin/cc \
	 -I/usr/ods30/usr/include -I/usr/ods30/usr/include/sys \
	-M2 $(CFLAGS) $(OFLAG) -s undos.c -o undos
	size undos; file undos
	-rm -f tounix todos unmac tomac tocpm unparity
	ln undos tounix
	ln undos todos
	ln undos unmac
	ln undos tomac
	ln undos tocpm
	ln undos unparity

x386:
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DUSG -DMD rz.c -o rz
	size rz
	-rm -f rb rx rc
	ln rz rb
	ln rz rx
	ln rz rc
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DUSG -DNFGVMIN -DREADCHECK sz.c -lx -o sz
	size sz
	-rm -f sb sx zcommand zcommandi
	ln sz sb
	ln sz sx
	ln sz zcommand
	ln sz zcommandi

sysv:
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DUSG -DMD -DOLD rz.c -o rz
	size rz
	-rm -f rb rx rc
	ln rz rb
	ln rz rx
	ln rz rc
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DUSG -DSV -DNFGVMIN -DOLD sz.c -o sz
	size sz
	-rm -f sb sx zcommand zcommandi
	ln sz sb
	ln sz sx
	ln sz zcommand
	ln sz zcommandi

sysiii:
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DUSG -DOLD rz.c -o rz
	size rz
	-rm -f rb rx rc
	ln rz rb
	ln rz rx
	ln rz rc
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DSV -DUSG -DNFGVMIN -DOLD sz.c -o sz
	size sz
	-rm -f sb sx zcommand zcommandi
	ln sz sb
	ln sz sx
	ln sz zcommand
	ln sz zcommandi

sysvr3:
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DUSG -DMD=2 rz.c -o rz
	size rz
	-rm -f rb rx rc
	ln rz rb
	ln rz rx
	ln rz rc
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DSV -DUSG -DNFGVMIN sz.c -o sz
	size sz
	-rm -f sb sx zcommand zcommandi
	ln sz sb
	ln sz sx
	ln sz zcommand
	ln sz zcommandi

sysvr4:
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DUSG -DMD=2 rz.c -o rz
	size rz
	-rm -f rb rx rc
	ln rz rb
	ln rz rx
	ln rz rc
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DSV -DUSG sz.c -o sz
	size sz
	-rm -f sb sx zcommand zcommandi
	ln sz sb
	ln sz sx
	ln sz zcommand
	ln sz zcommandi

odt:
	cc -O -n $(RFLAGS) -DUSG -DMD=2 rz.c -o rz
	size rz
	-rm -f rb rx rc
	ln rz rb
	ln rz rx
	ln rz rc
	cc -O -n $(RFLAGS) -DUSG -DREADCHECK sz.c -lx -o sz
	size sz
	-rm -f sb sx zcommand zcommandi
	ln sz sb
	ln sz sx
	ln sz zcommand
	ln sz zcommandi

everest:
	cc -b elf -w 3 -O3 $(RFLAGS) -DUSG -DMD=2 rz.c -o rz
	size rz
	-rm -f rb rx rc
	ln rz rb
	ln rz rx
	ln rz rc
	cc -b elf -w 3 $(RFLAGS) -O3 -DUSG -DREADCHECK sz.c -lx -o sz
	size sz
	-rm -f sb sx zcommand zcommandi
	ln sz sb
	ln sz sx
	ln sz zcommand
	ln sz zcommandi

posix:
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DPOSIX -DMD=2 rz.c -o rz
	size rz
	-rm -f rb rx rc
	ln rz rb
	ln rz rx
	ln rz rc
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DPOSIX sz.c -o sz
	size sz
	-rm -f sb sx zcommand zcommandi
	ln sz sb
	ln sz sx
	ln sz zcommand
	ln sz zcommandi

POSIX:
	@echo "Well, stricter, as in *safer sex* ..."
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DPOSIX -DMD=2 -DCOMPL rz.c -o rz
	size rz
	-rm -f rb rx rc
	ln rz rb
	ln rz rx
	ln rz rc
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DPOSIX -DCOMPL sz.c -o sz
	size sz
	-rm -f sb sx zcommand zcommandi
	ln sz sb
	ln sz sx
	ln sz zcommand
	ln sz zcommandi


bsd:
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DMD=2 -Dstrchr=index -DV7 rz.c -o rz
	size rz
	-rm -f rb rx rc
	ln rz rb
	ln rz rx
	ln rz rc
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DV7 -DNFGVMIN sz.c -o sz
	size sz
	-rm -f sb sx zcommand zcommandi
	ln sz sb
	ln sz sx
	ln sz zcommand
	ln sz zcommandi

tandy:
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAGS) -n -DUSG -DMD -DT6K sz.c -lx -o sz
	size sz
	-rm -f sb sx zcommand zcommandi
	ln sz sb
	ln sz sx
	ln sz zcommand
	ln sz zcommandi
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAGS) -n -DUSG -DMD -DT6K rz.c -lx -o rz
	size rz
	-rm -f rb rx rc
	ln rz rb
	ln rz rx
	ln rz rc

dnix:
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DUSG -DMD rz.c -o rz
	size rz
	-rm -f rb rx rc
	ln rz rb
	ln rz rx
	ln rz rc
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DSV -DUSG -DNFGVMIN -DREADCHECK sz.c -o sz
	size sz
	-rm -f sb sx zcommand zcommandi
	ln sz sb
	ln sz sx
	ln sz zcommand
	ln sz zcommandi

dnix5r3:
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DUSG -DMD=2 rz.c -o rz
	size rz
	-rm -f rb rx rc
	ln rz rb
	ln rz rx
	ln rz rc
	$(CC) $(CFLAGS) $(RFLAGS) $(OFLAG) -DUSG -DSV -DNFGVMIN -DREADCHECK sz.c -o sz
	size sz
	-rm -f sb sx zcommand zcommandi
	ln sz sb
	ln sz sx
	ln sz zcommand
	ln sz zcommandi


amiga:
	$(CC) $(CFLAGS) $(OFLAG) -DUSG -DNFGVMIN -g rz.c -o rz
	size rz
	-rm -f rb rx rc
	ln rz rb
	ln rz rx
	ln rz rc
	$(CC) $(CFLAGS) $(OFLAG) -DUSG -DSV -DNFGVMIN -g sz.c -o sz
	size sz
	-rm -f sb sx zcommand zcommandi
	ln sz sb
	ln sz sx
	ln sz zcommand
	ln sz zcommandi

aix:
	@echo "As of July 26 1996, ..."
	@echo "IBM sez if you have the very latest PTFs, 'make posix' will work."
	@echo ""

next:
	LIBS=-lposix
	$(CC) -g -posix $(OFLAG) -DPOSIX -DMD=2 rz.c -o rz
	size rz
	-rm -f rb rx rc
	ln rz rb
	ln rz rx
	ln rz rc
	$(CC) -g -posix $(OFLAG) -DPOSIX sz.c -o sz
	size sz
	-rm -f sb sx zcommand zcommandi
	ln sz sb
	ln sz sx
	ln sz zcommand
	ln sz zcommandi

undos:	undos.c
	cc -O undos.c -o undos
	-rm -f tounix todos unmac tomac tocpm unparity
	ln undos tounix
	ln undos todos
	ln undos unmac
	ln undos tomac
	ln undos tocpm
	ln undos unparity


lint:
	lint -DUSG -DSV -DOLD sz.c >/tmp/sz.fluff
	lint -DUSG -DSV -DOLD rz.c >/tmp/rz.fluff


sz: nothing
sb: nothing
rz: nothing
rb: nothing

tftp-hpa项目
利用tftp协议在IP网络传输文件客户端工具,可以与3CDaemon配合使用
tftp 类似于FTP,但使用UDP协议,并且命令更为简单,并且没有用户检验机制
编译过程
    tar xvzf tftp-hpa.tar.gz 
    cd tftp-hpa
    make
执行
    tftp 192.168.0.1 -c get hxy.txt
        从tftp服务器 192.168.0.1上取文件hxy.txt
    tftp 192.168.0.1 -c put hxy2.txt
        向tftp服务器 192.168.0.1上传文件hxy2.txt

#
#
#

EXEC = tftp
OBJS = bsdsignal.o xmalloc.o xstrdup.o tftp.o  tftpsubs.o main.o 

INSTALLPATH = ../../ramdisk/target/bin/
CFLAGS += -I.

all: $(EXEC)

$(EXEC): $(OBJS)
	$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)
#	cp -f $(EXEC) /
install:
	cp $(EXEC) $(INSTALLPATH)
clean:
	-rm -f $(EXEC) *.o

分级makefile
独立的分级Makefile比较少,一般是以autoconf中的一个特殊来表现的
独立的分级makefile 的项目:
    busybox,嵌入式Shell
autoconf生成makefile
    openssl ssl加密库
    Kphone,基于QT的VOIP软件电话,可移植到ARM板上

Openssl makefile核心部分
sub_all:
    @for i in $(DIRS); \
    do \
    if [ -d "$$i" ]; then \
        (cd $$i && echo "making all in $$i..." && \
        $(MAKE) CC='${CC}' ...\
    else \
        $(MAKE) $$i; \
    fi; \
    done;

SUBDIRS=$(SL) dissipate2 gsm ilbc $(SE) $(SR) ringing kdial kaudio kphone

all dep:
    @set -e; for T in $(SUBDIRS); do make -C $$T $@; done

autoconf/configure

较大项目Makefile 都是相当复杂.手工编写大的项目,有相当难度
Autoconf/Automake 辅助生成Makefile的GNU工具
    Makefile而且常常会受到自己的开发环境的限制,只要环境参数不同或者路径更改,可能 Makefile 就得跟着修改修改。虽然有 GNU Makefile Conventions (GNU Makefile惯例例)订出一些使用 GNU 程式设计时撰写 Makefile 的一些标准和规范,但是内容很长而且很复杂,并且经常作一些调整,为了减轻程序开发人员维护Makefile 的负担 , 因此出现了Automake。
    Autoconf/Automake 本身采用一组宏来生成Makefile,本身有一定难度,也需要一定学习时间.因此在自行开发项目建议采用手工编写或用图形工具自动生成Makefile ,不需要使用此工具.
但是绝大部分开源项目都是用autoconf生成Makefile .因此作为开发者必须了解如何编译由autoconf处理 的项目以有生成原理即可.

autoconf 和automake 处理流程
必须软件:
    autoconf/automake/m4/perl/libtool(其中libtool非必须)。
autoconf是一个用于生成可以自动地配置软件源码包,用以适应多种UNIX类系统的shell脚本工具,其中autoconf需要用到 m4,便于生成脚本。 
automake是一个从Makefile.am文件自动生成Makefile.in的工具。为了生成Makefile.in
automake还需用到perl,由于automake创建的发布完全遵循GNU标准,所以在创建中不需要perl 
libtool是一款方便生成各种程序库的工具。  

生成 Makefile 的流程
生成流程
1) 运行autoscan命令
2) 将configure.scan 文件重命名为configure.in,并修改configure.in文件
3) 在project目录下新建Makefile.am文件,并在core和shell目录下也新建makefile.am文件
4) 在project目录下新建NEWS、 README、 ChangeLog 、AUTHORS文件
5) 将/usr/share/automake-1.X/目录下的depcomp和complie文件拷贝到本目录下
6) 运行aclocal命令
7) 运行autoconf命令
8) 运行automake -a命令
9) 运行./confiugre脚本

已在互联网发布项目通常由原开发者做到1-8步.最终使用者只需做9步即可,少部分可能做到第7步.

生成Makefile流程图

【MakeFile详解】_第2张图片 

Configure.in的内容
当我们利用autoscan工具生成confiugre.scan文件时,我们需要将confiugre.scan重命名为confiugre.in文件。confiugre.in调用一系列autoconf宏来测试程序需要的或用到的特性是否存在,以及这些特性的功能  
confiugre.scan 样例
每个configure.scan文件都是以AC_INIT开头,以AC_OUTPUT结束。我们不难从文件中看出confiugre.in文件的一般布局:
    AC_INIT 
    测试程序 
    测试函数库 
    测试头文件 
    测试类型定义 
    测试结构 
    测试编译器特性 
    测试库函数 
    测试系统调用 
    AC_OUTPUT 

其它文件说明
Makefile.am 
    Makefile.am是一种比Makefile更高层次的规则。只需指定要生成什么目标,它由什么源文件生成,要安装到什么目录等构成。
开发者通常要手工编写Makefile.am 和修改configure.in 
然后通过工具生成makefile.in和configure即可发布

处理开源项目的流程

最大开源网站
http://www.sourceforge.net
第一步:解压
    源代码是通常以压缩包的方式发布的 ,通常是tar.gz(tgz)或tar.biz2格式压缩包, 
    tar xvzf boa-0.94.13.tar.gz
    tar xvjf  php-5.2.3.tar.bz2
第二步,如果是补丁文件(以patch打头的压缩包),则需要patch命令进行补丁
    zcat ../../patch-2.4.5-rmk7.gz | patch -p1 
查找项目本向是否自带了Makefile,如果有,则直接调用make 进行编译项目.否则检测下列几步

查找是否有configure,如果有,执行下列操作.
    ./configure 开始运行,将检查您的系统。这个过程的输出将在终端上显示,并同时存放到新建的‘config.log’文件中。如果正常无误,则在同目录下生成Makefile
    如果碰到会阻碍完成编译的错误,检查将自动停止。同时显示出错信息,并写入‘config.log’文件.
    如果修正错误后,需要把config.cache’删除,并重新运行./configure 
通过configure 生成Makefile 通常都有all,clean,install,uninstall .表示缺省编译,清除中间文件,安装软件,卸载软件

如果找不到configure,再查找是否有configure.in
    如有,则在当前目录下执行
    autoconf  #生成configure
如果有Imakefile 表示是老版本configure,
    xmkmf -a #解释Imakefile 生成Makefile
如果有GNUmakefile,一般与Makefile  等效.
如果有 Makefile.cvs,
    Make –f Makefile.cvs 生成Configure
源码目录下没有任何 build 文件 
    find . -type f -perm -700  #查找可执行程序

查找是否有configure,如果有,执行下列操作.
    ./configure 开始运行,将检查您的系统。这个过程的输出将在终端上显示,并同时存放到新建的‘config.log’文件中。如果正常无误,则在同目录下生成Makefile
    如果碰到会阻碍完成编译的错误,检查将自动停止。同时显示出错信息,并写入‘config.log’文件.
    如果修正错误后,需要把config.cache’删除,并重新运行./configure 
通过configure 生成Makefile 通常都有all,clean,install,uninstall .表示缺省编译,清除中间文件,安装软件,卸载软件

如果找不到configure,再查找是否有configure.in
    如有,则在当前目录下执行
    autoconf  #生成configure
如果有Imakefile 表示是老版本configure,
    xmkmf -a #解释Imakefile 生成Makefile
如果有GNUmakefile,一般与Makefile  等效.
如果有 Makefile.cvs,
    Make –f Makefile.cvs 生成Configure
源码目录下没有任何 build 文件 
    find . -type f -perm -700  #查找可执行程序

configure脚本 选项
configure 有大量选项可供不同需求要求
    --help 查看所有选项
    --prefix=PEWFIX 输入安装目录前缀.
    ./configure --prefix=/opt/gnu 
    --bindir=DIR 进制安装目录
    --host 
    指定软件运行的系统平台.如果没有指定,将会运行`config.guess‘来检测.如arm通常用 –host=arm-linux
    '--target=GARGET' 
    指定软件面向(target to)的系统平台.这主要在程序语言工具如编译器和汇编器上下文中起作用.如果没有指定,默认将使用'--host'选项的值 

使用configure的项目
zlib ZIP压缩开发包
用于生成zip的压缩包的静态库和一个简单压缩工具,可直接用于项目开发
编译过程
    tar xvzf zlib-1.2.3.tar.gz
    cd zlib-1.2.3
    ./configure
    make
使用zlib
    一直接在应用程序链接libz.a使用zip功能
    使用命令行工具minizip进行压缩

# Makefile for zlib
# Copyright (C) 1995-2005 Jean-loup Gailly.
# For conditions of distribution and use, see copyright notice in zlib.h

# To compile and test, type:
#    ./configure; make test
# The call of configure is optional if you don't have special requirements
# If you wish to build zlib as a shared library, use: ./configure -s

# To use the asm code, type:
#    cp contrib/asm?86/match.S ./match.S
#    make LOC=-DASMV OBJA=match.o

# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
#    make install
# To install in $HOME instead of /usr/local, use:
#    make install prefix=$HOME

CC=gcc

CFLAGS=-O3 -DUSE_MMAP
#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
#CFLAGS=-g -DDEBUG
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
#           -Wstrict-prototypes -Wmissing-prototypes

LDFLAGS=-L. libz.a
LDSHARED=gcc
CPP=gcc -E

LIBS=libz.a
SHAREDLIB=libz.so
SHAREDLIBV=libz.so.1.2.3
SHAREDLIBM=libz.so.1

AR=ar rc
RANLIB=ranlib
TAR=tar
SHELL=/bin/sh
EXE=

prefix =/usr/local
exec_prefix =${prefix}
libdir =${exec_prefix}/lib
includedir =${prefix}/include
mandir =${prefix}/share/man
man3dir = ${mandir}/man3

OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
       zutil.o inflate.o infback.o inftrees.o inffast.o

OBJA =
# to use the asm code: make OBJA=match.o

TEST_OBJS = example.o minigzip.o

all: example$(EXE) minigzip$(EXE)

check: test
test: all
	@LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
	echo hello world | ./minigzip | ./minigzip -d || \
	  echo '		*** minigzip test FAILED ***' ; \
	if ./example; then \
	  echo '		*** zlib test OK ***'; \
	else \
	  echo '		*** zlib test FAILED ***'; \
	fi

libz.a: $(OBJS) $(OBJA)
	$(AR) $@ $(OBJS) $(OBJA)
	-@ ($(RANLIB) $@ || true) >/dev/null 2>&1

match.o: match.S
	$(CPP) match.S > _match.s
	$(CC) -c _match.s
	mv _match.o match.o
	rm -f _match.s

$(SHAREDLIBV): $(OBJS)
	$(LDSHARED) -o $@ $(OBJS)
	rm -f $(SHAREDLIB) $(SHAREDLIBM)
	ln -s $@ $(SHAREDLIB)
	ln -s $@ $(SHAREDLIBM)

example$(EXE): example.o $(LIBS)
	$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)

minigzip$(EXE): minigzip.o $(LIBS)
	$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)

install: $(LIBS)
	-@if [ ! -d $(exec_prefix) ]; then mkdir -p $(exec_prefix); fi
	-@if [ ! -d $(includedir)  ]; then mkdir -p $(includedir); fi
	-@if [ ! -d $(libdir)      ]; then mkdir -p $(libdir); fi
	-@if [ ! -d $(man3dir)     ]; then mkdir -p $(man3dir); fi
	cp zlib.h zconf.h $(includedir)
	chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h
	cp $(LIBS) $(libdir)
	cd $(libdir); chmod 755 $(LIBS)
	-@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1
	cd $(libdir); if test -f $(SHAREDLIBV); then \
	  rm -f $(SHAREDLIB) $(SHAREDLIBM); \
	  ln -s $(SHAREDLIBV) $(SHAREDLIB); \
	  ln -s $(SHAREDLIBV) $(SHAREDLIBM); \
	  (ldconfig || true)  >/dev/null 2>&1; \
	fi
	cp zlib.3 $(man3dir)
	chmod 644 $(man3dir)/zlib.3
# The ranlib in install is needed on NeXTSTEP which checks file times
# ldconfig is for Linux

uninstall:
	cd $(includedir); \
	cd $(libdir); rm -f libz.a; \
	if test -f $(SHAREDLIBV); then \
	  rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \
	fi
	cd $(man3dir); rm -f zlib.3

mostlyclean: clean
clean:
	rm -f *.o *~ example$(EXE) minigzip$(EXE) \
	   libz.* foo.gz so_locations \
	   _match.s maketree contrib/infback9/*.o

maintainer-clean: distclean
distclean: clean
	cp -p Makefile.in Makefile
	cp -p zconf.in.h zconf.h
	rm -f .DS_Store

tags:
	etags *.[ch]

depend:
	makedepend -- $(CFLAGS) -- *.[ch]

# DO NOT DELETE THIS LINE -- make depend depends on it.

adler32.o: zlib.h zconf.h
compress.o: zlib.h zconf.h
crc32.o: crc32.h zlib.h zconf.h
deflate.o: deflate.h zutil.h zlib.h zconf.h
example.o: zlib.h zconf.h
gzio.o: zutil.h zlib.h zconf.h
inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
minigzip.o: zlib.h zconf.h
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
uncompr.o: zlib.h zconf.h
zutil.o: zutil.h zlib.h zconf.h

zlib生成和构建过程

【MakeFile详解】_第3张图片


bridge-utils网桥配置工具
bridge-utils本身是一个很简单的网络工具,一般使用不多,但它有一个特点是没有configure,只有configure.in
    即开发者在发布少做了一步,这需要使用源码的开发者多做一步
编译过程
    tar xvzf bridge-utils-1.2.tar.gz
    cd bridge-utils-1.2
    autoconf
    ./configure
    make
使用
    brctl/brctl #使用配置工具

DESTDIR=
KERNEL_HEADERS=-I/usr/src/linux/include

INSTALL=/usr/bin/install -c

prefix=/usr/local
exec_prefix=${prefix}
bindir=${exec_prefix}/bin
sbindir=${exec_prefix}/sbin
mandir=${prefix}/man
distdir = $(PACKAGE)-$(VERSION)

SUBDIRS=libbridge brctl doc

all:
	for x in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$x ; done

clean:
	for x in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$x clean ; done

distclean:	clean
	rm -f config.log
	rm -f config.cache
	rm -f config.status

maintainer-clean: distclean
	rm -f Makefile
	rm -f brctl/Makefile
	rm -f libbridge/Makefile
	rm -f doc/Makefile

install:
	for x in $(SUBDIRS); do $(MAKE) $(MFLAGS) -C $$x install; done

【MakeFile详解】_第4张图片 

mc 资源管理器
mc是一个类似dos下经典工具norton Commder,在字符界面下实现双窗口图形界面,实用价值非常高
编译过程
    tar xvzf mc-4.6.1.tar.gz
    cd mc-4.6.1
    ./configure
    make
    make install #这样作为一个工具安装到系统
使用
    mc #调用mc界面

mc执行界面

【MakeFile详解】_第5张图片

mc configure错误解决
如果在configure阶段报如下错误

configure: error: Test for glib failed.
GNU Midnight Commander requires glib 1.2.6 or above.

表明缺少新版本的glibc,或安装不正确.解决办法是重新安装glibc开发库
    下载 glib-devel-1.2.10-11.1.i386.rpm 
    在redhat 安装
        rpm -Uvh glib-devel-1.2.10-11.1.i386.rpm 
然后重新运行mc的configure生成makefile即可

更多configure项目
较大项目:
    php :动态网页脚本, php-5.2.3.tar.bz2
    sqlite :嵌入式SQL数据库, sqlite-3.4.1.tar.gz
    BerkeleyDB:另一个嵌入式数据库, db-4.5.20CD.tar.gz
均采用configure 生成脚本模式


 

你可能感兴趣的:(gcc,工具,linux,运维,服务器)