Linux C Programming Learning 4---Multi-file project management, Makefile, a common Makefile

Source: Internet
Author: User
Tags first string

About GNU make

During the development of large-scale projects, several functional modules are often divided, which can ensure the maintainability of the software.

As part of the project, each module inevitably has a variety of connections, if one of the modules changes, then the other modules need to be updated accordingly. If you do this manually, it might be fine for a small project, but it's almost impossible for larger projects.

So the Linux system provides a tool make that automatically maintains and generates the target program, which can recompile the connection target code according to the changes of each module

The purpose of the Make tool is to automate the process of compiling connections. It defines a language that describes the relationship between a source file, a target file, and an executable file, checks the file's timestamp to determine which files in the program need to be updated, and sends the corresponding command

When we were developing the project, we divided the program into modules, which were decomposed into different files. When one of these parts changes, because the other file's target source file already exists, so the compiler does not need to compile all the code to generate a new executable file, and only need to compile the changed source files, and then connect all the target files on it, which is very important in the large project development, This can reduce the compilation time from several hours to a few minutes. That's what make can do.

Makefile Document Writing Specification

The Makefile file describes the compilation and connection rules for the entire program, including: which source files in the program need to be compiled and how to compile, which library files need to be created, how to create them, how to produce the final executables, etc.

Basic rules

# The starting line is the comment line

If a line is too long you can use a backslash \ To start another line, which is equivalent to a row

The role of the makefile file is to tell the make tool what to do, and in most cases how to compile and connect a program

Target: Rely on <tab keys > commands

The target is often the middle of the program or the resulting file name, such as the target file, executable file ...

Dependency refers to the input file name used to generate the target file, and a target is often dependent on one or more files

command, refers to any one file after the change, need to rebuild the target file needs to execute the command, there can be more than one command, but each command must be a separate line, and it should be noted that each command must be preceded by a <tab key, because make is used <tab > to identify the command line, and then complete the corresponding action

  Example 1, the first is a simple hello.c C language source program

#include <stdio.h>int main () {    printf ("Hello world\n");    return 0;}

Its makefile file can be

/** target: Dependent on <tab key > Command **/hello:hello.c    gcc-o Hello hello.c

Then execute the make command in the directory where makefile and hello.c are located, and you can compile hello.c to generate a hello executable file

  Example 2, the above example is too simple, there is only one file, the following example has three files and two header files

The general process

The corresponding makefile file for it is

EXAMPLE:SORT.O compute.o main.o    gcc sort.o compute.o main.o-o examplesort.o:sort.c lib1.h    gcc-c sort.c-o SORT.O compute.o:compute.c    gcc-c compute.c-o compute.omain.o:main.c lib2.h    gcc-c main.c-o MIAN.O

  Note that the last file to be generated needs to be written at the top of the makefile, and its approximate execution logic is this:

1) After the make command is entered on the command line, the makes command reads the makefile file in the current directory first

2) make handles the first rule in Makefile, which is the connection generated example executable file above

3) After you complete the first rule, you need to first deal with the target file that example depends on, namely SORT.O, COMPUTE.O, MAIN.O, the target file depends on whether the source file or header file it relies on is newer than the current target file, or whether the target file exists to determine whether it needs to be recompiled. After the target file is processed, make decides whether or not to reconnect to the build executable, there are three cases

1. If all the files are not compiled, compile all the source files and connect to generate the executable file

2. Recompile the source files that were modified after the last execute make command, generate a new target file, and then reconnect with the file that already exists, but this time it is not compiled to build the executable file

3. If a header file has been modified since the last make command, recompile all the source files that contain the header file, generate a new target file, and then reconnect with the file that already exists, but this time there is no compilation to build the executable file

Definition and use of variables

Makefile can define a variable in place of a string, which can be a target, a dependency or a command, and other parts of the Makefile, referring to the value of the variable, only need to use $ for good, example

OBJECTS=SORT.O compute.o main.occ=gcccflags=-wall-gexample:$ (objects)    $ (CC) & (objects)-O EXAMPLESORT.O: SORT.C lib1.h    $ (cc) $ (CFLAGS)-C sort.c-o sort.ocompute.o:compute.c    $ (cc) $ (CFLAGS)-C Compute.c-o Compute.omia N.O:MIAN.C lib2.h    $ (CC) $ (FLAGS)-C Mian.c-o MIAN.O

