Bing Zhao
Bing Zhao

Reputation: 608

Is my understanding correct for the first rule of the makefile?

I'm learning make, and try to understand the following makefile from Prerequisite-Types

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)

The first rule confuses me. It's to be firstly applied. Since $(OBJDIR) is not there, the last rule will be applied to mkdir objdir. Then, since there's nothing in the newly created directory, there's no stem.o, and correspondingly, no stem.c So the prerequisites and recipes seem to be meaningless.

The only thing that the first rule does is to make a directory, which seems to be unreal.

Upvotes: 0

Views: 115

Answers (2)

Beta
Beta

Reputation: 99094

  1. The first rule is a pattern rule, so it cannot be the default rule; it will not be the first applied unless you specify e.g. make thing.o.

  2. The first rule might not do what you expect. The recipe is $(COMPILE.c) $(OUTPUT_OPTION) $<, but you don't assign a value to OUTPUT_OPTION in the makefile; unless you provide a value from outside (e.g. make thing.o OPTION_OUTPUT=...) this recipe has no special instructions about where to put the file it builds, it has never heard of objdir/, and will use the compiler's default which is probably the working directory.

  3. The last rule will build objdir (if objdir does not already exist, and if Make invokes that rule). The command make objdir will work perfectly. If you try to build one of the object files listed in OBJS, Make will construct the directory (if the directory does not exit) -- not because it needs a place to put the file, but because $(OBJDIR) is a prerequisite of every member of $(OBJS), according to the third rule. It will not construct the directory if you try to build objdir/thing.o, because $(OBJDIR) is not a prerequisite of that target. You think Make should build it because it is obviously needed? Well, Make isn't that smart.

  4. The first rule has a prerequisite pattern %.c, and the recipe looks for the source file in the working directory, not in any newly constructed subdirectory. If there is no such source file in the working directory, Make will not run that rule.

Upvotes: 1

MadScientist
MadScientist

Reputation: 100836

I don't really follow your logic.

The first rule in your makefile is this:

all: $(OBJS)

so the default goal for this makefile (if you don't specify one on the command line) is all.

all depends on all the .o files. All the .o files have an order-only dependency on the directory. So, first the directory is created, then the .o files are created, then all is done (there is no recipe here to create a program or library or anything out of those .o files).

Upvotes: 0

Related Questions