Overview
——
What is makefile? Perhaps a lot of WINODWS programmers do not know this thing, because those Windows IDE has done this work for you, but I think to be a good and professional programmer, makefile still want to understand. It's like there are so many HTML editors now, but if you want to be a professional, you still have to understand the meaning of the HTML logo. Especially under the UNIX software compilation, you can not write makefile, will not write makefile, from a side to explain whether a person has the ability to complete large-scale projects.
Because, makefile related to the entire project compilation rules. The source files in a project are not counted, and they are placed in several directories by type, function and module, makefile defines a series of rules to specify which files need to be compiled first, which files need to be compiled, which files need to be recompiled, and even more complex function operations. Because makefile is like a shell script, it can also execute commands from the operating system.
Makefile brings the advantage is-"automated compilation", once written, only need a make command, the entire project is automatically compiled, greatly improving the efficiency of software development. Make is a command tool, a command tool that interprets instructions in makefile, and in General, most Ides have this command, such as: Delphi's Make,visual C + + Nmake,linux under GNU. Thus, Makefile has become a compilation method in engineering.
There are fewer articles on how to write makefile, which is why I want to write this article. Of course, different producers of make are different, but also have various syntax, but its essence is in the "file dependence" on the fuss, here, I only to the GNU make to tell, my environment is Redhat Linux 8.0,make version is 3.80. This make is the most widely used and most used. It is also best followed by the IEEE 1003.2-1992 Standard (POSIX.2).
In this document, we will be based on C + + source code, so it is necessary to involve some of the knowledge of C + + compiler, related to this aspect of the content, but also please review the relevant compiler documentation. The default compiler here is the GCC and cc under UNIX.
About compiling and linking programs
——————————
Here, I would like to say more about the program compiled some of the specifications and methods, generally speaking, whether it is C, C + +, or PAS, the first to compile the source files into an intermediate code file, under Windows is the. obj file, under Unix is the. o file, the Object file, This action is called compiling (compile). And then the large number of object file synthesis execution file, this action is called link.
At compile time, the compiler needs the correct syntax, and the declaration of functions and variables is correct. For the latter, usually you need to tell the compiler where the header file is located (the header file should only be declared, and the definition should be in a C + + file), as long as all the syntax is correct, the compiler can compile the intermediate target file. In general, each source file should correspond to an intermediate target file (o file or obj file).
Links are primarily link functions and global variables, so we can use these intermediate target files (o files or obj files) to link to our application. Linker and regardless of the function of the source file, just the function of the intermediate target files (object file), most of the time, due to too many source files, compile the resulting intermediate target file too many, and in the link need to clearly indicate the intermediate target file name, which is very inconvenient for compiling, so, We want to give a package to the intermediate target file, under Windows This package is called "library file", that is,. lib file, under Unix, is archive file, that is,. a files.
To summarize, the source file first generates an intermediate target file, which is then generated by the intermediate target file. At compile time, the compiler detects only the program syntax, and whether the function or variable is declared. If the function is not declared, the compiler will give you a warning, but you can generate an object File. When linking the program, the linker in all the object file to find the implementation of the function, if not found, then will report the link error code (Linker error), under the VC, this error is generally: Link 2001 error, meaning that the linker could not find the implementation of the function. You need to specify the function's object File.
Well, to start with, GNU make has a lot of content, gossip, or let's get started.
Makefile Introduction
———————
When the make command executes, a Makefile file is required to tell the make command what to do to compile and link the program.
First, we use an example to illustrate Makefile's writing rules. In order to give everyone a sense of awareness. 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.
First, the rule of makefile
Before I tell you about this makefile, let's take a cursory look at the rules of Makefile :
target ...: Prerequisites ...
Command
...
...
Target is a destination file, which can be either an object or an executable file. It can also be a label, which is described in the following "pseudo-targets" section for labels.
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 be back 1.1 points to combine my work experience to you slowly come. There's a lot of content. :)
second 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 above.
EDIT:MAIN.O KBD.O COMMAND.O display.o/
INSERT.O SEARCH.O FILES.O UTILS.O
Cc-o edit MAIN.O kbd.o command.o display.o/
INSERT.O SEARCH.O FILES.O UTILS.O
MAIN.O:MAIN.C Defs.h
Cc-c MAIN.C
KBD.O:KBD.C Defs.h Command.h
Cc-c KBD.C
COMMAND.O:COMMAND.C Defs.h Command.h
Cc-c COMMAND.C
DISPLAY.O:DISPLAY.C Defs.h Buffer.h
Cc-c display.c
Insert.o:insert.c Defs.h Buffer.h
Cc-c insert.c
SEARCH.O:SEARCH.C Defs.h Buffer.h
Cc-c search.c
FILES.O:FILES.C defs.h buffer.h Command.h
Cc-c FILES.C
UTILS.O:UTILS.C Defs.h
Cc-c UTILS.C
Clean:
RM Edit MAIN.O KBD.O COMMAND.O display.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 the file "Makefile" or "Makefile" file, and then directly enter the command "make" in this directory to generate the execution 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 cleanis 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 the dependency of the file, will not automatically execute the commands defined later. To execute subsequent commands, the lable name is clearly indicated 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.
third, how make is working
In the default way, we only enter the Make command. So
1. Make will find the file named "Makefile" or "Makefile" in the current directory.
2, if found, it will find the file in the first target file (target), in the above example, he will find "edit" This file, and put this file as the final target file.
3, if the edit file does not exist, or edit depends on the file modification time of the. o file is newer than the edit file, then he will execute the command defined later to generate the edit file.
4. If edit depends on the. o file that does not exist, then make will find the dependency of the. o file in the current file and, if found, then generate the. o file according to that rule. (This is a bit like a stack of process)
5. Of course, your C files and h files are there, so make generates. o files and then uses. o File the ultimate task of life 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.
Through the above analysis, we know thatlike clean, which is not directly or indirectly associated with the first target file, the commands defined later will not be automatically executed, but we can show that we 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 dependent relationship defined by the command), so FILE.O file is also the latest, so FILE.O file modification time is newer than edit, so edit will be re-linked (see edit The command defined after the file is marked).
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.
Iv. 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.O
Cc-o edit MAIN.O kbd.o command.o display.o/
INSERT.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 a variable, called OBJECTS, OBJECTS, Objs, Objs, obj, or obj, whatever it is, as long as it can represent the obj file. We did it at the beginning of makefile.definition:
objects =MAIN.O KBD.O COMMAND.O display.o/
INSERT.O SEARCH.O FILES.O UTILS.O
So that we can conveniently in our makefileUse this variable in a "$ (objects)" Way, so our improved version of Makefile becomes the following:
objects = MAIN.O KBD.O command.o display.o/
INSERT.O SEARCH.O FILES.O UTILS.O
Edit: $ (objects)
Cc-o Edit $ (objects)
MAIN.O:MAIN.C Defs.h
Cc-c MAIN.C
KBD.O:KBD.C Defs.h Command.h
Cc-c KBD.C
COMMAND.O:COMMAND.C Defs.h Command.h
Cc-c COMMAND.C
DISPLAY.O:DISPLAY.C Defs.h Buffer.h
Cc-c display.c
Insert.o:insert.c Defs.h Buffer.h
Cc-c insert.c
SEARCH.O:SEARCH.C Defs.h Buffer.h
Cc-c search.c
FILES.O:FILES.C defs.h buffer.h Command.h
Cc-c FILES.C
UTILS.O:UTILS.C Defs.h
Cc-c UTILS.C
Clean:
RM Edit $ (objects)
So if a new. o file is added, we simply need to modify the objects variable.
More on the topic of variables, I will give you one by one in the follow-up.
Five, let make automatic deduction
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, if make finds a whatever.o, then WHATEVER.C will be 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 out of the oven.
objects = MAIN.O KBD.O command.o display.o/
INSERT.O SEARCH.O FILES.O UTILS.O
Edit: $ (objects)
Cc-o Edit $ (objects)
Main.o:defs.h
Kbd.o:defs.h command.h
Command.o:defs.h command.h
Display.o:defs.h Buffer.h
Insert.o:defs.h Buffer.h
Search.o:defs.h Buffer.h
Files.o:defs.h Buffer.h Command.h
Utils.o:defs.h
. Phony:clean
Clean:
RM Edit $ (objects)
This method is the "cryptic rule" of make. The contents of the above file,". Phony "says Clean is a pseudo-target file。
For a more detailed"Cryptic Rules"And"pseudo-target file", I will give you one by one of the way in the follow-up.
Vi. Alternative style of makefile
Now that 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.O
Edit: $ (objects)
Cc-o Edit $ (objects)
$ (objects): Defs.h
KBD.O COMMAND.O Files.o:command.h
DISPLAY.O INSERT.O SEARCH.O Files.o:buffer.h
. Phony:clean
Clean:
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.
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)
The more robust approach is:
. Phony:clean
Clean:
-rm Edit $ (objects)
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, go ahead and do the following . Of course, clean's 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 an overview of the makefile, but also the basis of makefile, there are a lot of makefile details, ready? Come when you are ready.