Moving object files and dependency into a separate folder using Make - makefile

I have a series of source code directories as follows
main --- src1
|-src2
|-src3
My make system generates dependancy files (*.d) as well as object files (*.o).
The dependacy files are generated using the following code.
%.d: %.c
#echo calculating dependencies for $*.o
#if $(CC) $(CPPFLAGS) -MM -MG -MP -MT $*.o $< -MF temp.d; then \
echo $# "`cat temp.d`" >$#; \
rm temp.d; \
else \
rm -f temp.d; \
rm -f $#; \
false; \
fi;
I would like to move the dependency files and object files into two separate folders objects and dependency.
They are at the same level as main folder. How do I do this using Make subsystem

You should take a look at:
http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
Maybe the best is to generate dependency files as a side effect of compilation, instead of explicitly generating them in a specific rule, this way:
You're calling gcc once instead of twice per target
If the dependencies does not exists, it means than nothing has been built so everything will be built, dependencies are useless at this stage
While building, gcc -MMD will generate .d files
Make make include all .d files using a -include so it won't whine if they don't exists but read them if they do
A simple mv can move them whenever you want right after the compilation.
So I preconize dropping your %.d: %.c rule, dropping dependencies to .d files, and just include all .d files from the dependency directory.
Also I'll avoid if; then; else; fi, just do a simple:
gcc ... -MMD ...
cp ...
(By putting the -MMD and other dependency related flags in a variable like DEPFLAGS.)
If the gcc fails, the cp won't be executed, make will just whine about gcc failing and exit.
Then, to move your object files, what about a simple:
place_where_you_want_your_obj_files/%.o: place_where_gcc_put_them/%.o
mv $< $#

Related

Makefile - a command in a command?

