Write Makefile with me (5)

zhaozj2021-02-08  240

Sixth, multi-objective

Makefile's goals can be more than one, which supports multi-objective, there is a possible number of targets to depend on a file, and the resulting command is generally similar. So we can merge them. Of course, the execution command of the generation rules of multiple targets is the same, which may have to bring trouble, but in our use of an automated variable "$ @" (about automated variables, it will be described later), this Variables show a collection of all goals in the current rules, which may be abstract, or look at an example.

BIGOUTPUT LITTLEOUT: TEXT.G Generate Text.g - $ (Subst Output, $ @)> $ @

The above rules are equivalent to:

Bigoutput: text.g generate text.g -big> Bigoutput LittleOutput: text.g generate text.g -little> LittleOutput

Among them, "$" in-$ (subst output, $ @) means executing a Makefile function, the function is called Subst, which is the parameter. About the function will be described later. This function here is the meaning of the string, "$ @" indicates the collection of the target, just like an array, "$ @" takes out the goal, and it is committed to the command.

Seven, static mode

Static mode can be easier to define multi-objective rules that make our rules become more flexible and flexible. Let's first look at the syntax first:

: : ...

Targets defines a range of target files that can have wildcards. Is a collection of goals.

Target-Parrtern is a model of Targets, that is, the target set mode.

Prereq-Parrterns is the dependency mode of the target, which is defined for the mode of Target-Parrtern.

This three things may still be clear, or an example to explain it. If we define "% .o", it means that our collection is ".o", if our defines "% .c "It means the secondary definition of the target set formed by , the calculation method is to take"% "in mode (that is, the end of [.o] is ended), And add [.c] this end, the new collection of formed.

So, our "target mode" or "dependency mode" should have "%" characters, if you have "%" in your file name, you can use a backslash "/" to indicate, to indicate Real "%" characters.

Look at an example:

Objects = foo.o bar.o

All: $ (Objects)

$ (Objects):% .o:% .C $ (cc) -c $ (cflags) $ <-o $ @

In the above example, it indicates that our goal is obtained from $ Object, "%. O" indicates all the goals ending with ".o", that is, "foo.o bar.o", that is, the variable $ Object Collection The mode, and the dependency "% .C" is taken "% .o" "%", that is, "foo bar", and add ".c" suffix, so our dependency objective is "Foo.c bar.c". The "$ <" and "$ @" are automated variables in the command, "$ <" indicates that all dependence target sets (that is, "foo.c bar.c"), "$ @" indicates the target set (also It is "foo.o bar.o"). As a result, the following rules are equivalent to the following rules: foo.o: foo.c $ (cc) -c $ (cflags) foo. c c foo.o bar.o: bar.c $ (cc) -C $ (cflags) bar.c -o bar.o

Imagine if our "% .o" has hundreds, then we only use this very simple "static mode rule" to write a bunch of rules, it is too efficient. The Usage of Static Mode Rules is flexible, if you are used, it will be a very powerful feature. Look at an example:

FILES = foo.elc bar.o lose.o

$ (Filter% .o, $ (files)):% .o:% .c $ (cc) -c $ (cflags) $ <-o $ @ $ (file% .elc, $ (files):% .elc:% .el emacs -f batCh-byte-compile $

$ (Filter% .o, $ (files)) indicates that the Makefile's Filter function is filtered, and the "$ FILTER" set is filtered, as long as it is "% .o". Its content, I don't have to say more. This example shows greater flexibility in makefile.

Eight, automatically generate dependencies

In Makefile, our dependencies may need to include a series of headers, such as if there is a "#include" defs.h "in our main.c, then our dependency should be:

Main.o: main.c defs.h

However, if it is a relatively large engineering, you must know which C files contain which header files, and when you join or delete the header file, you need carefully to modify makefile, which is a very maintenance of work. In order to avoid this heavy and easy error, we can use a function of compilation of C / C . Most C / C compilers support a "-m" option, that is, automatically find the header files contained in the source file and generate a dependency. For example, if we do the following command:

cc -m main.c

Its output is:

Main.o: main.c defs.h

Therefore, the dependency of the compiler is automatically generated, so that you don't have to manually write the dependencies of several files, and the compiler is automatically generated. It is necessary to remind a sentence that if you use the GNU's C / C compiler, you have to use the "-mm" parameter, otherwise, "-m" parameters will also include some standard libraries' header files.

GCC -M main.c output is:

Main.o: main.c defs.h /usr/include/stdio.h /usr/include/features.h / /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h / / usr /LIB/GCC-LIB/I486-SUSE-LINUX/2.95.3/include/stddef.h / /usr/include/bits/types.h /usr/include/bits/pthreadtypes.h / / usr / include / bits /sched.h /usr/include/libio.h / /usr/include/_g_config.h /usr/include/wchar.h / /usr/include/bits/wchar.h /usr/include/gConv.h / / USR / LIB / GCC-LIB / I486-SUSE-Linux / 2.95.3 / include / stdarg.h //usr/include/bits/stdio_lim.hgcc -mm main.c output is:

Main.o: main.c defs.h

So, how this feature of the compiler is associated with our makefile. Because in this way, our makefile should also regenerate according to these source files, let Makefile dependent on the source file? This feature is not realistic, but we can have other means to go back to this function. The GNU organization recommends putting the compiler to automatically generated dependencies of each source file in a file, generate a "name.d" Makefile file for each "name.c" file, [D] file Store the dependency of the [.c] file in place.

Thus, we can write the [.c] file and [.d] file dependency, and let the make automatically update or self-contained [.d] files, and contain it in our master makefile, so we will It can automatically generate the dependence of each file.

Here, we give a pattern rule to generate [.d] files:

% .d:% .c @set -E; RM -F $ @; / $ (cc) -m $ (cppflags) $> $ @. $$$$; / sed 's, /( ($ *) ) /. O: @:, g '<$ @. $$$$> $ @; / rm -f $ @. $$$$

The meaning of this rule is that all [.d] files depend on the [.c] file, "RM -F $ @" means deleting all the goals, that is, [.d] file, the second line means For each dependency file "$ <", it is [.c] file generation dependencies, "$ @" represents the "% .d" file, if there is a C file is name.c, then "%" is "Name", "$$$$" means a random number, the second line of files may be "name.d.12345", the third line uses the sed command to make a replace, about the usage of the sed command See the relevant documentation. The fourth line is to delete a temporary file.

All in all, this mode is to do is to join the "dependency of the [.d] file in the dependency generated by the compiler, that is, depending on the relationship:

Main.o: main.c defs.h

Turn into:

Main.o main.d: main.c Defs.h

So, our [.d] file will be automatically updated, and will be automatically generated. Of course, you can also join in this [.d] file not just dependencies, including the generated commands can also join Let each [.d] file contain a decree rule. Once we finish this job, then we have to put these automatically generated rules into our master makefile. We can use the Makefile command to introduce other Makefile files (speaking earlier), for example: Sources = foo.c bar.c

INCLUDE $ (Sources: .c = .d)

".C = .d" in the above statement ".c = .d" means to make a replacement, replace all the strings of the variable $ (Sources) [.c] .d], about this "replace" content, I will have more detailed descriptions later. Of course, you have to pay attention to the order, because INCLUDE is filed as a file, the target in the [.D] file that is first loaded will become the default target.

<- Previous Next->

(All rights reserved, please indicate the author and the source when reproduced)

转载请注明原文地址:https://www.9cbs.com/read-1150.html

New Post(0)