roschach
roschach

Reputation: 9336

Makefile error no rule found but rule is present

This Makefile

CC = gcc

INC_PATH = -I../common/

SOURCEDIR := ./
SOURCES := $(wildcard $(SOURCEDIR)/*.c)
OBJDIR :=./obj
OBJECTS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.d, $(SOURCES))

COMMONDIR     := ../common
SOURCESCOMMON := $(wildcard $(COMMONDIR)/*.c)
OBJDIRCOMMON  := $(COMMONDIR)/obj
OBJECTSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.o, $(SOURCESCOMMON))
DEPENDSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.d, $(SOURCESCOMMON))

# ADD MORE WARNINGS!
WARNING := -Wall -Wextra

# OBJS_LOC is in current working directory,
EXECUTABLE := ../server
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean

# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: $(EXECUTABLE)

clean:
    $(RM) $(OBJECTS) $(DEPENDS) $(EXECUTABLE)

# Linking the executable from the object files
# $^   # "src.c src.h" (all prerequisites)
$(EXECUTABLE): $(OBJECTSCOMMON) $(OBJECTS)
    $(CC) $(WARNING) $^ -o $@

-include $(DEPENDS) $(DEPENDSCOMMON)

$(OBJDIR):
    mkdir -p $(OBJDIR)

$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
    $(CC) $(WARNING) -MMD -MP -c $(INC_PATH) $< -o $@

$(OBJDIRCOMMON):
    mkdir -p $(OBJDIRCOMMON)

$(OBJDIRCOMMON)/%.o: $(SOURCESCOMMON)/%.c | $(OBJDIRCOMMON)
    $(CC) $(WARNING) -MMD -MP -c $< -o $@

is generating the error:

 make[1]: *** No rule to make target '../common/obj/utilities.o', needed by '../server'.  Stop.

The main rule generating the rule has as input $(OBJECTSCOMMON) referring to the objects file *.o contained in the directory OBJDIRCOMMON. The rule to generate this objects has not explicit target but it is:

$(OBJDIRCOMMON)/%.o: $(SOURCESCOMMON)/%.c | $(OBJDIRCOMMON)
    $(CC) $(WARNING) -MMD -MP -c $< -o $@

and I think this is generating the error. I was expecting the definition OBJECTSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.o, $(SOURCESCOMMON)) made the rule and valid to generate $()

However a similar rule is used to generate $(OBJECTS) in the same Makefile and it is workin:

$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
    $(CC) $(WARNING) -MMD -MP -c $(INC_PATH) $< -o $@

So why the different behaviour between the rules?

Upvotes: 1

Views: 216

Answers (1)

Florian Weimer
Florian Weimer

Reputation: 33694

$(SOURCESCOMMON)/%.c expands to $(wildcard $(COMMONDIR)/*.c)/%.c, so the pattern will contain something like ../common/utilities.c/%.c (possibly with a different file name). This file does not exist, so the pattern rule is ignored.

The other rule uses $(SOURCEDIR), so it does not have this issue.

Upvotes: 2

Related Questions