This is the documentation of version 1.18. You may want the documentation of the stable version (2.0) or of the well tested 2.1 development snapshot or our homepage.

Makepp's makefile syntax

makepp tries to be extremely compatible with GNU make, so almost everything that GNU make supports in its makefile is supported. If you're not familiar with writing makefiles, you'll want to read the tutorial before reading this file.

Every nonblank line in the makefile is either a comment, a variable assignment, part of a rule, a conditional, or a statement.

Variable syntax
Details on assigning values to variables, and using those values elsewhere.
Rule syntax
A rule is what tells makepp the recipe for making a file.
Statement syntax
A statement is any line that begins with a word, such as include or begin_perl.
Makepp supports several different ways of selecting different parts of your makefile to use.
Wildcards in makefiles
Wildcards can be used reliably in rules. Wildcards match either files that currently exist, or files for which there is a build rule.
Filenames with special characters
If your filenames contain spaces or characters like "'\:*%, then makepp may be confused unless you quote them.

Variable assignment syntax

VARIABLE = text string
This is the usual assignment statement that all makes support. The expression on the right hand side is not evaluated until the value of $(VARIABLE) is actually used somewhere. Thus, if you do the following:
X = 1
Y = $(X)
X = 2
Then $(Y) later in the makefile will evaluate to "2".

Leading and trailing whitespace around the text string is stripped. If you need to control the whitespace in a variable, you must (currently) disable rc-style substitution using the --norc-substitution command line option, and then use a syntax like this:

null =
T = -o $(null)

When you do this, the variable T contains -o followed by a space.

VARIABLE := expr
This is the same as "VARIABLE = expr" except that the right hand side is evaluated at the time of the assignment. Thus if
X := 1
Y := $(X)
X := 2
then $(Y) later in the makefile will evaluate to "1" since that's what $(X) was when $(Y) was defined. The same warnings about leading and trailing whitespace apply to this syntax as well.
VARIABLE += expr
Appends the string to the variable. If the variable was previously assigned with :=, then the right hand side is evaluated before appending.
VARIABLE ?= expr
Sets the value of the variable, but only if the variable is not specified earlier in the makefile, on the command line, or in the environment.

Variable substitution

Makepp's variable substitution rules are similar to those of other makes, but somewhat more powerful. $(CC) or ${CC} both represent the value of the variable CC. If you need a literal dollar sign, put in a double dollar sign ($$).

By default, makepp uses rc-style substitution (so called because it was pioneered by the rc shell). This is best illustrated by an example:

MODULES = a b c d

mylib.a : module_dir/$(MODULES).o $(OTHER_OBJECTS)
	$(CXX) $(dependencies) -o $(target)

The prefix module_dir/ is prepended to each word in MODULES, and the suffix .o is appended to each word.

You can also use rc-style substitution without even putting the list of words into a variable; the syntax is $( word1 word2). Note the space between the parenthesis and the first word. So the above example could have been written as:

mylib.a : module_dir/$( a b c d).o $(OTHER_OBJECTS)
	$(CXX) $(dependencies) -o $(target)

