Write Makefile with me (seven)

zhaozj2021-02-08  257

Use variables ----

In Makefile, it is like a macro in the C / C language. He represents a text string. It will automatically start the original model when it is executed in Makefile. It is different from C / C that you can change its value in makefile. In Makefile, variables can be used in "target", "dependency", "command", or other parts of Makefile.

The name word of the variable can contain characters, numbers, and underscore (can be digital start), but should not contain ":", "#", "=" or empty characters (spaces, Enter, etc.). Variables are sensitive, "foo", "foo", and "foo" are three different variable names. The traditional Makefile variable name is a new name method, but I recommend using a variable name with case, such as: Makeflags. This avoids conflicts with the system's variables, and accidents occur.

Some variables are very strange strings, such as "$ <", "$ @", etc., these are automated variables, I will introduce later.

First, the basis of variables

Variables need to give initial values ​​when they declare, while in use, need to add "$" symbol before the variable name, but it is best to use small brackets "()" or parentheses "{}" gives the variables. If you want to use a real "$" character, you need to use "$$".

Variables can be used in many places, such as "depends", "dependencies", "command", and new variables. First look at an example:

Objects = program.o foo.o utils.o program: $ (bjects) cc -o program $ (Objects)

$ (Objects): Defs.h

Variables are exactly exactly using it, just like the macro in C / C , for example:

Foo = C Prog.O: PROG. $ (FOO) $ (FOO) $ (Foo) PROG. $ (foo)

After you get:

Prog.o: prog.c cc -c prog.c

Of course, don't do this in your makefile, here is just an example to indicate the true look of the variable in the Makefile. It can be seen that it is a "alternative" principle.

In addition, the variable plus parentheses is completely used for more securely using this variable, in the above example, if you don't want to add parentheses, it can, but I still recommend that you add parentheses to the variable.

Second, variables in variables

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

First, look at the first way, that is, the "=" number, "=" is the variable, the right side is the value of the variable, the value of the right variable can be defined anywhere in the file, that is, The variables in the right side are not necessarily a value that has been defined, and it can also use the value of the following definition. Such as:

Foo = $ (bar) bar = $ (ugh) ugh = huh?

All: Echo $ (foo)

We execute "make all" will play the value of the variable $ (foo) is "huh?" ($ (Foo) value is $ (bar), $ (bar) value is $ (UGH), $ (UGH) The value is "huh?") It can be seen that the variable can be defined using the rear variables. This feature has a good place, and there is a bad place. Well, we can push the true value of the variable to the back to define, such as:

CFLAGS = $ (include_dirs) -o incrude_dirs = -ifoo -ibar

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

Cflags = $ (cflags) -o

or:

A = $ (b) b = $ (a)

This will let Make fall into the unlimited variable expansion process, of course, our make is the ability to detect such definitions and will report an error. There is also if you use a function in a variable, then this way makes our maket time very slow, worse, he will use two Make functions "Wildcard" and "shell" unpredictable error. Because you won't know how many times the two functions will be called.

To avoid this method, we can use another variable to define variables in another variable. This method is used ": =" 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 cannot use the rear variable, and can only use the previously defined variables. if so:

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

Then, the value of Y is "bar" instead of "foo bar".

The above is a relatively simple variable is used, let us look at a complex example, including the use of Make functions, conditional expressions and a system variable "MakeElevel":

Ifeq (0, $ {MakeElevel}) 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 will say later, for system variable "MakeElevel", it means that if our make has a nested action (see "Nesting Make" in front of "Nesting Make"), then this variable Will record our current Makefile call layers.

Let's introduce two definition variables, please see an example, if we want to define a variable, its value is a space, then we can come:

nullstring: = Space: = $ (nullstring) # end of the line

nullstring is an EMPTY variable, where there is no, and our space is a space. Because it is difficult to describe a space on the right side of the operator, the technique used here is used, first using an EMPTY variable to indicate the value of the variable start, and the "#" comment is used to indicate the termination of the variable definition, so We can define the variables of a space. Please note that this characteristic of "#" is worth noting, if we define a variable, if we define a variable: Dir: = / foo / bar # Directory to Put the febs in

The value of the variable of DIR is "/ foo / bar", followed by 4 spaces, if we use this variable to specify other directories - "$ (dir) / file" then finish.

There is also a more useful operator "? =", First see example:

Foo? = Bar

The meaning is that if the foo is not defined, the value of the variable foo is "bar". If Foo is previously defined, then this language will not do anything, its equivalent:

IFEQ ($ (Origin foo), undefined) foo = bar endif

Third, the variable advanced usage

Here, the advanced use of two variables is introduced, the first is the replacement of variable values.

We can replace the common parts in variables, "$ (var: a = b)" or "$ = b)", it means that all of the variables "VAR" "A "" A "" "A" "end" is replaced with "B" string. The "end" here means "space" or "ending".

Still watching an example:

Foo: = a.O B.O C.O bar: = $ (foo: .o = .c)

In this example, we define a "$ (foo) variable, and the second line means all" end "all in" .o "string" "" "" .c " Therefore, our "$ (bar)" is "AC BC CC".

Another variable replacement technology is defined in "static mode" (see the previous chapter), such as:

Foo: = a.O B.O C.O Bar: = $ (foo:%. o =%. c)

This depends on the same mode in the replaced string, and a "%" character must contain a "%" character. This example also allows the value of the $ (bar) variable to "A.c B.C C.C".

The second advanced utility is - "The value of the variable is changed as a variable." First look at an example:

X = y y = z A: = $ ($ (x)))

In this example, the value of $ (x) is "y", so $ ($ (x)) is $ (y), and the value of $ (a) is "Z". (Note, "x = y", not "x = $ (y)")

We can also use more levels:

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

The value of $ (a) here is "U", the relevant derivation leaves the reader to do itself.

Let us be more complicated, use the first way to "use variables in variable definition" to see an example:

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

The $ ($ (x)) is replaced by $ ($ (y)) because the $ (y) value is "Z", so the end result is: A: = $ (z), that is, "Hello ". More complicated, we plus functions:

x = variable1 variable2: = Hello Y = $ (Subst 1, 2, $ (x)) z = y A: = $ ($ (z)))))

In this example, "$ ($ ($ (z)))" Extension is "$ ($ (y)", and it is once again extended to "$ ($ (SUBST 1, 2, $ (x)))))) ". The value of $ (x) is "variable1", the SUBST function replaces all the "1" strings in "variable1" into "2" strings, "Variable1" becomes "variable2", then takes the value, so , Finally, the value of $ (a) is the value of $ (variable2) - "Hello". (Oh, it's hard to be easy)

In this way, or can use multiple variables to form a variable name, and then take its value:

First_second = hello a = first b = second all = $ ($ A_ $ b)

The "$ A_ $ B" here consists of "first_second", so the value of $ (all) is "Hello".

Let's take a look at the example of combining the first technology:

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", the value of $ (Sources) is "AC BC CC"; if the value of $ (a1) is "1", then $ (Sourcees) The value is "1.c 2.c 3.c".

Let's take a look at an example of using this technology and "function" and "conditional statements":

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, then: foo: = $ (sort adbgqc), the value of $ (foo) is "abcdgq", and if "do_sort" is not defined, then: foo: = $ (Sort ADBGQC), calling the Strip function.

Of course, "the value of the variable is changed as a variable", which 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

Three variables are defined in this example: "DIR", "foo_sources" and "foo_print".

Fourth, add variable value

We can use the " =" operator to add value to the variable, 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 noother.o" (ANOTHER.O is added) Use the " =" operator, which can be simulated below This example:

Objects = main.o foo.o bar.o utils.o Objects: = $ (Objects) another.o

The difference is that it is more concise with " =".

If the variable is not defined before, " =" will automatically turn "=", if there is a variable definition in front, " =" will inherit the assassifier of the previous operation. If the previous one is ": =", " =" will assign the value as its ": =", such as:

Variable: = Value Variable = More

Equivalent to:

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

But if this is the case:

Variable = Value Variable = more

Since the previous assignment is "=", " =" will also be assigned as "=", then there will be a credit definition of the variable, which is very bad, so Make will automatically We solve this problem, we don't have to worry about this problem.

V. Override indicator

If there is a variable is usually set, the assignment of this variable will be ignored in the Makefile. If you want to set the value of such parameters in makefile, then you can use the "OVERRIDE" indicator. Its syntax is:

OVERRIDE =

OVERRIDE : =

Of course, you can also add:

OVERRIDE =

For multi-line variable definitions, we use the Define indicator, before the define indicator, you can also use the Ovveride indicator, such as:

Override Define Foo Bar Endef

<- Previous Next -> (All rights reserved, please indicate the author and source)

转载请注明原文地址:https://www.9cbs.com/read-1149.html

New Post(0)