Jepessen
Jepessen

Reputation: 12445

Makefile does not work properly

I've this folder structure

project
|_src
| |_test
|   |_main.cpp
|_Makefile

This is my makefile (trying to adapt from this link):

CC = g++
RM = rm
WFLAGS = -c -Wall -W
LDFLAGS =
SRCTESTD = src/test
EXECUTABLE = test

OBJD = .obj
DEPD = .dep
SRCSTEST = $(SRCTESTD)/main.cpp
OBJECTSTEST = $(patsubst %.cpp, $(OBJD)/test/%.o, $(notdir $(SRCSTEST)))
DEPDSTEST = $(patsubst %.cpp, $(DEPD)/test/%.d, $(notdir $(SRCSTEST)))

all: $(SRCSTEST) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTSTEST)
    $(CC)  $(LDFLAGS) $(OBJECTSTEST) -o $@

.cpp.o:
    $(CC) $(WFLAGS) $< -o $@

It does not work, and I've this error

make: *** No rule to make target `.obj/test/main.o', needed by `test'.  Stop.

What I'm doing wrong? Sorry for trivial question, but I'm a make newbie.

Upvotes: 0

Views: 199

Answers (2)

Chnossos
Chnossos

Reputation: 10506

The link shows outdated methods, such as suffix rules. Making dependencies can also be done during compilation by gcc/g++.

As for the rest, here is it :

EXE         :=  test

SRCDIR      :=  src
OBJDIR      :=  .obj

SRC         :=  $(shell find $(SRCDIR) -name "*.cpp")
OBJ         :=  $(SRC:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
DEP         :=  $(OBJ:.o=.d)

LDLIBS      :=  # -l flags
LDFLAGS     :=  # -L flags

CPPFLAGS    :=  -MMD -MP # -I flags also
CXXFLAGS    :=  -W -Wall # no -c flag here

.PHONY: all clean fclean re

all:    $(EXE)

clean:
    $(RM) -r $(OBJDIR)

fclean: clean
    $(RM) $(EXE)

re: fclean all

-include $(DEP)

$(EXE): $(OBJ)
    $(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $@

$(OBJDIR)/%.o:  $(SRCDIR)/%.cpp
    @mkdir -p $(@D)
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $<

No redefinition of internally defined variables, no suffix rules, correct linking step and dependencies generation.


Update: To avoid calling mkdir for every source file, one should use order-only prerequisites and the special target .SECONDEXPANSION.

Change this block:

$(OBJDIR)/%.o:  $(SRCDIR)/%.cpp
    @mkdir -p $(@D)
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $<

To this:

.SECONDEXPANSION:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp | $$(@D)/
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ -c $<

%/:
    mkdir $*

Upvotes: 2

kebs
kebs

Reputation: 6707

The error means make can't find a correct rule to build your object files. Your tree structure lacks some informations: only one file ? Where are the others ? Anyway, here are some hints:

In the last two lines, you are using an obsolete feature of make: suffix rules. I suggest you switch to a pattern rule, which is functionaly equivalent. Say something like:

%.o: %.cpp
    $(CXX) $(CXXFLAGS) $< -o $@

Another thing (that shouldn't be a problem here): you are using the variable CC which is internally defined as the default C compiler. It's okay because you redefine it, but as your sources seem to be C++ files, why not use the variable CXX, that is internally defined as the C++ compiler ?

Lastly, to make sure your set of files are correctly defined, you can print them with a dummy show target, see here.

show:
     @echo "OBJECTSTEST=$(OBJECTSTEST)"
     ...

Upvotes: 2

Related Questions