Reputation: 2162
I am trying to write a makefile, suppose I have 4 source files in a directory src/app/
:
src/app/file1.cpp
src/app/file2.cpp
src/app/file3.cpp
src/app/file4.cpp
and I want to create different object files (i.e. file1.o
, file2.o
etc.) into another directory called obj/
. In the makefile, I am defining the variables like this:
$(SRC) := $(wildcard src/app/*.cpp)
$(OBJ) := $(addprefix obj/,$(notdir $(SRC:.cpp=.o)))
and my commands are like this:
all: $(OBJ)
$(OBJ): $(SRC)
$(CC) $(CFLAGS) -I/src/app/app.h -c $< -o $@
so when I run make
, I see these operations:
g++ -g -Wall -I/src/app/app.h -c src/app/file1.cpp -o obj/file1.o
g++ -g -Wall -I/src/app/app.h -c src/app/file1.cpp -o obj/file2.o
g++ -g -Wall -I/src/app/app.h -c src/app/file1.cpp -o obj/file3.o
g++ -g -Wall -I/src/app/app.h -c src/app/file1.cpp -o obj/file4.o
You can see, the object files have different names but the source file is the same. How do I fix it ?
Please note that I can't use %.o: %.cpp
since I have other targets in my makefile for different purposes.
Upvotes: 0
Views: 309
Reputation: 6405
If you can't use
obj/%.o: src/app/%.cpp
then the second simplest way is to add $(OBJ):
to the front:
$(OBJ): obj/%.o: src/app/%.cpp
It's called "static pattern rules" - look it up in the GNU Make manual.
Upvotes: 3
Reputation: 154045
The $<
variable picks up the first dependency. It is used with generic targets which have variable targets and produce different results. The compile target would match a pattern as target and have a generic dependency. The first target doesn't change in your case.
Your constraint of not being able to use a generic rule is entirely defeating the purpose of the $<
variable. A somewhat naive work-around is to translate the destination name back into the source, e.g.,
$(OBJ): $(SRC)
$(CC) $(CFLAGS) -I/src/app/app.h -c $(@:%.o=%.cpp) -o $@
The problem with that approach is that no all object files depend on all source files. As a result, every time one of the source files is changed all object files are produced. For tiny projects and source that may be viable. On anything which I'd consider a real project neither of these conditions holds.
My understanding on your statement on not being able to use pattern rules is that you already have rules for the same pattern but you need to build some targets with some special rules. A work around for that situation is to build targets with a custom suffix which actually build something different and just use a marker file to prevent unnecessary rebuilds. For example:
all: $(OBJ:%=%.custom)
%.o.custom: %.cpp
$(CC) $(CFLAGS) -W -I/src/app/app.h -c $< -o $(@:%.custom=%) && touch $@
Upvotes: 0
Reputation: 2162
I have found a way to solve this (thanks to Zereges for the idea):
$(RGAOBJ): $(RGASRC)
$(CC) $(CFLAGS) -I/src/app/app.h -c \
$(addprefix src/app/,$(notdir $(@:.o=.cpp))) -o $@
I think there is a better way to do.
So any other pointer will be helpful.
Upvotes: 0