Filename : [Linux]GNU 自动化工具( automake 工具链)
Version : V1.0
Date : 12/01/2009
Author : S.C.Leon <[email protected]>
=====================================================================
Makefile 是用于自动编译和链接的,一个工程有很多文件组成,每一个文件的改变都会导致工程的重新链接,但是不是所有的文件都需要重新编译, Makefile 中纪录有文件的信息,在 make 时会决定在链接的时候需要重新编译哪些文件 Makefile 的宗旨就是:让编译器知道要编译一个文件需要依赖其他的哪些文件。当那些依赖文件有了改变,编译器会自动的发现最终的生成文件已经过时,而重新编译相应的模块。
二、 GNU 自动化工具
Makefile 的基本结构不是很复杂,但当一个程序开发人员开始写 Makefile 时,经常会怀疑自己写的是否符合惯例,而且自己写的 Makefile 经常和自己的开发环境相关联,当系统环境变量或路径发生了变化后, Makefile 可能还要跟着修改。这样就造成了手工书写 Makefile 的诸多问题。为辅助实现不同编译环境之间的源代码的可移植性,人们创造了 GNU 自动化工具( autotools ), autoconf , autoheader , libtools , automake 和其他许多脚本工具一起工作并共同构成了 GNU 编译系统。
使用 automake ,程序开发人员只需要写一些简单的含有预定义宏的文件,由 autoconf 根据一个宏文件生成 configure ,由 automake 根据另一个宏文件生成 Makefile.in ,再使用 configure 依据 Makefile.in 来生成一个符合惯例的 Makefile 。下面我们将详细介绍 Makefile 的 automake 生成方法。
使用的环境
本文所提到的程序是基于 Linux 发行版本: Ubuntu 9.04 ( linux 主流发行版均可),它包含了我们要用到的 autoconf , automake 。
三、 helloworld 示例
从最常使用的例子程序 helloworld 开始。
由 helloworld.c 源文件通过 automake 工具链自动生成 Makefile ,最后生成可执行文件的简要步骤如下:
1 )新建三个文件:
helloworld.c
configure.in
Makefile.am
其中 configure.in 和 Makefile.am 是需要我们自己创建的。具体写法详见后文。
2) 然后执行:
aclocal;
autoconf;
automake --add-missing;
./configure;
make;
./helloworld
但就本例而言, helloworld.c 的 Makefile 完全可以手写,但本例中绕了一个大圈通过 automake 工具最终自己生成了 Makefile 文件,意图阐明 automake 流程,和主要步骤,以对大型程序开发有借鉴意义。
现在开始介绍详细的过程:
1 、建目录
在你的工作目录下建一个 helloworld 目录,我们用它来存放 helloworld 程序及相关文件,这里特别要注意,使用 automake 工具默认文件系统为 ext3 ,在 win 的 fat32 等文件系统下无法完成以下步骤。 所以需在 liunx 文件系统下建立目录,比如我的用户目录为 /home/leon ,则在 /home/leon/build 下:
$ mkdir helloword
$ cd helloworld
2 、写源文件 helloworld.c
然后用你自己最喜欢的编辑器写一个 hellowrold.c 文件,如命令: vi helloworld.c 。使用下面的代码作为 helloworld.c 的内容。
<textarea cols="50" rows="15" name="code" class="python">#include<stdio.h> int main(int argc, char** argv) { printf("Hello, GNU automake!/n"); return 0; }</textarea>
完成后保存退出。
好了,现在在 helloworld 目录下就应该有一个你自己写的 helloworld.c 了。
3 、生成 configure.in
configure.in 是需要自己手写的,但是我们也可以使用 autoscan 命令来帮助我们根据目录下的源代码生成一个 configure.scan 的模板文件,再在此基础上修改为我们需要的 configure.in 。
命令:
$ autoscan
$ ls
configure.scan helloworld.c
执行后在 hellowrold 目录下会生成一个文件: configure.scan ,我们可以拿它作为 configure.in 的蓝本。
现在将 configure.scan 改名为 configure.in ,并且编辑它,按下面的内容修改,去掉无关的语句:
<textarea cols="50" rows="15" name="code" class="python"># -*- 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)</textarea>
文中提到的具体参数含义详见后文。
然后执行命令 aclocal 和 autoconf ,分别会产生 aclocal.m4 及 configure 两个文件:
$ aclocal
$ls
aclocal.m4 configure.in helloworld.c
$ autoconf
$ ls
aclocal.m4 autom4te.cache configure configure.in helloworld.c
大家可以看到 configure.in 内容是一些宏定义,这些宏经 autoconf 处理后会变成检查系统特性、环境变量、软件必须的参数的 shell 脚本。
autoconf 是用来生成自动配置软件源代码脚本( configure )的工具。 configure 脚本能独立于 autoconf 运行,且在运行的过程中,不需要用户的干预。
要生成 configure 文件,你必须告诉 autoconf 如何找到你所用的宏。方式是使用 aclocal 程序来生成你的 aclocal.m4 。
aclocal 根据 configure.in 文件的内容,自动生成 aclocal.m4 文件。 aclocal 是一个 perl 脚本程序,它的定义是: “aclocal - create aclocal.m4 by scanning configure.ac” 。
autoconf 从 configure.in 这个列举编译软件时所需要各种参数的模板文件中创建 configure 。
autoconf 需要 GNU m4 宏处理器来处理 aclocal.m4 ,生成 configure 脚本。
m4 是一个宏处理器。将输入拷贝到输出,同时将宏展开。宏可以是内嵌的,也可以是用户定义的。除了可以展开宏, m4 还有一些内建的函数,用来引用文件,执行命令,整数运算,文本操作,循环等。 m4 既可以作为编译器的前端,也可以单独作为一个宏处理器
5 、新建 Makefile.am
新建 Makefile.am 文件,命令:
$ vi Makefile.am
内容如下 :
AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS=helloworld
helloworld_SOURCES=helloworld.c
文中提到具体参数含义详见后文。
automake 会根据你写的 Makefile.am 来自动生成 Makefile.in 。
Makefile.am 中定义的宏和目标 , 会指导 automake 生成指定的代码。例如,宏 bin_PROGRAMS 将导致编译和连接的目标被生成。
6 、运行 automake
命令:
$ automake --add-missing
configure.in: installing `./install-sh'
configure.in: installing `./mkinstalldirs'
configure.in: installing `./missing'
Makefile.am: installing `./depcomp'
automake 会根据 Makefile.am 文件产生一些文件,包含最重要的 Makefile.in 。
7 、执行 configure 生成 Makefile
$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ANSI C... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
configure: creating ./config.status
config.status: creating Makefile
config.status: executing depfiles commands
$ ls -l Makefile
-rw-rw-r-- 1 yutao yutao 15035 Oct 15 10:40 Makefile
你可以看到,此时 Makefile 已经产生出来了。
8 、使用 Makefile 编译代码
$ make
if gcc -DPACKAGE_NAME=/"/" -DPACKAGE_TARNAME=/"/" -DPACKAGE_VERSION=/"/" -
DPACKAGE_STRING=/"/" -DPACKAGE_BUGREPORT=/"/" -DPACKAGE=/"helloworld/" -DVERSION=/"1.0/"
-I. -I. -g -O2 -MT helloworld.o -MD -MP -MF ".deps/helloworld.Tpo" /
-c -o helloworld.o `test -f 'helloworld.c' || echo './'`helloworld.c; /
then mv -f ".deps/helloworld.Tpo" ".deps/helloworld.Po"; /
else rm -f ".deps/helloworld.Tpo"; exit 1; /
fi
gcc -g -O2 -o helloworld helloworld.o
9 、运行 helloworld
$ ./helloworld
Hello, GNU automake!
这样 helloworld 就编译出来了,你如果按上面的步骤来做的话,应该也会很容易地编译出正确的 helloworld 文件。
你还可以试着使用一些其他的 make 命令,如 make clean , make install , make dist ,看看它们会给你什么样的效果。
是不是比自己写的 Makefile 专业多了。
四、参数详解
针对上面提到的各个命令,我们再做些详细的介绍。
1 、 autoscan
autoscan 是用来扫描源代码目录生成 configure.scan 文件的。 autoscan 可以用目录名做为参数,但如果你不使用参数的话,那么 autoscan 将认为使用的是当前目录。 autoscan 将扫描你所指定目录中的源文件,并创建 configure.scan 文件。
2 、 configure.scan
configure.scan 包含了系统配置的基本选项,里面都是一些宏定义。我们需要将它改名为 configure.in
3 、 aclocal
aclocal 是一个 perl 脚本程序。 aclocal 根据 configure.in 文件的内容,自动生成 aclocal.m4 文件。 aclocal 的定义是: “aclocal - create aclocal.m4 by scanning configure.ac” 。
4 、 autoconf
autoconf 是用来产生 configure 文件的。 configure 是一个脚本,它能设置源程序来适应各种不同的操作系统平台,并且根据不同的系统来产生合适的 Makefile ,从而可以使你的源代码能在不同的操作系统平台上被编译出来。
configure.in 文件的内容是一些宏,这些宏经过 autoconf 处理后会变成检查系统特性、环境变量、软件必须的参数的 shell 脚本。 configure.in 文件中的宏的顺序并没有规定,但是你必须在所有宏的最前面和最后面分别加上 AC_INIT 宏和 AC_OUTPUT 宏。
在 configure.ini 中:
# 号表示注释,这个宏后面的内容将被忽略。
AC_INIT(FILE)
这个宏用来检查源代码所在的路径。
AM_INIT_AUTOMAKE(PACKAGE, VERSION)
这个宏是必须的,它描述了我们将要生成的软件包的名字及其版本号: PACKAGE 是软件包的名字, VERSION 是版本号。当你使用 make dist 命令时,它会给你生成一个类似 helloworld-1.0.tar.gz 的软件发行包,其中就有对应的软件包的名字和版本号。
AC_PROG_CC
这个宏将检查系统所用的 C 编译器。
AC_OUTPUT(FILE)
这个宏是我们要输出的 Makefile 的名字。
我们在使用 automake 时,实际上还需要用到其他的一些宏,但我们可以用 aclocal 来帮我们自动产生。执行 aclocal 后我们会得到 aclocal.m4 文件。
产生了 configure.in 和 aclocal.m4 两个宏文件后,我们就可以使用 autoconf 来产生 configure 文件了。
5 、 Makefile.am
Makefile.am 是用来生成 Makefile.in 的,需要你手工书写。 Makefile.am 中定义了一些内容:
AUTOMAKE_OPTIONS
这个是 automake 的选项。在执行 automake 时,它会检查目录下是否存在标准 GNU 软件包中应具备的各种文件,例如 AUTHORS 、 ChangeLog 、 NEWS 等文件。我们将其设置成 foreign 时, automake 会改用一般软件包的标准来检查。
bin_PROGRAMS
这个是指定我们所要产生的可执行文件的文件名。如果你要产生多个可执行文件,那么在各个名字间用空格隔开。
helloworld_SOURCES
这个是指定产生 “helloworld” 时所需要的源代码。如果它用到了多个源文件,那么请使用空格符号将它们隔开。比如需要 helloworld.h , helloworld.c 那么请写成 helloworld_SOURCES= helloworld.h helloworld.c 。
如果你在 bin_PROGRAMS 定义了多个可执行文件,则对应每个可执行文件都要定义相对的 filename_SOURCES 。
6 、 automake
我们使用 automake --add-missing 来产生 Makefile.in 。
选项 --add-missing 的定义是 “add missing standard files to package” ,它会让 automake 加入一个标准的软件包所必须的一些文件。
我们用 automake 产生出来的 Makefile.in 文件是符合 GNU Makefile 惯例的,接下来我们只要执行 configure 这个 shell 脚本就可以产生合适的 Makefile 文件了。
7 、 Makefile
在符合 GNU Makefile 惯例的 Makefile 中,包含了一些基本的预先定义的操作:
make
根据 Makefile 编译源代码,连接,生成目标文件,可执行文件。
make clean
清除上次的 make 命令所产生的 object 文件(后缀为 “.o” 的文件)及可执行文件。
make install
将编译成功的可执行文件安装到系统目录中,一般为 /usr/local/bin 目录。
make dist
产生发布软件包文件(即 distribution package )。这个命令将会将可执行文件及相关文件打包成一个 tar.gz 压缩的文件用来作为发布软件的软件包。
它会在当前目录下生成一个名字类似 “PACKAGE-VERSION.tar.gz” 的文件。 PACKAGE 和 VERSION ,是我们在 configure.in 中定义的 AM_INIT_AUTOMAKE(PACKAGE, VERSION) 。
make distcheck
生成发布软件包并对其进行测试检查,以确定发布包的正确性。这个操作将自动把压缩包文件解开,然后执行 configure 命令,并且执行 make ,来确认编译不出现错误,最后提示你软件包已经准备好,可以发布了。
===============================================
helloworld-1.0.tar.gz is ready for distribution
===============================================
make distclean
类似 make clean ,但同时也将 configure 生成的文件全部删除掉,包括 Makefile 。
最后附上生成的Makefile
<textarea cols="50" rows="15" name="code" class="python:collapse"># Makefile.in generated by automake 1.10.2 from Makefile.am. # Makefile. Generated from Makefile.in by configure. # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. pkgdatadir = $(datadir)/helloworld pkglibdir = $(libdir)/helloworld pkgincludedir = $(includedir)/helloworld am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : bin_PROGRAMS = helloworld$(EXEEXT) subdir = . DIST_COMMON = $(am__configure_deps) $(srcdir)/Makefile.am / $(srcdir)/Makefile.in $(top_srcdir)/configure depcomp / install-sh missing ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.in am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) / $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log / configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_CLEAN_FILES = am__installdirs = "$(DESTDIR)$(bindir)" binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(bin_PROGRAMS) am_helloworld_OBJECTS = helloworld.$(OBJEXT) helloworld_OBJECTS = $(am_helloworld_OBJECTS) helloworld_LDADD = $(LDADD) DEFAULT_INCLUDES = -I. depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) / $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ SOURCES = $(helloworld_SOURCES) DIST_SOURCES = $(helloworld_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = / { test ! -d $(distdir) / || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' / && rm -fr $(distdir); }; } DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ACLOCAL = ${SHELL} /home/leon/test/missing --run aclocal-1.10 AMTAR = ${SHELL} /home/leon/test/missing --run tar AUTOCONF = ${SHELL} /home/leon/test/missing --run autoconf AUTOHEADER = ${SHELL} /home/leon/test/missing --run autoheader AUTOMAKE = ${SHELL} /home/leon/test/missing --run automake-1.10 AWK = mawk CC = gcc CCDEPMODE = depmode=gcc3 CFLAGS = -g -O2 CPPFLAGS = CYGPATH_W = echo DEFS = -DPACKAGE_NAME=/"/" -DPACKAGE_TARNAME=/"/" -DPACKAGE_VERSION=/"/" -DPACKAGE_STRING=/"/" -DPACKAGE_BUGREPORT=/"/" -DPACKAGE=/"helloworld/" -DVERSION=/"1.0/" DEPDIR = .deps ECHO_C = ECHO_N = -n ECHO_T = EXEEXT = INSTALL = /usr/bin/install -c INSTALL_DATA = ${INSTALL} -m 644 INSTALL_PROGRAM = ${INSTALL} INSTALL_SCRIPT = ${INSTALL} INSTALL_STRIP_PROGRAM = $(install_sh) -c -s LDFLAGS = LIBOBJS = LIBS = LTLIBOBJS = MAKEINFO = ${SHELL} /home/leon/test/missing --run makeinfo MKDIR_P = /bin/mkdir -p OBJEXT = o PACKAGE = helloworld PACKAGE_BUGREPORT = PACKAGE_NAME = PACKAGE_STRING = PACKAGE_TARNAME = PACKAGE_VERSION = PATH_SEPARATOR = : SET_MAKE = SHELL = /bin/bash STRIP = VERSION = 1.0 abs_builddir = /home/leon/test abs_srcdir = /home/leon/test abs_top_builddir = /home/leon/test abs_top_srcdir = /home/leon/test ac_ct_CC = gcc am__include = include am__leading_dot = . am__quote = am__tar = ${AMTAR} chof - "$$tardir" am__untar = ${AMTAR} xf - bindir = ${exec_prefix}/bin build_alias = builddir = . datadir = ${datarootdir} datarootdir = ${prefix}/share docdir = ${datarootdir}/doc/${PACKAGE} dvidir = ${docdir} exec_prefix = ${prefix} host_alias = htmldir = ${docdir} includedir = ${prefix}/include infodir = ${datarootdir}/info install_sh = $(SHELL) /home/leon/test/install-sh libdir = ${exec_prefix}/lib libexecdir = ${exec_prefix}/libexec localedir = ${datarootdir}/locale localstatedir = ${prefix}/var mandir = ${datarootdir}/man mkdir_p = /bin/mkdir -p oldincludedir = /usr/include pdfdir = ${docdir} prefix = /usr/local program_transform_name = s,x,x, psdir = ${docdir} sbindir = ${exec_prefix}/sbin sharedstatedir = ${prefix}/com srcdir = . sysconfdir = ${prefix}/etc target_alias = top_build_prefix = top_builddir = . top_srcdir = . AUTOMAKE_OPTIONS = foreign helloworld_SOURCES = helloworld.c all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj am--refresh: @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do / case '$(am__configure_deps)' in / *$$dep*) / echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; / cd $(srcdir) && $(AUTOMAKE) --foreign / && exit 0; / exit 1;; / esac; / done; / echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; / cd $(top_srcdir) && / $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in / *config.status*) / echo ' $(SHELL) ./config.status'; / $(SHELL) ./config.status;; / *) / echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; / cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; / esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) cd $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_PROGRAMS)'; for p in $$list; do / p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; / if test -f $$p / ; then / f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; / echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; / $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; / else :; fi; / done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; for p in $$list; do / f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; / echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; / rm -f "$(DESTDIR)$(bindir)/$$f"; / done clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) helloworld$(EXEEXT): $(helloworld_OBJECTS) $(helloworld_DEPENDENCIES) @rm -f helloworld$(EXEEXT) $(LINK) $(helloworld_OBJECTS) $(helloworld_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c include ./$(DEPDIR)/helloworld.Po .c.o: $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po # source='$<' object='$@' libtool=no / # DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) / # $(COMPILE) -c $< .c.obj: $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po # source='$<' object='$@' libtool=no / # DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) / # $(COMPILE) -c `$(CYGPATH_W) '$<'` ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; / unique=`for i in $$list; do / if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; / done | / $(AWK) '{ files[$$0] = 1; nonempty = 1; } / END { if (nonempty) { for (i in files) print i; }; }'`; / mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) / $(TAGS_FILES) $(LISP) tags=; / here=`pwd`; / list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; / unique=`for i in $$list; do / if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; / done | / $(AWK) '{ files[$$0] = 1; nonempty = 1; } / END { if (nonempty) { for (i in files) print i; }; }'`; / if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else / test -n "$$unique" || unique=$$empty_fix; / $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) / $$tags $$unique; / fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) / $(TAGS_FILES) $(LISP) tags=; / list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; / unique=`for i in $$list; do / if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; / done | / $(AWK) '{ files[$$0] = 1; nonempty = 1; } / END { if (nonempty) { for (i in files) print i; }; }'`; / test -z "$(CTAGS_ARGS)$$tags$$unique" / || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) / $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` / && cd $(top_srcdir) / && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) $(am__remove_distdir) test -d $(distdir) || mkdir $(distdir) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$//*]/////&/g'`; / topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$//*]/////&/g'`; / list='$(DISTFILES)'; / dist_files=`for file in $$list; do echo $$file; done | / sed -e "s|^$$srcdirstrip/||;t" / -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; / case $$dist_files in / */*) $(MKDIR_P) `echo "$$dist_files" | / sed '////!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | / sort -u` ;; / esac; / for file in $$dist_files; do / if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; / if test -d $$d/$$file; then / dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; / if test -d $(srcdir)/$$file && test $$d != $(srcdir); then / cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; / fi; / cp -pR $$d/$$file $(distdir)$$dir || exit 1; / else / test -f $(distdir)/$$file / || cp -p $$d/$$file $(distdir)/$$file / || exit 1; / fi; / done -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} /; -o / ! -type d ! -perm -444 -links 1 -exec chmod a+r {} /; -o / ! -type d ! -perm -400 -exec chmod a+r {} /; -o / ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} /; / || chmod -R a+r $(distdir) dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 $(am__remove_distdir) dist-lzma: distdir tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma $(am__remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__remove_distdir) dist dist-all: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in / *.tar.gz*) / GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;/ *.tar.bz2*) / bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;/ *.tar.lzma*) / unlzma -c $(distdir).tar.lzma | $(am__untar) ;;/ *.tar.Z*) / uncompress -c $(distdir).tar.Z | $(am__untar) ;;/ *.shar.gz*) / GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;/ *.zip*) / unzip $(distdir).zip ;;/ esac chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:///]:[///],/,'` / && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" / && cd $(distdir)/_build / && ../configure --srcdir=.. --prefix="$$dc_install_base" / $(DISTCHECK_CONFIGURE_FLAGS) / && $(MAKE) $(AM_MAKEFLAGS) / && $(MAKE) $(AM_MAKEFLAGS) dvi / && $(MAKE) $(AM_MAKEFLAGS) check / && $(MAKE) $(AM_MAKEFLAGS) install / && $(MAKE) $(AM_MAKEFLAGS) installcheck / && $(MAKE) $(AM_MAKEFLAGS) uninstall / && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" / distuninstallcheck / && chmod -R a-w "$$dc_install_base" / && ({ / (cd ../.. && umask 077 && mkdir "$$dc_destdir") / && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install / && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall / && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" / distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; / } || { rm -rf "$$dc_destdir"; exit 1; }) / && rm -rf "$$dc_destdir" / && $(MAKE) $(AM_MAKEFLAGS) dist / && rm -rf $(DIST_ARCHIVES) / && $(MAKE) $(AM_MAKEFLAGS) distcleancheck $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; / list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | / sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @cd $(distuninstallcheck_dir) / && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 / || { echo "ERROR: files left after uninstall:" ; / if test -n "$(DESTDIR)"; then / echo " (check DESTDIR support)"; / fi ; / $(distuninstallcheck_listfiles) ; / exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then / echo "ERROR: distcleancheck can only run from a VPATH build" ; / exit 1 ; / fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 / || { echo "ERROR: files left in build directory after distclean:" ; / $(distcleancheck_listfiles) ; / exit 1; } >&2 check-am: all-am check: check-am all-am: Makefile $(PROGRAMS) installdirs: for dir in "$(DESTDIR)$(bindir)"; do / test -z "$$dir" || $(MKDIR_P) "$$dir"; / done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" / install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s / `test -z '$(STRIP)' || / echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic mostlyclean-am distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic / distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-exec-am: install-binPROGRAMS install-html: install-html-am install-info: install-info-am install-man: install-pdf: install-pdf-am install-ps: install-ps-am installcheck-am: maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean / clean-binPROGRAMS clean-generic ctags dist dist-all dist-bzip2 / dist-gzip dist-lzma dist-shar dist-tarZ dist-zip distcheck / distclean distclean-compile distclean-generic distclean-tags / distcleancheck distdir distuninstallcheck dvi dvi-am html / html-am info info-am install install-am install-binPROGRAMS / install-data install-data-am install-dvi install-dvi-am / install-exec install-exec-am install-html install-html-am / install-info install-info-am install-man install-pdf / install-pdf-am install-ps install-ps-am install-strip / installcheck installcheck-am installdirs maintainer-clean / maintainer-clean-generic mostlyclean mostlyclean-compile / mostlyclean-generic pdf pdf-am ps ps-am tags uninstall / uninstall-am uninstall-binPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT:</textarea>
1 、《 Linux 高级程序设计》 Jon Masters 等 人民邮电出版社
2 、 http://www.lslnet.com 作者许明彦