|
NAMEmakepp_variables -- How to use variables in makeppDESCRIPTION?: $*, $+, $/, $<, $?, $@, $^, =, !=, &=, +=, :=, ;=, ?=, A: AR, ARFLAGS, AS, C: CC, CFLAGS, "changed_dependencies", changed_inputs, CURDIR, CXX, CXXFLAGS, D: "dependencies", "dependency", F: F77, FC, "foreach", I: input, inputs, L: LD, LEX, LIBTOOL, M: MAKE, MAKECMDGOALS, MAKEFLAGS, MAKEINFO, MAKEPPFLAGS, _MAKEPPFLAGS, MAKEPP_LN_CP, "makepp_percent_subdirs", "makepp_require_phony", "makepp_simple_concatenation", MAKEPP_VERSION, O: "output", "outputs", P: PWD, R: RM, ROOT, S: SHELL, "sorted_dependencies", sorted_inputs, "stem", T: target, targets, V: VPATH, Y: YACCMakefiles 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 many characters, but makepp will probably not be able to grok it if you do anything other than alphanumeric characters, "_", and "-". 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 include statement) or use "global" variables. Variable AssignmentA variable can assume a value in several different ways:
Variables are assigned with one of several assignment expressions, like this X = 1 MODULES := a b c d CC ?= gcc CFLAGS += -Wall define VAR var line 1 var line 2 enddef export PATH := $(PWD):$(PATH) global MYPROJECT.INFO = info to be seen in all makefiles Leading and trailing whitespace around values is always stripped off. The different assignment operators have somewhat different meanings. Simple assignment operators
Multiline variables The "define" statement is the multiline equivalent of the simple statements above. The operator after the variable is optional. If missing, it is equivalent to "define VARIABLE =". The "&=" and "+=" operators are slightly different here, in that they glue this to the old value with a newline, rather than a space. There must not be anything except a comment after the statement, i.e. the value starts on the next line. define VARIABLE := first line of variable's value second line of variable's value third line of variable's value endef override define VARIABLE ... enddef Keywords before "define" can be combinations of either one of "export" or "global" and "override". If you need a variable's value to contain newlines, you must use the "define" statement as shown (or you can assign the value directly in Perl). ("endef" was chosen for compatibility with GNU make. You may also use "enddef".) This is primarily useful for "canned command sequences", e.g., something like this: define COMPILE_C_PROGRAM @&echo "Compiling $(input)" @$(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -c $(input) -o $(output) endef Then you can use this multi-line variable in several rules, like this: %.o : %.c $(COMPILE_C_PROGRAM) $(ARCH)/%.o : $(ARCH)/%.c $(COMPILE_C_PROGRAM) Note that you can often achieve the same effect by using a semicolon instead of a newline, because the shell interprets that as a command delimeter too. For example, COMPILE_C_PROGRAM = @echo "Compiling $(input)"; \ $(CC) $(CFLAGS) $(CPPFLAGS) $(INCLUDES) -c $(input) -o $(output) will have the same effect, except that the semicolon forces Perl to pass it to the shell, instead of executing the command directly and more efficiently. You also have to put each builtin on a line of its own, meaning that you have to switch to the external echo in the semicolon case. There is one speciality when expanding within "define", i.e. "define X :=" or on a variable that was already ":=", "define X &=" and "define X +=". In this case the "$(shell command ...)" or builtin "$(&command ...)" do not get newlines transformed into spaces. Exporting variables to subprocesses export VAR ... export VAR = value override export VAR += value The first form marks the given variables for export to subprocesses, with whatever value the variable then has. The second form, which applies only to one variable, additionally assigns a value right away. All the variants of assignment are allowed. Sharing variables across makefiles global VAR ... global VAR = value override global VAR &= value The first form marks the given variables as global to all makefiles. If any of them already had a value, that value is moved from the makefile local variable to the global one. However if, at the time this statement is seen, any other makefiles already had a value for any of them, then those makefiles will not see the global one. The second form, which applies only to one variable, additionally assigns a value right away. All the variants of assignment are allowed. Note that ":=" will expand right away to the values in the local makefile. On the contrary "=" variables will expand to the values at the point of use. Global variables can be tricky to deal with, because makepp may load makefiles in any order, as the need arises to build some target for which no rule or makefiles is loaded. For this reason it is recommended to have a RootMakeppfile and to explicitly load all others which modify or use the variable with "load-makefile". global GLIBLIBS ;= $(shell pkg-config --libs glib-2.0) Also note that your project may some day be built together with other projects. For this reason it is recommended to always make the project name part of any global variable name. Target-specific assignments target: VARIABLE = string target: VARIABLE := string target: override VARIABLE += string Sets a target-specific value of the variable. A target-specific value is in effect only 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" files will be compiled with optimization ("-O2") except "special_file.c", which is compiled in debug mode ("-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 assignments are taken only from the first 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. Wildcard expansion is performed on the target, so you can do something like this: test_*.o : CFLAGS += -DTEST For compatibility with GNU make, "%" may be used in place of "*". Variable SubstitutionMakepp's variable substitution rules are similar to those of other makes, but somewhat more powerful. As in all makes, "$(CC)" or "${CC}" both represent the value of the variable CC. If you need a literal dollar sign, put in a double dollar sign ($$), like this:target: dep1 dep2 dep3 dep4 &rm -f $(output) for file in $(inputs); do cat $$file >> $(output); done Additionally makepp has a "$[VARIABLE]" syntax, which does the same thing as the other two, but before makepp groks anything else. This allows using it for complete rules and/or conditionals: define bracket_rule = ifdef SOME_VAR bracket: &echo this is a rule -o $(output) endif enddef $[bracket_rule] 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 "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) A variable will give rc-style substitution only when there is more than one word in it. With one word it is like traditional make. Alas, when the variable is empty, there is a conflict. Traditional makes simply expand it to the empty string. But when you think of it as a list, you'd want "-I$(DIRLIST)" to disapear, not to give a lonely "-I". The solution is to wrap it into a list that starts with a space: "-I$( $(DIRLIST))" gives you exactly as many options, as there are words in the list. 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 by setting the variable "makepp_simple_concatenation=1". You can turn it off globally on the command line or as an environment variable. Or on a per-makefile basis by setting the variable 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 "makepp_simple_concatenation" as early as possible.) You can even set it just for one target: target: makepp_simple_concatenation = 1 target: &echo before_first$(LIST)after_last -o $(output) Because "$[VARIABLE]" is evaluated earlier than "$(VARIABLE)", combining the two in rc-substitution will not give the result you may expect: A = a b N = 1 2 X := $(A)$[N] The last line gets read as X := $(A)1 2 which gives "X" a value of "a1 b1 2". 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 fot the "patsubst" function. Whitespace in variables If you need to control the whitespace in a variable, you must (currently) disable rc-style substitution (by setting "makepp_simple_concatenation=1") and then use a syntax like this: null = T = -o $(null) or, with an empty evaluation: T = -o $() When you do this, the variable "T" contains "-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. 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 "perl_begin" or "sub" statements), or to handle it in shell statements in the actions of rules. These cases typically come up when people attempt to use the same rules for different architectures which do not use typical Unix command syntax. E.g., sometimes one sees things like this in makefiles: ifeq ($(ARCH),weirdarch) O := /OUTPUT= else null := O := -o $(null) endif %.o : %.c $(COMPILER) $(input) $(O)$(output) You can do this with makepp if you really want to, but you will probably find that your makefiles are substantially more readable if you have less complicated variable substitution, e.g., ifeq ($(ARCH),weirdarch) %.o : %.c $(WEIRD_COMPILER) $(input) /OUTPUT=$(output) else %.o : %.c $(CC) -c $(input) -o $(output) endif Whitespace is never allowed in variable names, only in their values. This is different from some make implementations. Automatic VariablesAutomatic 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 happen to 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 $@.)The following is a complete list of all the automatic variables that makepp supports:
Predefined VariablesMakepp predefines a few variables, which you can override:
Variables and PerlVariable values are 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 makepp_extending for details.Accessing global variables from Perl is achieved by prefixing them with the "Mpp::global" package. In fact any variable, not yet present in the current makefile, and which you assign to in this package will from then on be global, as though you had just issued the "global" statement for it. This direct access is however error-prone! The user may have overridden these variables on the command line or through the environment. Some other makefile loaded before this one may have made the variable global or target specific. In these cases you would not find the value of the variable, or when assigning it, might take away its property (equivalent to an "override" modifier, except for target specifics.) With direct access you also bypass the expansion of these variables, if they are of type "=" or ";=". Special variables like "$(CC)" start out as functions, until they are assigned to. So in many cases you won't see their value. For these reasons it is better to let makepp determine the correct value. You can use the "makeperl" variant, in which the variable has been evaluated before the Perl code gets interpreted: makeperl { $$current_value = '$(MAKEFILE_VAR)' } If you need a variable in makefile perl blocks this is achieved via the Perl variable $makefile as follows: perl { $current_value = $makefile->expand_variable( 'MAKE_VAR' ) } Functions always get the makefile object passed in as the second argument $_[1]: sub f_f { $current_value = $_[1]->expand_variable( 'MAKE_VAR' ) } Commands are supposed to be called within a rule action, where the makefile object is accessible via "$Mpp::Subs::rule->{MAKEFILE}": sub c_cmd { $current_value = $Mpp::Subs::rule->{MAKEFILE}->expand_variable( 'MAKE_VAR' ) } AUTHORGary Holt (holt-makepp@gholt.net)POD ERRORSHey! The above document had some coding errors, which are explained below:
Visit the GSP FreeBSD Man Page Interface. |