10 Using Implicit Rules

3 Variables Used by Implicit Rules

The recipes in built-in implicit rules make liberal use of certain predefined variables. You can alter the values of these variables in the makefile, with arguments to make, or in the environment to alter how the implicit rules work without redefining the rules themselves. You can cancel all variables used by implicit rules with the -R or --no-builtin-variables option.

For example, the recipe used to compile a C source file actually says $(CC) -c $(CFLAGS) $(CPPFLAGS). The default values of the variables used are cc and nothing, resulting in the command cc -c. By redefining CC to ncc, you could cause ncc to be used for all C compilations performed by the implicit rule. By redefining CFLAGS to be -g, you could pass the -g option to each compilation. All implicit rules that do C compilation use $(CC) to get the program name for the compiler and all include $(CFLAGS) among the arguments given to the compiler.

The variables used in implicit rules fall into two classes: those that are names of programs (like CC) and those that contain arguments for the programs (like CFLAGS). (The “name of a program” may also contain some command arguments, but it must start with an actual executable program name.) If a variable value contains more than one argument, separate them with spaces.

The following tables describe of some of the more commonly-used predefined variables. This list is not exhaustive, and the default values shown here may not be what make selects for your environment. To see the complete list of predefined variables for your instance of GNU make you can run make -p in a directory with no makefiles.

Here is a table of some of the more common variables used as names of programs in built-in rules:

  • CC: Program for compiling C programs; default cc.
  • LDFLAGS: Extra flags to give to compilers when they are supposed to invoke the linker, ld, such as -L. Libraries (-lfoo) should be added to the LDLIBS variable instead.

5 Defining and Redefining Pattern Rules

You define an implicit rule by writing a pattern rule. A pattern rule looks like an ordinary rule, except that its target contains the character %. The target is considered a pattern for matching file names; the % can match any nonempty substring, while other characters match only themselves. The prerequisites likewise use % to show how their names relate to the target name.

Thus, a pattern rule %.o : %.c says how to make any file stem.o from another file stem.c.

Note that expansion using % in pattern rules occurs after any variable or function expansions, which take place when the makefile is read. See How to Use Variables, and Functions for Transforming Text.

5.1 Introduction to Pattern Rules

A pattern rule contains the character % in the target; otherwise, it looks exactly like an ordinary rule. The target is a pattern for matching file names; the % matches any nonempty substring, while other characters match only themselves.

For example, %.c as a pattern matches any file name that ends in .c. s.%.c as a pattern matches any file name that starts with s., ends in .c and is at least five characters long. (There must be at least one character to match the %.) The substring that the % matches is called the stem.

% in a prerequisite of a pattern rule stands for the same stem that was matched by the % in the target. In order for the pattern rule to apply, its target pattern must match the file name under consideration and all of its prerequisites (after pattern substitution) must name files that exist or can be made. These files become prerequisites of the target.

Thus, a rule of the form

%.o : %.c ; recipe…

specifies how to make a file n.o, with another file n.c as its prerequisite, provided that n.c exists or can be made.

There may also be prerequisites that do not use %; such a prerequisite attaches to every file made by this pattern rule. These unvarying prerequisites are useful occasionally.

A pattern rule need not have any prerequisites that contain %, or in fact any prerequisites at all. Such a rule is effectively a general wildcard. It provides a way to make any file that matches the target pattern. See Last Resort.

More than one pattern rule may match a target. In this case make will choose the “best fit” rule. See How Patterns Match.

Pattern rules may have more than one target; however, every target must contain a % character. Pattern rules are always treated as grouped targets (see Multiple Targets in a Rule) regardless of whether they use the : or &: separator.

5.2 Pattern Rule Examples

Here are some examples of pattern rules actually predefined in make. First, the rule that compiles .c files into .o files:

%.o : %.c
        $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@

defines a rule that can make any file x.o from x.c. The recipe uses the automatic variables $@ and $< to substitute the names of the target file and the source file in each case where the rule applies (see Automatic Variables).

Here is a second built-in rule:

% :: RCS/%,v
        $(CO) $(COFLAGS) $<

defines a rule that can make any file x whatsoever from a corresponding file x,v in the sub-directory RCS. Since the target is %, this rule will apply to any file whatever, provided the appropriate prerequisite file exists. The double colon makes the rule terminal, which means that its prerequisite may not be an intermediate file (see Match-Anything Pattern Rules).

