Documentation For The Make Utility Copyright © 1991 by Ben Eng Ben Eng 150 Beverley St. Apt #1L Toronto, Ontario M5T 1Y6 ben@contact.uucp BIX: jetpen OVERVIEW Make is a programming utility used to automate the process of recompiling multiple interdependent source files into an output file, called the goal. The rules for making the goal are explicitly stated in an input file called the Makefile, and implicitly determined from builtin inference rules. Normally, the Makefile for a goal is written so that the only thing that needs to be done to recompile newly modified source files is to run the Make program. MAKEFILE The Makefile is a text file which is read by the Make program. The Makefile is written to define the rules for making a goal up to date. A goal file is up to date if it has a modification datestamp that is more recent than all of its dependents, after all dependents are made up to date with respect to their dependents. This criterion for up to dateness is applied recursively, such that the most deeply nested dependent will be made before any target file that depends on it. Here is an example of a simple Makefile, that does not correspond to what would normally be used: # comment1 # comment2 goal: target.o ; command three target.o: source.c header.h command one command two In a Makefile, any line beginning with a `#' character is considered to be a comment line. Comment lines are ignored by the Make program. Rules are defined by a line that begins with one or more target filenames, followed by a colon, an optional list of dependent filenames, an optional semicolon and an optional command. Subsequent lines that begin with a tab character are command lines associated with the rule; the next line that does not begin with a tab character indicates the end of the current rule and the beginning of a new rule. In the above example, the Make program will read the Makefile and find the first target filename to be `goal'. It will then attempt to make `goal' up to date by first making its dependencies (namely, `target.o') up to date. In order to make `target.o' up to date, Make requires a rule that contains `target.o' as a target filename. Such a rule exists in the example Makefile with dependencies `source.c' and `header.h', which must in turn be made before `target.o' can be made up to date. Since `source.c' and `header.h' are not defined as targets in the Makefile, the Make program must use builtin rules of inference to make those files up to date, or it must give up and report that is doesn't know how to make the target. As it turns out, the source and header files are known by builtin rules of inference to require no further action to be made up to date, so the Make program can continue to make `target.o' now that its dependencies have fulfilled their requirements. In order to make `target.o' up to date, `command one' must be executed successfully, and then `command two' must be executed successfully after that. Finally, the goal can be made by executing the command line, `command three', and the Make program will terminate. DEPENDENCIES If there are no dependencies for a target, and a target needs to be remade by the Make program, then the target is always remade. A target with no dependencies will always have its commands executed when that target needs to be remade. Additional dependencies can be added to a target defined in another rule by writing a new rule which declares the additional dependencies. Only one of the rules may contain command lines, otherwise it is an error. An example where this might be done is given below: target1.o target2.o : global.h target1.o : target1.h target2.o : target2.h DOUBLE COLON RULES If multiple rules are given for a target name using `::' to delimit the target names from the dependencies, then such rules are called double colon rules. Each double colon rules is independent of the others. A Double colon rule allows a target name to depend upon multiple mutually exclusive dependencies. The first double colon rule whose dependencies are found to exist is the rule which applies to the target. (TODO: This feature is not supported yet.) MACROS and VARIABLES Variables can contain macro definitions of multiple filenames or other text. They are useful for replacing multiple occurrences of the same body of text with references to a variable (macro expansion). A variable is defined in the Makefile with an assignment statement. Only the last assignment of a variable is recognized, because the rules are processed after the entire Makefile has been interpreted into internal rules by the Make program. In a makefile, the line: myvariable = source.c header.h is used to assign the string `source.c header.h' to the variable named `myvariable'. In the following rule definition: target.o: $(myvariable) the `$(myvariable)' reference is expanded into the string assigned to `myvariable'. If the macro expansion contains further references to other variables, then they are also recursively expanded until the resulting string is fully expanded. Undefined macros are expanded to nothing (empty strings). `${myvariable}' is equivalent to `$(myvariable)'. For single character variable names, the parentheses or braces are not necessary to expand the macro; the single character may immediately follow the `$'. Additional text can be concatenated to the end of the value of an existing variable by using the `+=' operator, like this: alpha = abc alpha += def The result of `$(alpha)' is now `abc def'. Notice the space inserted at the point of concatenation. This ensures that filenames are not split between different lines. It is possible to define a variable which results in an infinitely recursive macro expansion. This is illegal, and it will result in an error when that variable is referenced. A variable can be defined, such that its value is expanded immediately at the time of assignment. These are called simple variables, and they are assigned with the `:=' operator. Note that when a simple variable is assigned, any other references to variables will expand to their value as assigned above the line of the simple variable being assigned. Here is an example: simplevar := $(myvariable) The only difference between an ordinary variable and a simple variable is that the value of the simple variable is expanded only once during its assignment, whereas the value of an ordinary variable needs to be expanded every time it is referenced. Referencing a simple variable requires only a simple substitution, whereas referencing an ordinary variable requires a recursive macro expansion, which requires more work (memory, stack, and CPU instructions). Variables referenced in the target and dependencies of a rule are expanded during the rule definition. Variables referenced in each command line associated with a rule are expanded when the command line is executed. Both `\$' and `$$' expand to the character `$', but the latter is recommended. AUTOMATIC VARIABLES There are a set of variables that are automatically defined at runtime by the Make program. $@ expands to: target filename $* expands to: target filename without its suffix $< expands to: the first dependent filename $^ expands to: all dependents of target newer than target (not-implemented) $% expands to: dependent member of the target archive (not-implemented) $? expands to: all dependents of the target archive (not-implemented) The value of automatic variables depends on where they are referenced. An automatic variable has a different value according to the objects of the rule to which it applies. $@ does not expand in the target position. Automatic variables making reference to dependencies do not make sense when used in the place of a target name or dependency, so they will not be defined when referenced in those situations; those variables will expand to their proper values in command lines. COMPLEX VARIABLE NAMES and MACRO EXPANSIONS Rarely is it necessary to apply what is discussed in this topic, but the information will be given for completeness. Because of the recursive nature of the macro expansion algorithm, it is possible to construct variables that act like arrays (or other complex data types) through the use of variable names that themselves contain a nested macro expansion. Here is an example of an obscure sort of Makefile that uses this technique: A1 = one.c A2 = two.c target.o: ${A$(B)} $(CC) -c $(CFLAGS) -o $@ $< Depending on whether the value of the variable `B' is set to `1' or `2', the target file will depend on `one.c' or `two.c'. Although there is no internal limit restricting the level to which macros can be nested (in the variable name and its value), it is recommended that nested be kept to a minimum to conserve on memory consumption and stack usage. Each level of nesting requires at least an additional 2K of memory. Please note that the maximum length of a variable name is 256 characters. FUNCTION CALLS Function calls of the form $(function arguments) or ${function arguments} will be processed differently than a normal macro expansion. A function call acts like a macro expansion in that it returns a string. All spaces, except for the sequence of spaces before the first argument (after expansion), are significant. Please note that the maximum length of the string within the parentheses is 1024 characters. STRING FUNCTIONS (see section 9.2 of the GNU Make manual) $(filter pattern,text) A pattern is a word that optionally contains a single wildcard character `%'. All words in `text' that do not match the `pattern' are removed, so that this function call returns only matching words. $(filter-out pattern,text) All words in `text' that match the `pattern' are removed, so that this function call returns only non-matching words. The result is the complement of the result of $(filter). $(findstring find,in) if the `in' string contains the `find' string then the `find' string is returned, otherwise the result is an empty string $(getenv name) The result is the contents of the environment variable ENV:name. Note that referencing an undefined macro automatically performs the equivalent of $(getenv macro). This function call is offered to allow the Makefile to explicitly reference an environment variable, instead of the internal Make variable. $(patsubst pattern,replacement,text) The result is a list of words derived from `text'. `text' is a whitespace separated list of words. Each word is compared with `pattern'. A `%' character in the pattern matches any number of characters; only one `%' may appear in the pattern. If the pattern does not match the word then the word is appended unchanged to the result, otherwise a substitution is performed on the word, the result of which is appended to the result. If a substitution is necessary, then the resulting word is formed by any characters preceding the `%' of `replacement', plus every character of the current word of `text' that was matched by the `%' of `pattern', plus any characters following the `%' of `replacement'. In other words, if the `%' character occurs in both `pattern' and `replacement' then the substring matched by the `%' will be substituted for the `%' in the `replacement' string, which will then be used as the next word of the result. For example, $(patsubst pre%post,a%b,dogfood preAApost) will result in the string `dogfood aAAb'. $(sort list) Not implemented yet $(strip string) strips leading and trailing whitespace from string, and replaces embedded sequences of spaces with a single space. $(subst from,to,text) replaces all occurrences in `text' that match the string `from' with the string `to'. FILENAME FUNCTIONS (see section 9.3 of the GNU Make manual) $(dir names) Extracts the directory part of each path name in `names', including the trailing slash or colon. No checking is done to determine whether the result is actually a directory or not; this command acts only as a string function, and knows nothing about the organization of the filesystem. $(notdir names) Extracts the file part of each path name in `names'. The result is the complement of $(dir names). $(suffix names) Extracts only the suffix of each path name in `names'. The suffix is the rightmost part of the name starting at the last `.' character. $(basename names) Extracts all but the suffix of each path name in `names'. The result is the complement of $(suffix names). $(addsuffix suffix,names) The result is the list of names with `suffix' appended to each word of the list. $(addprefix prefix,names) The result is the list of names with `suffix' prepended to each word of the list. $(join list1,list2) The result is the wordwise concatenation of `list1' with `list2'. $(word n,text) Returns the nth word of `text'. The first word of text is numbered 1, and the last word of text is numbered $(words text). $(words text) Returns the number of words in `text'. $(firstword names) Returns the first word of `names'. The result is the same as $(word 1,names) $(wildcard pattern) The `pattern' argument is an Amiga OS wildcard pattern. The result is a list of files matching that pattern. NOTE: Wildcards are only supported under Amiga OS 2.0 An example of a generic makefile that can be used to compile a program that depends only upon all of the .c files in the current directory follows: SRCS := $(wildcard #?.c) OBJS := $(subst .c,.o,$(SRCS)) a.out: $(OBJS) $(CC) -o $@ $(CFLAGS) $(OBJS) SPECIAL FUNCTIONS $(foreach var,list,text) (see section 9.4 of the GNU Make manual) This function call is not implemented. A workaround might be to unroll the loop manually. $(origin variable) (see section 9.5 of the GNU Make manual) Not implemented. $(shell command line) (see section 9.6 of the GNU Make manual) This function call is not implemented. A workaround might be to redirect the `command line' standard output into an environment variable and then capture the environment variable's value into a macro for Make to use. PATTERN RULES When no explicit rule is defined for a target, the Make program must use other means to determine how to make the target up to date. Rules of inference are defined by pattern rules. An example of a double pattern rule is: %.o: %.c $(CC) -c $(CFLAGS) -o $@ $< The above suffix rule defines how to make any target with a filename ending in `.o' if there is a corresponding dependent filename that ends in `.c'. The commands associated with a pattern rule are executed if the dependent file is newer than the target file, which matches the pattern. The `%' character matches any number of characters in the target name. Only one such wildcard character may exist per name. There may be only one dependent in a pattern rule (extra dependents given on the line are ignored). The `%' character in the dependency pattern is replaced with the stem (the sequence of characters which were matched by the `%') from the target name. A single pattern rule of the form: %.Z: compress $* is the same as a double pattern rule, except that there is no dependency pattern. As a result, the automatic variable `$<' is not defined in the scope of a single suffix rule. Since there are no dependencies, any target matching a single suffix rule will always be remade; the commands will always be executed. There may be more than one pattern rule applicable per target name. The first matching pattern rule will have priority. If several pattern rules are defined with the same target pattern, then the pattern rule that was defined earlier will have priority over all later definitions. Thus, pattern rules with the same target but different dependencies can be defined in natural prioritized order; the first one defined will be the first one applied to inference rules. However, if a new definition is given that exactly duplicates both the target pattern and the dependency pattern then the new definition will replace the old pattern rule. DIFFERENCES BETWEEN PATTERN RULES AND WILDCARDS The pattern rule `a%b : c%d' is roughly equivalent to $(wildcard a#?b) : $(patsubst a%b,c%d,$@) except that the target pattern `a%b' matches even more leniently than the wildcard `a#?b'. The target pattern would also match the target name `a/y/z/b', whereas a#?b would not. Patterns match strings, while wildcards match the names of actual files in the filesystem. Thus, pattern rules require fewer disk accesses than explicit target rules and wildcards. Pattern rules are used to define implicit rules, while wildcards are used to define explicit target rules. The author is not sure if this is different from GNU Make's interpretation of how pattern rules work. It appears as though GNU Make will only allow a pattern rule to match the file part of a pathname (so `a%c' would match `foobar/abc'). This behaviour seems to be inconsistent with how the patsubst function call works. .SUFFIX RULES To maintain compatibility with older versions of Make, suffix rules can be defined. They are a poor man's style of pattern rules. An example of a double suffix rule is: .c.o: $(CC) -c $(CFLAGS) -o $@ $< .SUFFIXES: .c .o The above suffix rule defines how to make any target with a filename ending in `.o' if there is a corresponding dependent filename that ends in `.c'. The commands associated with a suffix rule are executed if the dependent file is newer than the target file. A suffix rule has no dependencies listed to the right of the colon. If such dependencies exist, then the rule definition is considered to be an ordinary target rule. The .SUFFIXES directive is used to cause the Make program to find all ordinary rules, that can be interpreted as suffix rules matching the suffix arguments. Each suffix rule is transformed into its equivalent pattern rule at this time. PATTERN RULES versus SUFFIX RULES Pattern rules should be used because they are far more flexible than suffix rules. Suffix rules are internally represented by pattern rules anyway, but an extra `.SUFFIXES' directive must be given before a suffix rule is recognized. COMMAND LINES IN RULES Command lines are executed in order of appearance if any dependency is newer than the target. The commands executed for a rule should do something that causes the target's modification date to be updated. The Make program knows nothing about what the command lines mean or do. The command lines are simply passed to the shell for execution. If executing the command line results in an error, then the Make program will terminate. Sometimes it is desirable to ignore the error returned by a command, because failure to execute the command does not affect the successful completion of the Makefile. If this is true then the error returned by a command can be ignored by preceding the command with a `-' character. For example: clean: -delete #?.o Normally, each command is printed (echoed) before execution. Echoing for each command can be disabled by preceding it with a `@' character. This does not affect its execution. The `@' character does not redirect the standard output of the program being executed. Redirection must be stated explicitly. SPECIAL COMMANDS The `cd' command can be used to change the current directory of the Make program. This command is special; it is handled by the Make program itself, instead of being executed by the shell. After the current directory is changed, all subsequent commands which are executed from within Make will inherit the new current directory, until another `cd' command is issued. If no argument is given to `cd' then the original current directory is restored. The original current directory, where the Make program was executed, will be restored before the Make program exits. Conditional commands are also handled internally by the Make program. Refer to the section on CONDITIONAL DIRECTIVES on the behaviour of conditional commands. DEFAULT TARGET RULE Sometimes it might be desirable to define a rule that is only executed when all other rules have failed to make a target up to date. As a last resort, one might wish to simply `touch' the target file, or perform no action at all, and allow the Make to continue. .DEFAULT: command lines If the .DEFAULT target is given no commands (as is the default behaviour) then the Make program will terminate with an error whenever it encounters a target name that cannot be made. BUILTIN RULES By default, the Make program knows several builtin pattern rules. Here is a list of their definitions: %.a: RCS/%.a,v $(CO) -u $@ %.a: % %.c: RCS/%.c,v $(CO) -u $@ %.c: % %.h: RCS/%.h,v $(CO) -u $@ %.h: % %.i: RCS/%.i,v $(CO) -u $@ %.i: % %.o: %.c $(CC) -c $(CFLAGS) -o $@ $< %.o: %.a $(AS) -c $(AFLAGS) -o $@ $< Notice that assembler and C language headers and source files have no dependencies and require no commands to be executed in order to make them up to date. User defined rules should be added to the Makefile if that is not the case. USER DEFINED BUILTIN RULES If the user needs to supplement the internal builtin rules with addition suffix rules and variable definitions, they can be declared in one of two files: `S:builtins.make' or `builtins.make'. If they exist, these two files are read (in the order listed above) before the Makefile by the Make program. All rules and variables in these files may be referenced (or overridden) in the Makefile. CONDITIONAL DIRECTIVES A conditional directive can be used to control which parts of a Makefile are executed, based upon the value assigned to certain variables. The familiar if condition ...true... else ...false... endif syntax is used for this purpose, where `...true...' represents any number of lines which are executed if the condition is true, and `...false...' represents any number of lines which are executed if the condition is false. Each of the three conditional directives must appear as the first word on a line. The `else' directive is optional. The condition may be one of the following: eq(arg1,arg2) true if arg1 is exactly equal to arg2 neq(arg1,arg2) true if arg1 is not equal to arg2 def(variable) true if variable is defined ndef(variable) true if variable is undefined exists(pathname) true if pathname exists in the filesystem nexists(pathname) true if pathname does not exist in the filesystem Nested conditionals are acceptable. There is no way to perform logical AND and logical OR operations within the condition expression, so nested conditionals will have to be used instead to do the same job. Each `if' and `else' must have a matching `endif' directive associated with its conditional construct. The use of conditional directives in a Makefile is vaguely analogous to the use of #if, #else, and #endif preprocessor directives in C source code to control conditional compilation. CONDITIONAL COMMANDS The conditional commands can be used to control the behaviour of the command lines of rules. The syntax is exactly the same as the syntax for conditional directives, except that conditional commands are indented with a tab; they appear in the body of a rule along with other commands. Nesting is supported. Here is a example of where a conditional command might be useful for the checking out RCS files, when the RCS directory is not accessible by the Make program (when knowledge of RCS file organization is private to RCS itself): %.c: if nexists($@) $(CO) -u $@ endif PRAGMA DIRECTIVE Command line arguments for the Make program may be added to a line beginning in `pragma'. For example, pragma +m2048 will set the maximum line length to at least 2048 bytes, if that parameter has not already been set to a higher value. .INCLUDE DIRECTIVE Other Makefiles can be included from a Makefile with the `include' directive (it must appear at the beginning of a line, like any other directive). For example, .INCLUDE submakefile will read in all the rules and macros from a file called `submakefile' and then continue reading the current Makefile. This can be done from the builtins Makefiles as well as any user Makefile. Nesting of includes is allowed; the maximum nesting level is indefinite.