所有GNU发布的软件包的Makefile中,必须包含以下这些目标:
all
此目标的动作是编译整个软件包。“all”应该为Makefile的终极目标。该目标的动作不重建任何文档(只编译所有的源代码,生成可执行程序);Info文件应该作为发布文件的一部分,DVI文件只在明确指定的时候才应该被重建。
缺省情况下,对所有源程序的编译和连接应该使用选项“-g”,是最终的可执行程序中包含调试信息。当最终的可执行程序不需要包含调试信息时,可使用“strip”去掉可执行程序中的调试符号以减小最终的程序大小。
install
此目标的动作是完成程序的编译并将最终的可执行程序、库文件等拷贝到安装的目录。如果只是验证这些程序是否可被正确安装,它的动作应该是一个测试安装动作。
安装时一般不要对可执行程序进行strip(去掉可执行程序内部的调试信息)。存在另外一个目标“install-strip”,它实现安装的同时完成对可执行程序strip。
保证目标“install”的动作不更改程序创建目录(builid目录)下的任何文件,对这个目录下文件的修改(重建或者更新)是目标“all”所要定义的动作。
“install”目标定义的动作在安装目录不存在时,能够创建这些不存在的安装目录。这些目录包括:变量“prefix”和“exec_prefix”指定的目录和所有必要的子目录。完成此任务的方式可以使用下边介绍的“installdirs”目标。
在安装man文档的命令前使用“-”忽略这安装命令的错误,这样可以避免在没有Unix man文档的系统上执行安装时出现错误。
安装Info文档的方法是使用变量“INSTALL_DATA”将Info文档拷贝到“$(infodir)”目录下去(参考14.4安装目录的变量一节),如果存在“install-info”命令则执行它。“install-info”是一个编辑Info“dir”文件的程序,更新或者修改“info”文档的入口和目录;它是Texinfo软件包的一部分。这里有一个安装Info文档的例子:
$(DESTDIR)$(infodir)/foo.info: foo.info
$(POST_INSTALL)
# 可能在“.”(当前目录)存在一个新的文档,而不是“srcdir”。
-if test -f foo.info; then d=.; /
else d=$(srcdir); fi; /
$(INSTALL_DATA) $$d/foo.info $(DESTDIR)$@; /
#如果install-info命令存在则运行它
# 使用“if”代替在命令行前的“-”
# 这样,就可以看到运行install-info产生的真正错误
# 我们使用“$(SHELL) -c”是因为在一些shell中
# 遇到未知的命令不会运行失败
if $(SHELL) -c 'install-info --version' /
>/dev/null 2>&1; then /
install-info --dir-file=$(DESTDIR)$(infodir)/dir /
$(DESTDIR)$(infodir)/foo.info; /
else true; fi
目标install的命令需要分为三类:正常命令、预安装命令和安装后命令。参考14.6 安装命令分类一节
uninstall
删除所有已安装文件——由install创建的文件拷贝。规则所定义的命令不能修改编译目录下的文件,仅仅是删除安装目录下的文件。像install目标的命令一样,uninstall目标的命令也分为三类。参考14.6 安装命令分类一节
install-strip
和目标install的动作类似,但是install-strip指定的命令在安装时对可执行文件进行strip(去掉程序内部的调试信息)。它的定义如下:
install-strip:
$(MAKE) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
如果软件包的存在安装脚本时,目标install-strip所定义的命令就不能是对目标“install”的引用,它仅仅完成对可执行文件的strip。
“install-strip”不应该直接在build目录下对可执行文件进行strip,应该是对安装目录下的可执行文件进行strip。就是说“install-strip”所定义的命令不能对build 目录下的文件产生影响。
一般不建议安装时对可执行文件进行strip,因为去掉可执行文件的调试信息后,如果在程序中存在bug,就不能通过gdb对程序进行调试。
clean
清除当前目录下编译生成的所有文件,这些文件在make过程中产生。注意,clean动作不能删除软件包的配置文件,同时也不能删除build时创建的那些文件(诸如:目录、build生成的信息记录文件等)。因为这些文件都是发布版本的一部分。
对于.dvi文件,当它不作为发布版本的一部分时,可以删除。
distclean
类似于目标clean,但增加删除当前目录下的的配置文件、build过程产生的文件。目标“distclean”指定的删除命令应该删除软件包中所有非发布文件。
mostlyclean
类似于目标“clean”,但是可保留一些编译生成的文件,避免在下次编译时对这些文件重建。例如,对于gcc来说,此目标指定的命令不删除文件“libgcc.a”,因为在绝大多数情况下它都不需要重新编译。
maintainer-clean
此目标所定义的命令几乎会删除所有当前目录下能够由Makefile重建的文件。典型的,包括目标“distclean”删除的文件、由Bison生成的.c源文件、tags记录文件、Ifon文件等。但是有一个例外,就是执行“make maintainer-clean”不能删除“configure”这个配置脚本文件,即使“configure”可以由Makefile生成。因为“configure”是软件包的配置脚本。
目标“maintainer-clean”应该只能由维护软件包的用户使用,而不能被普通用户使用。因为它会删除一些软件包的发布文件,而重建这些文件可能需要专门的工具。因此我们在使用此目标是需要小心。
为了让用户能够在执行前得到提示,通常目标“maintainer-clean”的命令以下两行为开始:
@echo“该命令用于维护此软件包的用户使用”;
@echo“它删除的文件可能需要使用特殊的工具来重建。”
TAGS
此目标所定义的命令完成对该程序的tags记录文件的更新。tags文件通常可被编辑器作为符号记录文件,例如vim,Emacs等。
info
产生必要的Info文档。此目标应该按照如下书写:
info: foo.info
foo.info: foo.texi chap1.texi chap2.texi
$(MAKEINFO) $(srcdir)/foo.texi
必须在Makefile中定义变量“MAKEINFO”,代表命令工具makeinfo,该工具是发布软件Texinfo的一部分。
通常,GNU的发布程序会和Info文档会被一同创建,这意味着Info文档是在源文件的目录下。用户在创建发布软件时,一般情况下,make不更新Info文档,因为它们已经更新到最新了。
dvi
为所有的Texinfo文件创建对应的DVI文件。例如:
dvi: foo.dvi
foo.dvi: foo.texi chap1.texi chap2.texi
$(TEXI2DVI) $(srcdir)/foo.texi
必须在Makefile中定义变量“TEXI2DVI”。它代表命令工具texi2dvi,该工具是发布软件Texinfo一部分。
规则中也可以没有命令行,这样make程序会自动为它推导对应的命令。
dist
此目标指定的命令创建发布程序的tar文件。创建的tar文件应该是这个软件包的目录,文件名中也可以包含版本号(就是说创建的tar文件在解包之后应该是一个目录)。例如,发布的gcc 1.40版的tar文件解包的目录为“gcc-1.40”。
通常的做法是是创建一个空目录,如使用ln或cp将所需要的文件加入到这个目录中,之后对这个目录使用tar进行打包。打包之后的tar文件使用gzip压缩。例如,实际的gcc 1.40版的发布文件叫“gcc-1.40.tar.gz”。目标“dist”的依赖文件为软件包中所有的非源代码的文件,因此在使用目标进行发布软件打包压缩之前必须保证这些文件是最新的。
check
此目标指定的命令完成所有的自检功能。在执行检查之前,应确保所有程序已经被创建,可以不安装。为了对它们进行测试,需要实现在程序没有安装的情况下被执行的规则命令。
installcheck
执行安装检查。在执行安装检查之前,确保所有程序已经被创建并且被安装。需要注意的是:安装目录“$(bindir)”是否在搜索路径中。
installdirs
使用目标“installdirs”创建安装目录以及它的子目录在很多场合是非常有用的。脚本“mkinstalldirs”就是为了实现这个目的而编写的;发布的Texinfo软件包中就包含了这个脚本文件。Makefile中的规则可以这样书写:
# 确保所有安装目录(例如 $(bindir))存在,如有必要则创建这些目录
installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs $(bindir) $(datadir) /
$(libdir) $(infodir) /
$(mandir)
或者可以使用变量“DESTDIR”:
# 确保所有安装目录(例如 $(bindir))存在,如有必要则创建这些目录
installdirs: mkinstalldirs
$(srcdir)/mkinstalldirs /
$(DESTDIR)$(bindir) $(DESTDIR)$(datadir) /
$(DESTDIR)$(libdir) $(DESTDIR)$(infodir) /
$(DESTDIR)$(mandir)
该规则不能更改软件的编译目录,仅仅是创建程序的安装目录。