This pattern rule has two targets:

%.tab.c %.tab.h: %.y
        bison -d $<

This tells make that the recipe ‘bison -d x.y’ will make both x.tab.c and x.tab.h. If the file foo depends on the files parse.tab.o and scan.o and the file scan.o depends on the file parse.tab.h, when parse.y is changed, the recipe ‘bison -d parse.y’ will be executed only once, and the prerequisites of both parse.tab.o and scan.o will be satisfied. (Presumably the file parse.tab.o will be recompiled from parse.tab.c and the file scan.o from scan.c, while foo is linked from parse.tab.o, scan.o, and its other prerequisites, and it will execute happily ever after.)

5.3 Automatic Variables

Suppose you are writing a pattern rule to compile a .c file into a .o file: how do you write the cc command so that it operates on the right source file name? You cannot write the name in the recipe, because the name is different each time the implicit rule is applied.

What you do is use a special feature of make, the automatic variables. These variables have values computed afresh for each rule that is executed, based on the target and prerequisites of the rule. In this example, you would use $@ for the object file name and $< for the source file name.

It’s very important that you recognize the limited scope in which automatic variable values are available: they only have values within the recipe. In particular, you cannot use them anywhere within the target list of a rule; they have no value there and will expand to the empty string. Also, they cannot be accessed directly within the prerequisite list of a rule. A common mistake is attempting to use $@ within the prerequisites list; this will not work. However, there is a special feature of GNU make, secondary expansion (see Secondary Expansion), which will allow automatic variable values to be used in prerequisite lists.

Here is a table of automatic variables:

$@

The file name of the target of the rule. If the target is an archive member, then $@ is the name of the archive file. In a pattern rule that has multiple targets (see Introduction to Pattern Rules), $@ is the name of whichever target caused the rule’s recipe to be run.

$%

The target member name, when the target is an archive member. See Archives. For example, if the target is foo.a(bar.o) then $% is bar.o and $@ is foo.a. $% is empty when the target is not an archive member.

$<

The name of the first prerequisite. If the target got its recipe from an implicit rule, this will be the first prerequisite added by the implicit rule (see Implicit Rules).

$?

The names of all the prerequisites that are newer than the target, with spaces between them. If the target does not exist, all prerequisites will be included. For prerequisites which are archive members, only the named member is used (see Archives).

$? is useful even in explicit rules when you wish to operate on only the prerequisites that have changed. For example, suppose that an archive named lib is supposed to contain copies of several object files. This rule copies just the changed object files into the archive:

lib: foo.o bar.o lose.o win.o
        ar r lib $?

$^

The names of all the prerequisites, with spaces between them. For prerequisites which are archive members, only the named member is used (see Archives). A target has only one prerequisite on each other file it depends on, no matter how many times each file is listed as a prerequisite. So if you list a prerequisite more than once for a target, the value of $^ contains just one copy of the name. This list does not contain any of the order-only prerequisites; for those see the $| variable, below.

$+

This is like ‘$^’, but prerequisites listed more than once are duplicated in the order they were listed in the makefile. This is primarily useful for use in linking commands where it is meaningful to repeat library file names in a particular order.

待补充

Of the variables listed above, four have values that are single file names, and three have values that are lists of file names. These seven have variants that get just the file’s directory name or just the file name within the directory. The variant variables’ names are formed by appending ‘D’ or ‘F’, respectively. The functions dir and notdir can be used to obtain a similar effect (see Functions for File Names). Note, however, that the ‘D’ variants all omit the trailing slash which always appears in the output of the dir function. Here is a table of the variants:

$(@D)

The directory part of the file name of the target, with the trailing slash removed. If the value of ‘ @ ’ i s d i r / f o o . o t h e n ‘ @’ is dir/foo.o then ‘ @’isdir/foo.othen(@D)’ is dir. This value is . if ‘$@’ does not contain a slash.

$(@F)

The file-within-directory part of the file name of the target. If the value of ‘ @ ’ i s d i r / f o o . o t h e n ‘ @’ is dir/foo.o then ‘ @’isdir/foo.othen(@F)’ is foo.o. ‘ ( @ F ) ’ i s e q u i v a l e n t t o ‘ (@F)’ is equivalent to ‘ (@F)isequivalentto(notdir $@)’.

待补充

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值