Makefile Manual (III)

Source: Internet
Author: User
Write command

The command lines in each rule are the same as those in the operating system shell. Make will execute the command one by one in sequence. Each Command must start with a [Tab] key, unless the command is followed by a semicolon after the dependency rule. Spaces or blank lines between command lines are ignored. However, if the space or blank line starts with the tab key, make considers it an empty command.

We may use different shells in UNIX, but the make command is interpreted and executed by the standard shell of "/bin/sh" -- UNIX by default. Unless you specify another shell. In makefile, "#" is a annotator, which is similar to "//" in C/C ++. All subsequent characters of this line are annotated.

1. Display commands

Generally, make will output the command line to be executed to the screen before the command is executed. When we use the "@" character before the command line, this command will not be displayed by make. The most representative example is that we use this function to display some information like the screen. For example:

@ ECHO is compiling the xxx module ......

When make is executed, the "Compiling XXX module..." string is output, but no command is output. If no "@" is displayed, make will output:

ECHO is compiling XXX module ......

Compiling XXX module ......

If the make parameter "-n" or "-- just-print" is included during the make operation, the command is only displayed, but the command is not executed, this function is very helpful for us to debug our makefile and see what the commands we write are like or in what order.

The Make parameter "-s" or "-- slient" indicates that the command is fully forbidden.

Ii. Command Execution

When the dependent target is new to the target, that is, when the target of the rule needs to be updated, make will execute the subsequent command one by one. Note that if you want to apply the result of the previous command to the next command, you should use semicolons to separate the two commands. For example, if your first command is the CD command and you want the second command to be run on the basis of the CD command, you cannot write the two commands on two lines, the two commands should be written on one line and separated by semicolons. For example:

Example 1:

Exec:

CD/home/hchen

PWD

Example 2:

Exec:

CD/home/hchen; pwd

When we execute "make EXEC", the CD in the first example does not work. pwd prints the current makefile directory, and the CD works in the second example, PWD prints "/home/hchen ".

Make generally uses the system shell defined in the environment variable shell to execute commands. By default, it uses the standard UNIX shell --/bin/sh to execute commands. But it is a little special in MS-dos, because there is no shell environment variable in the MS-DOS, of course you can also specify. If you specify a Unix-style directory, make will first find the command interpreter in the path specified by shell. If it cannot be found, it will be searched in the current directory of the current drive letter. If it cannot be found, it will find it in all the paths defined in the PATH environment variable. In ms-dos, if your command interpreter is not found, it will add suffixes such as cmd.exe,. com,. bat, and. Sh to your command interpreter.

Iii. Command Error

After a command is run, make checks the return code of each command. If the command returns success, make executes the next command. When all the commands in the rule are successfully returned, this rule is successfully completed. If a command in a rule has an error (the exit code is not zero), make will terminate the execution of the current rule, which may terminate the execution of all rules.

Sometimes, a command error does not indicate that it is an error. For example, for the mkdir command, we must create a directory. If the directory does not exist, mkdir is successfully executed. Everything is fine. If the directory exists, an error occurs. The reason why we use mkdir is that we must have such a directory, so we do not want mkdir errors to terminate the rule operation.

To do this, ignore command errors, we can add a minus sign "-" (after the tab key) in front of the makefile command line ), it is regarded as successful no matter whether the command is output or not. For example:

Clean:

-Rm-f *. o

Another global method is to add the "-I" or "-- ignore-errors" parameter to make. Therefore, all commands in makefile will ignore the error. If a rule targets ". Ignore", all commands in the rule will ignore the error. These are different levels of methods to prevent Command Errors. You can set them according to your preference.

Another make parameter is "-k" or "-- keep-going". This parameter indicates that if a command in a rule fails, the rule is executed, but other rules are executed.

4. Execute make in a nested way

In some big projects, we place the source files of different modules or different functions in different directories. we can write a makefile for this directory in each directory, this makes our makefile more concise, instead of writing everything in a makefile, which makes it difficult to maintain our makefile, this technology is of great benefit to our module compilation and multipart compilation.

