Reputation: 1864
I'm new to Makefile. While trying to write a generic Makefile which could be used in most of my projects with least modification, I encountered a problem (simplified as the following):
My "project" looks like:
proj/
src1.cpp
subdir1/
src2.cpp
Makefile
Part of the Makefile
:
OBJ := bin/src1.o bin/subdir1/src2.o
OBJ_DIR := bin/ bin/subdir1/
PROGRAMS := prog1
define compile_template =
$(1)/%.o: %.cpp
mkdir -p $$(@D)
$$(CXX) $$(CXXFLAGS) -c $$< -o $$@
endef
define PROGRAM_template =
$(1): $$(OBJ)
$$(CXX) $$(LDFLAGS) $$^ -o $$@ $$(LDLIBS)
endef
$(foreach odir,$(OBJ_DIR),$(eval $(call compile_template,$(odir))))
$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))
And the error is:
gmake: *** No rule to make target `bin/src1.o', needed by `proj1'. Stop.
Another question is should I wrote my own Makefile or use automake etc if I only compile in particular machines (So I have control to the compiler, OS, ...)?
Upvotes: 0
Views: 622
Reputation: 101051
The best way to debug issues like this (problems with eval) is to replace the $(eval ...)
function with a call to $(info ...)
. This will print out the text that make is parsing and it's usually pretty obvious what your problem is. If you rewrite your eval lines to this:
$(foreach odir,$(OBJ_DIR),$(info $(call compile_template,$(odir))))
$(foreach prog,$(PROGRAMS),$(info $(call PROGRAM_template,$(prog))))
(and fixing your obvious syntax error, the space between :
and =
in the first line) you see:
bin//%.o: %.cpp
mkdir -p $(@D)
$(CXX) $(CXXFLAGS) -c $< -o $@
bin/subdir1//%.o: %.cpp
mkdir -p $(@D)
$(CXX) $(CXXFLAGS) -c $< -o $@
prog1: $(OBJ)
$(CXX) $(LDFLAGS) $^ -o $@ $(LDLIBS)
From this you can see the prog1
depends on bin/src1.o
and bin/subdir1/src2.o
so make wants to build bin/src1.o
. It looks through your rules, but in make's internal matching syntax bin//%.o
does not match bin/src1.o
because of the extra slash.
Change your assignment to remove the trailing slash and it should work better:
OBJ_DIR := bin bin/subdir1
Upvotes: 3