If rc-style substitution gets in the way, or if you need to have leading or trailing whitespace in your make variables, then you can turn off rc-style substitution with the --norc-substitution command line option. You can also turn it off on a per-makefile basis by setting the variable rc_substitution=0 in your makefile. You should do this near the top of the makefile, or else you may run into funny situations where rc-style substitution is used for some evaluations and not others. (All expressions evaluated before the assignment will use rc-style substitutions, and all expressions evaluated after will not. Since the time of evaluation of expressions in makefiles is complicated and not always obvious from the order of statements in the makefile, it's best to set rc_substitution as early as possible.)

Makepp also supports substitution references. A substitution reference has the form $(VAR:A=B), where A is a pattern to match and B is a pattern to replace it with. For example:

source_files = a.c b.c c.c d.c
object_files = $(source_files:%.c=%.o)

will set $(object_files) to a.o b.o c.o d.o. The % is a special character matches any arbitrary string. Substitution references are an abbreviation for the patsubst function.

Automatic variables

makepp supports most of the automatic variables that other versions of make use. In addition, it has less cryptic, longer names for most of them that you can use instead. (For legacy makefiles that redefine these names, the definition in the makefile overrides the default meaning. For example, if you say "target = abc" in your makefile, then $(target) will always expand to abc, and will no longer be equivalent to $@.)

$(target) or $(output) or $@
The target of the current rule. Actually, since makepp supports multiple targets for any rule, this is the first target.
$(targets) or $(outputs)
All targets of the current rule. Same as $(target) unless there is more than one target.
$(dependency) or $(input) or $<
The first explicit dependency of the rule.
$(dependencies) or $(inputs) or $^
All the dependencies of the target, not including .h files discovered by scanning for includes.
$(sorted_dependencies) or $(sorted_inputs) or $+
All the dependencies of the target, in sorted order, with duplicates removed. Equivalent to $(sort $(inputs)).
In most make versions, this is the dependencies of the target which have changed. This does not fit into makepp's conceptual framework, because on the next build it will make sure the command is exactly identical to the previous build, or else it considers the file out of date. So makepp attempts to support this variable for backward compatibility by making it equivalent to all dependencies (the same as $+).

This variable has no long name because its use is highly discouraged.

$(stem) or $*
The stem in a pattern rule (i.e., whatever the '%' matched). Alternatively, if this is not a pattern rule, recognizes the file name without the extension (i.e., it's equivalent to $(basename $(input)).
The current filename from the foreach clause. See below for more details on foreach.


Any expression of the format $(name arg1 arg2 arg3) or $(name) where name is not the name of a variable, is interpreted as a function call. The name may contain letters, underscores, or hyphens; to avoid confusion, you may use hyphens or underscores interchangeably, since internally hyphens are converted to underscores. Evaluating such an expression simply invokes a perl subroutine. You can define perl subroutines to do whatever you like. See the sub statement and the section on extending makepp for more details.

makepp has a number of builtin functions which may be useful. It supports almost all of GNU make's textual functions (see GNU make's documentation for details), and some of its own. The most useful functions are:

$(absolute-filename files)
Converts relative filenames into absolutes. For example, $(absolute-filename xyz.c) might return /usr/src/our_project/subdir/xyz.c.
$(basename filenames)
The basename is the entire file name (with the directory), minus the text after the last period. E.g., $(basename myfile/version-1.0-module.c) is myfile/version-1.0-module
$(filter patterns, words)
Returns all words in the list that match the patterns. Patterns may simply be other words, or they may have a % character, which means to match any string at that point.
$(filter-out patterns, words)
Returns all words in the list that do not match the patterns. Patterns may simply be other words, or they may have a % character, which means to match any string at that point.
$(notdir filenames)
Returns the non-directory portion of the filename(s).
$(only-targets filenames)
Returns only those filenames in the list that are actually targets of some rule (either explicit or pattern rules). This can be used for a clean target, for example:

.PHONY: clean

	rm -f $(only_targets *)

Now if you type makepp clean, it will delete everything it knows how to build.

Note that this refers only to files that are known to be targets at the time you invoke only-targets. If only-targets appears in the dependencies or actions of a rule, then all possible targets will be known because dependencies and actions are not evaluated until the rule is executed. If you evaluate try to evaluate it earlier in the makefile with a := variable like this:

ALL_TARGETS := $(only_targets *)

target1: dependency1

target2: dependency2

then only_targets will not know about the subsequent rules.

Similarly, only_targets doesn't know about targets produced in makefiles that are loaded with recursive make. (But you shouldn't be using recursive make anyway; use use the load_makefile statement, or implicit makefile loading instead.)

$(only-nontargets filenames)
Returns only those filenames in the list that are not targets of any rule (either explicit or pattern rules). This can be used for generating a distribution target, for example:

.PHONY: distribution

	mkdir our_product-$(VERSION)
	cp $(filter-out %~, $(only_nontargets *)) our_product-$(VERSION)
	tar cf - our_product-$(VERSION) | gzip -9c > our_product-$(VERSION).tar.gz

In this case, the $(only_nontargets *) returns every file in the current directory that is not a target of some rule. The $(filter-out %~, ...) removes editor backups.

