分享
 
 
 

GNU Make 使用手册!(8)

王朝other·作者佚名  2006-02-01
窄屏简体版  字體: |||超大  

您必须在makefile文件中定义变量TEXI2DVI。它将运行程序texi2dvi,该程序是发布的Texinfo一部分。要么仅仅编写依靠文件,要么允许GNU make提供命令,二者必选其一。

`dist'

为程序创建一个tar文件。创建tar文件可以将其中的文件名以子目录名开始,这些子目录名可以是用于发布的软件包名。另外,这些文件名中也可以包含版本号,例如,发布的GCC 1.40版的tar文件解包的子目录为‘gcc-1.40'。最方便的方法是创建合适的子目录名,如使用in或cp等作为子目录,在它们的下面安装适当的文件,然后把tar文件解包到这些子目录中。使用gzip压缩这些tar文件,例如,实际的GCC

1.40版的发布文件叫‘gcc-1.40.tar.gz'。目标dist明显的依靠所有的发布文件中不是源文件的文件,所以你应确保发布中的这些文件已经更新。参阅GNU标准编码中创建发布文件。

`check'

执行自我检查。用户应该在运行测试之前,应该先建立程序,但不必安装这些程序;您应该编写一个自我测试程序,在程序已建立但没有安装时执行。

以下目标建议使用习惯名,对于各种程序它们很有用:

installcheck

执行自我检查。用户应该在运行测试之前,应该先建立、安装这些程序。您不因该假设‘$(bindir)'在搜寻路径中。

installdirs

添加名为‘installdirs'目标对于创建文件要安装的目录以及它们的父目录十分有用。脚本‘mkinstalldirs'是专为这样处理方便而编写的;您可以在Texinfo软件包中找到它,您可以象这样使用规则:

# 确保所有安装目录(例如

$(bindir))

# 都实际存在,如果没有则创建它们。

installdirs: mkinstalldirs

$(srcdir)/mkinstalldirs $(bindir) $(datadir)

$(libdir)

$(infodir)

$(mandir)

该规则并不更改编译时创建的目录,它仅仅创建安装目录。

14.6 安装命令分类

编写已安装目标,您必须将所有命令分为三类:正常的命令、安装前命令和安装后命令。

正常情况下,命令把文件移动到合适的地方,并设置它们的模式。它们不会改变任何文件,仅仅把它们从软件包中完整地抽取出来。

安装前命令和安装后命令可能更改一些文件,如,它们编辑配置文件后数据库文件。

安装前命令在正常命令之前执行,安装后命令在正常命令执行后执行。

安装后命令最普通的用途是运行install-info程序。 这种工作不能由正常命令完成,因为它更改了一个文件(Info 目录),该文件不能全部、单独从软件包中安装。它是一个安装后命令,因为它需要在正常命令安装软件包中的Info文件后才能执行。

许多程序不需要安装前命令,但是我们提供这个特点,以便在需要时可以使用。

要将安装规则的命令分为这三类,应在命令中间插入category lines(分类行)。 分类行指定了下面叙述的命令的类别。

分类行包含一个Tab、一个特殊的make变量引用,以及行结尾的随机注释。您可以使用三个变量,每一个变量对应一个类别;变量名指定了类别。分类行不能出现在普通的执行文件中,因为这些make变量被由正常的定义(您也不应在makefile文件中定义)。

这里有三种分类行,后面的注释解释了它的含义:

$(PRE_INSTALL) # 以下是安装前命令

$(POST_INSTALL) # 以下是安装后命令

$(NORMAL_INSTALL) # 以下是正常命令

如果在安装规则开始您没有使用分类行,则在第一个分类行出现之前的所有命令都是正常命令。如果您没有使用任何分类行,则所有命令都是正常命令。

这是反安装的分类行

$(PRE_UNINSTALL) #以下是反安装前命令

$(POST_UNINSTALL) #以下是反安装后命令

$(NORMAL_UNINSTALL) #以下是正常命令

反安装前命令的典型用法是从Info目录删除全部内容。

