I have source in a bunch of subdirectories like:
src/widgets/apple.cpp
src/widgets/knob.cpp
src/tests/blend.cpp
src/ui/flash.cpp
In the root of the project I want to generate a single Makefile using a rule like:
%.o: %.cpp
$(CC) -c $<
build/test.exe: build/widgets/apple.o build/widgets/knob.o build/tests/blend.o src/ui/flash.o
$(LD) build/widgets/apple.o .... build/ui/flash.o -o build/test.exe
When I try this it does not find a rule for build/widgets/apple.o
. Can I change something so that the %.o: %.cpp
is used when it needs to make build/widgets/apple.o
?
The reason is that your rule
%.o: %.cpp
...
expects the .cpp file to reside in the same directory as the .o your building. Since test.exe in your case depends on build/widgets/apple.o (etc), make is expecting apple.cpp to be build/widgets/apple.cpp.
You can use VPATH to resolve this:
VPATH = src/widgets
BUILDDIR = build/widgets
$(BUILDDIR)/%.o: %.cpp
...
When attempting to build "build/widgets/apple.o", make will search for apple.cpp in VPATH. Note that the build rule has to use special variables in order to access the actual filename make finds:
$(BUILDDIR)/%.o: %.cpp
$(CC) $< -o $@
Where "$<" expands to the path where make located the first dependency.
Also note that this will build all the .o files in build/widgets. If you want to build the binaries in different directories, you can do something like
build/widgets/%.o: %.cpp
....
build/ui/%.o: %.cpp
....
build/tests/%.o: %.cpp
....
I would recommend that you use "canned command sequences" in order to avoid repeating the actual compiler build rule:
define cc-command
$(CC) $(CFLAGS) $< -o $@
endef
You can then have multiple rules like this:
build1/foo.o build1/bar.o: %.o: %.cpp
$(cc-command)
build2/frotz.o build2/fie.o: %.o: %.cpp
$(cc-command)