Makefile |

Makefile |

foreword

When learning the Makefile in the skynet project, I didn't understand the following statement:

3rd/jemalloc/Makefile : | 3rd/jemalloc/autogen.sh
	cd 3rd/jemalloc && ./autogen.sh --with-jemalloc-prefix=je_ --enable-prof

I couldn't find relevant news on Baidu, but now I probably understand the meaning of it, so I wrote a blog post to record it.

text

Google found the official documentation: https://www.gnu.org/software/make/manual/make.html

Then according to |the search, I got a paragraph and put it in the references. My understanding of this passage is roughly as follows:

There are two kinds of prerequisites: one is called normal-prerequisites and the other is called order-only-prerequisites. Both can co-exist, or both at the same time. For example, the following expressions are allowed:

a : b c 
a : | d e
a : b c | d e
a : b | b

In general, if a target's prerequisites are updated, the target should also be updated. order-only-prerequisites allows us to implement the prerequisites that update the target without updating the target. Let's explain with a simple example:

This Makefile performs several things, creates the objdir directory, and then creates two files ao and bo under this directory. Creating and deleting files in a directory will change the timestamp of the directory. Here is normal-prerequisites, so you can see that the touch command will be executed twice after make is executed.

wyw@DESKTOP-GJ20UDC:~/code/test_make$ cat Makefile
objdir = objdir
objs := $(addprefix $(objdir)/, a.o b.o)

$(objdir)/%.o:
        touch $@


all: $(objs)

$(objs): objdir

$(objdir):
        mkdir $(objdir)
wyw@DESKTOP-GJ20UDC:~/code/test_make$ make
mkdir objdir
touch objdir/a.o
touch objdir/b.o
wyw@DESKTOP-GJ20UDC:~/code/test_make$ ls --full-time
total 0
-rw-r--r-- 1 wyw wyw  145 2021-07-22 20:54:11.194231600 +0800 Makefile
drwxr-xr-x 1 wyw wyw 4096 2021-07-22 20:56:37.093678100 +0800 objdir
wyw@DESKTOP-GJ20UDC:~/code/test_make$ touch objdir/c.o
wyw@DESKTOP-GJ20UDC:~/code/test_make$ ls --full-time
total 0
-rw-r--r-- 1 wyw wyw  145 2021-07-22 20:54:11.194231600 +0800 Makefile
drwxr-xr-x 1 wyw wyw 4096 2021-07-22 20:57:16.898140600 +0800 objdir
wyw@DESKTOP-GJ20UDC:~/code/test_make$ make
touch objdir/a.o
touch objdir/b.o

In this version we modify the prerequisites to add pipe characters |.

wyw@DESKTOP-GJ20UDC:~/code/test_make$ cat Makefile
objdir = objdir
objs := $(addprefix $(objdir)/, a.o b.o)

$(objdir)/%.o:
        touch $@


all: $(objs)

$(objs): |objdir

$(objdir):
        mkdir $(objdir)
wyw@DESKTOP-GJ20UDC:~/code/test_make$ make
mkdir objdir
touch objdir/a.o
touch objdir/b.o
wyw@DESKTOP-GJ20UDC:~/code/test_make$ touch objdir/c.o
wyw@DESKTOP-GJ20UDC:~/code/test_make$ make
make: Nothing to be done for 'all'.

This time, the last make prompt is that the target does not need to be updated~

references

4.3 Types of Prerequisites

There are actually two different types of prerequisites understood by GNU make: normal prerequisites such as described in the previous section, and order-only prerequisites. A normal prerequisite makes two statements: first, it imposes an order in which recipes will be invoked: the recipes for all prerequisites of a target will be completed before the recipe for the target is run. Second, it imposes a dependency relationship: if any prerequisite is newer than the target, then the target is considered out-of-date and must be rebuilt.

Normally, this is exactly what you want: if a target’s prerequisite is updated, then the target should also be updated.

Occasionally, however, you have a situation where you want to impose a specific ordering on the rules to be invoked without forcing the target to be updated if one of those rules is executed. In that case, you want to define order-only prerequisites. Order-only prerequisites can be specified by placing a pipe symbol (|) in the prerequisites list: any prerequisites to the left of the pipe symbol are normal; any prerequisites to the right are order-only:

targets : normal-prerequisites | order-only-prerequisites

The normal prerequisites section may of course be empty. Also, you may still declare multiple lines of prerequisites for the same target: they are appended appropriately (normal prerequisites are appended to the list of normal prerequisites; order-only prerequisites are appended to the list of order-only prerequisites). Note that if you declare the same file to be both a normal and an order-only prerequisite, the normal prerequisite takes precedence (since they have a strict superset of the behavior of an order-only prerequisite).

Consider an example where your targets are to be placed in a separate directory, and that directory might not exist before make is run. In this situation, you want the directory to be created before any targets are placed into it but, because the timestamps on directories change whenever a file is added, removed, or renamed, we certainly don’t want to rebuild all the targets whenever the directory’s timestamp changes. One way to manage this is with order-only prerequisites: make the directory an order-only prerequisite on all the targets:

OBJDIR := objdir
OBJS := $(addprefix $(OBJDIR)/,foo.o bar.o baz.o)

$(OBJDIR)/%.o : %.c
       $(COMPILE.c) $(OUTPUT_OPTION) $<

all: $(OBJS)

$(OBJS): | $(OBJDIR)

$(OBJDIR):
       mkdir $(OBJDIR)

Now the rule to create the objdir directory will be run, if needed, before any ‘.o’ is built, but no ‘.o’ will be built because the objdir directory timestamp changed.

Guess you like

Origin blog.csdn.net/sayWhat_sayHello/article/details/119010996