如果目标install或 uninstall 有依赖作为安装程序的子程序,那么您应该使用分类行先启动每一个依赖的命令,再使用分类行启动主目标的命令。无论哪一个依赖实际执行,这种方式都能保证每一条命令都放置到了正确的分类中。

安装前命令和安装后命令除了对于下述命令外,不能运行其它程序:

basename bash cat chgrp chmod chown cmp cp

dd diff echo

egrep expand expr false fgrep find getopt

grep gunzip gzip

hostname install install-info kill

ldconfig ln ls md5sum

mkdir mkfifo mknod mv printenv pwd rm

rmdir sed sort tee

test touch true uname xargs yes

按照这种方式区分命令的原因是为了创建二进制软件包。典型的二进制软件包包括所有可执行文件、必须安装的其它文件以及它自己的安装文件——所以二进制软件包不需要运行任何正常命令。但是安装二进制软件包需要执行安装前命令和安装后命令。

建造二进制软件包的程序通过抽取安装前命令和安装后命令工作。这里有一个抽取安装前命令的方法:

make -n install -o all

PRE_INSTALL=pre-install

POST_INSTALL=post-install

NORMAL_INSTALL=normal-install

|

gawk -f pre-install.awk

这里文件‘pre-install.awk'可能包括:

$0 ~ /^\t[

\t]*(normal_install|post_install)[ \t]*$/ {on = 0}

on {print $0}

$0 ~ /^\t[ \t]*pre_install[ \t]*$/ {on =

1}

安装前命令的结果文件是象安装二进制软件包的一部分shell脚本一样执行。

15 快速参考

这是对指令、文本操作函数以及GNU make能够理解的变量等的汇总。对于其他方面的总结参阅特殊的内建目标名,隐含规则目录,选项概要。

这里是GNU make是别的指令的总结:

define variable

endef

定义多行递归调用扩展型变量。参阅定义固定次序的命令。

ifdef variable

ifndef variable

ifeq (a,b)

ifeq "a" "b"

ifeq 'a' 'b'

ifneq (a,b)

ifneq "a" "b"

ifneq 'a' 'b'

else

endif

makefile文件中的条件扩展,参阅makefile文件中的条件语句。

include file

-include file

sinclude file

包含其它makefile文件,参阅包含其它makefile文件。

override variable = value

override variable := value

override variable += value

override variable ?= value

override define variable

endef

定义变量、对以前的定义重载、以及对在命令行中定义的变量重载。参阅override指令。

export

告诉make缺省向子过程输出所有变量,参阅与子make通讯的变量。

export variable

export variable = value

export variable := value

export variable += value

export variable ?= value

unexport variable

告诉make是否向子过程输出一个特殊的变量。参业与子make通讯的变量。

vpath pattern path

制定搜寻匹配‘%’格式的文件的路径。参阅vpath指令。

vpath pattern

去除以前为‘pattern’指定的所有搜寻路径。

vpath

去除以前用vpath指令指定的所有搜寻路径。

这里是操作文本函数的总结,参阅文本转换函数:

$(subst from,to,text)

在‘text’中用‘to’代替‘from’,参阅字符串替换与分析函数。

$(patsubst pattern,replacement,text)

在‘text’中用‘replacement’代替匹配‘pattern’字,参阅字符串替换与分析函数。

$(strip string)

从字符串中移去多余的空格。参阅字符串替换与分析函数。

$(findstring find,text)

确定‘find’在‘text’中的位置。参阅字符串替换与分析函数。

$(filter pattern...,text)

在‘text’中选择匹配‘pattern’的字。参阅字符串替换与分析函数。

$(filter-out pattern...,text)

在‘text’中选择不匹配‘pattern’的字。参阅字符串替换与分析函数。

$(sort list)

将‘list’中的字按字母顺序排序,并删除重复的字。参阅字符串替换与分析函数。

$(dir names...)

从文件名中抽取路径名。参阅文件名函数。

$(notdir names...)

从文件名中抽取路径部分。参阅文件名函数。

$(suffix names...)

从文件名中抽取非路径部分。参阅文件名函数。

$(basename names...)

从文件名中抽取基本文件名。参阅文件名函数。

$(addsuffix suffix,names...)

为‘names’中的每个字添加后缀。参阅文件名函数。

