Write makefile with me (5)

Source: Internet
Author: User
Tags new set

Vi. Multi-Objective

There can be more than one target in the makefile rule, which supports multiple targets. It is possible that multiple targets depend on one file at the same time, and the generated commands are similar. So we can combine them. Of course, the execution command for Generating Rules for multiple targets is the same, which may cause us trouble, fortunately, we can use an automation variable "$ @" (the automation variable will be described later), which represents the set of all goals in the current rule, this may be very abstract. Let's look at an example.

Bigoutput littleoutput: Text. g
Generate text. G-$ (SUBST output, $ @) >$ @

The above rules are equivalent:

Bigoutput: Text. g
Generate text. G-big> bigoutput
Littleoutput: Text. g
Generate text. G-little> littleoutput

"$" In-$ (SUBST output, $ @) indicates to execute a makefile function. The function name is SUBST, followed by a parameter. The functions will be described later. Here, this function is used to intercept strings. "$ @" indicates the set of targets, just like an array. "$ @" extracts the targets in sequence and runs the commands.

VII. static mode

The static mode makes it easier to define rules with multiple targets and makes our rules more flexible and flexible. Let's take a look at the Syntax:

<Targets... >:< target-pattern >:< prereq-patterns...>
<Commands>
...

Targets defines a series of target files with wildcards. Is a set of targets.

Target-parrtern indicates the targets mode, that is, the target set mode.

Prereq-parrterns is the dependency mode of the target. It defines the dependency mode formed by target-parrtern again.

The three things may not be clearly described in this way. Let's give an example. If our <target-parrtern> is defined as "%. O ", which means that all of our <target> sets are". O ", and if our <prereq-parrterns> is defined as" %. C ", which means to perform a second definition of the target set formed by <target-parrtern>. The calculation method is, take "%" in the <target-parrtern> mode (that is, remove [. o]), and add [. c] A new set formed at the end.

Therefore, the "Target mode" or "dependency mode" must contain the character "%, if your file name contains "%", you can use the Backslash "/" to escape it to indicate the true "%" character.

Let's look at an example:

Objects = Foo. O Bar. o

ALL: $ (objects)

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


In the above example, we specify that our target is obtained from $ object, "%. O "indicates that all o. O Bar. "O", that is, the mode of the variable $ object set, and the dependency mode "%. c. The format is "%. O "" % ", that is," foo bar ", and add". c, so our dependency target is "foo. c bar. C ". In the command, "$ <" and "$ @" are automation variables. "$ <" indicates all dependent target sets (that is, "foo. c bar. c), "$ @" indicates the target set (that is, "Foo. O Bar. O "). As a result, the above rules are equivalent to the following rules:

Foo. O: Foo. c
$ (CC)-C $ (cflags) Foo. C-o Foo. o
Bar. O: bar. c
$ (CC)-C $ (cflags) bar. C-o Bar. o

Imagine that if we have hundreds of "%. O", it would be too efficient to write a bunch of rules as long as we use this simple "static mode rule. The usage of "static mode rules" is flexible. If used well, it will be very powerful. Let's look at another example:

Files = Foo. ELC bar. O lose. o

$ (Filter %. O, $ (Files): %. O: %. c
$ (CC)-C $ (cflags) $ <-o $ @
$ (Filter %. ELC, $ (Files): %. ELC: %. El
Emacs-F batch-byte-compile $ <


$ (Filter %. O, $ (Files) indicates that the filter function of makefile is called to filter the "$ filter" set, as long as the mode is "%. O. I don't have to say much about its content. This example shows greater elasticity in makefile.

8. Automatic dependency generation

In makefile, our dependency may need to contain a series of header files, for example, if our main. C contains the "# include" defs. H "", then our dependency should be:

Main. O: Main. c defs. h

However, if it is a relatively large project, you must know which c files contain header files, and when you add or delete header files, you also need to carefully modify the makefile, this is a very difficult task to maintain. To avoid this heavy and error-prone issue, we can use a C/C ++ compilation function. Most C/C ++ compilers support a "-M" option, that is, to automatically find the header file contained in the source file and generate a dependency. For example, if we execute the following command:

CC-m main. c

The output is:

Main. O: Main. c defs. h

So the dependencies automatically generated by the compiler do not have to manually write the dependencies of several files, but are automatically generated by the compiler. Note that if you use the gnu c/C ++ compiler, you must use the "-Mm" parameter. Otherwise, the "-M" parameter also contains header files of some standard libraries.

The output of GCC-m main. C 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.h

The output of GCC-mm main. C is:

Main. O: Main. c defs. h

Then, how does the compiler function relate to our makefile. As a result, our makefile must be regenerated based on these source files so that the makefile itself depends on the source file? This feature is not realistic, but we can use other methods to achieve it. The GNU Organization recommends that you put the dependency automatically generated by the compiler for each source file in one file, for each "name. c files generate a "name. d "makefile ,[. d] the corresponding [. c] File dependency.

Therefore, we can write [. c] file and [. d] File dependency, and make auto update or self-contained [. d] file and include it in our main makefile. In this way, we can automatically generate dependencies for each file.

Here, we provide a Pattern Rule to generate the [. d] file:

%. D: %. c
@ Set-E; RM-F $ @;/
$ (CC)-M $ (cppflags) $ <>$ @. $ ;/
Sed's,/($ */)/. O [:] *,/1.o $ @:, G' <$ @. $ >$ @;/
Rm-F $ @. $


This rule means that all [. d] the file depends on [. c] file. "RM-F $ @" means to delete all objects, that is [. d] file. The second line indicates "$ <" for each dependent file, that is [. c] The dependency file generated by the file. "$ @" indicates the mode "%. d "file. If there is a C file named name. c. "%" is "name", and "$" indicates a random number. The file generated in the second line may be "name. d.12345 ", the third line uses the SED command to make a replacement. For details about the usage of the SED command, see the relevant user manual. The fourth line is to delete temporary files.

All in all, the thing to do with this mode is to add the dependency of the [. d] file to the dependencies generated by the compiler, that is, the dependency:

Main. O: Main. c defs. h

Convert:

Main. O main. D: Main. c defs. h

So our [. d] the file is automatically updated and generated. Of course, you can also [. d] add not only dependencies to the file, but also the generated commands [. d] all files contain a complete rule. Once this is done, we will put these automatically generated rules into our main makefile. We can use the "include" command of makefile to introduce other makefile files (as mentioned earlier), for example:

Sources = Foo. c bar. c

Include $ (sources:. c =. d)

In the preceding statement, "$ (sources :. C =. d) ". C =. d "means to replace all the variables $ (sources [. c] strings are replaced [. d]. I will give more details about this "Replacement. Of course, you have to pay attention to the order, because include is used to load files on a per-time basis, the targets in the first [. d] file will become the default targets.

<-Previous PageNext page->

(All Rights Reserved. Please indicate the author and source when reprinting)

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.