这里介绍 GNU 的 tar 程序所使用的 makefile。这是一个中等复杂程度的 makefile 示例。开头的第 1 行使用 #! 这一设定,使该 makefile 可以直接执行。
由于这条规则是第一个目标,因此默认目标 (goal) 为 ‘all’。这个 makefile 有趣的一点是,testpad.h 是由名为 testpad 的程序自动生成的源文件。而 testpad 本身又是从 testpad.c 编译生成的。
如果输入 ‘make’ 或 ‘make all’,make 就会生成 tar 可执行文件、提供远程磁带访问的 rmt 守护进程,以及名为 tar.info 的 Info 文件。
如果输入 ‘make install’,make 不仅会生成 tar、rmt、tar.info,还会将它们安装到位。
如果输入 ‘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.texinfo 生成的 Info 文件群。
除此之外,还准备了用于创建发行套件的 shar 目标和 dist 目标。
#!/usr/bin/make -f
# 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
#### 系统配置部分的开始 ####
srcdir = .
# 如果使用 gcc,请运行随附的 fixincludes 脚本,
# 或者为 gcc 加上 -traditional 选项来使用。
# 否则在某些系统上 ioctl 调用
# 可能会被错误地编译。
CC = gcc -O
YACC = bison -y
INSTALL = /usr/local/bin/install -c
INSTALLDATA = /usr/local/bin/install -c -m 644
# 可以添加到 DEFS 的内容:
# -DSTDC_HEADERS 当有 ANSI C 的头文件和库
# 时。
# -DPOSIX 当有 POSIX.1 的头文件和库
# 时。
# -DBSD42 当有 sys/dir.h(使用 -DPOSIX 时
# 除外)、sys/file.h,以及
# `struct stat' 的 st_blocks 时。
# -DUSG 当有 System V/ANSI C 的字符串、
# 内存函数与头文件、sys/sysmacros.h、
# fcntl.h、getcwd,且没有 valloc,
# 并有 ndir.h(使用 -DDIRENT 时
# 除外)时。
# -DNO_MEMORY_H 当为 USG 或 STDC_HEADERS 但不
# include memory.h 时。
# -DDIRENT 当为 USG 且有 dirent.h 而非
# ndir.h 时。
# -DSIGTYPE=int 当信号处理函数返回 int 而非
# void 时。
# -DNO_MTIO 当没有 sys/mtio.h(磁带的 ioctl)
# 时。
# -DNO_REMOTE 当没有远程 shell 或 rexec
# 时。
# -DUSE_REXEC 当远程磁带操作使用 rexec 而非
# fork rsh 或 remsh
# 时。
# -DVPRINTF_MISSING 当没有 vprintf 函数(但有 _doprnt)
# 时。
# -DDOPRNT_MISSING 当没有 _doprnt 函数时。
# 这时还需要定义
# -DVPRINTF_MISSING。
# -DFTIME_MISSING 当没有 ftime 系统调用时。
# -DSTRSTR_MISSING 当没有 strstr 函数时。
# -DVALLOC_MISSING 当没有 valloc 函数时。
# -DMKDIR_MISSING 当没有 mkdir 和 rmdir 系统调用
# 时。
# -DRENAME_MISSING 当没有 rename 系统调用时。
# -DFTRUNCATE_MISSING 当没有 ftruncate 系统调用
# 时。
# -DV7 在 Version 7 Unix 上(很久
# 没有测试了)。
# -DEMUL_OPEN3 当没有三参数版的 open,且想用
# 手头的系统调用来模拟它
# 时。
# -DNO_OPEN3 当没有三参数的 open,且想禁用
# tar 的 -k 选项而非模拟 open
# 时。
# -DXENIX 当有 sys/inode.h,且需要在 94 处
# include 它时。
DEFS = -DSIGTYPE=int -DDIRENT -DSTRSTR_MISSING \
-DVPRINTF_MISSING -DBSD42
# 如果没有定义 NO_REMOTE,就把它设为 rtapelib.o。
# 如果定义了,请保持为空。
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
# 为每个安装的程序加上的前缀,
# 通常为空或 `g'。
binprefix =
# 安装 tar 的目录。
bindir = $(prefix)/bin
# 安装 info 文件的目录。
infodir = $(prefix)/info
#### 系统配置部分的结束 ####
SRCS_C = tar.c create.c extract.c buffer.c \
getoldopt.c update.c gnu.c mangle.c \
version.c list.c names.c diffarch.c \
port.c wildmat.c getopt.c getopt1.c \
regex.c
SRCS_Y = getdate.y
SRCS = $(SRCS_C) $(SRCS_Y)
OBJS = $(SRCS_C:.c=.o) $(SRCS_Y:.y=.o) $(RTAPELIB)
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
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 有 8 个 shift/reduce 冲突。
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