43

Assuming we have the rule:

a: b c d e

and b, c, d and e are independent of each other.

Is the order of making b, c, d, e defined? It seems that generally they will be made in order b, c, d, e, but may it sometimes happen, that the order will be different?

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
peper0
  • 433
  • 1
  • 4
  • 4

7 Answers7

38

No, the order is not defined. That is the whole point in using declarative dependency-oriented programming: that the computer can pick the optimal evaluation order, or in fact, evaluate them even at the same time.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
15

In what order prerequisites will be made by the GNU make?

It depends on the type of the prerequisite. According tho the GNU Make Manual, Section 4.2:

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.

jww
  • 97,681
  • 90
  • 411
  • 885
  • 10
    This doesn't really impose an ordering though, at least not any more than a normal prerequisite. It just says that for an order-only prerequisite gmake should ignore the timestamp. It is a prerequisite, so it has to exist before the current rule can be run, but since it is an order-only prerequisite its timestamp/state does not trigger the current rule. (Which does not rule out other dependencies causing the order-only dependencies from executing their commands.) – simpleuser Mar 19 '15 at 20:22
  • 7
    From the gnu make documentation above: `Occasionally, however, you have a situation where you want to impose a specific ordering on how the rules of a target are going to be invoked without forcing the target to be updated if one of those rules is executed.` This seems rather bad-worded for what the oder-only prerequisite really does. Up to my understanding a order-only prerequisite is simply a prerequisites which does not force `make` to rebuild the target if it changes. – clickMe Oct 06 '17 at 10:55
  • I think this is not what the OP was searching for. Try invoking `make -j` to find out whether dependencies are really executed in the order you expect. – dubbaluga Feb 22 '21 at 08:21
7

In the right order, based on the rules you provide. For your particular example, that could mean any one of a number of different (4! = 24, from memory) orders.

All make programs are free to choose the order they like as long as the dependencies are honored. If there were other rules in your example, say c: b, then c would be made before b (but that isn't the case, as you point out).

If you need to rely on a specific order, you'll need more rules to enforce it. Otherwise make can do what it pleases. The documentation for GNU Make only states how rules are processed, not the order in which dependencies within a rule are processed. The most logical order (to me, anyway) would be the order in which they're listed but that's not guaranteed.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
4

Sure, if I use make -j a, they might all get built at the same time (depending on whether b, c, d, or e in turn have other/interrelated dependencies).

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • 10
    This doesn't really answer the question so I'm surprised it was accepted. –  Oct 30 '09 at 01:11
  • 3
    The question I read there is "It seems that generally they will be made in order `b`, `c`, `d`, `e`, but may it sometimes happen, that the order will be different?". I'm pretty sure I provided a counterexample. Your opinion may vary, I suppose. – Carl Norum Oct 30 '09 at 06:59
  • *order-only-prerequisites* **are** built in a particular order. I'm not sure the poster knew there was anything other than *normal-prerequisites* based on his assumption, though. – jww Jul 27 '14 at 14:08
  • 3
    @jww no, order-only-prerequisites are not build in a particular order, they just don't **"[..] force the target to be updated if one of those rules is executed [..]"**. – juan.facorro Jun 15 '16 at 09:33
  • @user181548, don't be surprised, this is very typical SO behavior. – SO_fix_the_vote_sorting_bug Oct 27 '21 at 23:42
4

No, you can't count on the ordering when there are no dependency relationships.

  • make needs to do a topological sort, because dependencies may have additional and multiple relationships. The sort that make does is potentially quite complex, as nodes in the graph may be related multiple times at different levels
  • in general sorting algorithms are not naturally stable, even for simple key-based sorts
DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
4

I'll just add this for future reference. While GNU Make may not define a specific order when it comes to processing prerequisites, POSIX make requires that they be handled in the order they've been specified, namely left-to-right. Most implementations follow this rule. POSIX even gives an example where a make implementation not following this rule could break the build process of a program:

foo: y.tab.o lex.o main.o
    $(CC) $(CFLAGS) -o $@ t.tab.o lex.o main.o

where lex.o ends up using an incorrect y.tab.h. While this can be rewritten in a way that works with GNU Make, I thought I'd share this tidbit about prerequisite ordering.

2

If order matters, you can selectively enforce it using recursive make. For example, suppose you don't care what order b and c are made in, as long as they're both made before d and d is made before e. Then you could write your rule as:

a: b c
    $(MAKE) d
    $(MAKE) e
    # Additional steps to make a

Be aware that depending on the complexity of d and e, this approach may do Bad Things to your build times: see Recursive Make Considered Harmful (PDF) for arguments against doing it this way.

Simon Brady
  • 1,877
  • 3
  • 13
  • 10