makefile compiles all files instead of the last edited ones - c++

Note that there are similar questions on SO, however I think my situation is different, moreover my Makefile is extremely simple and straight forward. I am new to Makefile.
Suppose I need to compile a project, that looks like this --
.
├── [4.0K] bin
├── [ 517] Makefile
├── [4.0K] obj
└── [4.0K] src
├── [ 117] func1.cpp
├── [ 76] func2.cpp
├── [ 137] global.h
└── [ 97] main1.cpp
and my Makefile looks like this --
CC := g++
CFLAGS := -g -Wall -std=c++0x
LDFLAGS := -lm
NAMES := func1.cpp func2.cpp main1.cpp
SRC := $(addprefix src/,$(NAMES))
OBJ := $(addprefix obj/,$(NAMES:.cpp=.o))
DEPS := $(OBJ:.o=.d)
.PHONY: clean all debug
all: prog
debug:
$(info $$SRC: ${SRC})
$(info $$OBJ: ${OBJ})
$(info $$DEPS: ${DEPS})
prog: bin/prog
bin/prog: $(OBJ)
$(CC) $^ -o $#
$(OBJ): $(SRC)
$(CC) $(CFLAGS) -I/src/global.h -c $(addprefix src/,$(notdir $(#:.o=.cpp))) -o $#
-include $(DEPS)
clean:
rm -rf bin/*
rm -rf obj/*
Suppose I opened a file func1.cpp and made some changes. When I invoke make it compiles all files, but it was supposed to compile only one (func1.cpp).
How do I fix this ?
Note: I need prog, bin/prog for a different reason, also I can't do recipes like obj/%.o: src/%.c because I might have different target from the subset of the same objects.

When you write a rule like:
$(OBJ): $(SRC)
cmd
which in your case is
obj/func1.o obj/func2.o obj/main.o : src/func1.cpp src/func2.cpp src/main1.cpp
cmd
The prerequisites don't get zipped across. That generates one rule for each target, with all of the prerequisites. That is:
obj/func1.o : src/func1.cpp src/func2.cpp src/main1.cpp
cmd
obj/func2.o : src/func1.cpp src/func2.cpp src/main1.cpp
cmd
obj/main.o : src/func1.cpp src/func2.cpp src/main1.cpp
cmd
Since src/func1.cpp is a prereq for all of the object files, they all get recompiled.
What you want instead is to use a static pattern rule:
obj/%.o : src/%.cpp
$(CC) $(CFLAGS) -I/src -c $< -o $#
Note that -I is for include directories, not include files.

Related

C++ Makefile with source in multiple directories and multiple executables

I have a small project for school and I want to write a decent 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.
Here is the directory structure:
.
├── bin (this is where i want the executables)
├── build (this is where i want the .o)
├── extern
│ └── doctest.h
├── include
│ ├── file1.hpp
│ └── file2.hpp
├── src
│ ├── file1.cpp
│ └── file2.cpp
├── tests
│ ├── file1-test.cpp
│ └── file2-test.cpp
└── Makefile
PS: I'm using doctest for the unit testing (and i can't change).
Here is my Makefile for the moment:
BIN_DIR = ./bin/
BUILD_DIR = ./build/
EXTERN_DIR = ./extern/
INCLUDE_DIR = ./include/
SOURCE_DIR = ./src/
TESTS_DIR = ./tests/
CXX = clang++-7
CXXFLAGS = -Wall -std=c++11 -g -O3 -I$(INCLUDE_DIR)
EXEC_FILES = file1 file2
BIN = $(addprefix $(BIN_DIR), $(EXEC_FILES))
all: $(BIN)
$(BIN_DIR) $(BUILD_DIR):
mkdir -p $#
$(BUILD_DIR)%.o: $(SOURCE_DIR)%.cpp | $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -c -o $# $^
$(BUILD_DIR)%.o: $(TESTS_DIR)%.cpp | $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -I$(EXTERN_DIR) -c -o $# $^
$(BIN_DIR)file1-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file1-test.o | $(BIN_DIR)
$(CXX) -o $# $^
$(BIN_DIR)file2-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file2.o $(BUILD_DIR)file2-test.o | $(BIN_DIR)
$(CXX) -o $# $^
clean:
rm -f $(BIN_DIR)* $(BUILD_DIR)*
It's working well but I feel like it's doing useless stuff that i could avoid with more knownledge in the Makefile art, sadly I don't have much time.
My goal:
I want to run make and compile all the units tests (all the .cpp in the tests/ directory) and the main program (see PS below).
I want all the executables in the bin/ directory and all the binary files in the build/ directory.
PS: I don't have my main executable yet but it should be stored in the src/ directory at the very end (and be compiled as well while running make).
EDIT 1:
Basically, my question is: How can I write generic rules to prevent copying this (see below) for every new executable in my project ?
$(BIN_DIR)file2-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file2.o $(BUILD_DIR)file2 test.o | $(BIN_DIR)
$(CXX) -o $# $^
EDIT 2:
After some changes, I ended up with this:
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++-7
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 $# $^
# The problem is here
$(BIN_DIR)%: $(BUILD_DIR)%.o
#$(CXX) -o $# $^
$(BIN_DIR) $(BUILD_DIR):
#mkdir -p $#
clean:
-#rm -f $(BIN_DIR)* $(BUILD_DIR)*
I understand this rule (see below) like this: Compile every target in EXEC_FILES to the bin/ directory, from his equivalent .o (obj) in the build/ directory.
$(BIN_DIR)%: $(BUILD_DIR)%.o
#$(CXX) -o $# $^
But in fact I need a rule that will: Compile every target in EXEC_FILES to the bin/ directory, from all their related .o (obj) in the build/ directory.

C++ Makefile auto-depencies with multiple executables

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.

C++ Makefile, is it possible to factorize it even more?

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.
Here is my 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), file1-test file2-test)
OBJS_1 := $(addprefix $(BUILD_DIR), file1.o)
OBJS_2 := $(addprefix $(BUILD_DIR), file1.o file2.o)
CXX := clang++
CXXFLAGS := -Wall -std=c++11 -g -O3 -I$(INCLUDE_DIR) -I$(EXTERN_DIR)
vpath %.cpp $(SOURCE_DIR) $(TESTS_DIR)
.PHONY: all clean
all: $(EXE)
$(BUILD_DIR) $(BIN_DIR) $(BUILD_DIR)$(DEP_DIR):
#mkdir -p $#
$(BUILD_DIR)%.o: %.cpp | $(BUILD_DIR) $(BUILD_DIR)$(DEP_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)file1-test: $(OBJS_1)
$(BIN_DIR)file2-test: $(OBJS_2)
.PRECIOUS: $(BUILD_DIR)%.o
-include $(DEPENDS)
clean:
-rm -rf $(BIN_DIR) $(BUILD_DIR)
So my questions are:
Is my Makefile following good practices ?
Is it optimized ? If no, how can I make it even better ?
For every new executable I've to add a OBJS_X variable and a target $(BIN_DIR)fileX-test: $(OBJS_X), can i get rid of it ? If yes can someone write me some generic rule, so I don't have to specify a variable and a target every time I want a new executable.
If I want to compile only one executable I have to use make bin/fileX-test. Is it possible to run only make fileX-test instead of make bin/fileX-test (but still building it in the bin directory) ? I tried to implement a rule like this: fileX-test: $(BIN_DIR)fileX-test but it's not working as I want, at the very end of the compilation it starts executing builtin rules and I don't know why. Can someone explain ?
Final answer:
This is what I considere a good answer, if it can help someone later:
BIN_DIR := bin/
BUILD_DIR := build/
EXTERN_DIR := extern/
INCLUDE_DIR := include/
SOURCE_DIR := src/
TESTS_DIR := tests/
DEP_DIR := $(BUILD_DIR).dep/
CXX := g++
CXXFLAGS := -Wall -std=c++11 -g -O3 -I$(INCLUDE_DIR) -I$(EXTERN_DIR)
DEPFLAGS := -MMD -MP -MF $(DEP_DIR)
vpath %.cpp $(SOURCE_DIR) $(TESTS_DIR)
file1-test_OBJECTS := $(addprefix $(BUILD_DIR), file1.o)
file2-test_OBJECTS := $(addprefix $(BUILD_DIR), file1.o file2.o)
EXE := $(patsubst %_OBJECTS, %, $(filter %_OBJECTS, $(.VARIABLES)))
.PHONY: all keep help check clean $(EXE)
all: $(EXE:%=$(BIN_DIR)%)
$(foreach E, $(EXE), $(eval $(BIN_DIR)$E: $($E_OBJECTS)))
$(foreach E, $(EXE), $(eval $E: $(BIN_DIR)$E ;))
$(BUILD_DIR) $(BIN_DIR) $(DEP_DIR):
#mkdir -p $#
$(BUILD_DIR)%.o: %.cpp | $(BUILD_DIR) $(DEP_DIR) $(BIN_DIR)
#$(CXX) $(CXXFLAGS) $(DEPFLAGS)$(#F:.o=.d) -c $< -o $#
$(BIN_DIR)%: $(BUILD_DIR)%.o
#$(CXX) -o $# $^
-include $(wildcard $(DEP_DIR)*.d)
keep: $(EXE:%=$(BUILD_DIR)%.o)
clean:
-#rm -rf $(BIN_DIR)* $(BUILD_DIR)* $(DEP_DIR)*
Mostly your makefile is pretty good. There are some simplifications you can make, but they're just syntax and not really performance etc.:
DEP_DIR := .dep/
You never use this by itself so if you change its definition to:
DEP_DIR := $(BUILD_DIR).dep/
you can simplify the references to it.
DEPENDS := $(patsubst %.o, $(BUILD_DIR)$(DEP_DIR)%.d, $(notdir $(wildcard $(BUILD_DIR)*.o)))
-include $(DEPENDS)
this seems complex. Why not get rid of DEPENDS and just write:
include $(wildcard $(DEP_DIR)*.d)
This:
#$(CXX) $(CXXFLAGS) -MMD -MP -MF $(BUILD_DIR)$(DEP_DIR)$(notdir $(basename $#).d) -c $< -o $#
is also complex. You can write it (if you simply DEP_DIR) as:
#$(CXX) $(CXXFLAGS) -MMD -MP -MF $(DEP_DIR)$(#F:.o=.d) -c $< -o $#
For:
.PRECIOUS: $(BUILD_DIR)%.o
I would definitely NOT use this. .PRECIOUS should be rarely, if ever, used. If you're trying to avoid object files being considered intermediate it's best to just list them directly as prerequisites, such as:
keep : $(EXE:$(BIN_DIR)%=$(BUILD_DIR)%.o)
But unless you have special need to look at these object files it doesn't hurt to let make delete them.
Regarding your question about shortcuts: the reason you see the behavior you do is that your target definition:
fileX-test: $(BIN_DIR)fileX-test
has no recipe attached to it, so make will try to find a recipe using an implicit rule. It finds built-in recipe for % : %.c, and because you set vpath it can find a %.c file that matches, so it uses it. To avoid this you can just give an empty recipe; replace the above with:
fileX-test: $(BIN_DIR)fileX-test ;
(note added semicolon).
Your main question is how to simplify this:
EXE := $(addprefix $(BIN_DIR), file1-test file2-test)
OBJS_1 := $(addprefix $(BUILD_DIR), file1.o)
OBJS_2 := $(addprefix $(BUILD_DIR), file1.o file2.o)
all: $(EXE)
$(BIN_DIR)file1-test: $(OBJS_1)
$(BIN_DIR)file2-test: $(OBJS_2)
You can do this automatically but doing so requires knowing the deeper parts of GNU make. You might find this set of blog posts interesting: http://make.mad-scientist.net/category/metaprogramming/ (start with the bottom / oldest and work your way up).
Replace the above with:
# Write one of these for each program you need:
file1-test_OBJECTS = file1.o
file2-test_OBJECTS = file1.o file2.o
# Now everything below here is boilerplate
EXE = $(patsubst %_OBJECTS,%,$(filter %_OBJECTS,$(.VARIABLES)))
all: $(EXE:%=$(BIN_DIR)%)
$(foreach E,$(EXE),$(eval $(BIN_DIR)$E: $($E_OBJECTS)))
$(foreach E,$(EXE),$(eval $E: $(BIN_DIR)$E ;))
.PHONY: $(EXE)
I am turning my comment into an answer to allow others to disapprove this view: I think CMake is better here for you. Look at this SO for some differences between Make and CMake and arguments for CMake.
Advantages related to your questions:
It will allow you more easily to follow good practices
It scales much better
You do not have to write so muc boilerplate for new executable added to your code
Building a single executable is possible, see this SO as a hint.

makefile: pattern rules for subdirectory

Here is my project:
project
|--- main.cpp
|--- makefile
|--- test
|--- Test.cpp
|--- Test.h
Here is the makefile:
g++1x:=g++ -std=c++14 -stdlib=libc++ -MMD -MP
cflags:= -Wall -lncurses
PATHS:=./ ./test/
TARGET:=matrix.out
SRC:=$(foreach PATH,$(PATHS),$(wildcard $(PATH)/*.cpp))
OBJDIR:=.obj
OBJ:=$(addprefix $(OBJDIR)/,$(notdir $(SRC:.cpp=.o)))
.PHONY: install
install: $(OBJDIR) $(TARGET)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(TARGET): $(OBJ)
$(g++1x) $(cflags) -o $# $^ -g
$(OBJDIR)/%.o: %.cpp
$(g++1x) -c -o $# $< -g
$(OBJDIR)/%.o: ./test/%.cpp
$(g++1x) -c -o $# $< -g
-include $(addprefix $(OBJDIR)/,$(notdir $(SRC:.cpp=.d)))
.PHONY: clean
clean:
rm -f $(TARGET)
rm -rf $(OBJDIR)
It works well but I have two questions:
1) Is it possible to avoid foreach for PATHS so that I can use the same makefile for all of cpp projects?
2) As you see, to generate main.o and Test.o I write two blocks:
$(OBJDIR)/%.o: ./test/%.cpp and $(OBJDIR)/%.o: %.cpp.
Is it possible to write only once?
I've tried as below but it doesn't work:
$(OBJDIR)/%.o: $(foreach PATH,$(PATHS),$(wildcard $(PATH)/%.cpp))
$(g++1x) -c -o $# $< -g
I've even tried like this but it doesn't work still:
$(OBJDIR)/%.o: %.cpp ./test/%.cpp
$(g++1x) -c -o $# $< -g
You should keep the source tree into your object tree. This way it will be easier to create global rules and keep dependencies.
# Use the shell find command to get the source tree
SOURCES := $(shell find * -type f -name "*.c")
OBJDIR := .objects
# Keep the source tree into the objects tree
OBJECTS := $(addprefix $(OBJDIR)/,$(SOURCES:.c=.o))
all: mytarget
mytarget: $(OBJECTS)
$(CC) $^ -o $#
# As we keep the source tree we have to create the
# needed directories for every object
$(OBJECTS): $(OBJDIR)/%.o: %.c
mkdir -p $(#D)
$(CC) -MMD -MP -c $< -o $#
-include $(OBJECTS:.o=.d)
$ make
mkdir -p .objects
cc -MMD -MP -c main.c -o .objects/main.o
mkdir -p .objects/test
cc -MMD -MP -c test/test.c -o .objects/test/test.o
cc .objects/main.o .objects/test/test.o -o mytarget
$ tree -a
.
├── main.c
├── Makefile
├── mytarget
├── .objects
│   ├── main.d
│   ├── main.o
│   └── test
│   ├── test.d
│   └── test.o
└── test
├── test.c
└── test.h
3 directories, 9 files
EDIT: You can reduce the number of mkdir to the minimum by adding the object directory as an order only prerequisites:
# Do not create the directory
$(OBJECTS): $(OBJDIR)/%.o: %.c
$(CC) -MMD -MP -c $< -o $#
# Every target finishing with "/" is a directory
$(OBJDIR)%/:
mkdir -p $#
# Add the "directory/" as an order only prerequisite
$(foreach OBJECT,$(OBJECTS),$(eval $(OBJECT): | $(dir $(OBJECT))))
Because I can't edit jmlemetayer's answer, here's how to extend the commands for projects with both C and CPP source:
Firstly to generate the object list, just apply the patsubst twice, once for each extension:
SRC_LST := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))
OBJECTS := $(addprefix $(OBJDIR)/,$(SRC_LST))
Then to handle both .cpp and .c files in the implicit rule for compiling:
.SECONDEXPANSION:
$(OBJECTS): $(OBJDIR)/%.o: $$(wildcard %.c*)
mkdir -p $(#D)
ifeq "$(suffix $<)" ".cpp"
$(CPP) -MMD -MP -c $< -o $#
else
$(CC) -MMD -MP -c $< -o $#
endif
If there is a better way I'm happy to update this.

Modify the makefile to include subdirectories

I'm working with a small program in c++ to learn the makefile.
The program has 2 source files (main.cpp and classf.cpp) and one header file (classf.h). All files are included in the project directory which is called "testmake". This is the generated makefile by eclipse on windlows:
CXXFLAGS = -O2 -g -Wall -fmessage-length=0
OBJS = main.o classf.o
LIBS =
TARGET = createPddl.exe
$(TARGET): $(OBJS)
$(CXX) -o $(TARGET) $(OBJS) $(LIBS)
all: $(TARGET)
clean:
rm -f $(OBJS) $(TARGET)
I would like to modify the makefile to accept new sub-directories, e.g, when I add a folder called "testmake/src" and move the file main.cpp inside it, folder called "testmake/csource" and move the classf.cpp inside it, and create a folder called "testmake/cheader" and move the classf.h inside it.
This makefile was genereated automatically by eclipse, and does not accept any changes. There for i have created manually a make file which is working with any c++ project that has a structure as tree.
I actually use this Makefile in general
CC := g++ # This is the main compiler
SRCDIR := src
BUILDDIR := build
TARGETDIR :=bin/
TARGET := pddlcrate
DATADIR := data
SRCEXT := cpp
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
CFLAGS := -g # -Wall
#LIB := -pthread -lmongoclient -L lib -lboost_thread-mt -lboost_filesystem-
mt -lboost_system-mt
INC := -I include
$(TARGET): $(OBJECTS)
#echo " Linking..."
#echo " $(CC) $^ -o $(TARGETDIR)$(TARGET) $(LIB)"; $(CC) $^ -o
$(TARGETDIR)$(TARGET) $(LIB)
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
#mkdir -p $(BUILDDIR)
#echo " $(CC) $(CFLAGS) $(INC) -c -o $# $<"; $(CC) $(CFLAGS) $(INC) -c - o $# $<
clean:
#echo " Cleaning...";
#echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)
for any c++ project with this tree structure
$ tree .
├── Makefile
├── bin
>exefile
├── include
> *.h files
├── obj
> *.o files
├── src
>*.cpp