GNU make/打印版
声明,本文翻译的是GNU make 3.8.1版用户手册;本手册的原作者是司徒文(Richard M. Stallman),麦家府(Roland McGrath),史密斯(Paul D. Smith)。原手册发布于2006年4月。此为原文下载地址
make概述
[编辑]make工具能自动判断一个大程序的哪些部分需要再编译,并且能用命令来执行再编译操作。本文档讨论的GNU make原来是由司徒文与麦家府开发制作的,从3.76版开始由史密斯接管开发工作。
GNU make遵从IEEE 1003.2-1992标准(POSIX.2)第6.2条。
在本文例子中,笔者用的是C语言程序,这是因为C语言最为流行,但读者也可以用make来完成其他编程语言的编译工作,前提是这种语言的编译器能在 shell下运行。当然,make的应用不局限于程序;如果遇到一些任务,这些任务的文件必须随着其他文件或数据的变化而更新,那么读者就可以用make 来应对这些任务。
在使用make之前,请读者先写好Makefile文件,该文件须描述清楚程序文件之间的关系,还要给出更新每个文件的命令。通常,一个程序的可执行文件由OBJ文件来更新,而这些OBJ文件则由源代码编译产生。
只要有合适的Makefile文件,在修改了一些源代码后,只要在Shell命令行下输入:
- make
就足以完成所有必要的再编译。make程序通过Makefile的数据库以及诸文件的最后修改时间来判断哪些文件需要更新。对于每个需要更新的文件, make会用数据库中记录的命令来对其操作。
读者可以给make加上命令行参数,以此告诉make哪些文件需要再编译、怎样再编译。参见第九章如何运行make。
如何使用本文档
[编辑]如果读者是个make新手,或者想阅读大体介绍,那么在阅读每章时只需少量的看前几节,后面几节可以略过。每章的前几节会有该章介绍以及该章的大体信息,而后几节则会包括一些特殊的或技术性的信息。但第二章 make简介是个例外,全章都是介绍性的内容。
如果读者对其他make程序比较熟悉的话,请参阅第十二章 GNU make的特色功能,该章列出了GNU make的增强功能;另外请参阅第十三章 GNU make与标准make不兼容的部分,该章举出GNU make在少数功能上逊色于其他make的例子。
如果需要阅读摘要,请看第九章第七节 选项摘要、附录 A 快速参考以及第四章第八节所讲的特殊目标。
问题与漏洞
[编辑]如果读者发现了GNU make的一些问题或者认为发现了漏洞,那么请与开发者联系;我们不作任何承诺,但我们会尽力解决问题。
在提交漏洞报告之前,请核实漏洞的真实性。另外请认真反复阅读文档,确定文档介绍的应用方法在实际操作中有效,如果文档对功能上的一些问题没有阐述清楚,那么也请提交报告,这些都是文档的“漏洞”!
在提交漏洞报告或者自己解决漏洞之前,请将Makefile文件简化至最小且能体现漏洞问题的程度。然后把Makefile文件连同出错和警告信息一齐发给我们。请勿改动原信息,最好将其剪切复制到漏洞报告中。请确保用以生成最简Makefile文件的命令中不使用非自由软件或者不常用的程序(其实对于这种工具,读者随时都可以用简单的几句Shell命令来测试)。最后,请详述Makefile本应有的预期结果,以便于我们判断问题是否出在文档上。
如果读者发现了一个如假包换的错误,那么可以通过以下两种途径提交报告:一、通过发送电子邮件到:
与我们联系;
二、使用我们的在线项目管理来提交报告,网址是:
除了上述的信息以外,请将使用的make完整的版本号一并发给我们;读者可以通过使用命令“make --version”来获取版本信息。请确保报告中包含make所运行机器的硬件信息与操作系统信息;顺便提一句,获取这些信息的一种方法是使用命令 “make --help”,一切尽在命令的最后一行输出中。
make简介
[编辑]首先要有一个名为“Makefile”的文件告诉make需要作什么。绝大多数情况下,Makefile主要让make完成编译与链接程序的工作。
本章我们讨论一个简单的Makefile,这个Makefile会编译与链接一个由八个C源代码文件和三个头文件组成的文本编辑器程序。该 Makefile还会告诉make如何在有明确指示的时候运行各种各样的命令(比如说接到清除指示时,make运行删除某些文件的命令)。要阅读更复杂的 Makefile代码,翻至附录C 一个复杂的Makefile实例。
当make重新编译该文本编辑器时,所有的C源代码文件都会被重新编译。如果一个头文件被修改,那么为了保证整体程序无损,包含该头文件的所有C源代码文件都必须要重新编译。源代码文件每经过一次编译都会有一个与自己对应的OBJ文件生成。最后,若有源代码文件被重新编译,所有OBJ文件不管是以前生成的还是新生成的,都会被用来链接生成新的可执行文本编辑器程序。
规则大概是什么样的
[编辑]一个简单的Makefile所包含的“规则”形式如下
目标 ...:先决条件 命令 ... ...
目标的名称一般与生成的文件名称一致(像可执行程序和OBJ文件)。目标的名称
也可以是要进行的动作,比如说“clean”(参见第四章第五节 伪目标)。
先决条件是用以生成目标的输入文件,而一个目标往往依赖于多个文件。
命令是make要执行的动作,而一个规则往往要多行命令。请注意:在每个命令前都必须输入一个Tab!一般粗心大意的人容易在这个问题上犯错。
通常有先决条件规则的命令会在先决条件被改动之后执行。但也有一些执行特殊命令的规则没有先决条件,比如说目标“clean”所在的规则就没有先决条件,该规则含有删除命令。
接下来规则会说明与特定规则关联的文件应该何时被操作,如何被操作。然后make执行先决条件中的命令,用以生成或更新目标。此外,规则还可以对何时与如何进行一个动作下令。参见第四章 编写规则。
除了规则之外,Makefile文件也可以有其他内容,但一个简单的Makefile只需有规则即可。规则写出来会比模板中所写的略显复杂,但或多或少含有与其一致的部分。
一份简单的Makefile文件
[编辑]下面有一份简单易懂的Makefile文件,该文件描述了各种依赖关系:可执行程序edit依赖于八个OBJ文件,八个OBJ文件依赖于八个C源代码文件和三个头文件。
在本例中,所有C源代码文件都包含了“defs.h”头文件,只有定义了编辑命令的C源代码文件才包含“command.h”头文件,而只有只有能改变编辑器缓冲区的低层C源代码文件才包含“buffer.h”头文件。
edit : main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o cc -o edit main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o main.o : main.c defs.h cc -c main.c kbd.o : kbd.c defs.h command.h cc -c kbd.c command.o : command.c defs.h command.h cc -c command.c display.o : display.c defs.h buffer.h cc -c display.c insert.o : insert.c defs.h buffer.h cc -c insert.c search.o : search.c defs.h buffer.h cc -c search.c files.o : files.c defs.h buffer.h command.h cc -c files.c utils.o : utils.c defs.h cc -c utils.c clean : rm edit main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o
本例用反斜线“\”将每个长行都分成两行,如此功能上与长行相同,而且减少了阅读长行的难度。
要用此Makefile生成可执行程序edit,请键入:
- make
要用此Makefile删除目录中所有OBJ文件和可执行程序“edit”,请键入:
- make clean
在本例中,目标包括,可执行程序“edit”以及OBJ文件“main.o”与“kdb.o”;先决条件也有许多,如“main.c”与“defs.h”;而每个“.o”文件都既为目标,又是先决条件;命令包括“cc -c main.c”与“cc -c kbd.c”。
若目标为文件,则该文件会在其先决条件被改动后重编译与链接。另外,会自动生成的先决条件首先更新。本例中,“edit”依赖于八个OBJ文件;OBJ文件“main.o”依赖于源代码文件“main.c”与头文件“defs.h”。
Shell命令跟随在目标与先决条件的下一行,该命令控制更新目标文件。每个命令行首必须要有Tab键入,以此区分命令行与Makefile中的其他行。(想想看,make全然不知命令是如何工作的,必须由程序员提供命令来更新目标。make所能干的只有执行程序员给出命令,然后再根据命令判断目标文件是否需要更新;如需要,更新之)。
目标“clean”不是一个文件,仅仅是动作的名称而已。因为这个规则不包含其他动作,而且也不是其他任何规则的先决条件,所以,make不会执行此处操作,除非被特别指定。请注意,此规则既非其他规则之先决条件,亦无先决条件,故此规则唯一目的为运行特定命令。目标若只含命令而与其他文件不相关联,则称此目标为伪目标。可参阅第四章第五节 伪目标,了解详情。另外,请参阅第五章第五节 命令中的报错信息,了解如何忽略rm或者其他命令的报错信息。
make如何执行一个Makefie的指令
[编辑]在默认情况下,make的工作始于第一个目标(只要这个目标不是以“。”开头的)。此目标称为默认最终目标(如果不想使用这个默认规定,可以在命令行中输入“make 目标名”(参见第九章第二节 用以确定最终目标的参数)或者更改变量(参见第三章第六节 其它的特殊变量)“.DEFAULT_GOAL”以改变默认最终目标)。
上一节简单示例中,默认最终目标是更新可执行程序“edit”,故将其列入规则首位。
因此,输入以下命令:
- make
make首先读取本目录的Makefile,而后开始运行第一个规则。在此例中,规则用以重链接“edit”;但在执行这条规则之前,make必须完成所有“edit”依赖的规则,这些规则就是那些OBJ文件;而每个OBJ文件都会运行自己的一套规则,这些规则会通过编译各自源代码的方式来更新每个“.o”文件。如果头文件或者源代码文件的修改时间比依赖其的OBJ文件要晚,或者OBJ文件不存在,那么重新编译就必须要进行。
那些非最终目标之所以会被运行,是因为最终目标与之相关。而与最终目标无关的规则就不会被执行,除非被特指(如“make clean”)。
在重编译一个OBJ文件之前,make会先更新其先决条件,先决条件包括源代码文件与头文件。此例中的Makefile并没有针对源代码文件与头文件的操作,另外这些“.c”与“.h”文件也不是规则的名称,故make在此不做任何事情。但make会自动更新自动生成的C程序,比如说由Bison或Yacc生成的,由此次规则生成的。
在编译完所有需要的OBJ文件后,make会决定是否重链接“edit”。如果“edit”文件不存在或者OBJ文件比“edit”文件要新,则重链接工作一定要作。如果OBJ文件是刚编译出的,其时间晚于“edit”文件,故此时“edit”文件要被重链接。
因此,如果更改了“insert.c”文件再运行make;make会先编译“insert.c”文件生成“insert.o”文件,再链接生成“edit”文件。若更改的是“command.h”,再运行make;make会编译生成“kdb.o”、“command.o”、“files.o”再链接生成“edit”。
用变量简化Makefile
[编辑]在上例中,生成“edit”的OBJ文件组被列举了两次(这里在重复一次):
edit : main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o cc -o edit main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o
如此重复书写,容易造成错误;另外,若有新OBJ文件加入系统,本应可以只添加新文件而不考虑原有的OBJ文件。若采用变量协助工作,则既可减少出错几率,亦能简化Makefile。变量允许先对一段文本字符串定义,以后需要书写诸OBJ文件时,可以只输入变量而不需要把所有OBJ文件列出(参见第六章 如何使用变量)。
此处,一个习惯性做法是,在每个Makefile中加入名为“objects”、“OBJECTS”、“objs”、“OBJS”、“obj”或者“OBJ”的变量,用以列出全部OBJ文件的名称。在Makefile中,可以用如下方式定义变量“objects”:
objects = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o
定义之后,文件时需要列出诸OBJ文件处可用“$(objects)”代替(参见第六章 如何使用变量)。
下面就是用变量来描述诸OBJ文件的Makefile,简单而完整:
objects = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o edit : $(objects) cc -o edit $(objects) main.o : main.c defs.h cc -c main.c kbd.o : kbd.c defs.h command.h cc -c kbd.c command.o : command.c defs.h command.h cc -c command.c display.o : display.c defs.h buffer.h cc -c display.c insert.o : insert.c defs.h buffer.h cc -c insert.c search.o : search.c defs.h buffer.h cc -c search.c files.o : files.c defs.h buffer.h command.h cc -c files.c utils.o : utils.c defs.h cc -c utils.c clean : rm edit $(objects)
让make自己推算出要执行的命令
[编辑]不必将每个编译C源代码文件的命令全部写出,因为make可以构造出这些命令:make有一个隐规则可通过命令“cc -c”生成与“.c”文件前缀名一致的“.o”文件的命令,比如将“main.c”编译成“main.o”的命令“cc -c main.c -o main.o”。此处可以把命令中写“.o”的部分省略。参阅第十章 使用隐规则。
当“.c”文件以下例方法自动被使用时,“.c”文件会自动加入到先决条件中。在先决条件中省略“.c”文件的同时,编译命令也被省略了。
下面是个完整的例子。例子中包括了上面两种省略方法,而且也使用了上一节所说的“objects”变量。
objects = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o edit : $(objects) cc -o edit $(objects) main.o : defs.h kbd.o : defs.h command.h command.o : defs.h command.h display.o : defs.h buffer.h insert.o : defs.h buffer.h search.o : defs.h buffer.h files.o : defs.h buffer.h command.h utils.o : defs.h .PHONY : clean clean : rm edit $(objects)
本例与实际应用中Makefile相差无几(复杂化的“clean”规则在其他地方有所讨论。参见第四章第五节 伪目标与第五章第五节 命令中的报错信息)。
隐规则使用简便,故尤为重要。读者会频繁见到隐规则的使用。
另一种格式的Makefile
[编辑]当组成Makefile的全为规则时,可以用另一种形式的Makefile代替前面的。下面这种形式的Makefile全部以先决条件代替,此为全文:
objects = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o edit : $(objects) cc -o edit $(objects) $(objects) : defs.h kbd.o command.o files.o : command.h display.o insert.o search.o files.o : buffer.h
这里,“defs.h”为所有OBJ文件的先决条件;“command.h”与“buffer.h”为特定OBJ文件的先决条件。
不知这样紧凑的写法是否为一些人的爱好,但还是有一些人不喜欢这种写法,认为将一个目标跟与之对应的信息写在一起显得比较清楚。
清理目录的规则
[编辑]编写Makefile所要写的不仅仅编译程序。Makefile还能做一些编译外的事情,比如说,如何将一个目录里的OBJ文件与可执行文件清理干净。
下面就是一例,演示如何用make以完成清除工作:
clean: rm edit $(objects)
在实际应用中Makefile可能会写得更复杂,以应对突发事件,下为例:
.PHONY : clean clean : -rm edit $(objects)
本例的Makefile,可在有文件名为“clean”时避免混淆,还可在rm报错时仍旧执行。(参见第四章第五节 伪目标与第五章第五节 命令中的报错信息)
此类规则不可置于Makefile文首,这是由于一般不愿让其作为默认规则执行!故在前几节的完整Makefile示例中,用“edit”为默认规则,以便编译与重编译。
因为“clean”并非“edit”的先决条件,故此规则在make没有参数时不会运行。若要运行此规则,键入命令“make clean”(参见第九章 如何运行make)。
编写Makefile
[编辑]make重编译系统的信息源于Makefile构建的数据库。
Makefile里包含的是什么
[编辑]“Makefile”文件应该取什么样的名字
[编辑]包含其它的Makefile文件
[编辑]“MAKEFILES”变量
[编辑]“MAKEFILE_LIST”变量
[编辑]其它的特殊变量
[编辑]Makefile如可被make再执行
[编辑]调用其它Makefile的重要技巧
[编辑]make如何理解Makefile的内容
[编辑]编写规则
[编辑]规则的语法结构
[编辑]先决条件的种类
[编辑]在文件名中使用通配符
[编辑]通配符示例
[编辑]使用通配符的陷阱
[编辑]“wildcard”函数
[编辑]为先决条件搜索目录
[编辑]“VPATH”:为所有先决条件搜索路径
[编辑]“vpath”指令
[编辑]目录搜索是如何进行的
[编辑]编写带目录搜索功能的Shell命令
[编辑]目录搜索与隐规则
[编辑]为连接库而做的目录搜索
[编辑]伪目标
[编辑]无先决条件与命令的规则
[编辑]用目标对应的空文件记录事件
[编辑]特殊内建目标的名称
[编辑]单规则使用多目标
[编辑]单目标对应多规则
[编辑]静态模式规则
[编辑]静态模式规则的语法结构
[编辑]静态模式规则与隐规则的比较
[编辑]带双冒号的规则
[编辑]自动生成先决条件
[编辑]编写规则中的命令
[编辑]命令的语法结构
[编辑]将命令分为多行的方法
[编辑]在命令中使用变量
[编辑]输出信息命令
[编辑]命令的执行
[编辑]选择Shell
[编辑]并行执行
[编辑]命令中的报错信息
[编辑]中断或强制结束make
[编辑]递归使用make
[编辑]make的变量是怎样工作的
[编辑]与低层的make互传变量
[编辑]与低层的make互传选项
[编辑]“--print-directory”选项
[编辑]定义封装的命令组
[编辑]使用空命令
[编辑]如何使用变量
[编辑]变量的基本参考
[编辑]变量的两种风格
[编辑]变量高级功能参考
[编辑]替换功能参考
[编辑]可运算的变量名
[编辑]变量如何获取其值
[编辑]设置变量
[编辑]向变量追加文本内容
[编辑]“override”指令
[编辑]逐字定义变量
[编辑]来自环境变量的变量
[编辑]目标特定变量的赋值
[编辑]模式特定变量的赋值
[编辑]Makefile的条件控制部分
[编辑]条件示例
[编辑]条件的语法结构
[编辑]测试标志位的条件
[编辑]文本操控函数
[编辑]函数调用的语法结构
[编辑]对字符串做替换与分解的函数
[编辑]对文件名操作的函数
[编辑]条件控制函数
[编辑]“foreach”函数
[编辑]“call”函数
[编辑]“value”函数
[编辑]“eval”函数
[编辑]“shell”函数
[编辑]控制make的函数
[编辑]如何运行make
[编辑]用以确定Makefile文件的参数
[编辑]用以确定最终目标的参数
[编辑]用其它功能来取代执行命令的参数
[编辑]避免重新编译某些文件
[编辑]初始变量
[编辑]测试编译程序
[编辑]选项摘要
[编辑]使用隐规则
[编辑]使用隐规则
[编辑]隐规则章目
[编辑]隐规则使用的变量
[编辑]隐规则链
[编辑]定义与重定义模式的规则
[编辑]模式的规则介绍
[编辑]模式的规则示例
[编辑]自变变量
[编辑]模式是如何匹配的
[编辑]匹配一切的模式规则
[编辑]取消隐规则
[编辑]定义去除依赖的默认规则
[编辑]过时的附加规则
[编辑]隐规则的搜索算法
[编辑]使用make更新归档文件
[编辑]归档成员作为目标
[编辑]为归档成员目标而设的隐规则
[编辑]更新归档字符目录
[编辑]使用归档的风险
[编辑]归档文件的附加规则
[编辑]GNU make的特色功能
[编辑]GNU make与标准make不兼容的部分
[编辑]GNU make的一些不成文规定
[编辑]Makefile的通用习惯
[编辑]Makefile的工具
[编辑]指定变量的命令
[编辑]安装目录的变量
[编辑]为用户设计的标准目标
[编辑]安装命令的条目
[编辑]附录
[编辑]A 快速参考
[编辑]B 常见错误
[编辑]C 一个复杂的Makefile实例
[编辑]下面是一段为GNU tar程序设计的Makefile代码,相当复杂。
由于“all”是第一个目标,所以它也是默认目标。下面这个程序段有一个非常有趣的特色,这个特色就是源代码程序中的“testpad.h”文件是一个由名叫testpad程序自动生成的,而这个testpad又是又是由“testpad.c”这个程序经过编译产生的。
如果您输入“make”或者“make all”,则make会让名为“tar”的目标运行从而开始编译指令,会让名为“rmt”的目标运行从而生成一个远程磁带数据存取的守护程序,会让名为 “tar.info”的目标运行从而生成INFO文档。
如果您输入“make install”,那么make就执行的就不仅仅只是“tar”、“rmt”和“tar.info”这三个目标了,还会执行相应的安装操作。< /br>
如果您输入“make clean”,那么make会清除所有的“.o”文件,以及“tar”、“rmt”、“testpad”、“testpad.h”和“core”这些文件。
如果您输入“make distclean”,那么make除了会清除“make clean”会清除的文件外,还会清除“TAGS”、“Makefile”和“config.status”这些文件(虽然不明显,但下面这个 makefile和“config.status”都是用户通过tar发行版中的“configure”文件生成的,这个“configure”文件这里没有列出)。
如果您输入“make realclean”,那么make除了清除“make distclean”会清除的文件外,还会清除由“tar.info”生成的INFO文档。
# Generated automatically from Makefile.in by configure. # Un*x Makefile for GNU tar program. # Copyright (C) 1991 Free Software Foundation, Inc. # This program is free software; you can redistribute # it and/or modify it under the terms of the GNU # General Public License ... ... ... SHELL = /bin/sh #### Start of system configuration section. #### srcdir = . # If you use gcc, you should either run the # fixincludes script that comes with it or else use # gcc with the -traditional option. Otherwise ioctl # calls will be compiled incorrectly on some systems. CC = gcc -O YACC = bison -y INSTALL = /usr/local/bin/install -c INSTALLDATA = /usr/local/bin/install -c -m 644 # Things you might add to DEFS: # -DSTDC_HEADERS If you have ANSI C headers and # libraries. # -DPOSIX If you have POSIX.1 headers and # libraries. # -DBSD42 If you have sys/dir.h (unless # you use -DPOSIX), sys/file.h, # and st_blocks in `struct stat'. # -DUSG If you have System V/ANSI C # string and memory functions # and headers, sys/sysmacros.h, # fcntl.h, getcwd, no valloc, # and ndir.h (unless # you use -DDIRENT). # -DNO_MEMORY_H If USG or STDC_HEADERS but do not # include memory.h. # -DDIRENT If USG and you have dirent.h # instead of ndir.h. # -DSIGTYPE=int If your signal handlers # return int, not void. # -DNO_MTIO If you lack sys/mtio.h # (magtape ioctls). # -DNO_REMOTE If you do not have a remote shell # or rexec. # -DUSE_REXEC To use rexec for remote tape # operations instead of # forking rsh or remsh. # -DVPRINTF_MISSING If you lack vprintf function # (but have _doprnt). # -DDOPRNT_MISSING If you lack _doprnt function. # Also need to define # -DVPRINTF_MISSING. # -DFTIME_MISSING If you lack ftime system call. # -DSTRSTR_MISSING If you lack strstr function. # -DVALLOC_MISSING If you lack valloc function. # -DMKDIR_MISSING If you lack mkdir and # rmdir system calls. # -DRENAME_MISSING If you lack rename system call. # -DFTRUNCATE_MISSING If you lack ftruncate # system call. # -DV7 On Version 7 Unix (not # tested in a long time). # -DEMUL_OPEN3 If you lack a 3-argument version # of open, and want to emulate it # with system calls you do have. # -DNO_OPEN3 If you lack the 3-argument open # and want to disable the tar -k # option instead of emulating open. # -DXENIX If you have sys/inode.h # and need it 94 to be included. DEFS = -DSIGTYPE=int -DDIRENT -DSTRSTR_MISSING \ -DVPRINTF_MISSING -DBSD42 # Set this to rtapelib.o unless you defined NO_REMOTE, # in which case make it empty. RTAPELIB = rtapelib.o LIBS = DEF_AR_FILE = /dev/rmt8 DEFBLOCKING = 20 CDEBUG = -g CFLAGS = $(CDEBUG) -I. -I$(srcdir) $(DEFS) \ -DDEF_AR_FILE=\"$(DEF_AR_FILE)\" \ -DDEFBLOCKING=$(DEFBLOCKING) LDFLAGS = -g prefix = /usr/local # Prefix for each installed program, # normally empty or `g'. binprefix = # The directory to install tar in. bindir = $(prefix)/bin # The directory to install the info files in. infodir = $(prefix)/info #### End of system configuration section. #### SRC1 = tar.c create.c extract.c buffer.c \ getoldopt.c update.c gnu.c mangle.c SRC2 = version.c list.c names.c diffarch.c \ port.c wildmat.c getopt.c SRC3 = getopt1.c regex.c getdate.y SRCS = $(SRC1) $(SRC2) $(SRC3) OBJ1 = tar.o create.o extract.o buffer.o \ getoldopt.o update.o gnu.o mangle.o OBJ2 = version.o list.o names.o diffarch.o \ port.o wildmat.o getopt.o OBJ3 = getopt1.o regex.o getdate.o $(RTAPELIB) OBJS = $(OBJ1) $(OBJ2) $(OBJ3) AUX = README COPYING ChangeLog Makefile.in \ makefile.pc configure configure.in \ tar.texinfo tar.info* texinfo.tex \ tar.h port.h open3.h getopt.h regex.h \ rmt.h rmt.c rtapelib.c alloca.c \ msd_dir.h msd_dir.c tcexparg.c \ level-0 level-1 backup-specs testpad.c .PHONY: all all: tar rmt tar.info .PHONY: tar tar: $(OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) rmt: rmt.c $(CC) $(CFLAGS) $(LDFLAGS) -o $@ rmt.c tar.info: tar.texinfo makeinfo tar.texinfo .PHONY: install install: all $(INSTALL) tar $(bindir)/$(binprefix)tar -test ! -f rmt || $(INSTALL) rmt /etc/rmt $(INSTALLDATA) $(srcdir)/tar.info* $(infodir) $(OBJS): tar.h port.h testpad.h regex.o buffer.o tar.o: regex.h # getdate.y has 8 shift/reduce conflicts. testpad.h: testpad ./testpad testpad: testpad.o $(CC) -o $@ testpad.o TAGS: $(SRCS) etags $(SRCS) .PHONY: clean clean: rm -f *.o tar rmt testpad testpad.h core .PHONY: distclean distclean: clean rm -f TAGS Makefile config.status .PHONY: realclean realclean: distclean rm -f tar.info* .PHONY: shar shar: $(SRCS) $(AUX) shar $(SRCS) $(AUX) | compress \ > tar-`sed -e '/version_string/!d' \ -e 's/[^0-9.]*\([0-9.]*\).*/\1/' \ -e q version.c`.shar.Z .PHONY: dist dist: $(SRCS) $(AUX) echo tar-`sed \ -e '/version_string/!d' \ -e 's/[^0-9.]*\([0-9.]*\).*/\1/' \ -e q version.c` > .fname -rm -rf `cat .fname` mkdir `cat .fname` ln $(SRCS) $(AUX) `cat .fname` tar chZf `cat .fname`.tar.Z `cat .fname` -rm -rf `cat .fname` .fname tar.zoo: $(SRCS) $(AUX) -rm -rf tmp.dir -mkdir tmp.dir -rm tar.zoo for X in $(SRCS) $(AUX) ; do \ echo $$X ; \ sed 's/$$/^M/' $$X \ > tmp.dir/$$X ; done cd tmp.dir ; zoo aM ../tar.zoo * -rm -rf tmp.dir