Makefile 简明教程
Why Makefile?
编译源代码文件可能很累,尤其当您必须包含多个源文件并每次编译时都输入编译命令时。Makefile 是简化此任务的解决方案。
Compiling the source code files can be tiring, especially when you have to include several source files and type the compiling command every time you need to compile. Makefiles are the solution to simplify this task.
Makefile 是一种特殊格式的文件,它帮助自动构建和管理项目。
Makefiles are special format files that help build and manage the projects automatically.
例如,假设我们有以下源文件。
For example, let’s assume we have the following source files.
-
main.cpp
-
hello.cpp
-
factorial.cpp
-
functions.h
main.cpp
main.cpp
以下是 main.cpp 源文件的代码 −
The following is the code for main.cpp source file −
#include <iostream>
using namespace std;
#include "functions.h"
int main(){
print_hello();
cout << endl;
cout << "The factorial of 5 is " << factorial(5) << endl;
return 0;
}
hello.cpp
hello.cpp
下面给出的代码为 hello.cpp 源文件 −
The code given below is for hello.cpp source file −
#include <iostream>
using namespace std;
#include "functions.h"
void print_hello(){
cout << "Hello World!";
}
factorial.cpp
factorial.cpp
factorial.cpp 代码如下 −
The code for factorial.cpp is given below −
#include "functions.h"
int factorial(int n){
if(n!=1){
return(n * factorial(n-1));
} else return 1;
}
functions.h
functions.h
fnctions.h 代码如下 −
The following is the code for fnctions.h −
void print_hello();
int factorial(int n);
编译文件并获得可执行文件的简单方法是运行命令 −
The trivial way to compile the files and obtain an executable, is by running the command −
gcc main.cpp hello.cpp factorial.cpp -o hello
此命令生成 hello 二进制文件。在此示例中,我们只有四个文件,并且我们知道函数调用的顺序。因此,键入上述命令并准备最终二进制文件是可行的。
This command generates hello binary. In this example we have only four files and we know the sequence of the function calls. Hence, it is feasible to type the above command and prepare a final binary.
但是,对于拥有数千个源代码文件的较大型项目,维护二进制版本会变得很困难。
However, for a large project where we have thousands of source code files, it becomes difficult to maintain the binary builds.
make 命令允许您管理大型程序或程序组。当您开始编写大型程序时,您会注意到重新编译大型程序所需的时间比重新编译小型程序所需的时间长。此外,您会注意到您通常只处理程序中的一个小部分(例如,一个函数),并且剩余的大部分程序保持不变。
The make command allows you to manage large programs or groups of programs. As you begin to write large programs, you notice that re-compiling large programs takes longer time than re-compiling short programs. Moreover, you notice that you usually only work on a small section of the program ( such as a single function ), and much of the remaining program is unchanged.
在后续部分,我们将了解如何为我们的项目准备 makefile。
In the subsequent section, we see how to prepare a makefile for our project.
Makefile - Macros
make 程序允许您使用类似于变量的宏。宏在 Makefile 中定义为 = 对。以下展示了一个示例:
The make program allows you to use macros, which are similar to variables. Macros are defined in a Makefile as = pairs. An example has been shown below −
MACROS = -me
PSROFF = groff -Tps
DITROFF = groff -Tdvi
CFLAGS = -O -systype bsd43
LIBS = "-lncurses -lm -lsdl"
MYFACE = ":*)"
Special Macros
在目标规则集中发出任何命令之前,会预定义某些特殊宏:
Before issuing any command in a target rule set, there are certain special macros predefined −
-
$@ is the name of the file to be made.
-
$? is the names of the changed dependents.
例如,我们可使用如下规则:
For example, we could use a rule as follows −
hello: main.cpp hello.cpp factorial.cpp
$(CC) $(CFLAGS) $? $(LDFLAGS) -o $@
Alternatively:
hello: main.cpp hello.cpp factorial.cpp
$(CC) $(CFLAGS) $@.cpp $(LDFLAGS) -o $@
在此示例中,$@ 代表 hello,$? 或 $@.cpp 获取所有已更改的源文件。
In this example, $@ represents hello and $? or $@.cpp picks up all the changed source files.
隐式规则中使用了另外两个特殊的宏。它们是−
There are two more special macros used in the implicit rules. They are −
-
$< the name of the related file that caused the action.
-
$* the prefix shared by target and dependent files.
常见的隐式规则是使用 .cpp(源文件)生成 .o(对象)文件。
Common implicit rule is for the construction of .o (object) files out of .cpp (source files).
.cpp.o:
$(CC) $(CFLAGS) -c $<
Alternatively:
.cpp.o:
$(CC) $(CFLAGS) -c $*.c
Conventional Macros
有各种默认宏。您可以通过键入“make -p”来打印默认值来查看它们。大多数都是从它们所用的规则中显而易见的。
There are various default macros. You can see them by typing "make -p" to print out the defaults. Most are pretty obvious from the rules in which they are used.
这些预定义变量,即隐式规则中使用的宏分为两类。它们如下−
These predefined variables, i.e., macros used in implicit rules fall into two classes. They are as follows −
-
Macros that are names of programs (such as CC)
-
Macros that contain arguments of the programs (such as CFLAGS).
以下是 makefile 内置规则中用作程序名称的一些常见变量的表格−
Below is a table of some of the common variables used as names of programs in built-in rules of makefiles −
Sr.No |
Variables & Description |
1 |
AR Archive-maintaining program; default is `ar'. |
2 |
AS Program to compiling assembly files; default is `as'. |
3 |
CC Program to compiling C programs; default is `cc'. |
4 |
CO Program to checking out files from RCS; default is `co'. |
5 |
CXX Program to compiling C programs; default is `g'. |
6 |
CPP Program to running the C preprocessor, with results to standard output; default is `$(CC) -E'. |
7 |
FC Program to compiling or preprocessing Fortran and Ratfor programs; default is `f77'. |
8 |
GET Program to extract a file from SCCS; default is `get'. |
9 |
LEX Program to use to turn Lex grammars into source code; default is `lex'. |
10 |
YACC Program to use to turn Yacc grammars into source code; default is `yacc'. |
11 |
LINT Program to use to run lint on source code; default is `lint'. |
12 |
M2C Program to use to compile Modula-2 source code; default is `m2c'. |
13 |
PC Program for compile Pascal programs; default is `pc'. |
14 |
MAKEINFO Program to convert a Texinfo source file into an Info file; default is `makeinfo'. |
15 |
TEX Program to make TeX dvi files from TeX source; default is `tex'. |
16 |
TEXI2DVI Program to make TeX dvi files from Texinfo source; default is `texi2dvi'. |
17 |
WEAVE Program to translate Web into TeX; default is `weave'. |
18 |
CWEAVE Program to translate C Web into TeX; default is `cweave'. |
19 |
TANGLE Program to translate Web into Pascal; default is `tangle'. |
20 |
CTANGLE Program to translate C Web into C; default is `ctangle'. |
21 |
RM Command to remove a file; default is `rm -f'. |
以下是一个表,列出了变量,它们的取值是对上面程序的额外参数。除非另有说明,否则所有这些变量的默认值为一个空字符串。
Here is a table of variables whose values are additional arguments for the programs above. The default values for all of these is the empty string, unless otherwise noted.
Sr.No. |
Variables & Description |
1 |
ARFLAGS Flags to give the archive-maintaining program; default is `rv'. |
2 |
ASFLAGS Extra flags to give to the assembler when explicitly invoked on a `.s' or `.S' file. |
3 |
CFLAGS Extra flags to give to the C compiler. |
4 |
CXXFLAGS Extra flags to give to the C compiler. |
5 |
COFLAGS Extra flags to give to the RCS co program. |
6 |
CPPFLAGS Extra flags to give to the C preprocessor and programs, which use it (such as C and Fortran compilers). |
7 |
FFLAGS Extra flags to give to the Fortran compiler. |
8 |
GFLAGS Extra flags to give to the SCCS get program. |
9 |
LDFLAGS Extra flags to give to compilers when they are supposed to invoke the linker, `ld'. |
10 |
LFLAGS Extra flags to give to Lex. |
11 |
YFLAGS Extra flags to give to Yacc. |
12 |
PFLAGS Extra flags to give to the Pascal compiler. |
13 |
RFLAGS Extra flags to give to the Fortran compiler for Ratfor programs. |
14 |
LINTFLAGS Extra flags to give to lint. |
NOTE − 使用 -R'' 或
--no-builtin-variables'' 选项,可以取消隐式规则使用的所有变量。
NOTE − You can cancel all variables used by implicit rules with the '-R' or '--no-builtin-variables' option.
您还可以按如下所示在命令行定义宏−
You can also define macros at the command line as shown below −
make CPP = /home/courses/cop4530/spring02
Defining Dependencies in Makefile
最终二进制文件依赖于各种源代码和源头文件是非常常见的。依赖关系很重要,因为它们允许 make 知道任何目标的源代码。考虑以下示例 −
It is very common that a final binary will be dependent on various source code and source header files. Dependencies are important because they let the make Known about the source for any target. Consider the following example −
hello: main.o factorial.o hello.o
$(CC) main.o factorial.o hello.o -o hello
在这里,我们告诉 make hello 依赖于 main.o、factorial.o 和 hello.o 文件。因此,每当这些目标文件中的任何一个发生更改时, make 都会采取措施。
Here, we tell the make that hello is dependent on main.o, factorial.o, and hello.o files. Hence, whenever there is a change in any of these object files, make will take action.
同时,我们需要告诉 make 如何准备 .o 文件。因此,我们还需要定义这些依赖项,如下所示 −
At the same time, we need to tell the make how to prepare .o files. Hence we need to define those dependencies also as follows −
main.o: main.cpp functions.h
$(CC) -c main.cpp
factorial.o: factorial.cpp functions.h
$(CC) -c factorial.cpp
hello.o: hello.cpp functions.h
$(CC) -c hello.cpp
Defining Rules in Makefile
现在我们将学习 Makefile 的规则。
We will now learn the rules for Makefile.
Makefile 目标规则的一般语法为:
The general syntax of a Makefile target rule is −
target [target...] : [dependent ....]
[ command ...]
在以上代码中,括号中的参数是可选的,省略号表示一个或多个。此处,请注意,每个命令前缀的制表符是必需的。
In the above code, the arguments in brackets are optional and ellipsis means one or more. Here, note that the tab to preface each command is required.
下面给出了一个简单的示例,其中您定义了一个规则,以便从另外三个文件制作目标 hello。
A simple example is given below where you define a rule to make your target hello from three other files.
hello: main.o factorial.o hello.o
$(CC) main.o factorial.o hello.o -o hello
NOTE - 在此示例中,您必须提供从源文件制作所有目标文件的规则。
NOTE − In this example, you would have to give rules to make all object files from the source files.
语义非常简单。当您说“make target”时, make 查找适用的目标规则;并且,如果任何依赖项比目标新, make 会一次执行命令(在宏替换之后)。如果任何依赖项必须先制作,那么先发生这种情况(所以您有了递归)。
The semantics is very simple. When you say "make target", the make finds the target rule that applies; and, if any of the dependents are newer than the target, make executes the commands one at a time (after macro substitution). If any dependents have to be made, that happens first (so you have a recursion).
如果任何命令返回失败状态, Make 将终止。在这种情况下将显示以下规则:
Make terminates if any command returns a failure status. The following rule will be shown in such case −
clean:
-rm *.o *~ core paper
Make 忽略以破折号开头的命令行上的返回状态。例如,谁会在乎没有核心文件?
Make ignores the returned status on command lines that begin with a dash. For example, who cares if there is no core file?
Make 在宏替换后会反映命令,向你展示正在发生什么。有时你可能想要关闭它。例如:
Make echoes the commands, after macro substitution to show you what is happening. Sometimes you might want to turn that off. For example −
install:
@echo You must be root to install
人们预计 Makefile 中存在某些目标。你应该首先浏览。然而,合理解释就是所有目标(或仅仅是 make)、install 和 clean 都被找到了。
People have come to expect certain targets in Makefiles. You should always browse first. However, it is reasonable to expect that the targets all (or just make), install, and clean is found.
-
make all − It compiles everything so that you can do local testing before installing applications.
-
make install − It installs applications at right places.
-
make clean − It cleans applications, gets rid of the executables, any temporary files, object files, etc.
Makefile Implicit Rules
该命令是应该在我们使用源代码 x.cpp 构建可执行文件 x 时所有情况下都能起作用的命令。这可以表述为一个隐式规则:
The command is one that ought to work in all cases where we build an executable x out of the source code x.cpp. This can be stated as an implicit rule −
.cpp:
$(CC) $(CFLAGS) $@.cpp $(LDFLAGS) -o $@
此隐式规则说明如何使用 x.c 来制作 x——在 x.c 上运行 cc 并将输出称为 x。这条规则是隐式的,因为没有提及具体目标。它可以在所有情况下使用。
This implicit rule says how to make x out of x.c — run cc on x.c and call the output x. The rule is implicit because no particular target is mentioned. It can be used in all cases.
另一个常见的隐式规则是根据 .cpp(源文件)构造 .o(对象)文件。
Another common implicit rule is for the construction of .o (object) files out of .cpp (source files).
.cpp.o:
$(CC) $(CFLAGS) -c $<
alternatively
.cpp.o:
$(CC) $(CFLAGS) -c $*.cpp
Defining Custom Suffix Rules in Makefile
Make 可以使用 cc -c 针对相应 .c 文件自动创建 .o 文件。 make 中内置这些规则,您可以利用这个优势缩短 Makefile。如果仅在 Makefile 的依赖性行中指示当前目标依赖的 .h 文件, make 会知道已经需要相应的 .c 文件。您不必包含编译器的命令。
Make can automatically create a.o file, using cc -c on the corresponding .c file. These rules are built-in the make, and you can take this advantage to shorten your Makefile. If you indicate just the .h files in the dependency line of the Makefile on which the current target is dependent on, make will know that the corresponding .cfile is already required. You do not have to include the command for the compiler.
这会进一步缩减 Makefile,如下所示 −
This reduces the Makefile further, as shown below −
OBJECTS = main.o hello.o factorial.o
hello: $(OBJECTS)
cc $(OBJECTS) -o hello
hellp.o: functions.h
main.o: functions.h
factorial.o: functions.h
Make 使用一个名为 .SUFFIXES 的特殊目标,允许您定义自己的后缀。例如,请参考下方给出的依赖性行−
Make uses a special target, named .SUFFIXES to allow you to define your own suffixes. For example, refer the dependency line given below −
.SUFFIXES: .foo .bar
它会告知 make 您将使用这些特殊后缀来制定自己的规则。
It informs make that you will be using these special suffixes to make your own rules.
类似于 make 已知如何根据 .c 文件制作 .o 文件,您可按如下方式定义规则 −
Similar to how make already knows how to make a .o file from a .c file, you can define rules in the following manner −
.foo.bar:
tr '[A-Z][a-z]' '[N-Z][A-M][n-z][a-m]' < $< > $@
.c.o:
$(CC) $(CFLAGS) -c $<
第一条规则允许根据 .foo 文件创作 .bar 文件。它基本上会打乱该文件。第二条规则是 make 用来根据 .c 文件制作 .o 文件的默认规则。
The first rule allows you to create a .bar file from a .foo file. It basically scrambles the file. The second rule is the default rule used by make to create a .o file from a .c file.
Makefile - Directives
有许多不同形式的指令可用。系统上的 make 程序可能不支持所有指令。因此,请查看你的 make 是否支持我们在此处说明的指令。 GNU make 支持这些指令。
There are numerous directives available in various forms. The make program on your system may not support all the directives. So please check if your make supports the directives we are explaining here. GNU make supports these directives.
Conditional Directives
条件性指令为:
The conditional directives are −
-
The ifeq directive begins the conditional, and specifies the condition. It contains two arguments, separated by a comma and surrounded by parentheses. Variable substitution is performed on both arguments and then they are compared. The lines of the makefile following the ifeq are obeyed if the two arguments match; otherwise they are ignored.
-
The ifneq directive begins the conditional, and specifies the condition. It contains two arguments, separated by a comma and surrounded by parentheses. Variable substitution is performed on both arguments and then they are compared. The lines of the makefile following the ifneq are obeyed if the two arguments do not match; otherwise they are ignored.
-
The ifdef directive begins the conditional, and specifies the condition. It contains single argument. If the given argument is true then condition becomes true.
-
The ifndef directive begins the conditional, and specifies the condition. It contains single argument. If the given argument is false then condition becomes true.
-
The else directive causes the following lines to be obeyed if the previous conditional failed. In the example above this means the second alternative linking command is used whenever the first alternative is not used. It is optional to have an else in a conditional.
-
The endif directive ends the conditional. Every conditional must end with an endif.
Syntax of Conditionals Directives
不带 else 的简单条件的语法如下:
The syntax of a simple conditional with no else is as follows −
conditional-directive
text-if-true
endif
text-if-true 可能为任何文本行,如果条件为真,则被视为 makefile 的一部分。如果条件为假,则不使用任何文本。
The text-if-true may be any lines of text, to be considered as part of the makefile if the condition is true. If the condition is false, no text is used instead.
复杂条件的语法如下:
The syntax of a complex conditional is as follows −
conditional-directive
text-if-true
else
text-if-false
endif
如果条件为真,则使用 text-if-true;否则,使用 text-if-false。text-if-false 可以是任意数量的行文本。
If the condition is true, text-if-true is used; otherwise, text-if-false is used. The text-if-false can be any number of lines of text.
无论条件是简单条件还是复杂条件,条件指令的语法都是相同的。有四种不同的指令来测试各种条件。它们如下所述 −
The syntax of the conditional-directive is the same whether the conditional is simple or complex. There are four different directives that test various conditions. They are as given −
ifeq (arg1, arg2)
ifeq 'arg1' 'arg2'
ifeq "arg1" "arg2"
ifeq "arg1" 'arg2'
ifeq 'arg1' "arg2"
以上条件的反向指令如下 −
Opposite directives of the above conditions are are follows −
ifneq (arg1, arg2)
ifneq 'arg1' 'arg2'
ifneq "arg1" "arg2"
ifneq "arg1" 'arg2'
ifneq 'arg1' "arg2"
The include Directive
include directive 允许 make 挂起对当前 makefile 的读取并读取一个或多个其他 makefile,然后再继续。该指令是 makefile 中的一行,如下所示 −
The include directive allows make to suspend reading the current makefile and read one or more other makefiles before continuing. The directive is a line in the makefile that looks follows −
include filenames...
文件名可以包含 shell 文件名模式。行首允许并忽略额外的空格,但不允许制表符。例如,如果你有三个 .mk
文件,即 a.mk
、b.mk
和 c.mk
,并且 $(bar),那么它会扩展到 bish bash,然后是以下表达式。
The filenames can contain shell file name patterns. Extra spaces are allowed and ignored at the beginning of the line, but a tab is not allowed. For example, if you have three `.mk' files, namely, `a.mk', `b.mk', and `c.mk', and $(bar) then it expands to bish bash, and then the following expression.
include foo *.mk $(bar)
is equivalent to:
include foo a.mk b.mk c.mk bish bash
当 make 处理 include 指令时,它会挂起对 makefile 的读取并依次从每个列出的文件中读取。完成后, make 继续读取出现指令的 makefile。
When the make processes an include directive, it suspends reading of the makefile and reads from each listed file in turn. When that is finished, make resumes reading the makefile in which the directive appears.
The override Directive
如果变量已通过命令参数设置,则忽略 makefile 中的普通赋值。即使变量已通过命令参数设置,你仍希望在 makefile 中设置变量,则可以使用 override 指令,该指令是一行,如下所示−
If a variable has been set with a command argument, then ordinary assignments in the makefile are ignored. If you want to set the variable in the makefile even though it was set with a command argument, you can use an override directive, which is a line that looks follows−
override variable = value
or
override variable := value
Makefile - Recompilation
make 程序是一个智能实用程序,它会根据您对源文件所做的更改进行工作。如果您有四个文件,main.cpp、hello.cpp、factorial.cpp 和 functions.h,那么所有剩余文件都依赖于 functions.h,main.cpp 依赖于 hello.cpp 和 factorial.cpp。因此,如果您对 functions.h 做出任何更改, make 会重新编译所有源文件以生成新的对象文件。但是,如果您对 main.cpp 做出任何更改,由于这不依赖于任何其他文件,所以只重新编译 main.cpp 文件,而不会重新编译 help.cpp 和 factorial.cpp。
The make program is an intelligent utility and works based on the changes you do in your source files. If you have four files main.cpp, hello.cpp, factorial.cpp and functions.h, then all the remaining files are dependent on functions.h, and main.cpp is dependent on both hello.cpp and factorial.cpp. Hence if you make any changes in functions.h, then the make recompiles all the source files to generate new object files. However if you make any change in main.cpp, as this is not dependent of any other file, then only main.cpp file is recompiled, and help.cpp and factorial.cpp are not.
在编译文件时, make 会检查其对象文件并比较时间戳。如果源文件的时间戳比对象文件新,则它会假定源文件已更改,然后生成新的对象文件。
While compiling a file, the make checks its object file and compares the time stamps. If source file has a newer time stamp than the object file, then it generates new object file assuming that the source file has been changed.
Avoiding Recompilation
一个项目可能包含数千个文件。有时,您可能已更改源文件,但未必需要重新编译所有依赖于该源文件的文件。例如,假设您向其他文件依赖的头文件添加宏或声明。 make 会保守地假定头文件的任何更改都需要重新编译所有依赖文件,但您知道它们不需要重新编译,您不愿浪费时间等待它们编译。
There may be a project consisting of thousands of files. Sometimes you may have changed a source file but you may not want to recompile all the files that depend on it. For example, suppose you add a macro or a declaration to a header file, on which the other files depend. Being conservative, make assumes that any change in the header file requires recompilation of all dependent files, but you know that they do not need recompilation and you would rather not waste your time waiting for them to compile.
如果您在更改头文件之前预见到该问题,可以使用 -t
标记。此标记会 make 不运行规则中的命令,而是通过更改目标文件的上次修改日期,将目标标记为最新。您需要遵循此程序−
If you anticipate the problem before changing the header file, you can use the `-t' flag. This flag tells make not to run the commands in the rules, but rather to mark the target up to date by changing its last-modification date. You need to follow this procedure −
-
Use the command `make' to recompile the source files that really need recompilation.
-
Make the changes in the header files.
-
Use the command `make -t' to mark all the object files as up to date. The next time you run make, the changes in the header files do not cause any recompilation.
如果你在某些文件确实需要重新编译时已经更改了头文件,那就太晚了。相反,您可以使用 -o file
标志,它将指定的文件标记为“旧”。这意味着文件本身不会被重制,并且没有任何其他内容会被重制。您需要遵循以下过程:
If you have already changed the header file at a time when some files do need recompilation, it is too late to do this. Instead, you can use the `-o file' flag, which marks a specified file as "old". This means, the file itself will not be remade, and nothing else will be remade on its account. you need to follow this procedure −
-
Recompile the source files that need compilation for reasons independent of the particular header file, with `make -o header file'. If several header files are involved, use a separate `-o' option for each header file.
-
Update all the object files with `make -t'.
Makefile - Other Features
在本章中,我们将研究 Makefile 的其他各种特性。
In this chapter, we shall look into various other features of Makefile.
Recursive Use of Make
递归使用 make 意味着在 makefile 中使用 make 作为命令。当您想要为组成一个较大系统的各个子系统编写单独的 makefile 时,此技术非常有用。例如,假设您有一个名为 subdir
的子目录,它有自己的 makefile,并且您希望包含目录的 makefile 在子目录上运行 make 。您可以通过编写以下代码来实现:
Recursive use of make means using make as a command in a makefile. This technique is useful when you want separate makefiles for various subsystems that compose a larger system. For example, suppose you have a subdirectory named `subdir' which has its own makefile, and you would like the containing directory’s makefile to run make on the subdirectory. You can do it by writing the below code −
subsystem:
cd subdir && $(MAKE)
or, equivalently:
subsystem:
$(MAKE) -C subdir
您可以通过复制此示例来编写递归 make 命令。但是,您需要了解它们如何工作以及原因,以及子 make 如何与顶级 make 发生关联。
You can write recursive make commands just by copying this example. However, you need to know about how they work and why, and how the sub-make relates to the top-level make.
Communicating Variables to a Sub-Make
通过明确请求,可以将顶级 make 的变量值通过环境传递给子 make。这些变量在子 make 中定义为默认值。除非使用 -e
开关,否则不能覆盖子 make makefile 中指定的 makefile。
Variable values of the top-level make can be passed to the sub-make through the environment by explicit request. These variables are defined in the sub-make as defaults. You cannot override what is specified in the makefile used by the sub-make makefile unless you use the `-e' switch.
要传递或导出变量, make 将变量及其值添加到运行每个命令的环境中。子 Makefile 会使用该环境来初始化其变量值的表。
To pass down, or export, a variable, make adds the variable and its value to the environment for running each command. The sub-make, in turn, uses the environment to initialize its table of variable values.
特殊变量 SHELL 和 MAKEFLAGS 始终会导出(除非取消导出)。如果将 MAKEFILES 设置为任何值,则会导出 MAKEFILES。
The special variables SHELL and MAKEFLAGS are always exported (unless you unexport them). MAKEFILES is exported if you set it to anything.
如果要将特定变量导出到子 Makefile,请使用 export 指令,如下所示:
If you want to export specific variables to a sub-make, use the export directive, as shown below −
export variable ...
如果要阻止导出某个变量,请使用 unexport 指令,如下所示
If you want to prevent a variable from being exported, use the unexport directive, as shown below −
unexport variable ...
The Variable MAKEFILES
如果定义环境变量 MAKEFILES, make 会将它的值视为在读取其他 Makefile 之前要读取的附加 Makefile 的名称列表(由空格分隔)。这与 include 指令非常相似:会搜索各种目录查找这些文件。
If the environment variable MAKEFILES is defined, make considers its value as a list of names (separated by white space) of additional makefiles to be read before the others. This works much like the include directive: various directories are searched for those files.
使用 MAKEFILES 的主要目的是在 make 的递归调用之间进行通信。
The main use of MAKEFILES is in communication between recursive invocations of the make.
Including Header file from Different Directories
如果您将头文件放在不同的目录中,并且在不同的目录中运行 make ,则需要提供头文件的路径。这可以通过 Makefile 中的 -I 选项完成。假设 /home/tutorialspoint/header 文件夹中有 functions.h 文件,其余文件都位于 /home/tutorialspoint/src/ 文件夹中,那么 Makefile 将被写成如下形式:
If you have put the header files in different directories and you are running make in a different directory, then it is required to provide the path of header files. This can be done using -I option in makefile. Assuming that functions.h file is available in /home/tutorialspoint/header folder and rest of the files are available in /home/tutorialspoint/src/ folder, then the makefile would be written as follows −
INCLUDES = -I "/home/tutorialspoint/header"
CC = gcc
LIBS = -lm
CFLAGS = -g -Wall
OBJ = main.o factorial.o hello.o
hello: ${OBJ}
${CC} ${CFLAGS} ${INCLUDES} -o $@ ${OBJS} ${LIBS}
.cpp.o:
${CC} ${CFLAGS} ${INCLUDES} -c $<
Appending More Text to Variables
通常,将更多文本添加到已定义变量的值很有用。您可以使用包含 +=
的行来完成此操作,如下所示:
Often it is useful to add more text to the value of a variable already defined. You do this with a line containing `+=', as shown −
objects += another.o
它采用变量 objects 的值,并在其后添加文本 another.o
,前面有一个空格,如下所示。
It takes the value of the variable objects, and adds the text `another.o' to it, preceded by a single space as shown below.
objects = main.o hello.o factorial.o
objects += another.o
上述代码将 objects 设置为 main.o hello.o factorial.o another.o
。
The above code sets objects to `main.o hello.o factorial.o another.o'.
使用 +=
与以下类似:
Using `+=' is similar to:
objects = main.o hello.o factorial.o
objects := $(objects) another.o
Continuation Line in Makefile
如果您不喜欢 Makefile 中过长的行,则可以使用反斜杠 \"
来断行,如下所示:
If you do not like too big lines in your Makefile, then you can break your line using a back-slash "\" as shown below −
OBJ = main.o factorial.o \
hello.o
is equivalent to
OBJ = main.o factorial.o hello.o
Running Makefile from Command Prompt
如果您已准备好名为“Makefile”的 Makefile,则只需在命令提示符处编写 make,它便会运行 Makefile。但是,如果您给 Makefile 指定了任何其他名称,则使用以下命令:
If you have prepared the Makefile with name "Makefile", then simply write make at command prompt and it will run the Makefile file. But if you have given any other name to the Makefile, then use the following command −
make -f your-makefile-name
Makefile - Example
以下是用 Makefile 编译 hello 程序的示例。该程序包含三个文件 main.cpp、factorial.cpp 和 hello.cpp。
This is an example of the Makefile for compiling the hello program. This program consists of three files main.cpp, factorial.cpp and hello.cpp.
# Define required macros here
SHELL = /bin/sh
OBJS = main.o factorial.o hello.o
CFLAG = -Wall -g
CC = gcc
INCLUDE =
LIBS = -lm
hello:${OBJ}
${CC} ${CFLAGS} ${INCLUDES} -o $@ ${OBJS} ${LIBS}
clean:
-rm -f *.o core *.core
.cpp.o:
${CC} ${CFLAGS} ${INCLUDES} -c $<
现在,您可以使用 hello 构建程序 make 。如果您将发出命令 make clean ,则它将删除当前目录中所有可用的目标文件和核心文件。
Now you can build your program hello using the make. If you will issue a command make clean then it removes all the object files and core files available in the current directory.