I have a simple project that looks something like this
.
├── build
│ ├── file1.o
│ └── one
│ ├── file1.o
│ └── file2.o
├── .depend
├── Makefile
└── src
├── file1.cpp
└── one
├── file1.cpp
└── file2.cpp
The Makefile is something like this:
# Get all of the source files
SRC = $(shell find src/ -name "*.cpp")
# Get all of the object files
OBJ = $(subst src,build,$(SRC:.cpp=.o))
$(OBJ):
#mkdir -p $(shell dirname $#)
g++ -g -c $(subst build,src,$(subst .o,.cpp,$#)) -o $#
all: depend build
build: $(OBJ)
gcc -o project $^
depend:
g++ -MM $(SRC) > .depend
sed -i 's/.\/src/.\/build\//g' .depend
sinclude .depend
I am attempting to generate makefile dependencies by running g++ -MM src/file1.cpp src/one/file1.cpp src/one/file2.cpp > .depend, and it generates the following directives:
file1.o: src/file1.cpp <other headers>
file1.o: src/one/file1.cpp <other headers>
file2.o: src/one/file2.cpp <other headers>
The problem with this, is that build/file1.o does not match file1.o, and as a result, changing src/file1.cpp or any of the headers it depends on does not cause the object file to be rebuilt. At first I thought it might have been an issue where sinclude .depend was run before the .depend file was generated, but the problem persists even if I run make depend followed by make build. From everything I've read, there are no g++ arguments or options that would preserve the path of the name.
Is it possible to generate a dependency file this way, or is this a fundamentally incorrect approach to building a project?
I took a look at the answers for the question this question was marked as a possible duplicate of, but it seems that question is asking how to create a complete makefile for a project, whereas my issue is not with the creation of a Makefile, but rather an issue with gcc -MM dependency generation. The answers to that question do not address my problems.
What about:
# Get all of the source files
SRC = $(shell find src/ -name "*.cpp")
# Get all of the object files
OBJ = $(patsubst src/%.cpp,build/%.o,$(SRC))
.PHONY: all
all: project
project: $(OBJ)
gcc -o $# $^
$(OBJ): build/%.o: src/%.cpp
#mkdir -p $(dir $#)
g++ -g -c $< -o $#
.depend: $(SRC)
g++ -MM $^ > $# && \
sed -Ei 's#^(.*\.o: *)src/(.*/)?(.*\.cpp)#build/\2\1src/\2\3#' $#
include .depend
Dependencies computation
The sed command substitutes any:
file.o: src/file.cpp ...
by:
build/file.o: src/file.cpp ...
and any:
file.o: src/X/Y/Z/file.cpp ...
by:
build/X/Y/Z/file.o: src/X/Y/Z/file.cpp ...
The target is directly .depend and it has all source files as dependencies such that it is automatically rebuilt if missing or older than any source file. No need to use the depend phony target or to add it as a pre-requisite of all (make automatically tries to rebuild files included with include, if needed).
Note
I added some GNU make features (patsubst, static pattern rule, systematic use of automatic variables...) Rework the non-supported ones if you use another make.
Here are three approaches.
One, modify the output with sed (similar to Renaud Pacalet's answer):
depend:
g++ -MM $(SRC) | sed 's/.*: src\([^ ]*\)cpp/build\1o: src\1cpp/' > .depend
Two, use a shell loop:
STEMS := file1 one/file1 one/file2
depend:
rm -f .depend
for x in $(STEMS); do g++ -MM -MT build/$$x.o src/$$x.cpp >> .depend; done
Three, a Make approach:
DEPENDENCIES := $(addsuffix -depend,$(STEMS))
clear-depend:
rm -f .depend
depend: $(DEPENDENCIES)
%-depend: clear-depend
g++ -MM -MT build/$*.o src/$*.cpp >> .depend
(My favorite approach is to have a separate dependency file for each object file, instead of one big .depend file. It has several advantages, but it takes some time to explain, and it's also tricky if there are name collisions in your source tree, such as file1.cpp and file1.cpp.)
I use the following sequence for my build:
define req
$(subst ..,__,$(dir build-$(TARGET)$(build_dir_ext)/$(1)))%.o: $(dir $1)%.cpp
mkdir -p $$(dir $$(subst ..,__,$$#))
$$(CXX) -MM $$(CXXFLAGS) $$< -MT $$(subst ..,__,$$#) > $$(patsubst %.o,%.d,$$(subst ..,__,$$#))
$$(CXX) $$(CXXFLAGS) $$< -c -o $$(subst ..,__,$$#)
endef
$(eval $(foreach x,$(OBJ),$(call req,$(x))))
As a result make is now able to handle a path which can be "outside" the source tree, simply by using '__' instead of '..' and the build dir is set accordingly to the found patterns, so there is no problem with src and build anymore. I need the "outside" files to use a source pool where the local build dir is under the root of source pool and project directory.
In hope that helps...
EDIT 1: Why replacing '..'
Think of the following source tree:
./sourcepool/lib1/src/one.cpp
./sourcepool/project/build
If your Makefile is in the ./sourcepool/project path and one of the OBJ is "../lib1/src/one.o" the Makefile should create a equivalent path in the build directory. That is, if '..' is used, not possible, because the path is then not longer in build but one depth higher. If replacing .. with __ the result is as following:
./sourcepool/project/build/__/lib1/src/one.o
This makes it possible to not copy or link all used dirs to the local project and build file tree.
Related
I have a project for school and I want to write a Makefile, I have seen some examples of using Makefile with multiple source directories and multiple executables but still could not implement it properly to my Makefile.
PS: I'm using doctest for the unit testing (and I can't change it).
Here is the project structure (and I can't change it):
.
├── bin
├── build
├── extern
│ └── doctest.h
├── include
│ ├── file1.hpp
│ └── file2.hpp
├── src
│ ├── file1.cpp
│ └── file2.cpp
├── tests
│ ├── file1-test.cpp
│ └── file2-test.cpp
└── Makefile
I have the following directories:
bin: for all the executables.
build: for all the objects (.o).
extern: for the doctest header (this is where I would have stored any other library)
include: for all the headers (.hpp).
src: for all the classes (.cpp).
tests: for all the unit tests (also .cpp)
You can see file1.cpp as a class, file1.hpp as the class header and file1-test.cpp as the unit tests for the class.
In the exemple above I have 2 tests files but at the very end of the project I'll have a lot more, and for each test file I'll have an executable.
My goals:
I want to run make and compile all the units tests (all the .cpp in the tests/ directory).
And I want all the executables to be stored in the bin/ directory and all the binary files in the build/ directory.
Here is my Makefile:
BIN_DIR = ./bin/
BUILD_DIR = ./build/
EXTERN_DIR = ./extern/
INCLUDE_DIR = ./include/
SOURCE_DIR = ./src/
TESTS_DIR = ./tests/
vpath %.cpp $(SOURCE_DIR) $(TESTS_DIR)
CXX = clang++
CXXFLAGS = -Wall -std=c++11 -g -O3 -I$(INCLUDE_DIR) -I$(EXTERN_DIR)
EXEC_FILES = file1-test file2-test
BIN = $(addprefix $(BIN_DIR), $(EXEC_FILES))
all: $(BIN) | $(BIN_DIR)
$(BUILD_DIR)%.o: %.cpp | $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -c -o $# $^
$(BIN_DIR) $(BUILD_DIR):
mkdir -p $#
$(BIN_DIR)file1-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file1-test.o
$(CXX) -o $# $^
$(BIN_DIR)file2-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file2.o $(BUILD_DIR)file2-test.o
$(CXX) -o $# $^
clean:
-rm -f $(BIN_DIR)* $(BUILD_DIR)*
It's working well but I feel like it's doing redondant stuff that i could avoid with more knownledge in the Makefile art, especially here:
$(BIN_DIR)file1-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file1-test.o
$(CXX) -o $# $^
$(BIN_DIR)file2-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file2.o $(BUILD_DIR)file2-test.o
$(CXX) -o $# $^
For the moment this Makefile is correct because I only have 2 executables, but I'll end up with 15+ and I dont want to have 15 times this for each executable:
$(BIN_DIR)xxx-test: $(BUILD_DIR)xxx.o etc.
$(CXX) -o $# $^
What I exactly need ...:
Basically, I need to write a generic rule that will fetch all the appropriated dependencies for a given target.
After reading multiple posts I think it's all about auto-dependencies.
I'm pretty sure the final result would look like this, but sadly I can't make it works in my case:
$(BIN_DIR)%: ???
#$(CXX) -o $# $^
I already looked at this (and many other posts about the subject): http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/, but I still can't figure it out.
So how can I write an expression that will do the job, can someone give me a working exemple or something similar ?
EDIT 1:
Based on this post: Makefile (Auto-Dependency Generation).
I added these lines to my Makefile:
SRC = $(wildcard $(SOURCE_DIR)*.cpp)
SRC += $(wildcard $(TESTS_DIR)*.cpp)
The idea is to fetch all the .cpp from the source directories (src and tests). Then I added -MDD option to my CXXFLAGS variable to create a .d file for each target (atleast it's what I thought it's doing):
CXXFLAGS = -Wall -std=c++11 -g -O3 -I$(INCLUDE_DIR) -I$(EXTERN_DIR) -MMD
And finally, I added this:
$(BIN_DIR)%: $(SRC)
$(CXX) -o $# $^
-include $(SRC:.cpp=.d)
What I expect it to do:
Create a .d file with all the dependencies for each target.
Fetch the dependencies in the .d file and transform them to .o to get all the objects needed for the given target.
But it seems that it's not doing what I'm expecting.
EDIT 3:
After some changes I end up with this Makefile:
BIN_DIR := bin/
BUILD_DIR := build/
EXTERN_DIR := extern/
INCLUDE_DIR := include/
SOURCE_DIR := src/
TESTS_DIR := tests/
DEP_DIR := .dep/
DEPENDS := $(patsubst %.o, $(BUILD_DIR)$(DEP_DIR)%.d, $(notdir $(wildcard $(BUILD_DIR)*.o)))
EXE := $(addprefix $(BIN_DIR), Coord-test Fourmi-test)
OBJS_1 := $(addprefix $(BUILD_DIR), Coord.o)
OBJS_2 := $(addprefix $(BUILD_DIR), Coord.o Fourmi.o)
CXX := clang++
CXXFLAGS := -Wall -std=c++11 -g -O3 -I$(INCLUDE_DIR) -I$(EXTERN_DIR)
vpath %.cpp $(SOURCE_DIR) $(TESTS_DIR)
all: $(EXE)
$(BUILD_DIR):
mkdir -p $# $#/$(DEP_DIR)
$(BIN_DIR):
mkdir -p $#
$(BUILD_DIR)%.o: %.cpp | $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -MMD -MP -MF $(BUILD_DIR)$(DEP_DIR)$(notdir $(basename $#).d) -c $< -o $#
$(BIN_DIR)%: $(BUILD_DIR)%.o | $(BIN_DIR)
$(CXX) -o $# $^
$(BIN_DIR)Coord-test: $(OBJS_1)
$(BIN_DIR)Fourmi-test: $(OBJS_2)
.PRECIOUS: $(BUILD_DIR)%.o
-include $(DEPENDS)
clean:
-rm -f $(BIN_DIR)* $(BUILD_DIR)* $(BUILD_DIR)$(DEP_DIR)*
It's working but I'll have to add OBS_X for each new executable.
I also wanted factorize this, but I don't know if it's possible ? If someone could tell me.
$(BIN_DIR)%: $(BUILD_DIR)%.o | $(BIN_DIR)
$(CXX) -o $# $^
$(BIN_DIR)Coord-test: $(OBJS_1)
$(BIN_DIR)Fourmi-test: $(OBJS_2)
Since you know that you will always have a foo-test.o to build a foo-test program, you can write your pattern rule like this:
$(BIN_DIR)%: $(BUILD_DIR)%.o
$(CXX) -o $# $^
However, there's no way make can infer what OTHER objects might be needed to build these executables. You'll just have to tell it. So for the above examples you can add this:
$(BIN_DIR)file1-test: $(BUILD_DIR)file1.o
$(BIN_DIR)file2-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file2.o
You don't need to put the recipe here, this is just adding more prerequisites to these targets. You also don't have to put in the $(BUILD_DIR)file1-test.o etc. because this is inferred from the pattern rule.
But, if you do have other object files you need to use you'll have to list them explicitly, there's no way around it.
Can I configure my makefile in a way that it automatically compiles and links foo/bar.cpp if a target includes #include "foo/bar.hpp"?
Details: I have a makefile for a project structured like this:
src/
|-- program1/
| |-- main.cpp
| |-- makefile
|-- modules/
| |-- module1/
| | |-- foo.cpp
| | |-- foo.hpp
| |-- module1/
| | |-- bar.cpp
| | |-- bar.hpp
Currently my makefile for program1 contains a list of all the *.cpp files of all the modules it uses, which is kind of hard and error-prone to maintain and to keep in sync with my includes.
However, in my code, following the #include commands would provide an exact dependency-tree. For every *.hpp there is a corresponding *.cpp that I need to compile and link.
Can this process of compilation be automated via the makefile? May auto-dependencies help me out?
The makefile in question:
# compiler settings
CXX = g++
CXXFLAGS = -std=c++14
# object file generation path
tmpDir = .objs
# modules path
modPath = ../modules
# Names of modules and files to be compiled
names := \
main.o \
module1/foo.o \
module2/bar.o
# prepend tmpDir
names := $(addprefix $(tmpDir)/, $(names))
# Linking
main: $(names)
$(CXX) $(CXXFLAGS) -o main $^
# Rule for main file
$(tmpDir)/main.o: main.cpp
#mkdir -p $(tmpDir)
$(CXX) $(CXXFLAGS) -c main.cpp -o $# -I "$(modPath)"
# rules for module files
$(tmpDir)/%.o: $(modPath)/%.cpp
mkdir -p $(dir $#)
$(CXX) $(CXXFLAGS) -c $< -o $#
clean:
rm -rf *.o main $(tmpDir)
I'd like to avoid to manually set names.
A common way to automate generating the file names is using a $(wildcard ...) or some $(shell ...) command to scan the directories.
Based on the Makefile you linked I think you can track the dependencies using GCC with the -MMD -MP flags something like this:
# compiler settings
CXX = g++
# use flags to generate dependency files
CXXFLAGS = -std=c++14 -MMD -MP
# object file generation path
tmpDir = .objs
# modules path
modPath = ../modules
# Names of modules and files to be compiled
names := main.o
names += $(patsubst $(modPath)/%.cpp,%.o,$(shell find $(modPath) -iname "*.cpp"))
# prepend tmpDir
names := $(addprefix $(tmpDir)/, $(names))
# there should be a dep file for every object file
deps := $(patsubst %.o,%.d,$(names))
all: main
# Linking
main: $(names)
$(CXX) $(CXXFLAGS) -o main $^
# Rule for main file
$(tmpDir)/main.o: main.cpp
#mkdir -p $(tmpDir)
$(CXX) $(CXXFLAGS) -c main.cpp -o $# -I "$(modPath)"
# rules for module files
$(tmpDir)/%.o: $(modPath)/%.cpp
mkdir -p $(dir $#)
$(CXX) $(CXXFLAGS) -c $< -o $#
# include the dependencies if they exist
-include $(deps)
clean:
rm -rf *.o main $(tmpDir) $(deps)
Every compile command that uses the -MMD -MP flags will generate a dependency file corresponding to the output file (except with a .d extension).
regarding: *Currently my makefile for program1 contains a list of all the *.cpp files of all the modules it uses, which is kind of hard and error-prone to maintain and to keep in sync with my includes.
However, in my code, following the #include commands would provide an exact dependency-tree. For every *.hpp there is a corresponding *.cpp that I need to compile and link.
Can this process of compilation be automated via the makefile? May auto-dependencies help me out?*
In the makefile, you could use the output of a call to the find command to obtain a list of all the (for instance) *.cpp files in the directories below the modules directory rather than hard-coding the list.
I refined Galik's answer a bit. Now it behaves much like what I was searching for.
Instead of defining names manually, I invoke a search for files. The results then filters to match only *.cpp files that have a *.hpp file with the same name. This ignores all files containing the tests:
# find *.hpp files
names := $(shell find $(modPath) -iname "*.hpp")
# replace extension .hpp -> .cpp
names := $(patsubst %,%.cpp,$(basename $(names)))
# filter nonexistent *.cpp files
names := $(wildcard $(names))
I have a somewhat complicated source directory, and have written a makefile to compile it:
├── include
│ ├── subinc
│ │ ├── test_y.h
│ │ └── test_z.h
│ ├── test_w.h
│ └── test_x.h
├── makefile
├── src
│ ├── test_w.cpp
│ └── test_x.cpp
├── src2
│ ├── test_y.cpp
│ └── test_z.cpp
└── test.cpp
The makefile as shown below is working. But, I'm a bit confused why. It doesn't seem to be using $(DEPS), since it gives paths like ./include/./include/subinc/test_y.h when I echo it in the rule. That's obvious because of the patsubst line, but changing that to patsubst %,%,$(INCLUDES) breaks it too... (maybe that's the root of the whole problem!)
But, something funky happens when I remove that constant from the dependency list of the rule %.o, so the rule is just %.o: $(SOURCES). Upon running make, it uses the first item in $(SOURCES) as the target for every call to g++ creating object files:
$ make
g++ -c -o test.o test.cpp -I./include -I./include/subinc
g++ -c -o src/test_x.o test.cpp -I./include -I./include/subinc
g++ -c -o src/test_w.o test.cpp -I./include -I./include/subinc
g++ -c -o src2/test_z.o test.cpp -I./include -I./include/subinc
g++ -c -o src2/test_y.o test.cpp -I./include -I./include/subinc
I figured that makes sense, because $< is used.
But why does this only print the first in the dependency list when I take the second constant (of header files -- some even with bad format) out of the list?
My thought is that somehow make is intelligently matching the .cpp files in the list to the corresponding .h files in the list, and then removing them from the list each time it runs the rule....
Thanks
Makefile (working version, maybe full of bad practices...)
INCDIR=./include
SRCDIR=./src
CXX=g++
CXXFLAGS=-I$(INCDIR) -I$(INCDIR)/subinc
INCLUDES=$(shell find . -name "*.h" -o -name "*.hpp")
DEPS = $(patsubst %,$(INCDIR)/%,$(INCLUDES))
EXE=testexe
SOURCES=$(wildcard *.cpp) $(wildcard **/*.cpp)
OBJ=$(SOURCES:.cpp=.o)
####RULES
%.o: $(SOURCES) $(DEPS)
$(CXX) -c -o $# $< $(CXXFLAGS)
$(EXE): $(OBJ)
g++ -o $# $^ $(CXXFLAGS)
rm $(OBJ)
EDIT
If you'd like an MCVE for this, each test_*.h defines an empty class like
class T*{
T*(); //defined in test_*.cpp to print "T* created"
~T*(); //defined in test_*.cpp to print "T* destroyed"
};
And the main test.cpp file just creates a pointer to each of the classes, and then deletes it.
There are many issues here. First:
SOURCES=$(wildcard *.cpp) $(wildcard **/*.cpp)
GNU make uses simple globbing, which does not understand **. This behaves the same as *. Since you only have one level of subdirectory this works for you but if you add another (sub-subdirectory) level, this won't match it.
Second, this is wrong:
DEPS = $(patsubst %,$(INCDIR)/%,$(INCLUDES))
As you point out this changes the dependency paths from the (correct) ./include/xy/z.h to the (incorrect) ./include/./include/xy/z.h. I'm not sure why you're trying to change anything at all here: why not just use the INCLUDES variable content directly? Using $(patsubst %,%,$(INCLUDES)) is a no-op; it has no effect.
Third, you should be using simple expansion (:=) for these types of assignments, so that they are not rerun every time the variable is used.
Next, this is wrong:
%.o: $(SOURCES) $(DEPS)
$(CXX) -c -o $# $< $(CXXFLAGS)
This will expand to something like this after SOURCES are resolved:
%.o: test.cpp src/test_w.cpp src/test_x.cpp src2/test_y.cpp src2/test_z.cpp ./include/include/subinc/test_y.h $(DEPS)
$(CXX) -c -o $# $< $(CXXFLAGS)
What this means is that every object file depends on all source files (and all $(DEPS)). So if any source or header file ever changes ALL the object files will be rebuilt. Clearly that's not what you want.
Also, the reason it always compiles the same file is that the recipe uses $<, which represents the first prerequisite, and the first prerequisite here is test.cpp, so that's what's always compiled.
When you create a pattern rule, (at least) the first source file should (almost always) be a pattern as well, so that it changes along with the target to build each object file (in this case).
So, you want your pattern rule to look like this:
%.o: %.cpp $(INCLUDES)
$(CXX) -c -o $# $< $(CXXFLAGS)
Of course this does mean that every object file depends on all header files, so if you change any header file all your object files are rebuilt. Maybe that's OK; if not you'll need to do something more advanced.
Lastly, you asked why it your makefile seems to work properly if you create bogus paths in the $(DEPS) variable. Here's why: because those paths don't exist, make decides that your pattern rule doesn't apply (since not all the prerequisites can be created) and so it ignores your pattern rule completely.
Once that happens, make's default pattern rule for how to build an object file takes over, and that default rule builds things for you properly. However, you may notice that if you modify any of the header files, make won't rebuild your object files (because it doesn't know about that prerequisite relationship).
This is my current makefile:
# Compiler #
CXX = g++
DEBUG = -g
LFLAGS =
CXXFLAGS = -Wall
# Directories #
SRCDIR = src/
INCDIR = include/
BUILDDIR = build/
BINDIR = bin/
# Objects #
OBJ_NAMES = main.o dfa.o dfaException.o state.o
OBJS = $(addprefix $(BUILDDIR), $(OBJ_NAMES))
# Output #
NAME = pract3
TARGET = $(BINDIR)pract3
# Clean #
ifeq ($(OS),Windows_NT)
RM = del /q /s $(BUILDDIR:/=\)*.o $(BINDIR:/=\)$(NAME)*
else
RM = rm -rf $(BUILDDIR)*.o $(TARGET)*
endif
# Files #
$(TARGET): $(OBJS)
$(CXX) $(CXXFLAGS) $(LFLAGS) $(OBJS) -o $(TARGET)
$(BUILDDIR)%.o: $(SRCDIR)%.cpp
$(CXX) $(CXXFLAGS) $(LFLAGS) -c $< -o $#
clean:
$(RM)
And this is my project tree:
Porject/
bin/
build/
doc/
...
include/
connection.hpp
dfa.hpp
dfaException.hpp
state.hpp
src/
dfa.cpp
dfaException.cpp
main.cpp
state.cpp
Makefile
Readme
Now, I'm having three "problems".
First I want my makefile to create the bin and build directories just in case they aren't. I guess I just have to use:
mkdir $(BUILDDIR)
mkdir $(BINDIR)
But where should I put them ? And also, how can I prevent mkdir and rm (or del in windows) messages like "Cant find ..." or "x directory already exists ... "
Second, I'm guessing I can read the objects name from src/ (converting the .cpp to .o), but how can I read the file names from a directory ?
Last, I have one template class: connection.hpp (all functions are in the header). This file is included in state.hpp using: #include "../include/connection.hpp". I ran make one time with all correct and then I purposely make a syntax error in connection.hpp. Then I ran make again, but It only compiled the target file using the .o files in build without any error. Everytime I want to edit connection.hpp I have to use make clean and then make. Is there any better way to do this ?
If you need a directory to exist before you can proceed, simply put
mkdir -p ${DIRECTORY}
before you need it in your rule. If the directory already exists, mkdir -p will happily do nothing.
Likewise, if you use rm -f FILE, it should not complain if FILE does not exist in the first place.
There is no portable way to create a variable that holds the names of all files in a directory. But you are already using GNU Make features anyway, so you can just use
SOURCES = $(wildcard ${SRCDIR}/*.cpp)
and then
OBJECTS = $(SOURCES:.cpp=.o)
to transform them into object file names. You'll probably want to replace the leading directory name as well, I guess.
You didn't list any *.hpp files as prerequisites in your make file. You can either manually add them like
foo.o: foo.cpp bar.hpp baz.hpp
but that becomes unpleasant very quickly. Another trick is to use the compiler to tell you the headers (transitively) #included by a file. If you are using GCC, you can run
gcc -MM foo.cpp
to have it output above make-file snippet. You can put a pattern rule like the following
%.deps: %.cpp
${CXX} -MM ${CPPFLAGS} $< > $#
into your make-file and then include the generated *.deps files.
include $(SOURCES:.cpp=.deps)
GNU Make will be smart enough to first parse the make-file, recognize that the *.deps files don't exist and therefore cannot be included but figure out that there is a rule to generate them. So it will execute that rule and then continue parsing the make-file.
I have learned that trick from Peter Miller's great article Recursive Make Considered Harmful which is a good read if you want to learn how to write good make-files.
I'm currently trying to re-write a makefile for a project that I've inherited to make the source tree neater and easier to work with. At the moment the source tree is something like this:
Project/
----bin/
----build/
----include/
----main.h
----part1.h
----part2.h
----part3.h
----src/
----main.cpp
----part1.cpp
----Subdir/
----part2.c
----Subdir2/
----part3.cpp
What I want is a rule in my makefile that will find all of the .cpp and .c files in my src directory and compile them to a flat directory of objects in the build directory. At the moment I have the following in my makefile but this seems to miss a number of the cpp files:
BUILDDIR = build
$(BUILDDIR)/%.o : src/**/%.cpp | $(BUILDDIR)
$(BUILDDIR)/%.o : src/%.cpp | $(BUILDDIR)
$(CXX) $(CFLAGS) -c $< -o $# $(INCS)
$(BUILDDIR)/%.o : src/**/%.c | $(BUILDDIR)
$(BUILDDIR)/%.o : src/%.c | $(BUILDDIR)
$(CC) $(CFLAGS) -c $< -o $# $(INCS)
At the moment when I run make -n it seems that it has detected main.cpp and part1.cpp but none of the ones in subdirectories. Make then goes on to try and load the files according to later rules in the Makefile.
Due to the number of files in the project I'd rather not write a list of them manually but if it comes to that I might have to.
You can explicitly define directories with source files. For example:
DIRS = src src/subdir1 src/subdir2
SEARCHC = $(addsuffix /*.c ,$(DIRS))
SEARCHCPP = $(addsuffix /*.cpp ,$(DIRS))
SRCS = $(wildcard $(SEARCHC))
SRCS += $(wildcard $(SEARCHCPP))
And to let make find your sources files add to your Makefile:
vpath %.c $(DIRS)
vpath %.cpp $(DIRS)
I am also using special target to check my Makefile:
help:
#echo 'Sources:'
#echo $(SRCS)
Make's wildcard function could be of use to you here.
See also
Sources from subdirectories in Makefile