Home > Enterprise >  Many folders project Makefile
Many folders project Makefile

Time:10-02

I have the following project structure:

common
|-- foo.cpp
|-- foo.h
exercise_1
|-- main.cpp
|-- bar_1.cpp
|-- bar_1.h
exercise_2
|-- main.cpp
|-- bar_2.cpp
|-- bar_2.h
...

How can one organize Makefile to build such project from the main directory e.g.:

make exercise_10

So that this command would build object files in common directory, in exercise_10 folder and link them all to executable in exercise_10. I started with the following:

COMPILER = g  
INCLUDE = -I common/
DEPS = common/*.o

OBJECTS := $(patsubst common/%.cpp, common/%.o, $(wildcard common/*.cpp))

common: $(OBJECTS)

exercise_%:
    $(COMPILER) $@/main.cpp $(INCLUDE) -o $@/main $(DEPS)

But it's not working and I don't know what to do next.

Thanks!

CodePudding user response:

If you use GNU make you could define a macro to build any of your exercises. Something like the following:

EXERCISES      := $(wildcard exercise_*)
MAINS          := $(addsuffix /main,$(EXERCISES))

.PHONY: all
all: $(MAINS)

common-objs    := $(patsubst %.cpp,%.o,$(wildcard common/*.cpp))
common-headers := $(wildcard common/*.h)

%.o: %.cpp $(common-headers)
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -Icommon -c $< -o $@

# $(1): exercise directory
define BUILD_EXERCISE
.PHONY: $(1)

$(1): $(1)/main

$(1)-objs    := $$(patsubst %.cpp,%.o,$$(wildcard $(1)/*.cpp))
OBJS          = $$($(1)-objs)
$(1)-headers := $$(wildcard $(1)/*.h)

$$($(1)-objs): $$($(1)-headers)

$(1)/main: $$($(1)-objs) $$(common-objs)
    $$(CXX) $$(CXXFLAGS) $$(LDFLAGS) -o $$@ $$^ $$(LDLIBS)
endef
$(foreach e,$(EXERCISES),$(eval $(call BUILD_EXERCISE,$(e))))

.PHONY: clean
clean:
    rm -f $(MAINS) $(OBJS) $(common-objs)

It looks a bit complicated but it's not. The only trick is the $$ in the BUILD_EXERCISE macro. It is needed because the macro is expanded twice by make. Everything else is straightforward:

  • Related