Similar to only-targets (see above), only-nontargets only knows about targets that have been defined already. This is only a problem if you use it to define variables with the := assignment.

$(patsubst pattern, substitute, words)
Performs a substitution on each word in the word list. A % character matches any string. This is best illustrated by an example:
OBJS = $(patsubst %.c, object_dir/%.o, $(C_SOURCES))
takes every file in C_SOURCES and returns the name of an object file in object_dir. Sometimes it is more concise to use a substitution reference, e.g., the above could have been written as

OBJS = $(C_SOURCES:%.c=object_dir/%.o)
$(phony words)
Indicates that the list of words are actually phony targets, and returns the list of targets. It's intended to be used like this:

$(phony all): my_program

$(phony clean):
	rm -f *.o my_program

You can also declare one or more targets as phony with a line like this anywhere in your makefile:

.PHONY: all clean
$(print text)
Outputs the text and returns it. This is mostly useful for debugging, when you don't understand why variable substitution has the result that it does. For example,
XYZ := $(print $(patsubst %.c, %o, $(SOURCE_FILES)))
will print out the result of the patsubst call.
XYZ := $(patsubst %.c, %o, $(print $(SOURCE_FILES)))
will print out the last argument to the patsubst call.

$(shell shell-command)
Returns the output from the given shell command, with newlines replaced by spaces.

makepp also supports many other, less useful functions that GNU make has. See the GNU make documentation for details, because I don't feel like typing it in now. (The only ones it does not support are origin, call, error, and warning.) These are intended mainly to support existing makefiles; it's very easy to write your own functions in perl, or to put perl code to manipulate variables directly in your makefile, so you can do any kind of manipulation even if one of these built-in functions isn't adequate.

Rule syntax

A rule is what tells makepp how to build a file or a class of files. Makepp supports the same rule syntax as other makes, plus some additions of its own.

Explicit rules

target1 target2: dependency1 dependency2 ...
	actions to be performed

This syntax specifies that in order to make either target1 or target2, all the files dependency1, dependency2, etc., must already have been made. Then the given actions are executed by the shell to make the targets. Unlike traditional makes, makepp usually assumes that one invocation of the action makes all of the targets (unless there are no dependencies). For example, one invocation of yacc creates both output files for this rule: : parser.y
	$(YACC) -d parser.y

In some cases, however, makepp will execute the rule actions once for each target, so that old makefiles don't break. This happens if all of the following are true:

For example,

all test install:
	for subdir in $(SUBDIRS); do cd $$subdir && $(MAKE) $@; cd ..; done

is a common idiom in makefiles, and makepp supports it. (Note that you should never use recursive make in any new makefiles you write--use the load_makefile statement, or implicit makefile loading instead).

The list of targets may not contain any automatic variables (except $(foreach)). The dependency list may contain only automatic variables referring to the target ($(output), $(outputs), or their synonymns). The action may contain any automatic variables.

Rule actions

If makepp decides that the rule needs to be reexecuted, each line of the rule is executed sequentially, and if any returns a non-zero status, the remainder are not executed (and makepp aborts with an error unless you specified the -k option on the command line.) Each action should be only one line. If an action is too long to write conveniently on a single line, you can split it into several lines and put a backslash to indicate that the several lines should be combined into one.

In order to distinguish actions from the next rule, the action should be indented more than the line containing the targets and dependencies. Unlike other implementations of make, makepp doesn't really care how much you indent it or whether you use tab characters rather than spaces (since such things are hard to see by looking at the makefile on the screen). To keep backward compatibility, the rules makepp uses to decide when actions end and the next rule begins are somewhat complicated:

As with other implementations of make, the first explicit rule in a file is the default target, and is made if you do not specify any targets on the command line.

It is safe to specify wildcards in the dependency list. Wildcards match not only files that exist, but files which can be created given the rules in the makefile. (See below for more information on wildcards.) For example, to build a library from all .o files in a directory, you could write this:

libmine.a: *.o
	ar ru $(target) $(dependencies)

This will work even if none of the .o files have been created yet.

