Write Makefile with Me (vii)

Source: Internet
Author: User

Using variables
————

The variable defined in makefile, like a macro in the C/s + + language, represents a text string that, when executed in makefile, automatically expands as it is used in the original mode. What differs from C + + is that you can change its value in makefile. In makefile, variables can be used in "targets", "dependent targets", "commands", or other parts of makefile.

A variable's life name can contain characters, numbers, underscores (which can be the beginning of a number), but should not contain ":", "#", "=", or null characters (spaces, carriage returns, etc.). Variables are case sensitive, and "foo", "foo", and "foo" are three different variable names. The traditional makefile variable name is all uppercase naming, but I recommend using the case with the variable name, such as: Makeflags. This avoids conflicts with the system's variables, and unexpected things happen.

Some variables are very strange string, such as "$<", "$@" and so on, these are automation variables, I will introduce later.

first, the basis of the variable

A variable needs to be given an initial value when it is declared, and when used, a "$" symbol must precede the variable name, but it is best to include the variable in parentheses "()" or curly braces "{}". If you want to use the real "$" character then you need to use "$$" to represent it.

Variables can be used in many places, such as targets, dependencies, commands, and new variables in a rule. Let's look at one example:

objects = PROGRAM.O foo.o UTILS.O
Program: $ (objects)
Cc-o Program $ (objects)

$ (objects): Defs.h

The variable expands precisely where it is used, like a macro in C + +, such as:

Foo = c
prog.o:prog.$ (foo)
$ (foo) $ (foo)-$ (foo) prog.$ (foo)

To be expanded upon:

Prog.o:prog.c
Cc-c prog.c

Of course, do not do this in your makefile, here is just an example to show that the variable in the makefile in the actual appearance of the use place. It can be seen as an "alternative" principle.

Also, adding parentheses to a variable is all about using this variable in a more secure way, and in the example above, if you don't want to put parentheses in the variable, that's OK, but I strongly recommend that you put parentheses around the variable.


variables in a variable

When defining the value of a variable, we can use other variables to construct the value of the variable, and in makefile there are two ways to define the value of a variable with a variable.

Let's look at the first way, which is simply to use the "=" number, on the left side of "=" is the variable, the right side is the value of the variable, and the value of the right variable can be defined anywhere in the file, that is, the variable in the right side does not have to be a defined value, it can also use the values defined later. Such as:

Foo = $ (bar)
Bar = $ (ugh)
Ugh = Huh?

All
echo $ (foo)