$(addprefix prefix,names...)

为‘names’中的每个字添加前缀。参阅文件名函数。

$(join list1,list2)

连接两个并行的字列表。参阅文件名函数。

$(word n,text)

从‘text’中抽取第n个字。参阅文件名函数。

$(words text)

计算‘text’中字的数目。参阅文件名函数。

$(wordlist s,e,text)

返回‘text’中s到e之间的字。参阅文件名函数。

$(firstword names...)

在‘names…’中的第一个字。参阅文件名函数。

$(wildcard pattern...)

寻找匹配shell文件名格式的文件名。参阅wildcard函数。

$(error text...)

该函数执行时,make产生信息为‘text’的致命错误。参阅控制make的函数。

$(warning text...)

该函数执行时,make产生信息为‘text’的警告。参阅控制make的函数。

$(shell command)

执行shell命令并返回它的输出。参阅函数shell。

$(origin variable)

返回make变量‘variable’的定义信息。参阅函数origin。

$(foreach var,words,text)

将列表列表words中的每一个字对应后接var中的每一个字,将结果放在text中。参阅函数foreach。

$(call var,param,...)

使用对$(1), $(2)...对变量计算变量 var ,变量$(1), $(2)...分别代替参数 param 第一个、第二个…的值。参阅函数call。

这里是对自动变量的总结,完整的描述参阅自动变量。

$@

目标文件名。

$%

当目标是档案成员时,表示目标成员名。

$<

第一个依赖名。

$?

所有比目标‘新’的依赖的名字,名字之间用空格隔开。对于为档案成员的依赖,只能使用命名的成员。参阅使用make更新档案文件。

$^

$+

所有依赖的名字,名字之间用空格隔开。对于为档案成员的依赖,只能使用命名的成员。参阅使用make更新档案文件。变量 $^ 省略了重复的依赖,而变量 $+ 则按照原来次序保留重复项,

$*

和隐含规则匹配的stem(径)。参阅格式匹配。

$(@D)

$(@F)

变量$@.中的路径部分和文件名部分。

$(*D)

$(*F)

变量$*中的路径部分和文件名部分。

$(%D)

$(%F)

变量$%中的路径部分和文件名部分。

$(<D)

$(<F)

变量$<中的路径部分和文件名部分。

$(^D)

$(^F)

变量$^中的路径部分和文件名部分。

$(+D)

$(+F)

变量$+中的路径部分和文件名部分。

$(?D)

$(?F)

变量$?中的路径部分和文件名部分。

以下是GNU make使用变量:

MAKEFILES

每次调用make要读入的Makefiles文件。参阅变量MAKEFILES。

VPATH

对在当前目录下不能找到的文件搜索的路径。参阅VPATH: 所有依赖的搜寻路径。

SHELL

系统缺省命令解释程序名,通常是`/bin/sh'。您可以在makefile文件中设值变量SHELL改变运行程序使用的shell。参阅执行命令。

MAKESHELL

改变量仅用于MS-DOS,make使用的命令解释程序名,该变量的值比变量SHELL的值优先。参阅执行命令。

MAKE

调用的make名。在命令行中使用该变量有特殊的意义。参阅变量MAKE的工作方式。

MAKELEVEL

递归调用的层数(子makes)。参阅与子make通讯的变量。

MAKEFLAGS

向make提供标志。您可以在环境或makefile文件中使用该变量设置标志。参阅与子make通讯的变量。在命令行中不能直接使用该变量,应为它的内容不能在shell中正确引用,但总是允许递归调用make时通过环境传递给子make。

MAKECMDGOALS

该目标是在命令行中提供给make的。设置该变量对make的行为没有任何影响。参阅特别目标的参数。

CURDIR

设置当前工作目录的路径名,参阅递归调用make。

SUFFIXES

在读入任何makefile文件之前的后缀列表。

.LIBPATTERNS

定义make搜寻的库文件名,以及搜寻次序。参阅连接库搜寻目录。

16 make产生的错误

这里是您可以看到的由make产生绝大多数普通错误列表,以及它们的含义和修正它们信息。

有时make产生的错误不是致命的,如一般在命令脚本行前面存在前缀的情况下,和在命令行使用选向‘-k’的情况下产生的错误几乎都不是致命错误。使用字符串***作前缀将产生致命的错误。

错误信息前面都使用前缀,前缀的内容是产生错误的程序名或makefile文件中存在错误的文件名和包含该错误的行的行号和。

在下述的错误列表中,省略了普通的前缀:

`[foo] Error NN'

