=head1 NAME makepp_variables -- How to use variables in makepp =head1 DESCRIPTION Makefiles typically use variables in many places. One important reason for using variables is to ensure that information is contained in only one place in the makefile, so that if it changes, there is no danger of the two copies of the information getting out of sync. Variable names are case sensitive. In theory, variable names can be made of any characters, but you will probably confuse the makefile parser if you do anything other than alphanumeric characters, C<_>, and C<->. Each makefile has its own set of variables, and setting a variable in one makefile will have no effect on its value in any other makefile. If you want to have variables set in many makefiles, the best way to do it is to have each of them include a common definitions file (see the L). =head2 Variable Assignment A variable can assume a value in several different ways: =over 4 =item * A variable may be set inside a makefile. There are a number of different ways to do this; see below. =item * A variable's value may be specified on the command line, like this: makepp CFLAGS=-O2 my_program If more than one makefile is loaded, the CFLAGS variable is propagated to all of the makefiles. Variables set on the command line automatically override any setting of the variable in any of the makefiles. =item * If a variable is set in the environment, it can be referenced as a makepp variable. Ordinarily assignments to variables inside a makefile override settings from the environment, but you can change this by using the C<-e> or C<--environment-overrides> command line option. =back =head3 Setting variables inside a makefile Variables are assigned with one of several assignment expressions, like this X = 1 MODULES := a b c d CC ?= gcc CFLAGS += -Wall Leading and trailing whitespace around values is always stripped off. Variable values are always stored as ordinary perl scalars, so you can access them directly from perl code if you need to do any complicated manipulations with them; see L for details. The different assignment operators have somewhat different meanings. =over 4 =item = VARIABLE = text string This is the usual assignment statement that all implementations of make support. The expression on the right hand side is not evaluated until the value of C<$(VARIABLE)> is actually used somewhere. Thus, if you do the following: X = 1 Y = $(X) X = 2 Then C<$(Y)> later in the makefile will evaluate to "2". =item := 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 C<$(Y)> later in the makefile will evaluate to "1" since that's what C<$(X)> was when C<$(Y)> was defined. =item += VARIABLE += expr Appends the string to the previous contents of the variable, separated by a space. If the variable was previously assigned with C<:=>, then the right hand side is evaluated before appending. =item ?= 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. The above assignment is exactly equivalent to ifndef VARIABLE VARIABLE = expr endif =item != VARIABLE != shell command Runs the shell command and sets the variable to contain the command's standard output. This is exactly equivalent to VARIABLE := $(shell command) =back =head3 Target-specific assignments target : VARIABLE = string target : VARIABLE := string target : VARIABLE += string Sets a target-specific value of the variable. A target-specific value is in effect I in an action which produces the given target. This is primarily used for things like this: CFLAGS := -O2 my_prog: file1.o file2.o special_file.o special_file.o : CFLAGS := -g %.o: %.c $(CC) $(CFLAGS) -c $(input) -o $(output) What happens here is that all C<.c> files will be compiled with optimization (C<-O2>) I C, which is compiled in debug mode (C<-g>). This is a convenient way to specify different compilation options for only a few files. Target-specific variable assignments like this apply only to the actions of the rule; they are not in effect when evaluating the targets or the dependencies of a rule. If a rule has more than one target, target-specific variable assignents are taken only from the I target. Also note that makepp's target-specific variables are slightly different from GNU make's in that they only apply to the rule for the one file mentioned, and not to any of its predecessors; see L for details. Wildcard expansion is performed on the target, so you can do something like this: test_*.o : CFLAGS += -DTEST For compatibility with GNU make, C<%> may be used in place of C<*>. =head2 Variable Substitution Makepp's variable substitution rules are similar to those of other makes, but somewhat more powerful. As in all makes, C<$(CC)> or C<${CC}> both represent the value of the variable CC. If you need a literal dollar sign, put in a double dollar sign (C<$$>), like this: target: dep1 dep2 dep3 dep4 $(RM) -f $(output) for file in $(inputs); do cat $$file >> $(output); done =head3 rc-style substitution 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 C is prepended to each word in MODULES, and the suffix C<.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 S>. 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 you put several variables in the same word which expand to arrays of words, rc-style substitution actually takes the cartesian product, so you can do something like this if you want: DIRS = s1 s2 MODULES = a b c SUFFIXES = .o .c FILES := $(DIRS)/$(MODULES)$(SUFFIXES) and FILES will contain the string s1/a.o s1/a.c s1/b.o s1/b.c s1/c.o s1/c.c s2/a.o s2/a.c s2/b.o s2/b.c s2/c.o s2/c.c 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 C<--norc-substitution> command line option. You can also turn it off on a per-makefile basis by setting the variable C 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 C as early as possible.) =head3 Substitution References A substitution reference has the form C<$(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 C<$(object_files)> to S>. The C<%> is a special character matches any arbitrary string. Substitution references are an abbreviation fot the C function. =head3 Whitespace in variables If you need to control the whitespace in a variable, you must (currently) disable rc-style substitution (using the command line option C<--norc-substitution> or by setting C in the makefile) and then use a syntax like this: null = T = -o $(null) When you do this, the variable C contains C<-o> followed by a space. This kind of a technique to handle whitespace is not recommended. If you need variables in your makefile to contain spaces, you should think seriously about what you're doing: you're probably using make for something it wasn't intended. If you need to handle spaces, it is usually much better to put perl code into your makefile to take care of it (using the C or C statements), or to handle it in shell statements in the actions of rules. Whitespace is never allowed in variable names, only in their values. This is different from some make implementations. =head2 Automatic Variables Automatic variables are variables that assume different values depending on which rule they are evaluated in. 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 "C" in your makefile, then C<$(target)> will always expand to C, and will no longer be equivalent to C<$@>.) The following is a complete list of all the automatic variables that makepp supports: =over 4 =item target =item output =item $@ The target of the current rule. Actually, since makepp supports multiple targets for any rule, this is the B target. For example, in the following rule y.tab.c y.tab.h : parser.y $(YACC) $(YFLAGS) $(input) C<$(output)> will contain the value F. =item targets =item outputs All targets of the current rule. Same as C<$(target)> unless there is more than one target. In the above example, C<$(outputs)> will be S. =item dependency =item input =item $E The first explicit dependency of the rule. For example, in this rule %.o : %.c $(CC) $(CFLAGS) -c $(input) -o $(output) C<$(input)> will be the name of the F<.c> file, regardless of what F<.h> files makepp discovers. =item dependencies =item inputs =item $^ All the explicit dependencies of the target, not including F<.h> files discovered by L for includes. For example, in the rule myprog.o : *.o $(CC) $(CFLAGS) $(inputs) -o $(output) C<$(inputs)> will be all the .o files in the directory. =item sorted_dependencies =item sorted_inputs =item $+ All the dependencies of the target, in sorted order, with duplicates removed. Equivalent to S>. =item C<$?> In most make implementations, 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 C<$+>). This variable has no long name because its use is highly discouraged. Ordinarily it is used in commandsd like this: libmine.a : $(MODULES) $(AR) ru $@ $? i.e., F is told to replace only those modules that have changed. Makepp doesn't like this because it means that the command to build the library is different on each build, and makepp cannot guarantee that the builds are correct. In fact, this can often lead to incorrect builds: if you delete a source file, for example, the F<.o> file will still be in the library. It's better to build a library like this: libmine.a : $(MODULES) $(RM) -f $(output) $(AR) cr $(output) $(inputs) because then it is guaranteed that there are no stale modules inside the library. =item stem =item $* The stem in a pattern rule (i.e., whatever the '%' matched). Alternatively, if this is not a pattern rule, returns the file name without the extension (i.e., it's equivalent to S>. This is mostly for backward compatibility. For example, in old versions of make the only way to tell it how to compile any F<.c> file into the corresponding F<.o> file was like this: .c.o: $(CC) $(CFLAGS) -c $*.c -o $*.o This is a lousy way to write the rule. It's much clearer to use GNU-make style pattern rules, like this: %.o : %.c $(CC) $(CFLAGS) -c $(input) -o $(output) =item foreach The current filename from the C clause. C clauses are rarely used, but they are the most general-purpose kind of pattern rule that makepp supports. For example, # # Build .c files with some sort of a special preprocessor: # %.c : %.k $(preprocessor) $(input) > $(output) # # Compile .c files into .o files: # %.o : %.c $(CC) $(CFLAGS) -c $(input) -o $(output) # # Special alternate compilation flags for .c files which are derived # from .k files: # $(foreach:%.k=%.o) : $(foreach:%.k=%.c) : foreach *.k $(CC) $(SPECIAL_K_FLAGS) -c $(input) -o $(output) See the documentation on L for more details and examples. =back =head1 AUTHOR Gary Holt (holt-makepp@gholt.net)