For example, we have a subdirectory named subdir, which has a MAKEFILE file to specify the file compilation rules in this directory. The makefile of the general control can be written as follows:

Subsystem:

CD subdir & $ (make)

It is equivalent:

Subsystem:

$ (Make)-C subdir

The definition of $ (make) macro variable means that our make may need some parameters, so defining it as a variable is more conducive to maintenance. In both examples, the "subdir" directory is first entered, and then the make command is executed.

We call this makefile "Master makefile". the variables of the master makefile can be passed to the lower-level makefile (if you show the Declaration), but will not overwrite the variables defined in the lower-level makefile, unless the "-e" parameter is specified.

If you want to pass the variable to the lower-level makefile, you can use the following declaration:

Export <variable...>

If you do not want some variables to be passed to lower-level makefile, you can declare them as follows:

Unexport <variable...>

For example:

Example 1:

Export variable = Value

It is equivalent:

Variable = Value

Export variable

It is equivalent:

Export variable: = Value

It is equivalent:

Variable: = Value

Export variable

Example 2:

Export variable + = Value

It is equivalent:

Variable + = Value

Export variable

If you want to pass all the variables, you only need one export. You don't need to talk about anything next to it, indicating that all variables are passed.

Note that there are two variables: shell and makeflags. Whether export or not, these variables are always passed to the lower makefile, especially the makefiles variable, it contains the make parameter information. If the make parameter is defined in the upper-layer makefile when we execute the "general control makefile", The makefiles variable will be these parameters, it is passed to the lower-level makefile. This is a system-level environment variable.

But there are several parameters in the make command that are not passed down. They are "-c", "-F ", "-h", "-o", and "-W" (details about makefile parameters will be described later). If you do not want to pass parameters to the lower layer, you can do this:

Subsystem:

CD subdir & $ (make) makeflags =

If you define the environment variable makeflags, you must be sure that the options are used by everyone. If "-T", "-n ", and the "-Q" parameter will lead to unexpected results, and may cause you to panic abnormally.

There is also a useful parameter in "nested execution". "-W" or "-- print-directory" will output some information during the make process, let you see the current working directory. For example, if our lower-level make directory is "/home/hchen/GNU/make" and we use "make-W" for execution, when we enter this directory, we will see:

Make: Entering directory '/home/hchen/GNU/make '.

When you exit the directory after completing the lower-layer make, we will see:

Make: Leaving directory '/home/hchen/GNU/make'

When you use the "-c" parameter to specify the lower makefile of make, "-W" will be automatically opened. If the parameter contains "-s" ("-- slient") or "-- no-print-directory", "-W" is always invalid.

5. Define command packages

If the makefile contains some identical command sequences, we can define a variable for these identical command sequences. The syntax for defining this command sequence starts with "Define" and ends with "endef", for example:

Define run-YACC

YACC $ (firstword $ ^)

Mv y. Tab. C $ @

Endef

Here, "Run-YACC" is the name of the command package. It should not be the same as the variable name in makefile. The two lines in "Define" and "endef" are command sequences. The first command in this command package is to run the YACC program. Because the YACC program always generates the "Y. Tab. c" file, the second command is to change the file name. Let's take a look at this command package in an example.

Foo. C: Foo. Y

$ (Run-YACC)

We can see that to use this command package, we are just like using variables. In the use of this command package, "$ ^" in the Command package "Run-YACC" is "foo. Y "," $ @ "is" foo. C "(for this special variable starting with" $ ", we will introduce it later). When executing the command package, make will execute each command in the Command package independently.

Use Variables

Variables defined in makefile are like Macros in C/C ++. They represent a text string, when executed in makefile, the original mode is automatically expanded in the used place. Unlike C/C ++, you can change the value in makefile. In makefile, variables can be used in "target", "dependency target", "command", or other parts of makefile.

The name of a variable can contain characters, numbers, and underscores (can start with a number), but cannot contain ": "," # "," = ", or an empty character (space, carriage return, etc ). Variables are case sensitive. "foo", "foo", and "foo" are three different variable names. In traditional makefile, variable names are all named in uppercase. However, we recommend that you use a combination of uppercase and lowercase variables, such as makeflags. This avoids conflicts with system variables and unexpected events.

