tags:

views:

418

answers:

2

Hi,

I am new to Makefiles and g++ and i am struck with a problem while generating dependencies of the project files using -MM flag. I'm posting the Makefile i am using for your consideration. Please take a look.

OUTPUT_ROOT := output/
SOURCE_ROOT := source/

TITLE_NAME := TestProj 

SOURCES := \
 MyFile.cpp \
 stdAfx.cpp \
 Main.cpp \

OUT_DIR  := $(OUTPUT_ROOT)

OUT_O_DIR := $(OUT_DIR)

OBJS = $(SOURCES:%.cpp=$(OUT_O_DIR)%.o)
DEPS = $(OBJS:%.o=%.d)
DIRS = $(subst /,/,$(sort $(dir $(OBJS))))
SOURCE_TARGET = $(SOURCES:%.cpp=$(SOURCE_ROOT)%.cpp)
OUTPUT_TARGET = $(OUT_DIR)$(TITLE_NAME)

#---------------------------------------------------------------------
# executables
#---------------------------------------------------------------------
MD := mkdir -p
RM := rm
CC := g++

#---------------------------------------------------------------------
# rules
#---------------------------------------------------------------------
.PHONY: clean directories objects title

all: directories objects title

directories:
 @$(MD) $(DIRS)

clean:
 $(RM) -rf $(OUT_DIR)

$(OBJS): $(SOURCE_TARGET)
 @$(CC) -c $< -o $@

$(DEPS): $(SOURCE_TARGET)
 @$(CC) -c -MM $< > $(DEPS)

-include $(DEPS)

objects:$(OBJS) $(DEPS)

title: $(OBJS)
 @$(CC) $< -o $@

I tried several options and sooo many times. I googled for the solution but couldn't find any.

Is using "-MM" flag to generate dependencies the right option?? If not please suggest me the right way to generate the dependencies. I wanted to generated dependencies automatically because my project will have sooo many files. I thought it is the better option than to write down evey dependency manually.

These are the errors i am getting

g++: stdAfx.d: No such file or directory
g++: Main.d: No such file or directory
make: *** No rule to make target `stdAfx.d', needed by `objects'.  Stop.

Thanks in advance.

+4  A: 

It looks like you are trying to generate a dependency file (called *.d, by your makefile rules) for each .cpp file. This is not my understanding of how a dependencies file is used.

Use the -M option to generate a single dependencies file for your project and then include the dependencies file.

DEPS = $(OUR_DIR)/make.dep

$(DEPS): $(SOURCE_TARGET)
    @$(CC) -M $(SOURCE_TARGET) > $(DEPS)

include $(DEPS)

edit Your dependency file should also depend on your headers

$(DEPS): $(SOURCE_TARGET) $(HEADER_TARGET)
    @$(CC) -M $(SOURCE_TARGET) > $(DEPS)

where HEADER_TARGET is defined the same as SOURCE_TARGET. That way, when a header file is changed the dependency file is rebuilt.

mcdave
Thank you mcdave, thats a very good trick. i think Generating a single file is better than generating a lot... Thank you again.
Jabez
@mcdave: Just want to point out that `-MM` excludes system headers ( more or less ) possibly making the build faster since there's allot less files to 1) check 2) process for building the depends list. For example create foo.cpp with some stl includes and run `g++ -M foo.cpp` to see it spit out a list of close to 100 dependencies, none of which ever change, all of which make will have to check on each build.
Robert S. Barnes
@Robert: Thanks for the tip -- I didn't know this and will update my makefiles to make them more efficient!
mcdave
+3  A: 

For a beginner, you are doing some exotic stuff. You should start simple and only use code in your Makefile that you 100% understand and trust. Even on a large project with hundreds of files you will not spend much time maintaining the Makefile.

Variables assigned with := are immediately expanded--all the $(VAR) values are substituted into the variable's value during assignment. Variables assigned with = are expanded when they are used, so they can do things like refer to variables that aren't defined yet.

The -MM flag for g++ will generate a Makefile dependency line, e.g. foo.o: foo.cc foo.hh, but I've never found it useful. I had a phony "dependency" target that generated a single dependency file. Your idea of making a bunch of *.d files with those one line dependencies might work, but you'll end up with a lot of those files.

The error you are getting is from g++, not from make. It's because you are using $(DEPS) as if it were a single file when it's the entire list of *.d files. What happens is this line:

@$(CC) -c -MM $< > $(DEPS)

gets expanded to:

g++ -c -MM MyFile.cpp > MyFile.d stdAfx.d Main.cpp

mcdave just posted the code I have used to generate a dependency file. You can either switch to the single dependency file style, or change your -MM command to this:

@$(CC) -MM $< > $@

You may also have to fix the -include statement because I don't think it supports a list of files to include.

Ken Fox
Thank you Ken, i'm using single file now instead of soo many multiple files. Thank you telling the diff b/w '=' and ':=', that sure helps me alot.
Jabez