Learn makefile with Chenhao.

Source: Internet
Author: User
Tags error code


Author: Chenhao http://blog.csdn.net/haoel/article/details/2886/



This article was reproduced from: http://blog.csdn.net/ruglcc/article/details/7814546/



Makefile is important .
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.



0.1 about compiling and linking the program



    here, I would like to talk about some of the code and Methods of program compilation, in general, whether it is C, C + +, or PAS, the first to compile the source file into a intermediate code file , under Windows is also. obj file, under Unix is the. o file, the Object file, which is called compile (compile) . And then the large number of object file synthesis execution file, this action is called link.    
     
        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 , mainly linked functions and global variables, so we can use these intermediate target files (o files or obj files) to link our applications. 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 the intermediate target file a package, under Windows This package is called " library file" , which is the. lib file, under Unix, is the archive file, which is. A.



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 objectfile of the function.

Well, to start with, GNU make has a lot of content, gossip, or let's get started.



1 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, all of our C files will be compiled and linked.



2. If some 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 to 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.



1.1 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 is a destination file, which can be either an objector 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. :)



1.2 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 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 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 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.



1.3 How  make Works



In the default way, we only enter the Make command.   Then, make will find the 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 edit depends on the. o file also exists, 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) of course, your C files and h files are there, so make generates an. o file and then uses the. o file to declare the ultimate 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, however, we can display to make 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.



1.4  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 defined this at the beginning of makefile:



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 of Makefile becomes the following:


 objects = main.o kbd.o command.o display.o \
             insert.osearch.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.



1.5 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 out of the oven.


objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
Edit: $ (obje CTS)
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.hfiles.o:defs.h buffer.h command.h
utils.o:defs.h
. Phony:clean clean
:
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.



1.6 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: $ (obje CTS)
Cc-o Edit $ (objects)
$ (objects): Defs.h
kbd.o command.o files.o:command.hdisplay.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.



1.7 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:clean



Clean:



-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 to do. Come when you are ready.






2 Makefile General statement



2.1 there's something in  makefile.



Makefile contains five main things: explicit rules, cryptic rules, variable definitions, file instructions, and annotations. an explicit rule. Explicit rules explain 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 auto-derivation function, the obscure rules allow us to write makefile in a rough and simple way, which is supported by made. The definition of the variable. In makefile we want to define a series of variables, the variables are usually strings, this is a bit of your C language macro, when Makefile is executed, the variables will be extended to the corresponding reference position. 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, such as "\#".



Finally, it is worth mentioning that the command in makefile must start with the [Tab] key.



2.2 file name of 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 "parameter , such as: Make-f make.linux or make--file Make.aix.



2.3 References 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 be guaranteed with 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 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 searches for other makefile that the include indicates and places 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:


1. If make executes with the "-I" or "--include-dir" parameter, then make will look in the directory specified in this parameter.
2. If the directory/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.



2.4 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. It's just that, unlike include, the "target" of the makefile introduced from this environment 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.



2.5 How  make works



The GNU make-to- work execution steps into the following: (think other make is similar)



1. Read all the makefile.



2. Read the other makefile that are included in the include.



3. Initialize the variables in the file.



4. Derive the cryptic rules and analyze all the rules.





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.