`[foo] signal description'

这些错误并不是真的make的错误。它们意味着make调用的程序返回非零状态值,错误码(Error NN),这种情况make解释为失败,或非正常方式退出(一些类型信号),参阅命令错误。如果信息中没有附加***,则是子过程失败,但在makefile文件中的这条规则有特殊前缀,因此make忽略该错误。

`missing separator. Stop.'

`missing separator (did you mean TAB

instead of 8 spaces?). Stop.'

这意味着make在读取命令行时遇到不能理解的内容。GNU make 检查各种分隔符(:, =, 字符TAB,等) 从而帮助确定它在命令行中遇到了什么类型的错误。这意味着,make不能发现一个合法的分隔符。出现该信息的最可能的原因是您(或许您的编辑器,绝大部分是ms-windows的编辑器)在命令行缩进使用了空格代替了字符Tab。这种情况下,make将使用上述的第二种形式产生错误信息。一定切记,任何命令行都以字符Tab开始,八个空格也不算数。参阅规则的语法。

`commands commence before first target.

Stop.'

`missing rule before commands. Stop.'

这意味着在makefile中似乎以命令行开始:以Tab字符开始,但不是一个合法的命令行(例如,一个变量的赋值)。任何命令行必须和一定的目标相联系。产生第二种的错误信息是一行的第一个非空白字符为分号,make对此的解释是您遗漏了规则中的"target:

prerequisite" 部分,参阅规则的语法。

`No rule to make target `xxx'.'

`No rule to make target `xxx', needed by `yyy'.'

这意味着make决定必须建立一个目标,但却不能在makefile文件中发现任何用于创建该目标的指令,包括具体规则和隐含规则。如果您希望创建该目标,您需要另外为改目标编写规则。其它关于该问题产生原因可能是makefile文件是草稿(如文件名错)或破坏了源文件树(一个文件不能按照计划重建,仅仅由于一个依赖的问题)。

`No targets specified and no makefile

found. Stop.'

`No targets. Stop.'

前者意味着您没有为命令行提供要创建的目标,make不能读入任何makefile文件。后者意味着一些makefile文件被找到,但没有包含缺省目标以及命令行等。GNU make在这种情况下无事可做。参阅指定makefile文件的参数。

`Makefile `xxx' was not found.'

`Included makefile `xxx' was not found.'

在命令行中指定一个makefile文件(前者)或包含的makefile 文件(后者)没有找到。

`warning: overriding commands for

target `xxx''

`warning: ignoring old commands for

target `xxx''

GNU make允许命令在一个规则中只能对一个命令使用一次(双冒号规则除外)。如果您为一个目标指定一个命令,而该命令在目标定义是已经定义过,这种警告就会产生;第二个信息表明后来设置的命令将改写以前对该命令的设置。参阅具有多条规则的目标。

`Circular xxx <- yyy dependency dropped.'

这意味着make检测到一个相互依靠一个循环:在跟踪目标xxx的依赖yyy 时发现,依赖yyy的依赖中一个又以xxx为依赖。

`Recursive variable `xxx' references itself (eventually).

Stop.'

这意味着您定义一个正常(递归调用性)make变量xxx,当它扩展时,它将引用它自身。无论对于简单扩展型变量(:=)或追加定义(+=),这也都是不能允许的,参阅使用变量。

`Unterminated variable reference.

Stop.'

这意味着您在变量引用或函数调用时忘记写右括号。

`insufficient arguments to function `xxx'. Stop.'

这意味着您在调用函数是您密友提供需要数目的参数。关于函数参数的详细描述参阅文本转换函数。

`missing target pattern. Stop.'

`multiple target patterns. Stop.'

`target pattern contains no `%'. Stop.'