Some variables are very strange strings, such as "$ <" and "$ @". These are automated variables. I will introduce them later.

I. Basics of Variables

When declaring a variable, you need to give the initial value. When using the variable, you need to add the "$" symbol before the variable name, but it is best to use parentheses "() or braces "{}" to include the variable. If you want to use the true "$" character, you need to use "$" to represent it.

Variables can be used in many places, such as the "target", "dependency", "Command" in the rule, and new variables. Let's take a look at an example:

Objects = program. O Foo. O utils. o

Program: $ (objects)

CC-O program $ (objects)

$ (Objects): defs. h

Variables are precisely expanded where they are used, like Macros in C/C ++. For example:

Foo = C

Prog. O: Prog. $ (FOO)

$ (FOO)-$ (FOO) Prog. $ (FOO)

Expand and get:

Prog. O: Prog. c

CC-C Prog. c

Of course, do not do this in your makefile. Here is an example to show how variables in makefile are actually expanded in use. It can be seen that it is an alternative principle.

In addition, brackets are added to variables to make it safer to use them. In the above example, if you do not want to add parentheses to variables, you can also, however, I strongly recommend that you add parentheses to the variables.

2. Variables in Variables

When defining the value of a variable, we can use other variables to construct the value of the variable. There are two methods in makefile to define the value of the variable.

First, let's look at the first method, that is, simply using the "=" sign, on the left side of "=" is the variable, and on the right side is the value of the variable, the value of the variable on the right can be defined in any part of the file. That is to say, the variable on the right is not necessarily a defined value. It can also use the value defined later. For example:

Foo = $ (bar)

Bar = $ (ugh)

Ugh = huh?

ALL:

Echo $ (FOO)

When we execute "make all", the value of the variable $ (FOO) is "huh ?" ($ (FOO) is $ (bar), $ (bar) is $ (ugh), and $ (ugh) is "huh ?") It can be seen that variables can be defined using the following variables.

This feature has both good and bad features. The good thing is that we can push the real value of the variable to the end.

For example:

Cflags = $ (include_dirs)-O

Include_dirs =-ifoo-Ibar

When "cflags" is expanded in the command, it will be "-ifoo-Ibar-o ". But there is also a bad thing about this form, that is, recursive definition, such:

Cflags = $ (cflags)-O

Or:

A = $ (B)

B = $ ()

This will bring make into the infinite variable expansion process. Of course, our make is capable of detecting such a definition and reporting an error. In addition, if a function is used in a variable, this method will slow our make runtime. What's worse, he will use two make functions "wildcard" and "shell" to make unpredictable errors. Because you don't know how many times these two functions will be called.

To avoid this method, we can use another method in make to define variables. This method uses the ": =" operator, for example:

X: = foo

Y: = $ (x) bar

X: = later

It is equivalent:

Y: = Foo bar

X: = later

It is worth mentioning that, in this method, the preceding variables cannot use the following variables, but 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 are some simple variables used. Let's take a look at a complicated example, including the make function, 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

We will talk about conditional expressions and functions later. For the system variable "makelevel", it means, if make has a nested execution action (see the previous "use make nested"), this variable records the number of calls to the current makefile.

Next we need to know about two variables. Let's take a look at an example. If we want to define a variable whose value is a space, we can do this:

Nullstring: =

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

Nullstring is an empty variable with nothing in it, and our space value is a space. It is difficult to describe a space on the right side of the operator. The technology used here is very useful. First, use an empty variable to indicate the value of the variable, the "#" annotator is used later to indicate the termination of variable definition. In this way, we can define a variable whose value is a space. Please note that the usage of "#" here is worth noting for the feature of the annotator "#". If we define a variable like this:

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

The value of the Dir variable is "/Foo/bar", followed by four spaces. If we use this variable to specify another directory -- "$ (DIR) /file.

Another useful operator is "? = ", First look at the example:

Foo? = Bar

