Makefile Introduction
When the make command executes, a makefile file is required to tell the make command how to compile and link the program.
First, we use an example to illustrate Makefile's writing rules. In order to give everyone a perceptual knowledge. This example comes from the GNU Make manual, in which we have 8 C files, and 3 header files, and we're going to write a makefile to show how the Make command compiles and links the files. Our Rules are:
1) If the project has not been compiled, then all of our C files are compiled and linked.
2) If a few C files of this project are modified, then we only compile the modified C file and link the target program.
3) If the header file for this project is changed, then we need to compile the C file referencing the header files and link the target program.
As long as our makefile is well written and all of this is done with just one make command, the make command automatically and intelligently determines which files need to be recompiled according to the current file modification, compiling the required files and linking the target program.
the rules of makefile
Before I tell you about this makefile, let's take a cursory look at the rules of Makefile.
Target ...: Prerequisites ... command ....
Target can be either an object file or an executable file, or it can be a label. For labels This feature is described in subsequent "pseudo-target" chapters.
Prerequisites is to generate the desired file or target for that target.
command is what the make needs to execute. (Arbitrary shell Command)
This is a file dependency, that is, target one or more of the destination files depend on the files in the prerequisites, and their generation rules are defined in the command. White point is that if more than one file in the prerequisites is newer than the target file, command-defined commands are executed. This is the rule of makefile. This is the core content of makefile.
At the end of the makefile thing, it seems like my document is over. Oh. Not really, this is Makefile's main line and core, but to write a good makefile is not enough, I will take the back 1.1 points to combine my work experience to you slowly. There's a lot of content. :)
An example
As mentioned earlier, if a project has 3 header files, and 8 C files, our makefile should look like this in order to complete the three rules described earlier.
EDIT:MAIN.O kbd.o command.o display.o insert.o search.o files.o utils.o /* Note: If these. o files are newer than the edit executable file, then the following command is executed * /cc-o edit MAIN.O kbd.o command.o display.o insert.o search.o files.o utils.omain.o:main.c defs.hcc-c main.ckbd.o:kb D.C defs.h command.hcc-c kbd.ccommand.o:command.c defs.h command.hcc-c command.cdisplay.o:display.c defs.h BUFFER.HC C-c display.cinsert.o:insert.c defs.h buffer.hcc-c insert.csearch.o:search.c defs.h buffer.hcc-c SEARCH.CFILES.O: FILES.C defs.h buffer.h command.hcc-c files.cutils.o:utils.c defs.hcc-c utils.cclean:rm edit MAIN.O kbd.o command.o D ISPLAY.O INSERT.O search.o FILES.O UTILS.O
The backslash (\) is the meaning of the line break. This makes the makefile easier to read. We can save this content in a file named "Makefile" or "makefile", and then enter the command "make" directly in the directory to generate the Execute file edit. If you want to delete the execution file and all the intermediate target files, simply execute "make clean".
In this makefile, the target file contains: Execute file Edit and intermediate target file (*.O), and the dependent file (prerequisites) is the. c file and the. h file after the colon. Each of the. o files has a set of dependent files, and these. o files are also dependent files that execute file edit. Dependency is essentially a description of which files are generated by the target file, in other words, which files are updated by the target file.
After defining the dependencies, the subsequent line defines how to generate the operating system commands for the target file, so be sure to start with a TAB key. Remember, make and no matter how the command works, he just executes the defined command. Make compares the modified date of the targets file and the prerequisites file, and if the date of the prerequisites file is newer than the date of the targets file, or target does not exist, then make executes the subsequent defined command.
To illustrate the point is that clean is not a file, it is just an action name, a bit like the C language of lable, its colon after nothing, then make will not automatically find its dependencies, will not automatically execute the commands defined later. To execute subsequent commands (not only for clean, other lable also apply), it is necessary to clearly indicate the name of the lable after the make command. Such a method is very useful, we can in a makefile to define the unused compilation or compiler-independent commands, such as program packaging, program backup, and so on.
how make Works
In the default way, we only enter the Make command. So
- Make will find a file named "Makefile" or "Makefile" in the current directory.
- If found, it will find the first target file in the file (target), in the above example, he will find "edit" This file, and put this file as the final target file.
- If the edit file does not exist, or if the file modification time of the. o file that the edit depends on is newer than the edit file, then he will execute the command defined later to generate the edit file.
- If the. o file that the edit depends on does not exist, then make will look for a dependency on the. o file in the current file, and if found, generates an. o file based on that rule. (This is a bit like a stack of process)
- Of course, your C files and h files are there, so make generates the. o file and then uses the. o file to generate the final task of make, which is to execute the file edit.
This is the dependency of the entire make, which makes a layer-by-layer look at the dependencies of the file until the first target file is finally compiled. In the search process, if there is an error, such as the last dependent file can not be found, then make will directly exit, and error, and for the definition of the command errors, or the compilation is unsuccessful, make does not ignore. Make just file dependencies, that is, if after I find a dependency, the file after the colon is not, then I am sorry, I do not work.
From the above analysis, we know that, like clean, is not directly or indirectly associated with the first target file, then the command defined later will not be automatically executed, but we can explicitly want to make the execution. That is, the command-"make clean", which clears all the target files for re-compilation.
So in our programming, if this project has been compiled, when we modify one of the source files, For example FILE.C, according to our dependence, our target FILE.O will be recompiled (that is, in this dependency on the definition of the command), so FILE.O file is also the latest, so FILE.O file modification time than edit to be new, so Edit will also be re-linked (see the commands defined after the edit target file).
And if we change the "command.h", then the KDB.O, COMMAND.O, and FILES.O will be recompiled and the edit will be re-linked.
using variables in makefile
In the example above, let's take a look at the rules of Edit:
EDIT:MAIN.O kbd.o command.o display.o insert.o search.o files.o utils.occ-o edit main.o kbd.o command.o display.o inser T.O SEARCH.O FILES.O UTILS.O
We can see that the [. O] File string has been repeated two times, and if our project needs to add a new [. o] File, then we need to add in two places (should be three places and a place in clean). Of course, our makefile is not complicated, so we are not tired in two places, but if Makefile becomes complex, then we may forget a place to join and cause compilation to fail. Therefore, in order to makefile easy maintenance, we can use variables in makefile. The makefile variable is also a string, which can be better understood as a macro in the C language.
For example, we declare any variable name, called OBJECTS, OBJECTS, Objs, Objs, obj, or obj, as long as the obj file can be represented. We define this variable at the beginning of the makefile as follows:
objects = MAIN.O kbd.o command.o display.o insert.o search.o files.o UTILS.O
Thus, we can easily use this variable in our makefile in the form of "$ (objects)", so our modified version makefile becomes as follows:
objects = MAIN.O kbd.o command.o display.o insert.o search.o files.o utils.oedit: $ (objects) Cc-o edit $ (objects) MAIN.O: MAIN.C defs.hcc-c main.ckbd.o:kbd.c defs.h command.hcc-c kbd.ccommand.o:command.c defs.h command.hcc-c COMMAND.CDI SPLAY.O:DISPLAY.C defs.h buffer.hcc-c display.cinsert.o:insert.c defs.h buffer.hcc-c insert.csearch.o:search.c def S.h buffer.hcc-c search.cfiles.o:files.c defs.h buffer.h command.hcc-c files.cutils.o:utils.c defs.hcc-c utils.ccle AN:RM Edit $ (objects)
If a new. o file is added, we simply need to modify the variable objects.
More on the topic of variables, I will follow the detailed introduction.
let make automatically deduce
GNU make is very powerful, it can automatically deduce the file and the command behind the file dependencies, so we don't have to write a similar command after each [. o] File, because our make will automatically recognize and deduce the command ourselves.
As soon as make sees a [. o] File, it automatically adds the [. c] File to the dependency, and if makes finds a whatever.o, then WHATEVER.C is the WHATEVER.O dependent file. And Cc-c Whatever.c will also be deduced, so our makefile no longer need to write so complicated. Our new makefile is in the oven again.
objects = MAIN.O kbd.o command.o display.o insert.o search.o files.o utils.o cc = Gccedit: $ (objects) Cc-o Edit $ (objects ) main.o:defs.hkbd.o:defs.h command.hcommand.o:defs.h command.hdisplay.o:defs.h buffer.hinsert.o:defs.h buffer.hs Earch.o:defs.h buffer.hfiles.o:defs.h buffer.h command.hutils.o:defs.h.phony:cleanclean:rm Edit $ (objects)
This method, the "cryptic rule" of make. The contents of the above file, ". Phony "means that clean is a pseudo-target file.
For more detailed "cryptic rules" and "pseudo-target files," I'll give you one by one more in a follow-up.
alternative style of makefile
Since our make can automatically deduce the command, then I see that the pile of [. O] and [. h] Dependencies are a bit uncomfortable, so many repetitive [. h], can you put it together, OK, no problem, this is easy for make, who calls it a function of automatically deriving commands and files? Take a look at the newest style of makefile.
objects = MAIN.O kbd.o command.o display.o insert.o search.o files.o utils.oedit: $ (objects) Cc-o edit $ (objects) $ (object s): DEFS.HKBD.O command.o files.o:command.hdisplay.o insert.o search.o files.o:buffer.h.phony:cleanclean:rm Edit $ (objects)
This style makes our makefile very simple, but our file dependencies seem a bit messy. You can't have your cake and eat it both. I also see your preferences. I do not like this style, one is the document depends on the relationship can not see clearly, and second, if more than one file, to add a few new. o files, it is not clear.
rules for emptying target files
Each makefile should write a rule that clears the target file (. O and Execute file), which is not only easy to recompile, but also helps keep the file clean. This is a "culture" (hehe, remember my "programming accomplishment"). The general style is:
CLEAN:RM Edit $ (objects)
A more robust approach is to:
. Phony:cleanclean:-rm Edit $ (objects)
As I said before. Phony means that clean is a "pseudo-target". and a small minus sign in front of the RM command means that some files may be in trouble, but don't worry, keep doing what's behind. Of course, clean rules do not put in the beginning of the file, otherwise, it will become the default goal of make, I believe that no one is willing to do so. The unwritten rule is that "clean is always at the end of the file."
Above is a makefile of the general picture, is also the basis of makefile, there are many makefile the relevant details, ready? Come when you are ready.
What's in makefile?
Makefile contains five main things: explicit rules, cryptic rules, variable definitions, file instructions, and annotations.
- An explicit rule. Explicit rules describe how to generate one or more target files. This is clearly indicated by the writer of the makefile, to generate the file, the file's dependent file, the generated command.
- Obscure rules. Because our make has an automatic derivation function, the obscure rules allow us to write makefile in a relatively brief way, which is supported by made.
- The definition of the variable. In makefile we want to define a series of variables, which are usually strings, which is a bit like the macro in your C language, and when Makefile is executed, the variables are extended to the corresponding reference positions.
- File instructions. It consists of three parts, one referencing another makefile in one makefile, just like the include in C, and the other is specifying a valid part of makefile based on certain circumstances, just like the precompiled # if in C language And there is a command that defines a multiline. I'll tell you about this part of the story in the next section.
- Comments. In makefile, just the line comment, like the Unix shell script, is annotated with the "#" character, which is like the "//" in C/s + +. If you want to use the "#" character in your makefile, you can escape it with a backslash, for example: "\#".
Finally, it is worth mentioning that the command in makefile must start with the [Tab] key.
filename of the makefile
By default, the make command searches the current directory for files named "Gnumakefile", "Makefile", and "makefile" in the order found to interpret the file. In these three file names, it is best to use the "Makefile" file name, because the first character of this file name is uppercase, so there is a sense of purpose. It is best not to use "Gnumakefile", which is the GNU make recognition. There are other make that are only sensitive to the "makefile" file name in full lowercase, but basically, most of them support both the "makefile" and "makefile" default filenames.
Of course, you can use a different file name to write makefile, such as: "Make.linux", "Make.solaris", "Make.aix", etc., if you want to specify a specific makefile, you can use make "-F" and "--file" parameters , such as: Make-f make.linux or make--file Make.aix.
refer to other makefile
Using the Include keyword in makefile can include other makefile, much like the C # # #, where the contained file is placed in the current file's containing location. The syntax for include is:
Include <filename>;
FileName can be the file mode of the current operating system shell (can include path and wildcard characters)
There can be some empty characters in front of the include, but it must never be the [Tab] key to start. Include and <filename>; can be separated by one or more spaces. For example, you have a few makefile:a.mk, B.mk, C.mk, and a file called Foo.make, and a variable $ (bar) that contains e.mk and F.MK, then the following statement:
Include Foo.make *.mk $ (bar)
Equivalent to:
Include Foo.make a.mk b.mk c.mk e.mk f.mk
When the make command starts, it will look for the other makefile indicated by the include and place its contents in its current position. It's like a C + + # include directive. If the file does not specify an absolute path or a relative path, make will look in the current directory first, and if not found in the current directory, make will also be found in the following several directories:
- If make executes with the "-I" or "--include-dir" parameter, then make will look in the directory specified in this parameter.
- If the directory <prefix>;/include (typically:/usr/local/bin or/usr/include) exists, make will also look for it.
If a file is not found, make generates a warning message, but the fatal error does not occur immediately. It will continue to load other files, and once the makefile has been read, make will retry the files that are not found, or cannot be read, and if not, make will be presented with a fatal message. If you want make to ignore the unreadable files and continue, you can add a minus "-" before the include. Such as:
-include <filename>;
It indicates that no error will continue to occur, regardless of any errors in the include process. The related commands that are compatible with other versions of Make are sinclude, and the effect is the same as this one.
environment variable makefiles
If the environment variable makefiles is defined in your current environment, make makes an action similar to include in the value of this variable. The values in this variable are other makefile, separated by a space. But, unlike include, the makefile "target" introduced from this environment variable will not work, and if the file defined in the environment variable finds an error, make will ignore it.
But here I still recommend not to use this environment variable, because as long as this variable is defined, then when you use make, all the makefile will be affected by it, this is not what you want to see. In this case, just to tell you that there may be times when your makefile appear strange, then you can see if there is any definition of this variable in the current environment.
how make Works
The GNU make works at the following steps: (think of other make also similar)
- Read into all the makefile.
- Read the other makefile that are included.
- Initializes a variable in the file.
- Derive the cryptic rules and analyze all the rules.
- Create a dependency chain for all the target files.
- Depending on the dependencies, decide which targets to regenerate.
- Executes the build command.
1-5 steps for the first stage, and 6-7 for the second stage. In the first stage, if the defined variable is used, make will expand it to the location in use. But make does not start all at once, making uses procrastination tactics, and if a variable appears in a dependency rule, the variable will be expanded within it only if the dependency is determined to be used.
Of course, you don't have to be clear about the way you work, but you'll be more familiar with make when you know it. With this foundation, the following sections are easy to read.
C + + Makefile Advanced mode of work
In this paper, the realization of the universal makefile is given, and the key points are analyzed. The so-called C + + Universal Makefile, you can compile links to all C + + programs, and only a few changes.
Known as omnipotent makefile, Unified Lake. I made some changes to the original makefile. First to uncover its truth:
##################################################### Generic Makefile-Magnum makefile# for compiling and linking C + + Projects on Linux # author:george Foot Modified:jackie lee####################################################### customising## Adjust the following if necessary; Executable is the target# executable ' s filename, and LIBS are a list of libraries to link in# (e.g. Alleg, STDCX, Iostr, et c). You can override these on "s# command line of course" if you prefer to does it that way.# #EXECUTABLE: = Main # executable filename libdir:= # Static Library directory libs: = & nbsp # Static library filename includes:=. # header file directory srcdir:= # In addition to the current directory, other source code files directory # # # now alter any implicit rules ' variables if your like, e.g.:cc:=g++cflags: =-g-wall-o3cppflags: = $ (CFLAGS) Cppflags + = $ (addprefix-i,$ (includes)) Cppflags + =-mmd## # The next bit checks to see WHEther RM is in your DJGPP bin# # directory; If not it uses Del instead, but this can cause (harmless) # # ' File not found ' error messages. If you were not using DOS on all,# # set the variable to something which would unquestioningly remove# # files. #RM-F: RM- F # # shouldn ' t need to change anything below this point. #SRCS: = $ (wildcard *.cpp) $ (wildcard $ (Addsuffix/*.cpp, $ (SR Cdir)) Objs: = $ (Patsubst%.cpp,%.o,$ (SRCS)) DEPS: = $ (Patsubst%.o,%.d,$ (OBJS)) Missing_deps: = $ (Filter-out $ (wildcard $) (DEPS)), $ (DEPS)) Missing_deps_sources: = $ (wildcard $ (patsubst%.d,%.cpp,$ (missing_deps))). Phony:all deps objs Clean Veryclean rebuild Infoall: $ (executable) Deps: $ (deps) OBJS: $ (OBJS) Clean: @$ (rm-f) *. o @$ (rm-f) *.dveryclean:clean @$ (rm-f) $ (executable) Rebuild:veryclean Allifneq ($ (missing_deps),) $ (MISSING _deps): @$ (rm-f) $ (patsubst%.d,%.o,[email protected]) Endif-include $ (DEPS) $ (executable): $ (OBJS) $ (C C)-O $ (executable) $ (OBJS) $ (addprefix-l, $ (Libdir)) $ (addprefix-l,$ (LIBS)) Info: @echo $ (SRCS) @echo $ (OBJS) @echo $ (DEPS) @echo $ (MIS Sing_deps) @echo $ (missing_deps_sources)
Note: 1) The space character before the command line must be a tab (tab), for example, @$ (RM-F) is not a space before *.O, but a tab character;
Content resolution
1.Makefile Basic Syntax
Target is the destination file to be generated; dependency is a dependent file for target; command is used to generate the target line;
<target>: <dependency> <dependency> ... (tab) <command> (tab) <command> ...
2. Assignment symbol: = and =
: the difference between = and = is that the symbol: = indicates that the variable value is expanded immediately. For example:
A:=foo
b:=$ (A)
A:=bar
At this point, the value of B is still foo, because it has been expanded and will no longer change with the value of a.
3. Symbol # is a makefile comment symbol
4.wildcard function
srcs:=$ (wildcard *.cpp) indicates that all files with the. cpp extension in the current directory are enumerated and assigned to the variable SRCS. Please google for details.
5.patsubst function
OBJS: = $ (Patsubst%.cpp,%.o,$ (SRCS)) indicates that all strings that satisfy the pattern SRCs in $ (%.cpp) are replaced with%.O.
6.filter-out function
$ (Filter-out $ (A), $ (B)) means filtering out the contents of a from B and returning the remaining content;
7. ". Phony "
The target with the. Phony modifier is "pseudo-target" and does not need to generate a real file; make assumes that phony target is already generated and then updates the dependent file behind it and executes the command below it;
8.all deps OBJS Clean Veryclean rebuild Info
These are "pseudo-targets".
All is the first target, so it is executed by default when you enter make, and all generates or updates all *.cpp files corresponding to the *.d file and *.o file, and links all *.o files to generate executable $ (executable).
Deps only generate *.d files; What file is the. d file? It contains the dependency information for the code file.
OBJS only generates *.O files; o files are C + + code compiled intermediate result files, nonsense!
Clean is used to delete *.d files and *.o files.
Veryclean Delete the *.d file, *.o file, and also the executable file named $ (executable).
Rebuild call Veryclean to clear the result file before calling all recompile and link.
Info to view some information.
How to use:
Make Deps can execute deps;
9.ifneq...else...endif
Conditional statement, IFNEQ indicates that if you do not want to wait ... ;
10.include <files> Statements
Include indicates the inclusion of <files> content;
$ (DEPS) is a file that contains dependent information, and each source file corresponds to a. d file;-include $ (DEPS) means that the dependency information is included;
11. Link the *.o file, generate the executable file
Here comes the main course!
$ (executable): $ (OBJS) $ (CC)-O $ (executable) $ (OBJS) $ (addprefix-l,$ (LIBS))
$ (executable) is the executable file name; $ (OBJS) for all. O filenames; $ (CC) here is g++;$ (addprefix-l,$ (LIBS) Add Reference Library;
How was the *.d file and the *.O file generated earlier? It seems that there is no command to generate them! Please look at the implied rules!
12. Implied rule (implicit rules)
$ (executable) depends on $ (OBJS), but Makefile does not specify who the $ (OBJS) depends on and does not specify the command to generate them;
At this point, the implicit rules for make begin to work; for each target in $ (OBJS), make automatically calls:
$ (CC) $ (CFLAGS) $ (cppflags) $ (target_arch)-C $<-o [email protected]
Generate. o files and. d files in turn;
$< represents the first file name of a dependent file list;
[Email protected] Indicates the target file name;
The. d file is generated because of the "-MMD" compilation option. When you add this option to g++, the compiler generates file dependency information and stores it in a. d file.
Each of the. cpp files generates a. d file and an. o file accordingly.
[Email protected] Symbol
The @ symbol before the command line indicates that the command line is not echoed;
14.CFLAGS and Cppflags
The two contain compilation options, please Google for more details.
-G add gdb debug information;
-wall prompt warning information;
-O3 represents the 3rd level optimization;
Reproduced
http://wiki.ubuntu.org.cn/%E8%B7%9F%E6%88%91%E4%B8%80%E8%B5%B7%E5%86%99Makefile:MakeFile%E4%BB%8B%E7%BB%8D# Makefile. e7.9a.84.e8.a7.84.e5.88.99
http://blog.csdn.net/zhoujiaxq/article/details/25972859
Linux development-makefile