The
make
utility builds up-to-date versions of programs.
It is most
useful for large programming projects in which multiple source files are combined
to form a single program or for building a set of programs that are part of
a single product or application.
The
make
command accepts options to control or modify
how the building process is performed.
The
make
utility
does not address the problem of maintaining more than one version of the same
source file.
By using the
make
utility to maintain programs, you
can do the following:
Combine the instructions for creating a large program in a single file
Define macros to use within the
make
description
file
Use shell commands
Create or update libraries
Include files from other programs
The DIGITAL UNIX system provides several versions of the
make
command; this chapter describes the default version,
make(1).
The other versions, both of which offer features not provided by
make(1),
are
make(1u)
and
make(1p).
In addition to its extended feature set, the
make(1p)
version is POSIX compliant.
The
make(1)
and
make(1u)
versions are included in the base operating
system subsets.
The
make(1p)
version is included in the "Software Development
Environment (Software Development)" subset.
Refer to the respective reference pages for further information.
The
make
utility works by comparing the creation
date of a program to be built, called the
target
or
target file,
with the dates of the files that make it up,
called
dependency files
or
dependents.
If any of a given target's dependents are newer than the target,
make
considers that the target is out of date.
In this case,
make
rebuilds the target by performing the necessary compiling,
linking, or other steps.
Each dependent can also be a target; for example,
an executable program is made from object modules, which are in turn made
from source files.
Dependents that are newer than the target are called
younger
files.
The
make
utility uses the following sources of information:
A description file that you create
File names
Time stamps of the files from the file system
The
make
utility depends on files' time stamps.
For
make
to work
properly on a distributed system, the date and time on all systems in the
network must be synchronized.
The
make
utility creates a target file using the following step-by-step
procedure:
Finds the name of the target file in the description file
Finds a line that describes the dependents of the target, called a dependency line
Ensures that all the target's dependency files exist and are up to date
Determines if the target is current with respect to its dependents
Creates the target by one of the following methods if the target or one of the dependents is out of date:
Executes commands from the description file
Uses internal rules to create the file (if they apply)
Uses default rules from the description file
If all files described on the dependency line are up to date when
make
is run,
make
indicates that the target is
up to date and then stops.
If any dependents are newer than their targets,
make
recreates only those targets that are out of date.
Any missing files are deemed to be out of date.
If a given target has no dependents, it
is always out of date, and
make
rebuilds it every time you run
make.
The
make
process works from the top down in determining what targets need
to be rebuilt and from the bottom up in the actual rebuilding stage.
When the
make
utility runs commands to create a target,
it replaces macros with their values, echoes each command line to the standard
output, and then runs
the command.
(See
Section 7.2.9
for information about macros.) The
make
utility runs commands
that it can execute directly, such as
rm
or
cc,
without invoking a new shell.
The utility invokes
each command line that includes shell functions, such as pipes or redirection,
in a new shell.
You start the
make
utility in the
directory that contains the description file.
The syntax of the
make
command is as follows:
make
[
[-f ]
makefile
]
[ options
]
[ targets
]
[ macro definitions
]
The
make
utility examines the command line entries
to determine what to do.
First, it assigns values
for the macro definitions on the command line (entries containing equal signs),
if there are any, and for the macro definitions in the description file.
If there is a definition on the command line for a macro name that is also
defined in the description file,
make
uses
the command line definition and ignores the definition in the description
file.
Next,
make
looks at the options.
Refer to the
make(1)
reference page for a complete list of the options that
make
supports.
The
make
utility interprets the remaining command
line entries as the names of targets.
It processes the targets in left-to-right
order.
If there are no targets on the command line,
make
processes the first target named in the description file and then stops.
The description file tells
make
how to build the target by defining what dependencies are involved and what
their relationships are to the other files in the procedure.
The description
file contains the following information:
Definitions of macros in the description file
One or more target names
Dependency file names that make up the target files
Commands that create the target files from the dependents
Any of the pseudotargets
.DEFAULT,
.IGNORE,
.PRECIOUS,
.SILENT,
or
.SUFFIXES
These identifiers are called pseudotargets
because they are not real targets.
They are built-in names that
make
interprets in special ways.
For example, the
.SILENT
pseudotarget instructs
make
not
to echo command lines as it runs them.
Do not use any of these names for
a real target.
Refer to the
make(1)
reference page for additional information
on pseudotargets.
The
make
utility determines what files to create
to get an up-to-date copy of the target by checking the dates of the dependency
files.
If any dependency file was changed more recently than the target,
make
creates all the files that are affected by the change, including
the target.
In most cases, the description file is easy to write and does
not change often.
The
make
utility normally looks for a description
file named either
makefile
or
Makefile.
If you name the description file
makefile
or
Makefile
and are working in the directory containing that description
file, you enter the
make
command without any options or
arguments to bring the first target and its dependency files up to date, regardless
of the number of files that were changed since the last time
make
created the target file.
You can override the default file name
by using the
-f
option to the
make
utility to specify the name of the desired description file, as in the following
example:
% make -f my_makefile
This option lets you keep several description files in the same directory.
The general format of a description file entry is as follows:
[target1 [ target2... ] ]
[:]
[
[:]
]
[
[dependent...]
]
[
[; ]
commands
]
[
[# ]
comment...
]
The items inside brackets are optional.
Targets and dependents are
file names (strings of letters, numbers, periods, and slashes).
The
make
command recognizes wildcard characters, such as asterisks
( * ) and question marks
( ? ).
Each line in the description file that contains a target
name is called a dependency line.
The dependency line is followed by one
or more command lines that specify the process steps to create the target.
Because
make
uses the dollar sign
( $ ) to designate a macro, you must not use this character
in file names of targets and dependencies.
Similarly, do not use the dollar
sign in commands in the description file unless you are referring to a defined
make
macro.
(Macros are described in
Section 7.2.9,
Section 7.2.10, and
Section 7.2.12.)
To place comments in the description file, use a number sign ( # ) to begin the comment text.
The
make
utility ignores the number sign and all characters on the same line after
the number sign.
The
make
utility also ignores blank lines.
You can enter lines that are longer than the line width of the input
device by putting a backslash ( \ ) at the
end of the line that is to be continued.
Do not extend comment lines in this
way; begin each new comment line with its own number sign.
A command is any string of characters, except a
number sign or a newline character.
Commands can appear after a semicolon
( ; ) on a dependency line or on lines immediately
following a dependency line.
Each command line after the dependency line must
begin with a single tab character.
When you define command sequences for the targets in the description file, either specify one command sequence for each target or specify separate command sequences for special sets of dependencies.
To use one command sequence for every use of the target, use a single
colon ( : ) following the target name on
the dependency line.
For example, the following lines define a target,
test, with a set of dependency files and a set of commands to create
the target:
test: dependency list1...
command list...
.
.
.
test: dependency list2...
As shown here, a target name can appear in several places in the description
file with different dependency lists, but there can be only one command list
associated with the target name.
The
make
utility finds
all the dependency lines for a given target and concatenates all their dependency
lists into a single list.
When any of the dependents have been changed,
make
can run the commands in the one command list to create the
target.
To specify more than one set of commands to create a particular target
file, enter more than one dependency definition.
Each dependency line must
have the target name followed by two colons ( :: ),
a dependency list, and a command list that
make
uses if
any of the files in the dependency list changes.
For example, the following
lines define two separate processes to create the target file
test:
test:: dependency list1...
command list1...
.
.
.
test:: dependency list2...
command list2...
If any of the files in dependency
list1
changes,
make
runs command
list1; if any of the files
in dependency
list2
changes,
make
runs
command
list2.
To avoid conflicts, a given dependency file
cannot appear in both dependency
list1
and dependency
list2.
Note
Because
makeruns the commands on each command line independently of preceding or subsequent command lines, be careful when using certain commands (for example,cd). In the following example, thecdcommand has no effect on thecccommand that follows it:test: test.o cd /u/tom/newtest cc main.o subs.o -o testTo make the
cdcommand affect thecccommand, place both commands on the same line, separated by a semicolon. For example:test: test.o cd /u/tom/newtest; cc main.o subs.o -o testYou can simulate a multiline shell script by using backslashes on continued lines:
test: test.o cd /u/tom/newtest; \ cc main.o subs.o -o testThis example works exactly the same as the one immediately before it. Each line continued with a backslash (the
cdline in this example) must have a semicolon before the backslash.
To prevent
make
from echoing
the commands that it is executing to standard output, use any one of the following
procedures:
Use the
-s
flag on the command line when
you enter the
make
command.
Put the pseudotarget name
.SILENT:
on a
line by itself in the description file.
See
Section 7.2
for an explanation of pseudotargets.
Put an at sign
( @ )
in the first character position (after the tab) of each command line in the
description file that
make
should not echo.
The
make
utility usually stops
if any command returns a nonzero status code to indicate an error.
To prevent
make
from stopping on errors, use any
of the following procedures:
Use the
-i
flag on the command line when
you enter the
make
command.
Put the pseudotarget name
.IGNORE:
on a
line by itself in the description file.
See
Section 7.2
for an explanation of pseudotargets.
Put a hyphen ( - ) in the
first character position (after the tab) of each command line in the description
file where
make
should not stop on errors.
When
make
creates a target but cannot find either explicit command lines
or internal rules to create the file, it looks at the description file for
default conditions.
To define the commands that
make
performs
in this case, use the
.DEFAULT:
pseudotarget name in the
description file, entering the default command sequence as for any other target.
Use the
.DEFAULT:
pseudotarget for an error recovery
routine or for a general procedure to create all files in the program that
are not defined by an internal rule of the
make
utility.
To prevent completion of a build
using potentially corrupted target files,
make
usually
removes target files if an error is returned during the build.
To prevent
make
from removing files when an error is detected, use the
.PRECIOUS:
pseudotarget in the description file.
After the pseudotarget
name, list the target names to be saved.
If you specify the
-u
option on the command line,
make
does not remove any RCS
files it checked out.
See the
make(1)
reference page for more information
on how
make
interacts with RCS.
In
Example 7-1,
a program named
prog
is made by compiling and loading three
C language files:
x.c,
y.c, and
z.c.
The files
x.c
and
y.c
share some declarations in a file named
defs.
The
z.c
file does not share those declarations.
# Make prog from 3 object files
prog: x.o y.o z.o
# Use the cc program to make prog
cc x.o y.o z.o -o prog
# Make x.o from 2 other files
x.o: x.c defs
# Use the cc program to make x.o
cc -c x.c
# Make y.o from 2 other files
y.o: y.c defs
# Use the cc program to make y.o
cc -c y.c
# Make z.o from z.c
z.o: z.c
# Use the cc program to make z.o
cc -c z.c
If this file is called
makefile, you can enter
the
make
command with no options or arguments to make an
up-to-date copy of
prog
after making changes to any of
the four source files
x.c,
y.c,
z.c, or
defs.
To make the description
file simpler, use the internal rules of the
make
utility.
Using file system naming conventions,
make
knows that
there are three
.c
files corresponding to the needed
.o
files.
It also knows how to generate an object from a source
file (that is, issue a
cc -c
command).
By taking advantage
of these internal rules, the description file becomes the following:
# Make prog from 3 object files
prog: x.o y.o z.o
# Use the cc program to make prog
cc x.o y.o z.o -o prog
# Use the file defs and the appropriate .c file
# when making x.o and y.o
x.o y.o: defs
Section 7.2.14
describes
the internal rules used by
make.
A macro is a name to use in place of one or more other names. It is a shorthand way of using the longer string of characters. You can define macros in the description file or on the command line. To define a macro in the description file, do the following:
Start a new line with the name of the macro.
Follow the name with an equal sign ( = ).
To the right of the equal sign, enter the string of characters that the macro name represents. The string can contain blanks.
The macro definition can contain blanks before and after the equal sign
without affecting the result.
The macro definition cannot contain a colon
( : ) or a tab before the equal sign.
The
make
utility ignores leading and trailing blanks in the defining
string.
The following examples are macro definitions:
# Macro ABC has a value of "ls -la" ABC = ls -la # Macro LIBES has a null value LIBES = # Macro DIRECT includes the definition of macro ROOT # The expanded value of DIRECT is "/usr/home/fred" ROOT = /usr/home DIRECT = $(ROOT)/fred
The
DIRECT
macro
in this example use another definition as part of its own definition.
See
Section 7.2.10
for instructions on using macros.
To define a macro on a command
line, follow the same syntax as for defining macros in the description file,
but include all of your macro definitions on the same line.
When you define
a macro with blanks from the command line, enclose the definition in quotation
marks ( "name = definition" ).
Without the
quotation marks, the shell interprets the blanks as parameter separators and
not as part of the macro.
After you define a macro in a description
file, refer to the macro's value in the description file by putting a dollar
sign ( $ ) before the name of the macro.
If the macro name is longer than one character, put parentheses or braces
around it, as illustrated by the following examples:
$(CFLAGS)
${xy}
$Z
$(Z)
The effect of the last two examples is identical.
You can substitute a different value for part or all of a macro's defined value. The three forms of macro substitution are as follows:
The first form replaces every occurrence of string1 in the defined value of MACRO with string2:
[$(MACRO:string1=string2)]
For example:
# Define macro MAC1 MAC1 = xxx yyy zzz
.
.
.
# Evaluate MAC1 project: @ echo $(MAC1:yyy=abc)
When you run
make
with this description file,
make
substitutes
abc
for the occurrence of
yyy, and displays the
following line:
xxx abc zzz
The second form applies a substitution to each word in the defined value. The location parameter specifies what portion of the word is to be replaced with string:
[$(MACRO/location/string)]
The location parameter is restricted to the following values:
Circumflex ( ^ ) -
The
string
value is added as a prefix to each defined
word.
For example:
# Define macro MAC1 MAC1 = abc def ghi
.
.
.
# Evaluate MAC1 project: @ echo $(MAC1/^/xyz)
When you run
make
with this description file,
make
adds
xyz
to the beginning of each defined word and displays the following line:
xyzabc xyzdef xyzghi
Asterisk
( * ) -
The
string
value replaces all of each defined word.
For example:
# Define macro MAC1 MAC1 = abc def ghi
.
.
.
# Evaluate MAC1 project: @ echo $(MAC1/*/xyz)
When you run
make
with this description file,
make
substitutes
xyz
for each defined word and displays the following line:
xyz xyz xyz
With the asterisk, you can use an
ampersand
( & )
in the
string
value.
The ampersand represents
the defined word that is being substituted for, and it causes that word to
be interpolated in the result.
For example:
# Define macro MAC1 MAC1 = abc def ghi
.
.
.
# Evaluate MAC1 project: @ echo $(MAC1/*/x&z)
When you run
make
with this description file,
make
substitutes
x&z
for each defined word, interpolating the defined word for
the ampersand, and displays the following line:
xabcz xdefz xghiz
Dollar sign ( $ ) -
The
string
value is appended to each defined word.
For example:
# Define macro MAC1 MAC1 = abc def ghi
.
.
.
# Evaluate MAC1 project: @ echo $(MAC1/$/xyz)
When you run
make
with this description file,
make
appends
xyz
to the end of each defined word and displays the following line:
abcxyz defxyz ghixyz
The third form makes one of two possible substitutions depending on whether MACRO is defined:
[$(MACRO?string1:string2)]
If MACRO is defined, string1 is substituted for the entire defined value. If MACRO is not defined, string2 is used. For example:
# Define macro MAC1 MAC1 = abc def ghi
.
.
.
# Evaluate MAC1 and MAC2. MAC2 is not defined. project: @ echo $(MAC1?uvw:xyz) @ echo $(MAC2?123:456)
When you run
make
with this description file,
make
substitutes
uvw
for the value of
MAC1
and
456
for the undefined
MAC2, and displays the following lines:
uvw 456
The first two forms of substitution produce a null string if MACRO is undefined.
The value of a macro can be assigned based on a preexisting condition. This type of macro is a conditional macro. You cannot define conditional macros on the command line; all conditional macro definitions must be in the description file. The syntax of the conditional macro is as follows:
[target:=MACRO = string]
The macro is assigned the value of the string if the specified
target is the current target of the
make
command.
Otherwise,
the macro's value is null.
The following description file uses a conditional
substitution for
MAC1:
# Define the conditional macro MAC1 target2:=MAC1 = xxx yyy xxxyyy
.
.
.
#list targets and command lines # target1:;@echo $(MAC1) target2:;@echo $(MAC1)
When you run
make
with this description file, you
get the following results:
% make target1 % make target2 xxx yyy xxxyyy
You can nest calls to
the
make
utility within a
make
description
file by including the
$(MAKE)
macro in one of the command lines in the
file.
If this macro is present,
make
executes another
copy of
make, even if the
-n
option
is set.
See
Section 7.2.16
for a description of
the
-n
option.
The
make
utility has built-in
macro definitions for use in the description file.
These macros help specify
variables in the description file.
The
make
utility replaces
the macros with the values indicated in
Table 7-1.
| Macro | Valuex |
$@ |
The name of the current target file |
$$@ |
The target names on the dependency line |
$? |
The names of the dependency files that have changed more recently than the target |
$< |
The name of the out-of-date file that caused a target file to be created |
$* |
The name of the current dependency file without the suffix |
Each of these macros resolves to a single file name at the time
make
is actually using it.
You can modify the interpretation of
any of these macros by using a
D
suffix to indicate that
you want only the directory portion of the name.
For example, if the current
target is
/u/tom/bin/fred, the
$(@D)
macro returns only the
/u/tom/bin
portion of the name.
Similarly, an
F
suffix returns only the file name portion.
For example, the
$(@F)
macro returns
fred
if given the same target.
All internal macros except the
$?
macro can take the
D
or
F
suffix.
Before using any internal macros on a distributed file system, you must
ensure that the system clocks show the same date and time for all nodes that
contain files for
make
to process.
The
make
utility replaces these symbols only when
it runs commands from the description file to create the target file.
The
following sections explain these macros in more detail.
The
make
utility
substitutes the full name of the current target for every occurrence of the
$@
macro in the command
sequence for building the target.
The replacement is made before running
the command.
For example:
/u/tom/bin/test: test.o
cc test.o -o $@
This example produces an executable
file named
/u/tom/bin/test.
If the
$$@
macro is used on the
right side of the colon on a dependency line in a description file,
make
replaces this symbol with the label name that is on the left
side of the colon in the dependency line.
This name could be a target name
or the name of another macro.
For example:
cat: $$@.c
The
make
utility interprets this line
as follows:
cat: cat.c
Use this macro to build a group of files, each of which has only one source file. For example, to maintain a directory of system commands, use a description file like the following:
# Define macro CMDS as a series of command names
CMDS = cat dd echo date cc cmp comm ar ld chown
# Each command depends on a .c file
$(CMDS): $$@.c
# Create the new command set by compiling the out of
# date files ($?) to the current target file name ($@)
cc -O $? -o $@
The
make
utility changes the
$$(@F)
macro to the file part of
$@
when it runs.
For example,
you could use this symbol when maintaining the
usr/include
directory while using a description file in another directory.
That description
file would look like the following example:
# Define directory name macro INCDIR
INCDIR = /usr/include
# Define a group of files in the directory
# with the macro name INCLUDES
INCLUDES = \
$(INCDIR)/stdio.h \
$(INCDIR)/pwd.h \
$(INCDIR)/dir.h \
$(INCDIR)/a.out.h
# Each file in the list depends on a file
# of the same name in the current directory
$(INCLUDES): $$(@F)
# Copy the younger files from the current
# directory to /usr/include
cp $? $@
# Set the target files to read only status
chmod 0444 $@
This description file creates a file
in the
/usr/include
directory when the corresponding file
in the current directory has been changed.
If the
$?
macro is in the command
sequence in the description file,
make
replaces the symbol
with a list of dependency files that have been changed since the target file
was last changed.
If the
$<
macro is in the command sequence in the
description file,
make
replaces the symbol with the name
of the file that started the file creation.
The file name is the name of
the specific dependency file that was out of date with the target file and
therefore caused
make
to create the target file again.
The difference between this symbol and the
$?
symbol,
which returns a complete list of younger files.
The
make
utility replaces this symbol only when it
runs commands from its internal rules or from the
.DEFAULT:
list.
The symbol has no effect in an explicitly stated command line.
If the
$*
macro is in the command
sequence in the description file,
make
replaces the symbol
with the file name part (without the suffix) of the dependency file that
make
is currently using to generate the target file.
For example,
if
make
is building the target
test.c,
the
$*
symbol represents the file name
test.
The
make
utility replaces this symbol only when it
runs commands from its internal rules or from the
.DEFAULT:
list.
The symbol has no effect in an explicitly stated command line.
Each time
make
runs, it reads the
current environment variables and adds them to its defined macros.
In addition,
it creates a new macro called
MAKEFLAGS.
This macro is a collection of all
the options that were entered on the command line.
Command line options
and assignments in the description file can also change the value of the
MAKEFLAGS
macro.
When
make
starts another process,
it exports
MAKEFLAGS
to that process.
See
Section 7.2.16
for a discussion of how the
MAKEFLAGS
macro affects recursive
make
processes.
The
make
utility assigns macro definitions in the
following order with later steps overriding earlier ones where there are conflicts:
Reads the
MAKEFLAGS
environment variable
to set options specified by the variable.
If
MAKEFLAGS
is not present or is null,
make
sets its internal
MAKEFLAGS
macro to the null string.
Otherwise,
make
assumes that each letter in
MAKEFLAGS
is an input option.
The
make
utility uses these options (except for
-f,
-p, and
-r)
to determine its operating conditions.
Reads and sets the input flags from the command line.
Any
options specified explicitly on the command line are added to the settings
from the
MAKEFLAGS
environment variable.
Reads macro definitions from the command line. These definitions override any definitions for the same names in the description file.
Reads the internal macro definitions.
Reads the environment, including the
MAKEFLAGS
macro.
The
make
utility treats all environment variables
as macro definitions and passes them to shells it invokes to execute commands.
The
make
utility
has a set of internal rules that it uses to determine how to build a target.
You can override these rules by invoking
make
with the
-r
option; in this case, you must supply any rules that
are required to build the targets in your description file.
The internal
rules contain a list of file name suffixes defined using the pseudotarget
.SUFFIXES:, along with the rules that tell
make
how to create a file with one suffix from a file with another suffix.
To see
the complete list of conversions supported by
make's internal
rules, run the following command:
% make -p | more
If you do not change the list by default,
make
understands the following suffixes:
| Suffix | File Type |
.o |
Object file |
.c |
C source file |
.e |
efl
source file |
.r |
Ratfor source file |
.f
or
.F |
FORTRAN source file |
.s |
Assembler source file |
.y |
yacc
C source grammar |
.yr |
yacc
Ratfor source grammar |
.ye |
yacc efl
source grammar |
.l |
lex
source grammar |
.out |
Executable file |
.p |
Pascal source file |
.sh |
Bourne shell script |
.csh |
C shell script |
.h |
C header file |
You can add suffixes to this list by
including a
.SUFFIXES:
line in the description file with
one or more space-separated suffixes.
For example, the following line adds
the suffixes
.f77
and
.ksh
to the existing
list.
For example:
.SUFFIXES: .f77 .ksh
To erase
make's default list of suffixes, include a
.SUFFIXES:
line with no
names on it.
You can replace the default list with a completely new list
by using first an empty list and then your new list:
.SUFFIXES: .SUFFIXES: .o .c .p .sh .ksh .csh
Because
make
looks at the suffixes list in left-to-right order, the order of the entries
is important.
The preceding example ensures that
make
will look first for an object file, then a C source file, and so on.
The
make
utility uses the first entry in the list
that satisfies the following two requirements:
The entry matches input and output suffix requirements.
The entry has a rule assigned to it.
If you add suffixes to the list that
make
recognizes,
you must provide rules that describe how to build a target from its dependents.
A rule looks like a dependency line and the corresponding series of commands.
The
make
utility creates
the name of the rule from the two suffixes of the files that the rule defines.
For example, the name of the rule to transform a
.r
file
to a
.o
file is
.r.o.
Example 7-2
illustrates a portion of the standard default rules file.
# Create a .o file from a .c
# file with the cc program
.c.o
$(CC) $(CFLAGS) -c $<
# Create a .o file from either a
# .e , a .r , or a .f
# file with the efl compiler
$(EC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $<
# Create a .o file from
# a .s file with the assembler
.s.o:
$(AS) -o $@ $<
.y.o:
# Use yacc to create an intermediate file
$(YACC) $(YFLAGS) $<
# Use cc compiler
$(CC) $(CFLAGS) -c y.tab.c
# Erase the intermediate file
rm y.tab.c
# Move to target file
mv y.tab.o $@
.y.c:
# Use yacc to create an intermediate file
$(YACC) $(YFLAGS) $<
# Move to target file
mv y.tab.c $@
The
make
utility also has a set of single suffix rules to create targets with no suffixes,
such as command files.
The
make
utility has rules to change
the following source files with a suffix to object files without a suffix:
| Suffix | Source File Type |
.c |
From a C language source file |
.sh |
From a shell file |
For example, to maintain a program like
cat
if
all of the needed files are in the current directory, enter the following
command:
% make cat
The
make
utility uses macro definitions in its internal
rules.
To change these macro definitions, enter new definitions for those
macros on the command line or in the description file.
For commands and language
processors, the
make
utility uses the following macro names:
| Command or Function | Command Macro | Command Options or Other Macros |
Archive program (ar) |
AR | ARFLAGS |
| Archive table of contents creation | RANLIB | |
| Assembler | AS | ASFLAGS |
| C Compiler | CC | CFLAGS |
| C libraries | LOADLIBS | |
| RCS checkout | CO | COFLAGS |
The copy command (cp) |
CP | CPFLAGS |
efl
compiler |
EC | EFLAGS |
Linker command (ld) |
LD | LDFLAGS |
The
lex
command |
LEX | LFLAGS |
The
lint
command |
LINT | LINTFLAGS |
The
make
command |
MAKE | |
Recursive
make
calling
flags |
MAKEFLAGS | |
The
mv
command |
MV | MVFLAGS |
The
pc
command |
PC | PFLAGS |
The
f77
compiler |
RC | FFLAGS |
| Ratfor compiler flags | RFLAGS | |
The
rm
command |
RM | RMFLAGS |
| For locating files related to dependency | VPATH | |
The
yacc
command |
YACC | YFLAGS |
The
yacc -e
command |
YACCE | YFLAGS |
The
yacc -r
command |
YACCR | YFLAGS |
For example, the following command runs
make, substituting
the
newcc
program in place of the previously defined C
language compiler:
% make CC=newcc
Similarly, the following command tells
make
to optimize the final object code produced by the C language
compiler.
% make "CFLAGS=-O"
To look at the internal rules that
make
uses, enter
the following command from the Bourne shell:
$ make -fp -< /dev/null 2>/dev/null
The output appears on the standard output.
You can include files in addition to the current
description file by using the word
include
as the first
word on any line in the description file.
Follow the word with a blank or
a tab and then the set of file names for
make
to include
in the operation.
For example:
include /u/tom/temp /u/tom/sample
To test a description
file, run
make
with the
-n
command option.
This option instructs
make
to echo command lines without
executing them.
Even commands preceded by at signs ( @ )
are echoed so that you can see the entire process as
make
would execute it.
When the
-n
option is in effect, the
$(MAKE)
macro, unlike
all other commands, is actually executed.
If the description file includes an instance of the
$(MAKE)
macro,
make
calls the new copy of
make
with the
MAKEFLAGS
macro's value set to
the list of options, including
-n, that you entered on
the command line.
The new copy of
make
observes that the
-n
option is set, and it bypasses command execution in the same
way as the copy that called it.
You can test a set of description files that
use recursive calls to
make
by entering a single
make
command.
Example 7-3
shows the description file that maintains the
make
utility.
The source code for
make
is contained in a number of C
language source files and a
yacc
grammar file.
For more
information on
yacc, see
Chapter 4.
# Description file for the Make program
# Macro def: send to be printed
P = lpr
# Macro def: source file names used
FILES = Makefile version.c defs main.c
doname.c misc.c files.c
dosy.c gram.y lex.c gcos.c
# Macro def: object file names used
OBJECTS = version.o main.o doname.o \
misc.o files.o dosys.o gram.o
# Macro def: lint program and flags
LINT = lint -p
# Macro def: C compiler flags
CFLAGS = -O
# make depends on the files specified
# in the OBJECTS macro definition
make: $(OBJECTS)
# Build make with the cc program
cc $(CFLAGS) $(OBJECTS) -o make
# Show the file sizes
size make
# The object files depend on a file
# named defs
$(OBJECTS): defs
# The file gram.o depends on lex.c
# uses internal rules to build gram.o
gram.o: lex.c
# Clean up the intermediate files
clean:
rm *.o gram.c
# Copy the newly created program
# to /usr/bin and deletes the program
# from the current directory
install:
cp make /usr/bin/make ; rm make
# Empty file ''print'' depends on the
# files included in the macro FILES
print: $(FILES)
# Print the recently changed files
lpr $?
# Change the date on the empty file,
# print, to show the date of the last
# printing
touch print
# Check the date of the old
# file against the date
# of the newly created file
test:
make -dp | grep -v TIME >1zap
/usr/bin/make -dp | grep -v TIME >2zap
diff 1zap 2zap
rm 1zap 2zap
# The program, lint, depends on the
# files that are listed
lint: dosys.c doname.c files.c main.c misc.c \
version.c gram.c
# Run lint on the files listed
# LINT is an internal macro
$(LINT) dosys. doname.c files.c main.c \
misc.c version.c gram.c
rm gram.c
# Archive the files that build make
arch:
ar uv /sys/source/s2/make.a $(FILES)