The meaning is that if Foo has not been defined, the value of the variable foo is bar. If Foo has been previously defined, then this language will do nothing, which is equivalent:

Ifeq ($ (origin Foo), undefined)

Foo = bar

Endif

Iii. Advanced variable usage

This section describes the advanced usage of the two variables. The first is the replacement of the variable value.

We can replace the common parts of the variable in the format of "$ (VaR: A = B)" or "$ {var: a = B}", which means, replace all "a" in the variable "var" with "B" string ending with ". Here the "end" 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, and the second line means to put all the values in "$ (FOO)" as ". O "string" end "is replaced with". C ", so the value of" $ (bar) "is". c B. c. C ".

Another technique for variable replacement is defined as "static mode" (see the previous section), for example:

Foo: = A. o B. O C. O

Bar: = $ (FOO: %. O = %. c)

This relies on the same pattern in the replaced string. The pattern must contain a "%" character. In this example, the value of the $ (bar) variable is also set to ". c B. c. C ".

The second advanced usage is to "treat the value of a variable as a variable ". Let's take a look at an example:

X = y

Y = z

A: =$ ($ (x ))

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

We can also use more layers:

X = y

Y = z

Z = u

A: =$ ($ (X )))

Here, the value of $ (a) is "U". Let the readers do the derivation.

Let's make it more complicated. Let's look at an example using the first method of "using variables in variable definition:

X = $ (y)

Y = z

Z = Hello

A: =$ ($ (x ))

Here $ (x) is replaced with $ (y), because the $ (y) value is "Z", the final result is:: = $ (z), that is, "hello ".

To be more complex, we add the following functions:

X = variable1

Variable2: = Hello

Y = $ (SUBST 1, 2, $ (x ))

Z = y

A: =$ ($ (z )))

In this example, "$ (z)" is extended to "$ (y ))", it is expanded to "$ (SUBST, $ (x)" again )))". The value of $ (X) is "variable1". The SUBST function replaces all "1" strings in "variable1" with "2". Therefore, "variable1" is changed to "variable2 ", then, the value of $ (a) is the value of $ (variable2) -- "hello ". (Oh, It's hard)

In this way, you can use multiple variables to form the name of a variable, and then obtain its value:

First_second = Hello

A = first

B = Second

All = $ ($ A _ $ B)

Here, "$ A _ $ B" forms "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

Export 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 ". c B. c. C "; if the value of $ (A1) is" 1 ", then the value of $ (sources) is" 1.C 2.c 3. C ".

Let's take a look at an example of this technology and the use of "functions" 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 a d B g Q C), then $ (FOO) the value 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 technology of "taking the value of a variable 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

In this example, three variables are defined: "dir", "foo_sources", and "foo_print ".

Iv. append variable values

We can use the "+ =" operator to append a value to the variable, for example:

Objects = Main. O Foo. O Bar. O utils. o

Objects + = another. o

So our $ (objects) value is changed to "Main. O Foo. O Bar. O utils. o another. O" (another. O is appended)

Using the "+ =" operator, we can simulate the following example:

Objects = Main. O Foo. O Bar. O utils. o

Objects: = $ (objects) Another. o

The difference is that "+ =" is more concise.

If the variable has not been defined before, "+ =" is automatically changed to "=". If there is a variable definition before, "+ =" is inherited from the value assignment of the previous operation. If the previous value is ": =", "+ =" uses ": =" as its value assignment, for example:

Variable: = Value

Variable + = more

It is equivalent:

Variable: = Value

Variable: = $ (variable) More

However, in this case:

Variable = Value

Variable + = more

Because the previous value assignment is "=", "+ =" will also use "=" as the value assignment, so it is difficult to implement the progressive population definition of variables, so make will automatically solve this problem for us and we don't have to worry about it.

V. Override indicator

If a variable is set by the command line parameter of make, the value of this variable in makefile is ignored. If you want to set the value of this type of parameter in makefile, you can use the "Override" indicator. Its syntax is:

Override <variable >=< value>

Override <variable >:= <value>

Of course, you can also append:

Override <variable> + = <more text>

