ytm
ytm

Reputation: 503

How can I make a Makefile file target depend on a different path?

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

Answers (1)

MadScientist
MadScientist

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

Related Questions