We execute "make all" and the value of the variable $ (foo) will be typed "Huh?" (The value of $ (foo) is $ (bar), the value of $ (bar) is $ (ugh), and the value of $ (ugh) is "Huh?" Is visible, variables can be defined by using subsequent variables.

This feature has good places, there are bad places, the good thing is that we can push the real value of the variable to the back to define, such as:

Cflags = $ (include_dirs)-O
Include_dirs =-ifoo-ibar

When "Cflags" is expanded in the command, it will be "-ifoo-ibar-o". But there is a bad place in this form, and that is the recursive definition, such as:

Cflags = $ (cflags)-O

Or:

A = $ (B)
B = $ (A)

This will allow make to go into the infinite variable expansion process, of course, our make is able to detect such a definition, and will be an error. Also, if you use a function in a variable, this way it makes our make run very slow and, worse, he uses the function "wildcard" and "shell" with two make to have unpredictable errors. Because you never know how many times these two functions will be invoked.

To avoid this approach, we can use another method in make to define a variable with a variable. This method uses the ": =" operator, such as:

x: = foo
Y: = $ (x) bar
x: = Later

It is equivalent to:

Y: = foo bar
x: = Later

It is worth mentioning that this method, the previous variable can not use the following variables, only the previously defined variables. If this is the case:

Y: = $ (x) bar
x: = foo

Then, the value of y is "bar", not "foo bar".

Here are some simpler variables to use, let's take a look at a complex example that includes the function of make, the conditional expression, and the use of a system variable "Makelevel":

Ifeq (0,${makelevel})
Cur-dir: = $ (shell pwd)
WHOAMI: = $ (Shell whoami)
Host-type: = $ (Shell arch)
Make: = ${make} host-type=${host-type} Whoami=${whoami}
endif

About conditional expressions and functions, we'll talk later, for the system variable "makelevel," which means that if our make has a nested action (see "Nested Use Make" earlier), then this variable will record the number of call layers for our current makefile.

Here's another example of what we need to know about two defining variables, so if we're going to define a variable whose value is a space, then we can do this:

NullString: =
Space: = $ (nullstring) # End of the line

NullString is a empty variable with nothing in it, and the value of our spaces is a space. Because it's hard to describe a space on the right side of the operator, the technology used here is very useful, first with a empty variable to indicate the value of the variable began, and the following "#" annotation to indicate the termination of the definition of the variable, so that we can define its value is a space variable. Note here about the use of "#", the feature of the annotation character "#" that deserves our attention if we define a variable like this:

Dir: =/foo/bar # directory to put the frobs in

Dir, the value of this variable is "/foo/bar", followed by 4 spaces, if we use this variable to specify a different directory-"$ (dir)/file" then it's over.

There is also a more useful operator is "? =", first look at the example:

FOO? = Bar

The implication is that if Foo is not defined, then the value of variable foo is "bar", and if Foo was previously defined, then the phrase would do nothing, equivalent to:

Ifeq ($ (Origin FOO), undefined)
FOO = Bar
endif


Iii. advanced usage of variables

This article describes the advanced use of two variables, the first of which is the substitution of variable values.

We can replace a shared part of a variable in the format "$ (var:a=b)" or "${var:a=b}", meaning that all "a" in the variable "var" with "a" string "end" is replaced with a "B" string. The "end" here means "space" or "Terminator".

Let's look at an example:

Foo: = A.O b.o C.O
Bar: = $ (FOO:.O=.C)

In this example, we first define a "$ (foo)" variable, the second line means that all of the ". O" string "End" in "$ (foo)" is replaced with ". C", so our value for "$ (bar)" is "A.C B.C c.c".

Another technique for variable substitution is defined in "static mode" (see previous section), such as:

Foo: = A.O b.o C.O
Bar: = $ (FOO:%.O=%.C)

This relies on the same pattern in the substituted string, which must contain a "%" character, which also makes the value of the $ (bar) variable "A.C B.C c.c".

The second advanced usage is-"Take the value of a variable again as a variable". Let's look at one example:

x = y
y = Z
A: = $ ($ (x))

In this example, the value of $ (x) is "Y", so $ ($ (x)) is $ (y), so the value of $ (a) is "Z". (Note that it is "x=y" instead of "x=$ (y)")

We can also use more layers:

x = y
y = Z
z = u
A: = $ ($ ($ (x)))

The value of $ (a) here is "U", and the relevant deduction is left to the reader to do it himself.

Let's be a little more complicated by using the first way of "using variables in variable definitions" to look at an example:

x = $ (y)
y = Z
z = Hello
A: = $ ($ (x))

The $ ($ (x)) is replaced with $ ($ (y)) because the value of $ (y) is "z", so the end result is: a:=$ (z), which is "Hello".

A little more complicated, we add the function:

x = Variable1
Variable2: = Hello
y = $ (subst 1,2,$ (x))
z = y
A: = $ ($ ($ (z)))

In this example, "$ ($ (Z))" is extended to "$ ($ (Y))" and is again extended to $ ($ (subst 1,2,$ (x))). The value of $ (x) is "Variable1", the SUBST function replaces all the "1" strings in "Variable1" with the "2" string, so "variable1" becomes "variable2" and then its value, so, ultimately, the value of $ (a) is $ ( Variable2) Value--"Hello". (Oh, it's not easy)

In this way, or you can use more than one variable to form the name of a variable, and then take its value:

First_second = Hello
A = the
B = Second
All = $ ($a _$b)

The "$a _$b" here consists of "First_second", so the value of $ (all) is "Hello".

Take another look at the combination of the first technique:

A_objects: = A.O b.o C.O
1_objects: = 1.o 2.o 3.o

Sources: = $ ($ (A1) _OBJECTS:.O=.C)

In this example, if the value of $ (A1) is "A", then the value of $ (sources) is "A.C B.C c.c" and if the value of $ (A1) is "1", then the value of $ (sources) is "1.c 2.c 3.c".

Let's look at an example of this technique and the use of "function" and "conditional statement":

Ifdef do_sort
Func: = sort
Else
Func: = Strip
endif

Bar: = a d b g Q c

Foo: = $ ($ (func) $ (bar))

In this example, if "Do_sort" is defined, so: foo: = $ (sort a d B g Q C), so the value of $ (foo) is "a b c D g Q", and if "do_sort" is not defined, then: foo: = $ (sort a d b g Q c ), the strip function is called.

Of course, the technique of "taking the value of a variable again as a variable" can also be used on the left side of the operator:

DIR = foo
$ (dir) _sources: = $ (Wildcard $ (dir)/*.c)
Define $ (dir) _print
LPR $ ($ (dir) _sources)
Endef

This example defines three variables: "dir", "Foo_sources" and "Foo_print".


Four, append variable value

We can append a value to a variable using the "+ +" operator, such as:

objects = MAIN.O foo.o bar.o utils.o
Objects + + ANOTHER.O

Thus, our $ (objects) value becomes: "MAIN.O foo.o bar.o utils.o another.o" (ANOTHER.O is appended)

Using the "+ +" operator, you can simulate the following example:

objects = MAIN.O foo.o bar.o utils.o
Objects: = $ (objects) ANOTHER.O

The difference is, with "+ +" more concise.

If the variable has not been defined before, then "+ =" Automatically becomes "=", and if the previous variable is defined, then "+ =" inherits the assignment from the previous operation. If the previous time is ": =", then "+ =" will be the ": =" as its assignment, such as:

Variable: = value
Variable + +

Equivalent to:

Variable: = value
Variable: = $ (variable) more

But if this is the case:

Variable = value
Variable + +

Because the last assignment is "=", so "+ +" will also be "=" as an assignment, then will not be the definition of the recurrence of variables, this is very bad, so make will automatically solve the problem for us, we do not have to worry about this problem.


Five, override indicator

If a variable is set on a command-line parameter that is usually make, then the assignment to that variable in makefile is ignored. If you want to set the value of such a parameter in makefile, you can use the "override" designator. Its syntax is:

Override <variable> = <value>

Override <variable>: = <value>

Of course, you can also add:

Override <variable> + <more text>

For multiple-row variable definitions, we use the define indicator, which, before the define indicator, can also use the ovveride indicator, such as:

Override define Foo
Bar
Endef

Original: http://blog.csdn.net/haoel/article/details/2892

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.