For variable definitions of multiple rows, we use the define indicator. We can also use the ovveride indicator before the define indicator, for example:

Override define foo

Bar

Endef

6. multiline Variables

Another way to set the variable value is to use the define keyword. You can use the define keyword to set variable values with line breaks, which helps to define a series of commands (the "command package" technology we mentioned earlier is to use this keyword ).

The define indicator is followed by the variable name, and the variable value is defined in a new line. The definition ends with the endef keyword. It works in the same way as the "=" operator. Variable values can include functions, commands, text, or other variables. Because the command must start with the [Tab] key, if the command variable defined by define does not start with the [Tab] key, make will not regard it as a command.

The following example shows how to use define:

Define two-Lines

Echo foo

Echo $ (bar)

Endef

VII. Environment Variables

The system environment variable during the make operation can be loaded into the MAKEFILE file when make starts running. However, if the makefile has defined this variable, or the variable is imported by the make command line, then the system environment variable value will be overwritten. (If make specifies the "-e" parameter, the system environment variable overwrites the variable defined in makefile)

Therefore, if we set the "cflags" environment variable in the environment variable, we can use this variable in all makefiles. This is of great benefit to the use of unified compilation parameters. If cflags is defined in makefile, this variable in makefile will be used. If no definition is made, the value of the system environment variable will be used, which is a unity of commonality and individuality, it is similar to the features of "global variables" and "local variables.

When you make a nested call (see the previous "nested call" section), the variables defined in the upper makefile are passed to the lower makefile as system environment variables. Of course, by default, only variables set through the command line will be passed. Variables defined in files must be declared using the exprot keyword if they are to be passed to lower-level makefile. (See the previous chapter)

Of course, I do not recommend defining many variables in the system environment. In this way, when we execute makefiles that are not used, some of them have the same set of system variables, this may cause more trouble.

8. target variables

The variables defined in makefile are all "global variables", which can be accessed throughout the file. Of course, except for "automation variables", for example, "$ <" and other types of automation variables belong to "rule variables ", the value of this variable depends on the rule's target and the target's definition.

Of course, I can also set a local variable for a target. This variable is called "target-specific variable" and can have the same name as "global variable, because its scope is only in this rule and associated rules, its value is only valid within the scope. The value of global variables other than the rule chain is not affected.

Its syntax is:

<Target...>: <variable-assignment>

<Target...>: overide <variable-assignment>

<Variable-assignment> can be a variety of value assignment expressions, such as "=", ": =", "+ =", or "? = ". The second syntax is for variables or system environment variables brought in by the make command line.

This feature is very useful. When we set such a variable, it will apply to all the rules caused by this target. For example:

Prog: cflags =-G

Prog: Prog. O Foo. O Bar. o

$ (CC) $ (cflags) Prog. O Foo. O Bar. o

Prog. O: Prog. c

$ (CC) $ (cflags) Prog. c

Foo. O: Foo. c

$ (CC) $ (cflags) Foo. c

Bar. O: bar. c

$ (CC) $ (cflags) bar. c

In this example, no matter what the global $ (cflags) value is. O Foo. O Bar. O rules), $ (cflags) values are "-g ".

9. Mode Variables

In GNU make, pattern-specific variable is also supported. Through the above target variables, we know that variables can be defined on a specific target. The advantage of pattern variables is that we can give a "pattern" to define variables on all targets that conform to this pattern.

We know that the "pattern" of make generally contains at least one "%", so we can define the target variable for all targets ending with [. O] in the following way:

%. O: cflags =-o

Similarly, the syntax of pattern variables is the same as that of "target variables:

<Pattern... >:< variable-assignment>

<Pattern...>: override <variable-assignment>

Override is also for variables passed in the system environment or variables specified by the make command line.

Condition Determination

Conditional judgment allows make to select different execution branches based on different running conditions. Conditional expressions are acceptable.

Is to compare the value of a variable, or compare the value of a variable and a constant.

I. Example

In the following example, determine whether the $ (CC) variable is "GCC". If yes, use the GNU function to compile the target.

Libs_for_gcc =-lgnu

