Giuseppe
Giuseppe

Reputation: 550

Subdirectories and GCC problem with MakeFile

I'm writing a makefile for a very small personal project written in C.
My project is divided into subdirectories, but the directives for these utilme are not found even if (I think) the code is right:

TARGET = example.out

ENV = /usr/bin/env
MKDIR = mkdir
RMV = rm
CP = cp

CC = gcc
CFLAGS = -lm

BINDIR = ./bin
OBJDIR = ./obj
SRCDIR = ./src

SRCS = master.o request/request.o util/util.o # these are all .c files (./src/...)

# ---
.PHONY: build
build: prepare $(SRCS)
    $(ENV) $(CC) $(addprefix $(OBJDIR)/, $(SRCS)) -o $(BINDIR)/$(TARGET)

# ---
.PHONY: prepare
prepare:
    @$(ENV) $(MKDIR) -p $(BINDIR) $(OBJDIR)
    @$(ENV) $(CP) data.txt $(BINDIR)/data.txt

# ---
.PHONY: clean
clean:
    @$(ENV) $(RM) -rf $(BINDIR) $(OBJDIR)

# ---
$(OBJDIR)/%.o: $(SRCDIR)/%.c
    $(ENV) $(CC) $(CFLAGS) -c $<

It says:

make: *** No rule to make target 'master.o', needed by 'build'.  Stop.

And if I change $(OBJDIR)/%.o: $(SRCDIR)/%.c to %.o: $(SRCDIR)/%.c, it says:

make: *** No rule to make target 'request/request.o', needed by 'build'.  Stop.

Upvotes: 0

Views: 59

Answers (2)

koder
koder

Reputation: 2103

You have effectively no rule to create master.o from master.c.

In the following rule:

$(OBJDIR)/%.o: $(SRCDIR)/%.c

./obj/%.o does not match master.o

And if master.c is in src (as indicated by the comment) the default rules don't match either.

So in order to match the rule, the target must be ./obj/master.o

The same goes for all the other .o files and you will run into trouble with the subdirectories. To get around that you can create the target directory in the recipe directly:

$(OBJDIR)/%.o: $(SRCDIR)/%.c
        mkdir -p $(dir $@)
        $(CC) -c -o $@  $(CFLAGS) $<

Upvotes: 2

thejonny
thejonny

Reputation: 533

the default behaviour of gcc is to place the .o-file beneath the .c-file. to place it into the object file directory, you have to use an -o $@ argument:

$(OBJDIR)/%.o: $(SRCDIR)/%.c
    $(ENV) $(CC) $(CFLAGS) -c $< -o $@

And the build rule shoud depend on $(addprefix $(OBJDIR)/, $(SRCS)) if this is what is used in the command.

build: prepare $(addprefix $(OBJDIR)/, $(SRCS))
    $(ENV) $(CC) $(addprefix $(OBJDIR)/, $(SRCS)) -o $(BINDIR)/$(TARGET)

Upvotes: 0

Related Questions