• No results found

For large systems, it is often desirable to put sources in a separate directory from the binaries. Thedirectory searchfeatures ofmakefacilitate this by searching several directories automatically to find a prerequisite. When you redistribute the files among directories, you do not need to change the individual rules, just the search paths.

4.4.1

VPATH: Search Path for All Prerequisites

The value of themake variableVPATHspecifies a list of directories that makeshould search. Most often, the directories are expected to contain prerequisite files that are not in the current directory; however, make uses VPATH as a search list for both prerequisites and targets of rules.

Thus, if a file that is listed as a target or prerequisite does not exist in the current directory, makesearches the directories listed in VPATHfor a file with that name. If a file is found in one of them, that file may become the prerequisite (see below). Rules may then specify the names of files in the prerequisite list as if they all existed in the current directory. SeeSection 4.4.4 [Writing Recipes with Directory Search], page 27.

In the VPATH variable, directory names are separated by colons or blanks. The order in which directories are listed is the order followed by make in its search. (On MS-DOS and MS-Windows, semi-colons are used as separators of directory names in VPATH, since the colon can be used in the pathname itself, after the drive letter.)

For example,

VPATH = src:../headers

specifies a path containing two directories, src and ../headers, which make searches in that order.

With this value of VPATH, the following rule, foo.o : foo.c

foo.o : src/foo.c

assuming the filefoo.cdoes not exist in the current directory but is found in the directory src.

4.4.2 The

vpath

Directive

Similar to theVPATH variable, but more selective, is the vpathdirective (note lower case), which allows you to specify a search path for a particular class of file names: those that match a particular pattern. Thus you can supply certain search directories for one class of file names and other directories (or none) for other file names.

There are three forms of the vpathdirective:

vpathpattern directories

Specify the search path directories for file names that match pattern.

The search path, directories, is a list of directories to be searched, separated by colons (semi-colons on MS-DOS and MS-Windows) or blanks, just like the search path used in the VPATHvariable.

vpathpattern

Clear out the search path associated withpattern.

vpath

Clear all search paths previously specified with vpathdirectives.

A vpath pattern is a string containing a ‘%’ character. The string must match the file

name of a prerequisite that is being searched for, the ‘%’ character matching any sequence of zero or more characters (as in pattern rules; see Section 10.5 [Defining and Redefining Pattern Rules], page 118). For example, %.h matches files that end in .h. (If there is no ‘%’, the pattern must match the prerequisite exactly, which is not useful very often.)

‘%’ characters in avpath directive’s pattern can be quoted with preceding backslashes (‘\’). Backslashes that would otherwise quote ‘%’ characters can be quoted with more backslashes. Backslashes that quote ‘%’ characters or other backslashes are removed from the pattern before it is compared to file names. Backslashes that are not in danger of quoting ‘%’ characters go unmolested.

When a prerequisite fails to exist in the current directory, if the pattern in a vpath directive matches the name of the prerequisite file, then thedirectoriesin that directive are searched just like (and before) the directories in the VPATHvariable.

For example,

vpath %.h ../headers

tells maketo look for any prerequisite whose name ends in .hin the directory ../headers if the file is not found in the current directory.

If several vpath patterns match the prerequisite file’s name, then make processes each matching vpath directive one by one, searching all the directories mentioned in each di- rective. make handles multiple vpath directives in the order in which they appear in the makefile; multiple directives with the same pattern are independent of each other.

vpath %.c foo

vpath % blish

vpath %.c bar

will look for a file ending in ‘.c’ infoo, thenblish, thenbar, while vpath %.c foo:bar

vpath % blish

will look for a file ending in ‘.c’ infoo, thenbar, thenblish.

4.4.3 How Directory Searches are Performed

When a prerequisite is found through directory search, regardless of type (general or se- lective), the pathname located may not be the one that make actually provides you in the prerequisite list. Sometimes the path discovered through directory search is thrown away.

The algorithmmakeuses to decide whether to keep or abandon a path found via directory search is as follows:

1. If a target file does not exist at the path specified in the makefile, directory search is performed.

2. If the directory search is successful, that path is kept and this file is tentatively stored as the target.

3. All prerequisites of this target are examined using this same method.

4. After processing the prerequisites, the target may or may not need to be rebuilt: a. If the target doesnot need to be rebuilt, the path to the file found during directory

