5
votes

I am trying to make an order-only prerequisite to make sure a build directory exists before outputting files. According to the GNU Make manual:

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).

So I expect this should work:

BUILDDIR:=build

all: $(BUILDDIR)/test.o
clean:
    rm -rf $(BUILDDIR)

$(BUILDDIR):
    mkdir -p $(@)

$(BUILDDIR)/%.o: | $(BUILDDIR)
$(BUILDDIR)/%.o: %.c
    gcc -o $@ -c $<

But it does not, failing to create the directory. However, when I put the rule on a single line, it does work:

$(BUILDDIR)/%.o: %.c | $(BUILDDIR)

In this simple example, it doesn't matter, but I need to make multiple prerequisite lists like this for my more complicated makefile, and the manual makes it sounds like it should work. How can I accomplish this?

In case it matters:

$ make -v
GNU Make 3.81
1

1 Answers

3
votes

An implicit rule with no recipes is dropped during implicit rule search, its only purpose is to cancel any previously defined identical rule. This means that the line $(BUILDDIR)/%.o: | $(BUILDDIR) essentially has no effect.

Since you already have a list of prerequisites you can use regular and static pattern rules instead:

BUILDDIR := build
OBJS     := $(BUILDDIR)/test.o

all: $(OBJS)
clean:
    $(RM) -r $(BUILDDIR)

$(BUILDDIR):
    mkdir -p $@

$(OBJS): | $(BUILDDIR)
$(OBJS): $(BUILDDIR)/%.o: %.c
    $(CC) -o $@ -c $<