A while ago, I read the makefile variable Writing Method in the linux driver. Some of them are not clear.
Simply want to understand the content of this section. Here, I would like to thank Dragonfly for recommending it to me.
After reading a good article, I hope you will enjoy it.
For the original article, see here:
Http://www.gnu.org/software/make... r/make_6.html # SEC65
If you are bored with English, let me give you a joke first. I did not translate words, but I wrote something that I think is useful.
I. Why use variables?
Variables are used to represent a string in makefile to represent
1. Names of a series of Files
2. parameters passed to the Compiler
3. programs to be run
4. Find the source code directory
5. directory where you need to output information
6. Other things you want to do. [/List: u]
To put it bluntly, some of these are similar to Macros in programming languages.
Ii. Methods and suggestions for defining variables
Variable names are sensitive to the size. In terms of the size, variables in makefile are divided into two types,
One is defined by "=". A foreigner is called "right-hand sides of variable". The other is defined"
The define keyword is defined as bodies of variable. Let's talk about this in detail later.
Traditionally, uppercase letters are used to name variables. However, it is recommended that lower-case letters be used inside makefile.
The name of the variable to be used. Use uppercase letters to define parameters in the implicit rule or allow users
The parameters are redefined.
3. Basic variable reference
$ (Name) or $ {name} is used to reference a variable. Therefore, when you want to represent a $ symbol, you need to use $.
When you use only one letter as the variable name, you can use $ name to reference this variable.
This method is not recommended because it is usually used to reference Automatic Variables ).
Iv. variable definitions in two styles
GNU has two ways to define variables. Their differences are embodied in defining their styles and how they are expanded.
The first class is called the recursive expansion Variable (Recursively Expanded Variable ). Use the = or define keywords
This variable can be defined. If the definition of the variable references other variables, the reference will continue to expand,
Until the latest definition of the referenced variable is found and returned as the value of the change volume. For example:
[Code: 1] foo = $ (bar)
Bar = $ (ugh)
Ugh = Huh? [/Code: 1]
What is the value of $ (foo? $ (Foo) is expanded to $ (bar), $ (bar) is expanded to $ (ugh), and finally $ (ugh)
Expanded to "Huh ?", Then the value of $ (foo) is "Huh ?" This type of variable is supported by all other make tools.
Variable type. It has its own advantages and disadvantages:
Advantages:
It can reference variables backward.
Disadvantages:
1). You cannot extend the variable, for example
CFLAGS = $ (CFLAGS)-O
This will cause infinite loop expansion. All recursive expansion variables are not allowed.
2) if a variable in makefile calls some functions, the function will be called every time the variable is expanded,
Make is a little slower. Worse, some shell functions and the results of repeated calls of wildcards are often
Is unpredictable.
Finally, an example is provided to illustrate the problem above. Use this makefile to try it out. (enable and cancel the third line, respectively,
You can see the result)
[Code: 1] bar = test
Foo = $ (bar)
Bar = $ (ugh)
Ugh = Huh?
All:; echo foo [/code: 1]
To solve these problems, GNU defines another variable of another style, called the simple extension variable (Simply Expanded Variables)
Simple extension variables are defined by the symbol: =. variables defined in this way are defined according to the current value of the referenced variable at the variable definition point.
. Write an example and test it. It is too difficult to express it in text.
[Code: 1] m: = mm
X: = $ (m)
Y: = $ (x) bar
X: = later
All:; echo $ (x) $ (y) [/code: 1]
This method of defining variables is more suitable for large programming projects, because it is more like our general programming language.
In fact, GNU also made a third extension to the way variables are defined in makefile? = Defines a variable. It means that if the variable has not been defined
Define it, such as FOO? = Am I defined ?, It is equivalent to the following code snippet.
[Code: 1] ifeq ($ (origin FOO), undefined)
FOO = Am I defined?
Endif [/code: 1]
This method can be used to provide users with default options, that is, if the user is not defined, it is provided to the user by default. In addition, it should be noted that the variable
It is also a variable defined as NULl. At this time? = Will no longer work.
Note:
Finally, no matter which style we use to define variables, do not add a random number space after the row that defines the variables, and then write comments,
What we think is different, for example
Ml = magic_linux
And
Ml = magic_linux # My favorite linux distribution
These are two completely different variables. The value of the first ml is magic_linux, and the value of the last ml is 'Magic _ linux ', so unless
You want to define variables with spaces at the end. Otherwise, do not add spaces and comments at the end of the definition variable line.
5. Advanced variable reference methods
There are two methods: 1. Replace the variable reference 2. Calculate the value of the variable (more specifically, the derivation)
First
Definition method: $ (var: a = B) $ {var: a = B}
Meaning: Replace the last subtitle of each word in the value of its variable a with B.
For example:
[Code: 1] foo: = a. o B. o c. o
Bar: = $ (foo:. o =. c)
All:; echo $ (bar) [/code: 1]
The bar value is equal to a. c B. c.
In addition, we can also use bar :=$ (foo: %. o = %. c ).
Second
This is an advanced makefile programming technology. Generally, we seldom use it, but it is not difficult. Let's look at an example first.
[Code: 1] x = y
Y = z
A: = $ (x) [/code: 1]
What is the value of? The answer is z. Because the $ (x) of the inner layer is y, while the $ (y) of the outer layer is z, that is, the value of a is calculated by $ (x ).
It is called the value of a variable. Of course there are many layers of nesting. Please try it yourself. You can also include function calls when referencing nested variables,
For example:
[Code: 1] x = variable1
Variable2: = Hello
Y = $ (subst 1, 2, $ (x ))
Z = y
A: =$ ($ (z) [/code: 1]
Some derivation, the value of a is equal to Hello
Multiple variables can be involved in the entire deduction process. In this way, a variable can have multiple literal values, for example:
[Code: 1] a_dirs: = dira dirb
Nvidirs: = dir1 dir2
A_files: = filea fileb
Program Files: = file1 file2
Ifeq "$ (use_a)" "yes"
A1: =
Else
A1: = 1
Endif
Ifeq "$ (use_dirs)" "yes"
Df: = dirs
Else
Df: = files
Endif
Dirs: = $ (a1) _ $ (df) [/code: 1]
Dirs can have different values based on the values of usa_a and use_dirs.
In addition, the derived variable value can also be used to replace the variable reference, for example:
[Code: 1] a_objects: = a. o B. o c. o
Export objects: = 1.o 2.o 3.o
Sources: = $ (a1) _ objects:. o =. c) [/code: 1]
Source can be equal to a. c B. c. c or 1.c 2.c 3.c according to the a1 value above.
The restriction of embedded variables is that you cannot use function calls as a way to define variables. For example
[Code: 1] ifdef do_sort
Func: = sort
Else
Func: = strip
Endif
Bar: = a d B g q c
Foo: = $ (func) $ (bar) [/code: 1]
What is foo? It is sort a d B g q c or strip a d B g q c, instead of using a d B g q c as the parameter.
Pass to sort or strip
You can also use the derived variable name as the left value of the variable.
[Code: 1] dir = foo
$ (Dir) _ sources: = $ (wildcard $ (dir)/*. c) [/code: 1]
Note that recursive extension variables and nested extension variables should be separated.
6. How to get the value of a Variable
1) override the variable value when you run make, for example, make CFLAGS = '-g-O'
2) assign values to variables using the method described above in makefile
3) The set environment variable can be a variable in makefile.
4) GNU defined automatic variables, see http://www.gnu.org/software/make... make_10.html # SEC111
5) some variables have fixed initial values, see http://www.gnu.org/software/make... make_10.html # SEC106 [/list: u]
7. Add a value for the variable
You can add a new value for a defined variable through + =, for example
[Code: 1] objects = main. o foo. o bar. o utils. o
Objects + = another. o [/code: 1]
It looks like some of the code below is + =
[Code: 1] objects = main. o foo. o bar. o utils. o
Objects: = $ (objects) another. o [/code: 1]
However, they still have these differences.
When a variable has never been defined before, + = is the same as =, it defines a recursive expansion variable. However, when a variable has already been defined, + = is just simple.
To add characters.
If you use: = to define a variable at first, then + = only uses the current value of the variable to add it. This is the same as our intuition, for example:
Variable: = magic _
Variable + = linux
The value of variable is magic_linux.
If we use = to define a variable at first, the behavior of + = will become somewhat odd. It will not expand the variable immediately in the place where + = is used, but will push the expansion work back,
Until it finds the final definition of the variable, this is similar to the act of defining the variable =, but it is not intuitive, for example:
[Code: 1] var = I love
Variable = linux
Var + = $ (variable)
Variable = magic
All:; echo $ (var) [/code: 1]
When you compare var: = I love with the above situation, this difference is obvious. This definition method is used when other variables are referenced in the variable.
Very useful. For example:
[Code: 1] CFLAGS = $ (primary des)-O
...
CFLAGS + =-pg # enable profiling [/code: 1]
Since CFLAGS are recursively extended, make does not extend CFLAGS when processing CFLAGS. Therefore, you only need to define include before using CFLAGS.
It seems that we can use CFLAGS: = $ (CFLAGS)-O to complete the above tasks, but there are still differences between them, which will make CFLAGS a simple extended type change.
If the include parameter is not defined at this time, the entire CFLAGS will become-O-pg, and we want to set the CFLAGS to $ (include)-O-pg with + =, this is obviously
We imagine a gap.
8. Use the override keyword
Generally, if you define a variable using a command line parameter, the definition in makefile will be ignored. If you want to make your definition valid
Use the override keyword as follows:
Override variable = magic or override variable: = magic
In this case, the value specified by the user in the command line will be ignored. If you want to add your own text after the user-specified command line, use the following method
Override variable + = magic
The motivation for using this item is that you can specify options that you want them to use by default. For example:
Override CFLAGS + =-g
9. Use define to define variables
Define can define a variable that represents multiple-line commands, such
[Code: 1] define two-lines
Echo foo
Echo $ (bar)
Endef [/code: 1]
It is equivalent
[Code: 1] two-lines = echo foo; echo $ (bar) [/code: 1]
10. Specify variable values for specific targets
When compiling a specific target file, we can set a special value for the variable, for example:
[Code: 1] prog: CFLAGS =-g
Prog: prog. o foo. o bar. o [/code: 1]
In this dependency, the-g option is added to the compilation parameters when the prog is compiled. You can also use the override keyword.
[Code: 1] prog: override CFLAGS =-g
Prog: prog. o foo. o bar. o [/code: 1]
11. Specify variable values for files of specific styles
We can also specify special compilation parameters for various types of files, such
%. O: CFLAGS =-O
In this way, the-o option is added to all compilation parameters that generate. O.