Harvey Dent
Harvey Dent

Reputation: 339

C/C++ Makefile: How to build dependencies between with .c files and object files in other directories?

here is my .c and .o files hierarchy:

---/src/IRBuild/main.c
                func1.c
                func2.c
---/inclue/main.h
           func1.h
           func2.h

---/build/IRBuild/main.o
                  func1.o
                  func2.o 
                  irbuild

Below is my Makefile under ~/src/IRBuild/, I had build compile dependency with .c and .h files, which means whenever .c or .h files are changed. "make" will rebuild the object files. BUT because I output .o files to ~/build/IRBuild/, instead of current directory, "make" will rebuild all the .o files everytime I do make.

How should I build dependencies with .o files in other directories? Only re-compile the particular file when it's .c, .h, or .o file changed?

Stuck here for two days, thanks a lot!

   EXE=irbuild

# G++ as default compiler
CC=g++

# Compile time flags
CXXFLAGS = -g -Wall

# Library paths in addition to /usr/lib
LFLAGS=-std=c++0x

# Libraries to link into executable:
#LIBS = -lmylib -lm

# Include files directory other than /usr/include
INCLUDES=-I../../include/

SRC=$(wildcard *.cpp)
OBJ=$(SRC:.cpp=.o)
DEP=$(OBJ:.o=.d)
BUILD=../../build/IRBuild
TESTS=../../tests/

OBJS :=$(foreach obj, $(OBJ), $(BUILD)/$(obj))

.PHONY: depend clean

all: $(EXE)
        cp $(EXE) $(TESTS)
$(EXE): $(OBJ)
        $(CC) $(CXXFLAGS) $(LFLAGS) $(INCLUDES) -o $(EXE) $(OBJS)

.cpp.o:
        $(CC) $(CXXFLAGS) $(LFLAGS) $(INCLUDES) -c $< -o $(BUILD)/$@

clean:
        rm -f $(OBJS) $(DEP) $(EXE)

depend: .depend
.depend: $(SRC)
        rm -f ./.depend
        $(CC) $(CXXFLAGS) $(LFLAGS) $(INCLUDES) -MM $^ -MF ./.depend;
include .depend
   

Upvotes: 2

Views: 1849

Answers (1)

Etan Reisner
Etan Reisner

Reputation: 80911

You are violating rule 2 from http://make.mad-scientist.net/rules.html which is why it rebuilds them all the time it thinks they don't exist. (Listing $(OBJ) in the prereqs and $(OBJS) in the recipe linking line is also a bit of a makefile "smell".)

You need to use a rule that correctly maps from your target files to their prerequisites.

Either manually or using vpath.

There are a number of ways to make the manual method work depending on how much effort you want to put in to setting things up. The vpath method is likely to be a fair bit easier.

Using vpath should just require using $(OBJS) as the $(EXE) prereqs and then adding vpath %.cpp . and vpath %.h ../../include or something like that.

Upvotes: 1

Related Questions