Reputation: 503
I apologize for the ambiguous title, I couldn't think of a simple way to phrase it due to my lack of knowledge in GNU make.
I'm writing a simple Makefile for a small project, and I'm trying to enable it to generate individual objects by using their base name (without path) as the target:
$(BASE_OBJS) : %.o : $(SRC_DIR)/%.c $(OBJDIR) $(INCLUDES)
@echo $(CC): [$(notdir $<)] '->' [$(notdir $@)]
@$(CC) -c $< $(CFLAGS) -o $(OBJDIR)/$@
The problem is that the 'make' app obviously expects the target object to be present in the current folder, but it's actually found in the $(OBJDIR) subfolder. The causes those targets to unnecessarily rebuild.
Alternatively, this rule does check for the object's existence in the right place:
$(OBJS) : $(OBJDIR)/%.o: $(SRC_DIR)/%.c $(INCLUDES)
@echo $(CC): [$(notdir $<)] '->' [$(notdir $@)]
@$(CC) -c $< $(CFLAGS) -o $@
But it can't be used for running things like 'make main.o', as $(OBJS) includes the full path of the objects, so it only allows things like 'make output/main.o'.
If it's a duplicate then I'm sorry, I was looking for a while and couldn't find a similar question.
For reference, these are the variable definitions:
BASE_SRC=$(notdir $(SOURCES))
BASE_OBJS = $(BASE_SRC:%.c=%.o)
OBJS = $(BASE_OBJS:%.o=$(OBJDIR)/%.o)
Upvotes: 0
Views: 1631
Reputation: 100836
Your main set of targets and prerequisites must use the full path, because that's how make works. So you must have something like:
$(OBJS) : $(OBJDIR)/%.o: $(SRC_DIR)/%.c $(INCLUDES)
@echo $(CC): [$(notdir $<)] '->' [$(notdir $@)]
@$(CC) -c $< $(CFLAGS) -o $@
Now if in addition you want to be able to run a simple make foo.o
, then to do that you should define extra "alias" targets for the real targets. These rules only exist for the short-hand, they don't actually do anything. Something like:
$(BASE_OBJS) : %.o : $(OBJDIR)/%.o
Upvotes: 1