Variable names are case sensitive, General command-related variables are used in uppercase (CC), file-related variables are used in lowercase (objects), parameter-dependent variables are also used in uppercase (CFLAGS)

If the variable name is single-character, you can use the $ variable name directly to refer to, $C, but the variable name is more than one character of the string, at the time of reference, must use the form of $ (variable name), such as $ (CFLAGS), otherwise the Make tool will only parse the first character, such as $CFLAGS, will only parse The $C variable, followed by flags as a normal string, is equivalent to $ (C) flags, so it could be an error

Depending on the definition and presentation of the variables, the variables inside the makefile can be divided into

1) Recursive expansion variables

By means of a definition, the reference is made with strict text substitution, and references to other variables or functions in the variable are expanded when used . Example

a=$ (B) b=$ (C) C=hello

If there is a reference to the variable A in this makefile: $ (a), then when the Make command is executed, the variable begins to be replaced, the variable A is replaced with the variable B, and the variable A is replaced by C, and finally to the Hello

The advantage of recursive expansion is that variable definitions can refer to subsequent defined variables

The downside is that it's possible to have an infinite loop when the variable is expanded, which hurts.

2) Direct Expansion variable

To avoid problems with recursive expansion variables, you can use the direct expansion variable, defined by: =. references to other variables or functions in a variable are expanded at the time of definition .

  Example 1

a=hellob=$ (A) Worlda:=hi

Because it is expanded at the time of definition, the value of variable B is HelloWorld, rather than hiworld in recursive expansion, because a is first defined as Hello and then B because it is expanded at the time of definition, so the value of B is HelloWorld, and then A is redefined later is not going to affect the B.

  Example 2

b=$ (A) Worlda=hi

The value of the final B is world, because a is not defined at the time of definition B, so make will assume that A is null

Implied rules

Implicit rules are special rules that are predefined by the system or user, mainly the common dependencies and update commands.

The general rule uses the full name of the file, and both the target file and the dependent file that appear in the implied rule use only the file's extension. If the file's dependencies are not explicitly given in the makefile file, make will find the corresponding implied rule based on the file's extension, and then follow the implied rules to update the target

example, the implied rule is

. C:    $ (CC) $ (CFLAGS)-O &@ $<.c. O:    $ (CC) $ (CFLAGS)-C $<

The makefile given below is the use of the implied rules above

OBJECTS=SORT.O compute.o mian.occ=gcccflags=-wall-gexample:$ (objects)    $ (CC) $^-o [email PROTECTED]SORT.O: Lib1.hmian.o:lib2.h

Pseudo target

The goals in the Makefile file are divided into two categories: real and pseudo targets.

A real goal is a target that is actually generated to be stored on disk as a file, as explained above, and the pseudo-target does not require the actual file to be generated, it is mainly used to complete some auxiliary operations. Example

Clean    RM Example $ (objects)

After adding the above rule to the makefile, enter the command inside the command: make clean executes the command: RM example SORT.O COMPUTE.O MIAN.O

However, this form of writing is not very rigorous, because there may be a file named clean under the current directory, because this time: there is no dependency on the file, so make think this file is up-to-date, so will not execute RM example SORT.O COMPUTE.O MIAN.O

So in order to avoid this, it is recommended to use this

. Phony:cleanclean:    RM Example $ (objects)

This way, the RM example SORT.O COMPUTE.O MIAN.O command is executed regardless of whether a file with the file name clean exists in the current directory

Function

GNU make provides a number of functions that can be called in the makefile file to handle file names, variables, and commands.

Functions are called in the same way as variables, using the $ symbol

1) Patsubst function

Mainly used for string operations and parsing, the format is

$ (Patsubst pattern,replacement,text)

Example 1

$ (patsubst%.c,%.o,sort.o compute.c main.c)

This is the output to the source file corresponding to the target file list, the output is

SORT.O COMPUTE.O MAIN.O

2) dir function

Used primarily to get the path of the file, example

$ (dir main.c)

If the MAIN.C is in the current directory, it will output

./

3) Notdir function

Extracts characters other than the path in the file name, example

$ (notdir/home/perfect/mywork/c/main.c./makefile

Output is

MAIN.C Makefile

4) Suffix function

Gets the suffix of the file name

$ (suffix./main.c)

The output is

