0
votes

Consider this makefile:

CXX        = g++-7
CC         = gcc-7

CXXFLAGS   = -Wall -Wimplicit-fallthrough -Wextra -g -fstack-protector-all -std=c++11
LDFLAGS    = 
EXECUTABLE = engine
EXTENSION  = cc
SOURCES    = $(basename $(shell find . -name '*.$(EXTENSION)'))

.PHONY: all
all: $(EXECUTABLE)

$(EXECUTABLE): $(addsuffix .o, $(SOURCES))
    $(CXX) $(LDFLAGS) $^ -o $@

%.d: %.$(EXTENSION)
    $(CXX) $(CXXFLAGS) -MM $< -o $@

-include $(addsuffix .d, $(SOURCES))

.PHONY: clean
clean:
    find . -name '*.o' -or -name '*.d' -or -name '*~' -delete

This makefile places all the .d and .o files in the "src" folder, where my .cc and .h files are located.

I edited the makefile to place the .d objects inside a "obj" folder, but somehow I now need a .o rule.

This is the edited makefile: it creates the %.d files in the "obj" folder but then fails with this error: 'make: *** No rule to make target 'obj/wireframe.o', needed by 'engine'. Stop.'

CXX        = g++-7
CC         = gcc-7

$(shell mkdir "obj")

CXXFLAGS   = -Wall -Wimplicit-fallthrough -Wextra -g -fstack-protector-all -std=c++11
LDFLAGS    = 
EXECUTABLE = engine
EXTENSION  = cc
SRCDIR     = src
OBJDIR     = obj
SOURCES    = $(basename $(shell find $(SRCDIR) -name '*.$(EXTENSION)' -printf '%f\n'))



.PHONY: all
all: $(EXECUTABLE)

$(EXECUTABLE): $(OBJDIR)/$(addsuffix .o, $(SOURCES))
    $(CXX) $(LDFLAGS) $^ -o $@

%.d: $(SRCDIR)/%.$(EXTENSION)
    $(CXX) $(CXXFLAGS) -MM $< -o $(OBJDIR)/$@

-include $(addsuffix .d, $(SOURCES))

.PHONY: clean
clean:
    find . -name '*.o' -or -name '*.d' -or -name '*~' -delete
1
And what happens when you try to write the .o rule? If you're having trouble, I suggest you start with $(OBJDIR)/%.o: $(SRCDIR)/%.ccBeta

1 Answers

1
votes

This won't do what you appear to want:

$(EXECUTABLE): $(OBJDIR)/$(addsuffix .o, $(SOURCES))

How does this expand? Look at the "first level" of expansion:

engine: obj/$(addsuffix .o, foo bar biz baz)

Then if you then expand the rest of the way you'll get:

engine: obj/foo.o bar.o biz.o baz.o

Just sticking a string ($(OBJDIR)/) before the expansion of a list of things doesn't apply that string to all the elements of the list! It only adds it to the first item in the list.

You want something like this:

# Use := here, not =, so you don't run this shell command lots of times!
SOURCES := $(shell find $(SRCDIR) -name '*.$(EXTENSION)' -print)

OBJECTS := $(patsubst %.$(EXTENSION),$(OBJDIR)/%.o,$(notdir $(SOURCES)))

$(EXECUTABLE): $(OBJECTS)