这些错误信息是畸形的静态格式规则引起的。第一条意味着在规则的目标部分没有规则,第二条意味着在目标部分有多个规则,第三条意味着没有包含格式符%。参阅静态格式规则语法。

`warning: -jN forced in submake:

disabling jobserver mode.'

该条警告和下条警告是在make检测到在能与子make通讯的系统中包含并行处理的错误(参阅与子make通讯选项)。该警告信息是如果递归调用一个make过程,而且还使用了‘-jn’选项(这里n大于1)。这种情况很可能发生,例如,如果您设置环境变量MAKE为‘make –j2’。这种情况下,子make不能与其它make过程通讯, 而且还简单假装它由两个任务。

`warning: jobserver unavailable: using

-j1. Add `+' to parent make rule.'

为了保证make过程之间通讯,父层make将传递信息给子make。这可能导致问题,因为子过程有可能不是实际的一个make,而父过程仅仅认为子过程是一个make而将所有信息传递给子过程。父过程是采用正常的算法决定这些的(参阅变量MAKE的工作方式)。如果makefile文件构建了这样的父过程,它并不知道子过程是否为make,那么,子过程将拒收那些没有用的信息。这种情况下,子过程就会产生该警告信息,然后按照它内建的次序方式进行处理。

17 复杂的makfile文件例子

这是一个用于GNU tar程序的makefile文件;这是一个中等复杂的makefile文件。

因为‘all’是第一个目标,所以它是缺省目标。该makefile文件一个有趣的地方是‘testpad.h'是由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')是用户用configure程序产生的,该程序是由发布的tar文件提供,但这里不进行说明。)

如果您键入‘make realclean', 则make删除‘make distclean

'删除的所有文件,而且包括由‘tar.texinfo'产生的Info文件。

另外,目标shar和dist创造了发布文件的核心。

# 自动从makefile.in产生

# 用于GNU tar 程序的Unix

Makefile

# Copyright (C) 1991 Free Software Foundation, Inc.

# 本程序是自由软件;在遵照GNU条款的情况下

# 您可以重新发布它或更改它

# 普通公众许可证 ...

...

...

SHELL = /bin/sh

#### 启动系统配置部分 ####

srcdir = .

# 如果您使用gcc, 您应该在运行

# 和它一起创建的固定包含的脚本程序以及

# 使用-traditional选项运行gcc中间选择其一。

# 另外的ioctl调用在一些系统上不能正确编译

CC = gcc -O

YACC = bison -y

INSTALL = /usr/local/bin/install -c

INSTALLDATA = /usr/local/bin/install -c -m 644

# 您应该在DEFS中添加的内容:

# -DSTDC_HEADERS

如果您有标准C的头文件和

# 库文件。

# -DPOSIX

如果您有POSIX.1的头文件和

#

库文件。

# -DBSD42

如果您有sys/dir.h (除非

#

您使用-DPOSIX), sys/file.h,

#

和st_blocks在`struct stat'中。

# -DUSG

如果您有System V/ANSI C

#

字符串和内存控制函数

#

和头文件, sys/sysmacros.h,

#

fcntl.h, getcwd, no valloc,

#

和 ndir.h (除非

#

您使用-DDIRENT)。

# -DNO_MEMORY_H

如果USG或STDC_HEADERS 但是不

#

包括memory.h.

# -DDIRENT

如果USG而且您又用dirent.h

#

代替ndir.h。

# -DSIGTYPE=int

如果您的信号控制器

#

返回int,非void.

# -DNO_MTIO

如果您缺少sys/mtio.h

# (magtape ioctls).

# -DNO_REMOTE

如果您没有一个远程shell

#

或rexec.

# -DUSE_REXEC

对远程磁带使用rexec

#

操作代替

#

分支rsh或remsh.

# -DVPRINTF_MISSING

如果您缺少函数vprintf

#

(但是有_doprnt).

# -DDOPRNT_MISSING

如果您缺少函数 _doprnt.

#

同样需要定义

#

-DVPRINTF_MISSING.

第一頁    上一頁    第8頁/共9頁    下一頁    最後頁
第01頁 第02頁 第03頁 第04頁 第05頁 第06頁 第07頁 第08頁 第09頁 
 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有