search is used for any prerequisite lists which contain this target. In short, ifmake doesn’t need to rebuild the target then you use the path found via directory search. b. If the target does need to be rebuilt (is out-of-date), the pathname found during directory search is thrown away, and the target is rebuilt using the file name specified in the makefile. In short, ifmake must rebuild, then the target is rebuilt locally, not in the directory found via directory search.

This algorithm may seem complex, but in practice it is quite often exactly what you want.

Other versions ofmake use a simpler algorithm: if the file does not exist, and it is found via directory search, then that pathname is always used whether or not the target needs to be built. Thus, if the target is rebuilt it is created at the pathname discovered during directory search.

If, in fact, this is the behavior you want for some or all of your directories, you can use

theGPATH variable to indicate this tomake.

GPATHhas the same syntax and format asVPATH(that is, a space- or colon-delimited list

of pathnames). If an out-of-date target is found by directory search in a directory that also appears in GPATH, then that pathname is not thrown away. The target is rebuilt using the expanded path.

4.4.4 Writing Recipes with Directory Search

When a prerequisite is found in another directory through directory search, this cannot change the recipe of the rule; they will execute as written. Therefore, you must write the recipe with care so that it will look for the prerequisite in the directory wheremakefinds it.

This is done with the automatic variables such as ‘$^’ (see Section 10.5.3 [Automatic Variables], page 120). For instance, the value of ‘$^’ is a list of all the prerequisites of the rule, including the names of the directories in which they were found, and the value of ‘$@’ is the target. Thus:

foo.o : foo.c

cc -c $(CFLAGS) $^ -o $@

(The variableCFLAGSexists so you can specify flags for C compilation by implicit rules; we use it here for consistency so it will affect all C compilations uniformly; see Section 10.3 [Variables Used by Implicit Rules], page 115.)

Often the prerequisites include header files as well, which you do not want to mention in the recipe. The automatic variable ‘$<’ is just the first prerequisite:

VPATH = src:../headers foo.o : foo.c defs.h hack.h

cc -c $(CFLAGS) $< -o $@

4.4.5 Directory Search and Implicit Rules

The search through the directories specified in VPATH or with vpath also happens during consideration of implicit rules (see Chapter 10 [Using Implicit Rules], page 111).

For example, when a file foo.ohas no explicit rule, make considers implicit rules, such as the built-in rule to compilefoo.cif that file exists. If such a file is lacking in the current directory, the appropriate directories are searched for it. If foo.c exists (or is mentioned in the makefile) in any of the directories, the implicit rule for C compilation is applied.

The recipes of implicit rules normally use automatic variables as a matter of necessity; consequently they will use the file names found by directory search with no extra effort.

4.4.6 Directory Search for Link Libraries

Directory search applies in a special way to libraries used with the linker. This special feature comes into play when you write a prerequisite whose name is of the form ‘-lname’. (You can tell something strange is going on here because the prerequisite is normally the name of a file, and the file name of a library generally looks like libname.a, not like ‘-lname’.)

When a prerequisite’s name has the form ‘-lname’,makehandles it specially by searching for the filelibname.so, and, if it is not found, for the filelibname.ain the current directory, in directories specified by matchingvpathsearch paths and theVPATHsearch path, and then in the directories /lib, /usr/lib, and prefix/lib (normally /usr/local/lib, but MS- DOS/MS-Windows versions of make behave as if prefix is defined to be the root of the DJGPP installation tree).

For example, if there is a /usr/lib/libcurses.a library on your system (and no

/usr/lib/libcurses.so file), then

foo : foo.c -lcurses cc $^ -o $@

would cause the command ‘cc foo.c /usr/lib/libcurses.a -o foo’ to be executed when foois older than foo.cor than/usr/lib/libcurses.a.

Although the default set of files to be searched for is libname.soand libname.a, this is customizable via the .LIBPATTERNS variable. Each word in the value of this variable is

a pattern string. When a prerequisite like ‘-lname’ is seen, make will replace the percent in each pattern in the list with name and perform the above directory searches using each library file name.

The default value for .LIBPATTERNS is ‘lib%.so lib%.a’, which provides the default behavior described above.

You can turn off link library expansion completely by setting this variable to an empty value.