I have an embarrassingly simple makefile question but I can't google it due to lack of knowledge - I don't know the words for things I don't know.
Basically, I want to run the makefile in the current directory, look into the ./SRC directory for source files and when everything is finished, move the object files into the ./OBJ directory.
Makefile:
move_obj:
mv -f -t ./OBJ_DIR ./$(OBJ_FILES)
file.o: other_file.h
$(CC) $(CFLAGS) $(CPPFLAGS) -c file.c
move_obj
I want to call "move_obj" after compiling the source files but since I don't know what
result: dependency
evaluation
actually represents (and all makefile introduction guides I've found state "This is what a makefile looks like, off you go then"), I don't know why this isn't working. I assume I need some evaluate command or need to define a function or...?
Thanks for any help in advance.
You can do this by creating another rule for example move, like below
all: $(EXECUTABLE) move
$(EXECUTABLE): $(OBJECTFILES)
$(CC) -o $# $<
$(OBJECTFILES): $(SOURCEFILES)
$(CC) $(CFLAGS) -c -o $# -I $(INCLUDE_PATH) $<
# Move the .o to Object directory #
move:
$(MV) $(OBJECTFILES) $(OBJECT_PATH)
But by doing the above, you will defeat the purpose of the Makefile.
Since your rule is dependent on .o, Make will look for .o in current directory and not find it (because you've moved it) and thus rebuild.
To avoid this, you should output it to ./obj directory and use it from there.
Something like
gcc -g -Wall -o obj/foo.o -c src/foo.c -I ./include
gcc -g -Wall -o obj/main.o -c src/main.c -I ./include
gcc -o exe obj/foo.o obj/main.o -lanylibrary
Below is the makefile doing the same.
C_FLAGS := -g -Wall -Wextra
CC := gcc
RM := rm
LINKFLAGS := -lanylibrary
.PHONY: $(TARGET) clean
VPATH:= ./src/ ./obj/ ./include/
# Path for .c , .h and .o Files
SRC_PATH := ./src/
OBJ_PATH := ./obj/
INC_PATH := -I ./include
# Executable Name
TARGET := exe
# Files to compile
OBJ1 := foo.o \
main.o
OBJ := $(patsubst %,$(OBJ_PATH)%,$(OBJ1))
# Build .o first
$(OBJ_PATH)%.o: $(SRC_PATH)%.c
#echo [CC] $<
#$(CC) $(C_FLAGS) -o $# -c $< $(INC_PATH)
# Build final Binary
$(TARGET): $(OBJ)
#echo [INFO] Creating Binary Executable [$(TARGET)]
#$(CC) -o $# $^ $(LINKFLAGS)
# Clean all the object files and the binary
clean:
#echo "[Cleaning]"
#$(RM) -rfv $(OBJ_PATH)*
#$(RM) -rfv $(TARGET)
Refer to this answer for a better understanding
EDIT:
You can also output your executable to directory, add the following changes to your Makefile.
Ensure that the bin directory is created beforehand, and not deleted by clean.
# Path for .c , .h and .o Files, and ./bin directory
BIN_PATH := ./bin
# Executable Name
TARGET := $(BIN_PATH)/exe
# Clean all the object files and the binary
clean:
#echo "[Cleaning]"
#$(RM) -rfv $(OBJ_PATH)*
#$(RM) -fv $(TARGET)
If you want to build a target(move_obj) after another(file.o), add the move_obj to the dependency list of file.o so that the commands under the move_obj will be executed.
So your Makefile should be:
file.o: other_file.h move_obj
$(CC) $(CFLAGS) $(CPPFLAGS) -c file.c
move_obj:
mv -f -t ./OBJ_DIR ./$(OBJ_FILES)
As Colonel Thirty Two mentioned in the comment section, instead of compiling and then move, you can build the object files in the required directory
file.o: other_file.h
$(CC) $(CFLAGS) $(CPPFLAGS) -c file.c -o ./$(OBJ_FILES)/$#
This is flawed in various ways.
result normally is an actual file that should be present after the recipe is executed. If the file is already there and is not older than any of its dependencies, make does nothing. So instead of creating a file somewhere and then moving it around with another rule, make sure the rule creates it where it should FINALLY be. Otherwise make can never check whether it has to rebuild it (and always will). In this case, use the -o flag of the compiler to directly create it where it should be (e.g. -o $(OBJ_DIR)/file.o)
dependency should list ALL files that are needed to build the result, so make really rebuilds it if ANY of these files changed. In your case, at least file.c is missing from the dependency list
In order to place files in a directory, you should make sure it exists. you could do it like this:
$(OBJ_DIR):
mkdir -p $(OBJ_DIR)
$(OBJ_DIR)/file.o: $(OBJ_DIR) file.c other_file.h
$(CC) $(CFLAGS) $(CPPFLAGS) -c file.c -o $(OBJ_DIR)/file.o
Your move_obj recipe, although not suitable in this case, would be a PHONY target, meaning it does not create a file. If you need such rules, mark them accordingly by mentioning them as dependency of the special target .PHONY:
.PHONY: move_obj
The reason for this is that you could (by accident) have a file named move_obj in your working directory. In that case, make would decide there's nothing to do for move_obj, and this is not what you want. Marking it as phony tells make that this rule does not create its target and the recipe must be executed no matter what.
All in all, your question comes down to misunderstanding a Makefile as kind of a script. It is not. It's a declarative file that tells make what has to be done in order to build files (your evaluation block) and when this needs to be done (your dependency block). It's better not to try to misuse a Makefile as a script.

Makefile with Fortran - src and bin directories

I'm having some trouble understanding how to design my makefile to build my project the way I want to. Specifically, I can't figure out how to keep all source files in a src directory, while putting all binaries in a bin directory except the linked executable, which goes in the project root.
This is my makefile:
# Compiler options
FC := mpif90
FFLAGS := -O3 -g -Wall -Warray-bounds -ffixed-line-length-none -fbounds-check
VPATH := src
BINDIR := bin
# Define file extensions
.SUFFIXES:
.SUFFIXES: .f .o .mod
# All modules
OBJS := $(BINDIR)/ratecoeffs.o $(BINDIR)/interpolation.o $(BINDIR)/io.o $(BINDIR)/eedf.o $(BINDIR)/single_particle.o $(BINDIR)/physics.o $(BINDIR)/random.o $(BINDIR)/mpi.o $(BINDIR)/precision.o $(BINDIR)/populations.o
# Build rules
all: runner | $(BINDIR)
$(BINDIR):
mkdir -p $(BINDIR)
$(BINDIR)/%.o: $(VPATH)/%.f | $(BINDIR)
$(FC) $(FFLAGS) -c $^ -o $#
runner: $(OBJS)
clean:
#rm -rf $(BINDIR)
Running make builds everything allright - it finds all source files in src and puts all .o files in bin - but the module files (.mod) that are generated by the compiler are put in the project root instead of in the bin directory. I realize I could just specify a rule to place them there, but that messes with the build order, and will sometimes break the build.
What is the "correct" way to get this behavior?
And yes, I've looked at autotools and automake, but I've never used them before and they seem to be overkill for this project. As I couldn't find any good tutorials on how they work (no, I didn't like the tutorial on gnu.org) I'd prefer if I could avoid having to learn this tool just to get this work...
Assuming your underlying Fortran compiler is gfortran, use the -J command line option.
$(FC) $(FFLAGS) -c $^ -o $# -J$(BINDIR)
With an eye to the future, you may be better off creating a MODDIR or similar variable, that you use instead of BINDIR. Object code (*.o) and mod files have different roles to play in later compilation and linking steps - in larger projects they are often kept separate.
It would be probably more in the sense of the make system to change into the obj-directory and do the compilation from there. Via the VPATH option you can let make to find your source files automatically. You could easily call your makefile recursively from the right directory. Below you find a trivial example which would be straightforward to adapt to your case. Please note, that it only works with GNU make.
ifeq (1,$(RECURSED))
VPATH = $(SRCDIR)
########################################################################
# Project specific makefile
########################################################################
FC = gfortran
FCOPTS =
LN = $(FC)
LNOPTS =
OBJS = accuracy.o eqsolver.o io.o linsolve.o
linsolve: $(OBJS)
$(LN) $(LNOPTS) -o $# $^
%.o: %.f90
$(FC) $(FCOPTS) -c $<
.PHONY: clean realclean
clean:
rm -f *.mod *.o
realclean: clean
rm -f linsolve
accuracy.o:
eqsolver.o: accuracy.o
io.o: accuracy.o
linsolve.o: accuracy.o eqsolver.o io.o
else
########################################################################
# Recusive invokation
########################################################################
BUILDDIR = _build
LOCALGOALS = $(BUILDDIR) distclean
RECURSIVEGOALS = $(filter-out $(LOCALGOALS), $(MAKECMDGOALS))
.PHONY: all $(RECURSIVE_GOALS) distclean
all $(RECURSIVEGOALS): $(BUILDDIR)
+$(MAKE) -C $(BUILDDIR) -f $(CURDIR)/GNUmakefile SRCDIR=$(CURDIR) \
RECURSED=1 $(RECURSIVEGOALS)
$(BUILDDIR):
mkdir $(BUILDDIR)
distclean:
rm -rf $(BUILDDIR)
endif
The principle is simple:
In the first part you write your normal makefile, as if you would create the object files in the source directory. However, additionally you add the VPATH option to make sure the source files are found (as make will be in the directory BUILDDIR when this part of the makefile is processed).
In the second part (which is executed first, when the variable RECURSED is not set yet), you change to the BUILDIR directory and invoke your makefile from there. You pass some helper variables (e.g. the current directory) and all make goals, apart of those, which must be executed from outside BUILDDIR (e.g. distclean and the one creating BUILDDIR itself). The rules for those goals you specify also in the second part.

Adding dependencies changes the target to the first C file

Consider the following makefile:
.SUFFIXES:
SRC:=../Src
OBJ:=../Obj
# Sources
SOURCES := $(SRC)/App/a.c $(SRC)/App/b.c $(SRC)/App/c.c
HEADERS := $(wildcard $(SRC)/App/*.h)
# Directories
INC_DIRS := $(SRC)/App
OBJ_INC_DIRS := $(INC_DIRS:$(SRC)/%=$(OBJ)/%)
# Objects
OBJECTS := $(SOURCES:$(SRC)%=$(OBJ)%.obj)
# Dependencies
DEPS := $(SOURCES:$(SRC)%.c=$(OBJ)%.d)
-include $(DEPS)
GCC_INCLUDES := $(foreach directory, $(INC_DIRS), -I$(directory))
all: target
target: $(OBJECTS)
touch target
#Objects
$(OBJ)%.c.obj: $(SRC)%.c
#echo Compiling $#
#touch $#
# Dependencies
$(OBJ)%.d: $(SRC)%.c
#echo Checking dependencies for $<
#gcc -MM $< $(GCC_INCLUDES) -MT '$(patsubst %.d,%.c.obj,$#)' -MT '$#' -MF '$#'
#[ ! -s $# ] && rm -f $#
# Creating directory tree before checking dependencies
$(DEPS):|$(OBJ_INC_DIRS)
$(OBJ_INC_DIRS):
#mkdir $#
clean:
echo clean
#rm $(OBJ_INC_DIRS)
When running the first time, I get:
Checking dependencies for ../Src/App/a.c
Checking dependencies for ../Src/App/b.c
Checking dependencies for ../Src/App/c.c
clean
Compiling ../Obj/App/a.c.obj
Compiling ../Obj/App/b.c.obj
Compiling ../Obj/App/c.c.obj
touch target
It's ok, but now, make again (without modifying any file):
make: `../Obj/App/a.c.obj' is up to date.
Now if I modify the file a.c
Checking dependencies for ../Src/App/a.c
Compiling ../Obj/App/a.c.obj
target isn't remade !
It's like my file a.c is the target but it isn't... Can someone explain me what's wrong here?
If I remove the include to the DEPS, I observe the expected behavior...
Thanks
EDIT
By putting the include at the end as mentioned by #Beta works but now I added the target clean and show the result...
I'll have to do some experiments to be sure, but I think the problem is:
-include $(DEPS)
...
all: target
You include $(DEPS) before the first target. So if you modify a.c, Make sees that it must rebuild a.d, then since it includes that file it must start over, and now a.c.obj is an earlier target than all.
Try moving -include $(DEPS) to the end of the makefile.
EDIT:
(Two small points: your clean rule is incorrect, since it tries to rm a directory, and I would do make clean; make all rather than make all, since I am not certain that Make promises to build targets in the given order in all cases.)
Yes, this makefile will rebuild the DEPS even when running clean. The makefile includes those files and has a rule for them, so if they are missing or out of date it must rebuild them and restart, no matter what the target is. The best way to deal with this is by Advanced Auto-Dependency Generation; basically, the commands that build dependency files go in the %.obj rule, so that a.d is a side effect of building a.c.obj. It's a sophisticated technique, not obvious, but it works beautifully. (Let us know if you try this and have trouble setting it up.)

Makefile (Auto-Dependency Generation)

just for quick terminology:
#basic makefile rule
target: dependencies
recipe
The Problem: I want to generate the dependencies automatically.
For example, I am hoping to turn this:
#one of my targets
file.o: file.cpp 1.h 2.h 3.h 4.h 5.h 6.h 7.h 8.h another.h lots.h evenMore.h
$(COMPILE)
Into this:
#one of my targets
file.o: $(GENERATE)
$(COMPILE)
and I'm not too sure if it's possible..
What I do know:
I can use this compiler flag:
g++ -MM file.cpp
and it will return the proper target and dependency.
so from the example, it would return:
file.o: file.cpp 1.h 2.h 3.h 4.h 5.h 6.h 7.h 8.h another.h lots.h evenMore.h
however, 'make' does NOT allow me to explicitly write shell code in the target or dependency section of a rule :(
I know there is a 'make' function called shell
but I can't quite plug this in as dependency and do parsing magic because it relies on the macro $# which represents the target.. or at least I think that’s what the problem is
I've even tried just replacing the "file.cpp" dependency with this makefile function and that won't work either..
#it's suppose to turn the $# (file.o) into file.cpp
THE_CPP := $(addsuffix $(.cpp),$(basename $#))
#one of my targets
file.o: $(THE_CPP) 1.h 2.h 3.h 4.h 5.h 6.h 7.h 8.h another.h lots.h evenMore.h
$(COMPILE)
#this does not work
So all over google, there appear to be two solutions. both of which I don't fully grasp.
From GNU Make Manual
Some Site that says the GNU Make Manual one is out-of-date
So my ultimate question is: Is it possible to do it the way I want to do it,
and if not, can somebody break down the code from one of these sites and explain to me in detail how they work. I'll implement it one of these ways if I have to, but I'm weary to just paste a chunk of code into my makefile before understanding it
Newer versions of GCC have an -MP option which can be used with -MD. I simply added -MP and -MD to the CPPFLAGS variable for my project (I did not write a custom recipe for compiling C++) and added an "-include $(SRC:.cpp=.d)" line.
Using -MD and -MP gives a dependency file which includes both the dependencies (without having to use some weird sed) and dummy targets (so that deleting header files will not cause errors).
To manipulate the filenames when you already know what the dependencies should be, you can use a pattern rule:
file.o: %.o : %.cpp 1.h 2.h 3.h 4.h 5.h 6.h 7.h 8.h another.h lots.h evenMore.h
$(COMPILE)
And you can reuse the rule for other targets:
# Note these two rules without recipes:
file.o: 1.h 2.h 3.h 4.h 5.h 6.h 7.h 8.h another.h lots.h evenMore.h
anotherFile.o: 4.h 9.h yetAnother.h
file.o anotherFile.o: %.o : %.cpp
$(COMPILE)
But if you want Make to figure out the list of dependencies automatically, the best way (that I know of) is Advanced Auto-Dependency Generation. It looks like this:
%.o : %.cc
#g++ -MD -c -o $# $<
#cp $*.d $*.P; \
sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P; \
rm -f $*.d
-include *.P
Basically, when it builds file.o, it also builds file.d. Then it runs file.d through a bewildering sed command that turns the list of dependencies into a rule with no recipes. The last line is an instruction to include any such rules that exist. The logic here is subtle and ingenious: you don't actually need the dependencies the first time you build foo.o, because Make already knows that foo.o must be built, because it doesn't exist. The next time you run Make, it will use the dependency list it created last time. If you change one of the files so that there is actually a new dependency which is not in the list, Make will still rebuild foo.o because you changed a file which was a dependency. Try it, it really works!
Excellent answers but in my build I put the .obj files in a subdirectory based on build type (ie: debug vs. release). So for example, if I'm building debug, I put all the object files in a build/debug folder. It was a mind-numbing task to try to get the multiline sed command above to use the correct destination folder, but after some experimentation, I stumbled on a solution that works great for my build. Hopefully it'll help someone else as well.
Here's a snippet:
# List my sources
CPP_SOURCES := foo.cpp bar.cpp
# If I'm debugging, change my output location
ifeq (1,$(DEBUG))
OBJ_DIR:=./obj/debug
CXXFLAGS+= -g -DDEBUG -O0 -std=c++0x
else
CXXFLAGS+= -s -O2
OBJ_DIR:=./obj/release
endif
# destination path macro we'll use below
df = $(OBJ_DIR)/$(*F)
# create a list of auto dependencies
AUTODEPS:= $(patsubst %.cpp,$(OBJ_DIR)/%.d,$(CPP_SOURCES))
# include by auto dependencies
-include $(AUTODEPS)
.... other rules
# and last but not least my generic compiler rule
$(OBJ_DIR)/%.o: %.cpp
## Build the dependency file
#$(CXX) -MM -MP -MT $(df).o -MT $(df).d $(CXXFLAGS) $< > $(df).d
## Compile the object file
#echo " C++ : " $< " => " $#
#$(CXX) -c $< $(CXXFLAGS) -o $#
Now for the details:
The first execution of CXX in my generic build rule is the interesting one. Note that I'm not using any "sed" commands. Newer versions of gcc do everything I needed (I'm using gcc 4.7.2).
-MM builds the main dependency rule including project headers but not system headers. If I left it like this, my .obj file would NOT have the correct path. So I use the -MT option to specify the "real" path to my .obj destination. (using the "df" macro I created).
I also use a second -MT option to make sure the resulting dependency file (ie: .d file) has the correct path, and that it is included in the target list and therefor has the same dependencies as the source file.
Last but not least is the inclusion of the -MP option. This tell gcc to also make stubbed rules for each header solving the problem that occurs if I delete a header causing make to generate an error.
I suspect that since I'm using gcc for all the dependency generation instead of piping out to sed, my build is faster (although I've yet to prove that since my build is relatively small at this point). If you see ways I can improve upon this, I'm always open to suggestions. Enjoy
For the record, this is how I generate dependencies automatically now:
CPPFLAGS = -std=c++1y -MD -MP
SRC = $(wildcard *.cpp)
all: main
main: $(SRC:%.cpp=%.o)
g++ $(CPPFLAGS) -o $# $^
-include $(SRC:%.cpp=%.d)
The compiler flags -MD and -MP help do the trick.
First, you can have THE_CPP=$(patsubst %.o,%.cpp,$#)
Then you can run make -p to understand the builtin rules of make
A usual way of doing could be to generate the makefile dependencies into *.md files:
%.o: %.c
$(COMPILE.c) $(OUTPUT_OPTION) $< -MMD -MF $(patsubst %.c,%.md,$#)
and later in your Makefile including them with something like
-include $(wildcard *.md)
But you can also consider using other builders like omake and many many others
WOOO! I did manage to get the code in Beta's post to work on a small test project.
I should note, for anyone else who may come across this,
If you're using the bash shell(which I was), you will need to add an escape character in front of the pound sign to escape from making the rest of the expression a comment. (see 4th line of code)
%.o : %.cpp
g++ -c -MD -o $# $<
cp $*.d $*.P; \
sed -e 's/\#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $*.d >> $*.P; \
rm -f $*.d
-include *.P
Now I want to share information that I found in Managing Projects with GNU Make, 3rd Edition. because it's points out some important issues on this matter, and supplies code that I still don't fully grasp yet.
A method appears in the book that is similar to the method found on the Make manual page.
It looks like this:
include $(subst .c,.d,$(SOURCES))
%.d: %.c
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\).o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
This is what I believe is happening.
Right away, 'make' wants to include a ".d" file for every source file.
Because no .d files initially exist, the chunk of code is ran again and again in order to create all the missing .d files.
This means make will start over again and again until every .d file is created and included in the makefile.
Each ".d" file is what Beta said: a target with a set of dependencies and NO recipe.
If a header file is ever changed, those rules that are included in, will need the dependencies updated first. This is what throws me off a bit, how is it that the chunk of code is able to be called again? It is used to update .d files, so if a .h file changes how does it get called? Aside from this, I realize that the default rule is used to compile the object. Any clarifications/misconceptions to this explanation are appreciated.
Later in the book it points out problems with this method, and problems that I believe also exist in the Advanced Auto-Dependency Generation implementation.
Problem 1: It's inefficient. 'make' must restart every time it makes a .d file
Problem 2: make generates warning messages for all the missing .d files- Which is mostly just a nuisance and can be hidden by adding a "-" in front of the include statement.
Problem 3: If you delete a src file because it's no longer needed, 'make' will crash the next time you try to compile because some .d file has the missing src as a dependency, and because there is no rule to recreate that src, make will refuse to go any further.
They say a fix to these issues is Tromey's method, but the code looks very different from the code on the website. Perhaps it's just because they used some macros, made it a function call, and wrote it slightly different. I'm still looking into it, but wanted to share some discoveries I've made so far. Hopefully this opens up a little bit more discussion, and gets me closer to the bottom of all this.
A simple and elegant solution, inclusive of a detailed explanation of how it works, is available here.
DEPDIR := .deps
DEPFLAGS = -MT $# -MMD -MP -MF $(DEPDIR)/$*.d
%.o : %.cpp
%.o : %.cpp $(DEPDIR)/%.d | $(DEPDIR)
g++ -c $(DEPFLAGS) $(CFLAGS) $<
$(DEPDIR): ; #mkdir -p $#
DEPFILES := $(SRCS:%.c=$(DEPDIR)/%.d)
$(DEPFILES):
include $(wildcard $(DEPFILES))
I prefer to use $(shell ...) function with find. Here is a sample of one of my Makefiles:
SRCDIR = src
OBJDIR = obj
LIBDIR = lib
DOCDIR = doc
# Get Only the Internal Structure of Directories from SRCDIR
STRUCTURE := $(shell find $(SRCDIR) -type d)
#Filter-out hidden directories
STRUCTURE := $(filter-out $(shell find $(SRCDIR)/.* -type d),$(STRUCTURE))
# Get All Files From STRUCTURE
CODEFILES := $(addsuffix /*,$(STRUCTURE))
CODEFILES := $(wildcard $(CODEFILES))
## Filter Only Specific Files
SRCFILES := $(filter %.c,$(CODEFILES))
HDRFILES := $(filter %.h,$(CODEFILES))
OBJFILES := $(subst $(SRCDIR),$(OBJDIR),$(SRCFILES:%.c=%.o))
DOCFILES := $(addprefix $(DOCDIR)/, \
$(addsuffix .md, \
$(basename $(SRCFILES))))
# Filter Out Function main for Libraries
LIBDEPS := $(filter-out $(OBJDIR)/main.o,$(OBJFILES))
In this approach, I first get all the internal directory structure, with any depth. Then I get all files inside the Structure. At this time, I can use filter, filter-out, addsuffix, etc, to get exactly what I need at each time.
This example covers *.c files, but you can change it to *.cpp as well.
Building on the content of the Auto-Dependency Generation article referenced in comments on a previous post at I've created an annotated makefile project which includes a generic Makefile annotated with comments and implemented for a simple project with 3 .c files and 2 .h files. See full Makefile content below. Simple projects should be able to just customize the TODO section
# See http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
# for the template used to start this file
# -- TODO: customize the list below for your project ---
# List of source .c files used with the project
SRCS := main.c file1.c file2.c
# The aplication generated
APPNAME = depend-generation-test
# -- End of customization section ---
# Replace .c extension on SRCS to get objfiles using gnu make pattern rules and substitution references.
# See https://www.gnu.org/software/make/manual/html_node/Pattern-Intro.html#Pattern-Intro for pattern rules and
# https://www.gnu.org/software/make/manual/html_node/Substitution-Refs.html#Substitution-Refs for substitution references overview
OBJFILES := $(SRCS:%.c=%.o)
# Build the app you've specified in APPNAME for the "all" or "default" target
all : $(APPNAME)
default : $(APPNAME)
# Remove all build intermediates and output file
clean : ; #rm -rf $(APPNAME) *.o
# Build the application by running the link step with all objfile inputs
$(APPNAME) : $(OBJFILES)
$(CC) $(LDFLAGS) $^ -o $(APPNAME)
# Add all warnings/errors to cflags default. This is not required but is a best practice
CFLAGS += -Wall -Werror
# The below content is from http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
# with the following changes:
# 1) Added comments
# 2) Removed TARGET_ARCH from COMPILE.c since it's no longer listed in the [default rules](https://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html#Catalogue-of-Rules) and [isn't documented](https://lists.gnu.org/archive/html/help-make/2010-06/msg00005.html)
# Original content below is:
# Copyright © 1997-2019 Paul D. Smith Verbatim copying and distribution is permitted in any medium, provided this notice is preserved.
# The directory (hidden) where dependency files will be stored
DEPDIR := .deps
# Flags passed to gcc to automatically build dependencies when compiling
# See https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html for detail about variable names
# $# references the target file of the rule and will be "main.o" when compiling "main.c"
# $* references the stem of the rule, and will be "main" when target is "main.o"
DEPFLAGS = -MT $# -MMD -MP -MF $(DEPDIR)/$*.d
# Rules for compiling a C file, including DEPFLAGS along with Implicit GCC variables.
# See https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html
# and see https://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html#Catalogue-of-Rules
# for the default c rule
COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) -c
# Delete the built-in rules for building object files from .c files
%.o : %.c
# Define a rule to build object files based on .c or dependency files by making the associated dependency file
# a prerequisite of the target. Make the DEPDIR an order only prerequisite of the target, so it will be created when needed, meaning
# the targets won't get rebuilt when the timestamp on DEPDIR changes
# See https://www.gnu.org/software/make/manual/html_node/Prerequisite-Types.html for order only prerequesites overview.
%.o : %.c $(DEPDIR)/%.d | $(DEPDIR)
$(COMPILE.c) $(OUTPUT_OPTION) $<
# Create the DEPDIR when it doesn't exist
$(DEPDIR): ; #mkdir -p $#
# Use pattern rules to build a list of DEPFILES
DEPFILES := $(SRCS:%.c=$(DEPDIR)/%.d)
# Mention each of the dependency files as a target, so make won't fail if the file doesn't exist
$(DEPFILES):
# Include all dependency files which exist, to include the relevant targets.
# See https://www.gnu.org/software/make/manual/html_node/Wildcard-Function.html for wildcard function documentation
include $(wildcard $(DEPFILES))

Problem generating dependencies in Makefile using -MM

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.
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.
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.

Resources