As usual, the actions must be indented, though (unlike the standard make) makepp doesn't really care how much. The actions are terminated by a line that does not begin with whitespace or a comment.

Normally, each shell command is printed as it is executed. However, if the first word of the action is noecho (or if it begins with the character @), then the command is not printed. For example,

%.o: %.cxx
      noecho $(LIBTOOL) --mode=compile $(CC) -c $(input)

This means that when the libtool command is executed, it is not printed. (Libtool itself usually prints the modified command that it executes, so it's redundant to print it twice.)

Normally, if the shell command returns a non-zero status, then makepp aborts because the command failed. However, some programs incorrectly set the status on exit, or there may be an error which really isn't fatal and shouldn't abort the whole compilation. You can cause makepp to ignore the return status by specifying ignore_error as the first word of the command line (or - as the first character). For example,

$(phony distribution):
	ignore_error rm -r my_program-$(VERSION) # Get rid of previous junk.
	mkdir my_program-$(VERSION)
	cp $(FILES) my_program-$(VERSION)
	tar cf my_program-$(VERSION).tar my_program-$(VERSION)

This command makes a directory, copies a bunch of files into it, and then puts everything into a tar file for distribution. It's a good idea to clean out the previous contents of the directory, if there was anything there previously, and that's what the first line does. The rm might fail, but its return status is ignored.

Pattern rules

A pattern rule is a rule that is applied based on some textual pattern. This is used to apply the same rule to a whole class of files. The syntax is the same as GNU make's pattern rules:

%.o: %.c
	$(CC) -c $(input) -o $(output)

This says that any file which matches *.c can be converted into the corresponding .o file using the given command. (Note that if you specify the command line option --percent-subdirs, then the above rule will also compile .c files in subdirectories as well.)

(If you're used to traditional make, you might not recognize the automatic variables $(input) and $(output). $(input) is a synonymn for $<, and $(output) is a synonymn for $@.)

Note that several pattern dependencies may be supplied. For example, if your xyz.o file depends on the corresponding xyz.cpp file, and also on a file called moc_xyz.cpp, this could be expressed with:

%.o: %.cpp moc_%.cpp
	$(CXX) -c $(inputs) -o $(output)

You may also have several pattern targets. For example, : %.y
	yacc -d $(input)
	mv $(stem).tab.h
	mv $(stem).tab.c

:foreach rules

The above pattern rule syntax is powerful enough to support almost all builds, but occasionally it is necessary to do something more complicated. Makepp provides a more powerful syntax: the :foreach clause for the rule.

target-expression : dependency-expression : foreach file-list

The variable $(foreach) is set in turn to each file matching the file-list, and the target and dependency expressions are evaluated. The file-list may contain wildcards, and these match even files which don't exist yet but which can be built (see the section on wildcards for details).

The above pattern rule can be expressed in this format as follows:

$(patsubst %.c, %.o, $(foreach)) : $(foreach) : foreach *.c
	... shell commands here

(In fact, it's converted to that internally.) This is an unwieldy syntax but it is extremely flexible, because the $(foreach) variable may appear in any way in the expression. For example, if you want to specify to make a .o file from a .cpp file, but only if a corresponding .h file exists, you could do it like this:

$(foreach:%.h=%.o) : $(foreach:%.h=%.cpp) : foreach *.h
	... shell commands here

(This uses the slightly more concise substitution reference syntax rather than calling patsubst explicitly. See the section on variable substitution for details.)

Legacy suffix rules

For backward compatibility, makepp supports the old-style suffix rules.


is equivalent to

%.suffix2: %.suffix1

but much harder to remember.

Conflicting rules

When there is more than one way to make a file, makepp uses a simple procedure to determine which rule to use.

  1. It is an error to have conflicting explicit rules for building a file.
  2. Pattern rules and foreach rules with wildcards never override explicit rules. Thus explicit rules can be used to specify exceptions for pattern rules. (Note that simply using a :foreach clause doesn't make something a pattern rule. It must have a wildcard (like "*" or "?") as part of the filename in the :foreach clause. If it is just an explicit list of files, it is treated as an explicit rule for those files.)

  3. When conflicting pattern rules come from different makefiles, rules from "nearer" makefiles override rules from "farther" makefiles. "Nearer" means that the makefile is located closer to the target in the directory hierarchy (i.e., the file name of the target relative to the directory the makefile is run from is shorter). If this doesn't distinguish the makefiles, then the rule from the makefile which is loaded latest is used.
  4. Pattern rules that have a shorter chain of inference are preferred over other pattern rules. For example, if you had the following rules (based on an example from the linux kernel):
    %.s: %.c
    	$(CC) -s $(input) -o $(output)
    %.o: %.s
    	$(AS) $(input) -o $(output)
    %.o: %.c
    	$(CC) -c $(input) -o $(output)

    If we need to build xyz.o, we could either build the intermediate .s file and then run that through the assembler using the first two rules, or we could go directly to a .o file using the last rule. The last rule is preferred because there are fewer steps in the chain of inference (one instead of two).

  5. Rules later in a makefile override rules that are earlier. (This is backwards from GNU make.) This means that you should put your more general rules earlier, and your more specific rules later. For example,
    %.o: %.c                            # General compilation rule.
    special_%.o: special_%.c            # Special rule for files with a
    	different action            # "special_" prefix.

Rule options

Sometimes it is necessary to supply additional options to modify how makepp executes the rule. These options are specified as :optionname value, either on the line containing the dependencies, or separated on subsequent lines.

Supplying the options on separate lines may make it possible for you to use the same makefile with makepp and a traditional make. For example,

target : dependencies
	: signature target_newer

will work fine with a traditional unix make, because it interprets the : signature line as a shell command, and a command beginning with a colon does nothing.

:signature signature_method

This tells makepp what algorithm to use to determine if the file is out of date. See the section on signature checking for more details. Legal values for this option are exact_match, target_newer, md5, and c_compilation_md5. This overrides any signature method specified with the -m or --signature-method command line options, or with the signature statement.

:scanner name

This tells makepp how to scan for include files. Usually, makepp guess how to do this based on the words in the command itself (see the section on scanning for more details). However, if makepp guesses wrongly, you may want to explicitly indicate the scanner, like this:

	: scanner c_compilation
	action here

This causes makepp to perform the same scanning that it does for C/C++ build commands, even if it doesn't recognize the action as a C compilation.

Legal values for :scanner are (currently):

Don't bother scanning the command or any files at all. Makepp will not know about any dependencies or targets other than those explicitly listed in the rule. This is the default for all commands that makepp does not recognize.

Uses thes scanner for C/C++ compilation, which looks for include files. See the section on scanning for includes for details.

The default scanner depends on the command. If you do not specify a :scanner option, then the first word of the command is examined. If it looks like a compile command, then makepp will use the c_compilation scanner; otherwise it usese the none scanner. For more details on this, or if you want to write your own scanner or change makepp's default scanners, see the section on scanning.

Statement syntax

A statement is any line beginning with a word which does not have a ":" in it. (A colon implies that the line is a rule.) For example, these are statements:

load_makefile subdir

Makepp has a number of builtin statements which you may occasionally need to use. Note that wherever you see an underscore, you may also use a dash, because makepp converts dashes to underscores in statement names.


This inserts the contents of another makefile into the current makefile. It can be useful if you have boilerplate files with a number of rules or variables, and each directory only needs to make a few modifications. The include statement also used to be commonly used in traditional makes in conjunction with automatic include file scanners, but this is no longer necessary with makepp.

include searches the current directory, then the parent of the current directory, then its parent, etc. If it does not find a file of the given name by the time it reaches the top of the directory hierarchy, then it looks in the makepp dadta directory (/usr/local/share/makepp if you installed makepp in /usr/local) for one of the include files that comes with makepp. If you want to include a template file in every makefile in a whole directory hierarchy, you can place your makefile template at the top directory. The makefiles do not have to know exactly where they are in the hierarchy; each makefile can contain a line like this:


instead of something more complicated, like this:

include ../../../  # Is this the right number of ..?

You can specify as many files as you want, and variables are allowed:

include file1 file2 file3 $(other_include_files)

A minor variant on this, the -include statement, includes the file if it exists but doesn't generate a fatal error if it does not. The -include statement used to be important for include file scanning, but is seldom useful for makepp. (Makepp will not try to make the file and then reread it, unlike GNU make.)


load_makefile /some/directory/somewhere/Makefile
load_makefile subdir
load_makefile VAR1=value1 VAR2=value2 subdir

This statement causes makepp to cd to the directory containing the makefile and load its rules into makepp's internal database. If you specify just a directory instead of a makefile, load_makefile looks for Makeppfile, makefile, or Makefile in that directory.

Any variables you specify with the syntax VAR=value (or VAR="value1 value2") are passed to the loaded makefiles. They override any settings in those makefiles, just as if you had typed them on the command line.

Using load_makefile is different from the command

include dir/makefile

in two ways. First, load_makefile does not transfer any variables from the top-level makefile into the subordinate makefile; each makefile exists in its own namespace. The subordinate makefile cannot influence the variables in the top-level makefile in any way.

Second, each build command is tagged with the directory of the makefile that it came from. When makepp executes a rule from a different makefile, it first cd's to the directory containing that makefile before executing the command. Makefiles which are seen with the include statement are actually treated as part of the makefile that included them, and therefore their rules are not tagged with a different directory.

You usually do not have to load a makefile explicitly, unless it has an unusual name, or it has targets which are not contained in the same directory as the makefile itself, or you have disabled implicit makefile loading. By default, if makepp is trying to build a file and doesn't have a rule to build it, or if it is evaluating a wildcarded filename in a directory, it will automatically attempt to load a makefile from that directory. See the section on building with multiple directories for more details.

You cannot use load_makefile to load several makefiles that apply to the same directory. Use include for several pieces of the makefile that apply to the same directory, and load_makefile for makefiles that apply to different directories.


This statement turns off implicit loading of makefiles from a set of directories. This can be useful if you want to load makefiles automatically from most directories, but there are some directories which for various reasons you do not want makepp to attempt to update. (E.g., maybe the directory has a makefile for some other version of make which makepp does not understand.)

Specify a list of directories after the statement, like this:

no_implicit_load dir1 dir2/*

You may use wildcards in the statement. Non-directory files that match the wildcard are ignored.

The above statement will turn off implicit loading for makefiles in dir1 and all of its subdirectories. It will also turn of implicit makefile loading for all subdirectories of dir2 (and all of their subdirectories), but not for dir2 itself.


This statement introduces a block of code which is interpreted verbatim by perl. It can be useful for defining functions, but you can do this more concisely with the sub statement. A block of perl code in your makefile can be useful for several reasons:

The remainder of the line following the perl_begin statement is ignored. All text up until a line that begins at the left margin with perl_end is sent verbatim to the perl interpreter.


repository dirname
repostiory destdir=srcdir

Specifies one or more repository directories. The first repository specified has precedence over the others if the same file exists in multiple repositories and there is no build command for it.

If you specify just a directory after repository, its contents are linked into the current directory. You can link its contents into any arbitrary place in the file system by specifying the location before an equals sign, e.g,

repository subdir1/subdir2=/users/joe/joes_nifty_library


signature exact_match
signature target_newer
signature md5
signature c_compilation_md5
signature default

Overrides the default signature method for all rules following the signature statement. This overrides the signature method specified on the command line with -m or --signature-method, but does not override signature methods specified with the :signature rule modifier.

Specify signature default to return to makepp's default, either the builtin default or the default specified on the command line.

For more information about signature methods, see the section on signature checking.


This statement provides a way to define a perl subroutine inside your makefile. The syntax is identical to that of the perl sub statement, except that the closing brace must be at the left margin.

A perl subroutine is invoked whenever a statement is seen, or when an expression like $(name words) is seen. For example, suppose that for some reason you need to load the contents of a file into a make variable. (You could do this by saying $(shell cat filename) but it's possible to do it without ever invoking the shell.) This can be done by placing the following into your makefile:

sub f_file_contents {
  my ($filename) = @_;		# Name the arguments.
  my $file_contents;
  open FILE, $filename || die "$!\n";
  my $line;
  while (defined($line = <FILE>)) {  # Read another line.
    $file_contents .= $line;
  close FILE;

  return $file_contents;

Now, with this function defined, you can write

X = $(file_contents filename)

and the variable $(X) will contain the contents of the given file.

See the section on extending makepp for more details.


Often it is convenient to do different things in your makefile depending on what architecture you are on, or what set of options you are building with. Makepp supports several ways of doing such conditionals.

ifeq, ifneq, ifdef, and ifndef
These are the conditionals that GNU make supports. Makepp's implementation is completely compatible with GNU make (as far as I know). Later I will update this manual to explain it in more detail, but for the moment, refer to the GNU make manual.
Perl statements in your makefile
Often your conditionals may be complicated or hard to express using equality/inequality of strings. But you can include perl code verbatim in your makefile. You have access to the full power of the perl interpreter. For example:

if ($ARCH =~ /^i[56]86/) {
  $CFLAGS = '-O6 -malign-double';	# On intel machines > 486, there
					# is a substantial speed penalty
					# for doubles that aren't quadword aligned.
} else {
  $CFLAGS = '-O6';


%.o: %.c
	$(CC) $(CFLAGS) -c $(input) -o $(output)

Any make variable can be accessed directly as a perl scalar. In this case, we've set the value of CFLAGS differently based on a regular expression match on the architecture flags.


makepp makes it much safer and more reliable to use wildcards in your makefile. makepp's wildcard expansion returns all existing files that match the wildcard, and all files which do not yet exist but which can be built using the rules. Thus a rule like this:

libmylib.a : *.o
	$(CC) $(inputs) -o $(output)

will do exactly what it should, even if none of the .o files exists in the directory yet. (Of course, if you create extra bogus .o files in the directory, makepp has no way of knowing that you don't want them in mylib.a.) In other versions of make, the *.o wildcard will only return existing object files and so the dependency list will vary depending on what files have been created.

makepp supports all the usual shell wildcards (*, ?, and []). It also has a wildcard ** which matches any number of intervening directories. (This idea was stolen from zsh.) For example, **/*.c matches all the .c files in the entire source tree. objects/**/*.o matches all the .o files contained anywhere in the subdirectory objects or any of its subdirectories or any of their subdirectories. The ** wildcard will not follow soft links to directories.

Special characters in filenames

makepp can support filenames that have special characters in them like a colon or a space. Suppose, for example, you want to create a file called a:thing from the file b:thing. You can't write the rule this way:

a:thing : b:thing
	commands here
because makepp won't know which colons separate targets from dependencies and which are part of the filenames. Instead, simply enclose the name in quotes, like this:

"a:thing" : "b:thing"
	commands here

Now the rule is unambiguous.

makepp's quoting rules are quite similar to the shell's. You can, for example, use single quotes instead of double quotes, or you can escape special characters with a backslash:

a\:thing : 'b:thing'
	commands here

Suppose, for example, that your filename is '"!;\$. Now why you'd want such a filename I don't know, but here are several ways you could specify it to make (and the shell):


Note that (unlike the shell) variables beginning with $ are expanded even inside single quotes. Dollar signs cannot be protected by quotes or backslashes. To get a literal dollar sign, use a double dollar sign.

Generally, you should be able to deal with just about any special character by quoting it in some way. This includes spaces, control characters, etc. However, be aware that at present, makepp's comment stripping is somewhat simplistic, and any # characters preceded by whitespace will be interpreted as comments no matter how they are quoted.

When a target or dependency name is put into an automatic variable like $(target), then the quotes and any backslashes are stripped. This means that if you want to reference the filename in the actions, you will probably have to quote it again, like this:

"a file name with spaces":
	echo "Special contents" > "$@"

If you don't put the quotes around $@, then the shell will see the command

echo "Special contents" > a file name with spaces

which writes the string "Special contents file name with spaces" to the file called a. This is probably not what you want.

Table of contents | Next (command line syntax) | Previous (signature checking)
Last modified: Wed May 16 09:26:50 PDT 2001