. C

Universal Makefile File

As you can see, writing a makefile is still very complicated.

The following is a generic makefile file, the author of which is supposed to be gorge Foot, the reason that it is generic, mainly because it does not need to be modified to apply to most projects

####################################### Copyright (c) 1997 George Foot ([email protected]) # All rights reserved.## #################################### #目标 (executable document) name, library (such as stdcx,iostr,mysql, etc.), header file path destination: = Testlibs: = includes: =. RM: = suffix of the RM-F#C,CC or CPP file ps=cpp# the implied variable definition of GNU make cc=g++cppflags =-g-wall-o3-march=i486cppflags + $ (addprefix-i,$ (I Ncludes)) Cppflags + =-mmd# The following sections do not need to modify the SOURCE: = $ (Wildcard *.$ (PS)) Objs: = $ (Patsubst%.$ (PS),%.o,$ (SOURCE)) DEPS: = $ ( Patsubst%.o,%.d,$ (OBJS)) Missing_deps: = $ (Filter-out $ (wildcard $ (DEPS)), $ (DEPS)) Missing_deps_sources: = $ (Wildcard $ (Patsubst%.d,%.$ (PS), $ (missing_deps))). Phony:all deps objs Clean rebuildall: $ (DESTINATION) Deps: $ (deps) $ (CC)-MM-MMD $ (SOURCE) OBJS: $ (OBJS) Clean : @$ (RM) *.o @$ (RM) *.d @$ (RM) $ (DESTINATION) Rebuild:clean all Ifneq ($ (missing_deps),) $ (missing_ DEPS): @$ (RM) $ (patsubst%.d,%.o,[email protected]) Endif-include $ (DEPS) $ (DESTINATION): $ (OBJS) $ (C C)-O$ (DESTINATION) $ (OBJS) $ (addprefix-l,$ (LIBS)) #结束 

  Introduction (through the study of this makefile file can be a good understanding of makefile rules)

    • The original author is Gorge Foot, writing this makefile is still a student
    • ": =" assignment, and "=" are different, ": =" at the same time as the assignment, all the variables in the assignment statement are expanded in place, that is, after a:=$ (b), the change of B value no longer affects A
    • implied rules . GUN make uses such compiled commands as the following, if not specifically specified: $ (CC) $ (CFLAGS) $ (cppflags) $ (target_arch)-C $<-o [email protected], This is why this makefile last command did not add $ (cppflags) because the default is to include this variable
    • functions and variables are similar: "$ (a function name, a space, a column of parameters separated by commas)"
    • SOURCES = $ (wildcard *.cpp) lists files in the working directory where the file name meets the "*.cpp" criteria, separated by spaces, and assigns the list to the source variable
    • patsubst function: 3 parameters. The function is to replace each item in the third argument (separated by a space) with the value of the second argument as the part of the first parameter description
    • addprefix function: 2 parameters. Adds a prefix (the 1th parameter) to each item in the source string (the 2nd argument, separated by a space)
    • filter-out function: 2 parameters. Filter out the items contained in the first string from the second string
    • $ (CC)-MM-MMD $ (source): Generates a dependency on each source file (Dependence,make determines whether a file needs to be recompiled by relying on a rule), "D" generates a ". D" file,-mm the header file that removes the system inside the depends (using <> included header file (if you use-m all inclusive, in fact, the system header file is very unlikely to be modified, do not need to perform dependency checking)
    • . Phony, do not check the following to establish whether there is a file with the same name
    • IFNEG...ELSE...ENDIF, conditional statements in makefile
    • -include $ (DEPS): Contains the file in DEPS, "-" indicates that the file does not exist error
    • @$ (RM) *.O: "@" at the beginning means that this command is not displayed when make is displayed (GNU make defaults)
    • All: As the first occurrence of the target project, make will use it as the primary and default item ("Make" means "makes all")
    • Deps: Generate only dependent files (. d files)
    • OBJS: Generate or update '. d ' files and '. O ' files for each source code program
    • Clean: Delete all '. d ', '. O ' and executable files
    • Rebuild:clean then rebuild
    • Internal variables [email protected], $< $^ : Indicates the target name (the previous part, for example all), depends on the first dependent file in the list (: Later section), all dependent on the file

Linux C Programming Learning 4---Multi-file project management, Makefile, a common Makefile

Related Article

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.