Normal_libs =

Foo: $ (objects)

Ifeq ($ (CC), GCC)

$ (CC)-O Foo $ (objects) $ (libs_for_gcc)

Else

$ (CC)-O Foo $ (objects) $ (normal_libs)

Endif

It can be seen that in the rule in the above example, the target "foo" can select different function libraries based on the variable "$ (CC)" value to compile the program.

From the preceding example, we can see three keywords: ifeq, else, And endif. Ifeq indicates the start of a Condition Statement and specifies a condition expression. The expression contains two parameters separated by commas (,). The expression is enclosed in parentheses. Else indicates that the conditional expression is false. Endif indicates the end of a condition statement. Any condition expression should end with endif.

When the $ (CC) value of our variable is "GCC", the rule for the target foo is:

Foo: $ (objects)

$ (CC)-O Foo $ (objects) $ (libs_for_gcc)

When the value of $ (CC) is not "GCC" (for example, "cc"), the rule for the target foo is:

Foo: $ (objects)

$ (CC)-O Foo $ (objects) $ (normal_libs)

Of course, we can also write the above example more concisely:

Libs_for_gcc =-lgnu

Normal_libs =

Ifeq ($ (CC), GCC)

Libs = $ (libs_for_gcc)

Else

Libs = $ (normal_libs)

Endif

Foo: $ (objects)

$ (CC)-O Foo $ (objects) $ (libs)

Ii. Syntax

The syntax of the conditional expression is:

<Conditional-Directive>

<Text-if-true>

Endif

And:

<Conditional-Directive>

<Text-if-true>

Else

<Text-if-false>

Endif

<Conditional-Directive> indicates the condition keyword, for example, "ifeq ". There are four keywords.

The first one is the "ifeq" we have seen before"

Ifeq (<arg1>, <arg2>)

Ifeq '<arg1> ''<arg2>'

Ifeq "<arg1>" "<arg2>"

Ifeq "<arg1>" '<arg2>'

Ifeq '<arg1>' "<arg2>"

Compare whether the values of "arg1" and "arg2" are the same. Of course, we can also use the make function in parameters. For example:

Ifeq ($ (Strip $ (FOO )),)

<Text-if-empty>

Endif

In this example, the "Strip" function is used. If the returned value of this function is empty, <text-if-empty> takes effect.

The second condition keyword is "ifneq ". Syntax:

Ifneq (<arg1>, <arg2>)

Ifneq '<arg1> ''<arg2>'

Ifneq "<arg1>" "<arg2>"

Ifneq "<arg1>" '<arg2>'

Ifneq '<arg1>' "<arg2>"

The comparison parameters "arg1" and "arg2" have the same values. If they are different, they are true. Similar to "ifeq.

The third condition keyword is "ifdef ". Syntax:

Ifdef <variable-Name>

If the value of variable <variable-Name> is not empty, the expression is true. Otherwise, the expression is false. Of course, <variable-Name> can also be the return value of a function. Note that ifdef only tests whether a variable has a value and does not extend the variable to the current position. Let's look at two examples:

Example 1:

Bar =

Foo = $ (bar)

Ifdef foo

Frobozz = Yes

Else

Frobozz = No

Endif

Example 2:

Foo =

Ifdef foo

Frobozz = Yes

Else

Frobozz = No

Endif

In the first example, the value of "$ (frobozz)" is "yes", and the second value is "no ".

The fourth condition keyword is "ifndef ". Its syntax is:

Ifndef <variable-Name>

I will not say much about this. It is the opposite of "ifdef.

On the <conditional-Directive> line, extra spaces are allowed, but cannot start with the [Tab] Key (otherwise it is considered a command ). The annotator "#" is also safe. The same is true for "else" and "endif", as long as it does not start with the [Tab] key.

Note that make calculates the value of the conditional expression when reading makefile and selects the statement based on the value of the conditional expression, you 'd better not put automation variables (such as "$ @") into conditional expressions, because automation variables are available at runtime.

In addition, to avoid confusion, make does not allow the entire Condition Statement to be divided into two parts and placed in different files.

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.