[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


7    Building Programs with the make Utility

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:

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.


[Return to Library] [Contents] [Previous Chapter] [Next Section] [Next Chapter] [Index] [Help]


7.1    Operation of the make Utility

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:

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:

  1. Finds the name of the target file in the description file

  2. Finds a line that describes the dependents of the target, called a dependency line

  3. Ensures that all the target's dependency files exist and are up to date

  4. Determines if the target is current with respect to its dependents

  5. Creates the target by one of the following methods if the target or one of the dependents is out of date:

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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2    Description Files

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:

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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.1    Format of a Description File Entry

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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.2    Using Commands in a Description File

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 make runs 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, the cd command has no effect on the cc command that follows it:

test:  test.o
        cd /u/tom/newtest
        cc main.o subs.o -o test


To make the cd command affect the cc command, 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 test

You 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 test

This example works exactly the same as the one immediately before it. Each line continued with a backslash (the cd line in this example) must have a semicolon before the backslash.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.3    Preventing the make Utility from Echoing Commands

To prevent make from echoing the commands that it is executing to standard output, use any one of the following procedures:


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.4    Preventing the make Utility from Stopping on Errors

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:


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.5    Defining Default Conditions

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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.6    Preventing make from Deleting Files

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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.7    Simple Description File

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.

Example 7-1: A Simple Description File

# 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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.8    Making the Description File Simpler

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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.9    Defining Macros

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:

  1. Start a new line with the name of the macro.

  2. Follow the name with an equal sign (=).

  3. 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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.10    Using Macros in a Description File

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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.10.1    Macro Substitution

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 two forms of substitution produce a null string if MACRO is undefined.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.10.2    Conditional Macros

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


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.11    Calling the make Utility from a Description File

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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.12    Internal Macros

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.

Table 7-1: Internal make Macros

Macro Value
$@ 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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.12.1    Internal Target File Name Macro

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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.12.2    Internal Label Name Macro

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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.12.3    Internal Younger Files Macro

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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.12.4    Internal First Out-of-Date File Macro

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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.12.5    Internal Current File Name Prefix Macro

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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.13    How make Uses Environment Variables

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:

  1. 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.

  2. 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.

  3. Reads macro definitions from the command line. These definitions override any definitions for the same names in the description file.

  4. Reads the internal macro definitions.

  5. 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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.14    Internal Rules

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:

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.

Example 7-2: 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 $@


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.14.1    Single Suffix Rules

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


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.14.2    Overriding Built-In make Macros

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 Command Options
Macro 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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.15    Including Other Files

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


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Section] [Next Chapter] [Index] [Help]


7.2.16    Testing Description Files

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.


[Return to Library] [Contents] [Previous Chapter] [Previous Section] [Next Chapter] [Index] [Help]


7.2.17    Description File

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.

Example 7-3: The makefile for the make Utility

# 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)