This chapter is devoted to those facilities in PMake that allow you to do a great deal in a makefile with very little work, as well as do some things you could not do in Make without a great deal of work (and perhaps the use of other programs). The problem with these features, is they must be handled with care, or you will end up with a mess.
Once more, I assume a greater familiarity with UNIX® or Sprite than I did in the previous two chapters.
PMake supports the dispersal of
files into multiple directories by allowing you to specify
places to look for sources with .PATH
targets in the makefile. The directories you give as sources
for these targets make up a “search path”. Only
those files used exclusively as sources are actually sought on a
search path, the assumption being that anything listed as a
target in the makefile can be created by the makefile and thus
should be in the current directory.
There are two types of search paths in
PMake: one is used for all types of
files (including included makefiles) and is specified with a
plain .PATH
target (e.g. .PATH
: RCS
), while the other is specific to a certain
type of file, as indicated by the file's suffix. A specific
search path is indicated by immediately following the
.PATH
with the suffix of the file. For
instance:
.PATH.h : /sprite/lib/include /sprite/att/lib/include
would tell PMake to look in the
directories /sprite/lib/include
and
/sprite/att/lib/include
for any
files whose suffix is .h
.
The current directory is always consulted first to see if a file exists. Only if it cannot be found there are the directories in the specific search path, followed by those in the general search path, consulted.
A search path is also used when expanding wildcard characters. If the pattern has a recognizable suffix on it, the path for that suffix will be used for the expansion. Otherwise the default search path is employed.
When a file is found in some directory other than the
current one, all local variables that would have contained the
target's name (.ALLSRC
, and
.IMPSRC
) will instead contain
the path to the file, as found by
PMake.
Thus if you have a file ../lib/mumble.c
and a makefile like this:
.PATH.c : ../lib mumble : mumble.c $(CC) -o $(.TARGET) $(.ALLSRC)
the command executed to create mumble would be
cc -o mumble ../lib/mumble.c.
(as an aside, the command in this case is not strictly
necessary, since it will be found using transformation rules
if it is not given. This is because .out
is the null suffix by default and a transformation exists
from .c
to
.out
. Just thought I would throw that in).
If a file exists in two directories on the same search path,
the file in the first directory on the path will be the one
PMake uses. So if you have
a large system spread over many directories, it would
behoove you to follow a naming convention that avoids such
conflicts.
Something you should know about the way search paths are
implemented is that each directory is read, and its contents
cached, exactly once – when it is first encountered
– so any changes to the directories while
PMake is running will not be noted
when searching for implicit sources, nor will they be found when
PMake attempts to discover when the
file was last modified, unless the file was created in the
current directory. While people have suggested that
PMake should read the directories
each time, my experience suggests that the caching seldom causes
problems. In addition, not caching the directories slows things
down enormously because of PMake's attempts
to apply transformation rules through non-existent files – the
number of extra file-system searches is truly staggering,
especially if many files without suffixes are used and the null
suffix is not changed from .out
.
All FreeBSD documents are available for download at https://download.freebsd.org/ftp/doc/
Questions that are not answered by the
documentation may be
sent to <freebsd-questions@FreeBSD.org>.
Send questions about this document to <freebsd-doc@FreeBSD.org>.