Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem generating dependencies in Makefile using -MM

Tags:

makefile

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.

like image 355
Jabez Avatar asked Dec 30 '09 12:12

Jabez


People also ask

What are the makefile tools to be used to automate the creation of dependencies?

Use GNU Automake It generates dependencies using the compiler if it can, or using makedepend if not.

What are makefile dependencies?

A dependency is a file that is used as input to create the target. A target often depends on several files. A command is an action that make carries out. A rule may have more than one command, each on its own line.

What does $@ mean in makefile?

The file name of the target of the rule. If the target is an archive member, then ' $@ ' is the name of the archive file. In a pattern rule that has multiple targets (see Introduction to Pattern Rules), ' $@ ' is the name of whichever target caused the rule's recipe to be run.

What is $$ in makefile?

Double dollar sign If you want a string to have a dollar sign, you can use $$ . This is how to use a shell variable in bash or sh . Note the differences between Makefile variables and Shell variables in this next example.


2 Answers

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.

like image 182
mcdave Avatar answered Oct 27 '22 09:10

mcdave


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.

like image 3
Ken Fox Avatar answered Oct 27 '22 09:10

Ken Fox