I'm new to Makefiles. I've been making a simple C++ library using WiringPi for my RaspberyPi related projects. So far its very simple with things like an LED class, DuelLED, Motor, Button, etc (both .h and .cpp). I was able to piece together a Makefile but I am getting an error "No rule to make target RumPi.o needed by RumPi". (Note: The name of my library is called RumPi)
Thanks for all the help, Here is the final fix:
CXX = g++
CXXFLAGS = -std=c++11
LDLIBS = -lwiringPi
HEADERS = Components/Headers/RumPi.h ./Common.h Components/Headers/Component.h Components/Headers/Vehicle.h Components/Headers/Motor.h Components/Headers/Receiver.h Components/Headers/DualLED.h Components/Headers/LED.h Components/Headers/RGBLED.h Components/Headers/Relay.h
OBJECTS = RumPi.o Vehicle.o Motor.o Receiver.o DualLED.o LED.o RGBLED.o Relay.o
default: RumPi
RumPi: $(OBJECTS)
$(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $#
%.o: Components/Implementations/%.cpp
$(CXX) $(CXXFLAGS) -c -o $# $<
$(OBJECTS): $(HEADERS)
clean:
-rm -f $(OBJECTS)
-rm -f RumPi
That message means make can't figure out how to build that target (RumPi.o). Do you have a Components/Implementations/RumPi.cpp file? Do all the header files you've listed in the $(HEADERS) variable actually exist? If either of those is not true, then your pattern rule will not match. If your pattern rule doesn't match (and the default rule doesn't match) then make can't figure out how to build the object file.
If you want full details you can run make -d and examine the debug output. You might want to redirect it to a file so you can look at it with less or a text editor since there's a lot of output.
By the way, you should not add the -lwiringPi option to your compile line. Libraries are only used at link time, not compile time.
ETA
Something else you should consider is rewriting your pattern rule so that only the source file is listed as a prerequisite and moving the headers to a separate line:
%.o: Components/Implementations/%.cpp
gcc -c $< -o $# -lwiringPi
$(OBJECTS): $(HEADERS)
The advantage to this is you'll get a clearer error message if one of the headers is not found. When you use a pattern rule, make will try to match all the patterns it can and if none match it tells you it doesn't know how to build the target. Since there are usually many different ways to build a target, make doesn't show an error for every one that doesn't match.
But if you declare a direct explicit prerequisite relationship between two files, rather than using a pattern that may or may not match, then if there is a missing file make will tell you directly.
ETA2
In your original makefile you had a rule like this:
RumPi: $(OBJECTS)
gcc $(OBJECTS) -o $# -lwiringPi
but then later you removed it. Why did you take this out? You need this rule to tell make how to link your executable file RumPi.
Also, you shouldn't be using gcc as the compiler/linker for C++ code; gcc is for C, not C++. You should use g++ for C++ code. And it's best to contain this information in variables so it's easy to find and modify (even from the command line if you like). The standard variable names for the C++ compiler is CXX etc.
Your makefile should look something like this:
CXX = g++
CXXFLAGS = -std=c++11
LDLIBS = -lwiringPi
HEADERS = Components/Headers/RumPi.h ./Common.h Components/Headers/Component.h \
Components/Headers/Vehicle.h Components/Headers/Motor.h Components/Headers/Receiver.h \
Components/Headers/DualLED.h Components/Headers/LED.h Components/Headers/RGBLED.h \
Components/Headers/Relay.h
OBJECTS = RumPi.o Vehicle.o Motor.o Receiver.o DualLED.o LED.o RGBLED.o Relay.o
default: RumPi
RumPi: $(OBJECTS)
$(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $#
%.o: Components/Implementations/%.cpp
$(CXX) $(CXXFLAGS) -c -o $# $<
$(OBJECTS): $(HEADERS)
clean:
-rm -f $(OBJECTS)
-rm -f RumPi
Related
I am trying to write a makefile, suppose I have 4 source files in a directory src/app/:
src/app/file1.cpp
src/app/file2.cpp
src/app/file3.cpp
src/app/file4.cpp
and I want to create different object files (i.e. file1.o, file2.o etc.) into another directory called obj/. In the makefile, I am defining the variables like this:
$(SRC) := $(wildcard src/app/*.cpp)
$(OBJ) := $(addprefix obj/,$(notdir $(SRC:.cpp=.o)))
and my commands are like this:
all: $(OBJ)
$(OBJ): $(SRC)
$(CC) $(CFLAGS) -I/src/app/app.h -c $< -o $#
so when I run make, I see these operations:
g++ -g -Wall -I/src/app/app.h -c src/app/file1.cpp -o obj/file1.o
g++ -g -Wall -I/src/app/app.h -c src/app/file1.cpp -o obj/file2.o
g++ -g -Wall -I/src/app/app.h -c src/app/file1.cpp -o obj/file3.o
g++ -g -Wall -I/src/app/app.h -c src/app/file1.cpp -o obj/file4.o
You can see, the object files have different names but the source file is the same. How do I fix it ?
Please note that I can't use %.o: %.cpp since I have other targets in my makefile for different purposes.
If you can't use
obj/%.o: src/app/%.cpp
then the second simplest way is to add $(OBJ): to the front:
$(OBJ): obj/%.o: src/app/%.cpp
It's called "static pattern rules" - look it up in the GNU Make manual.
I have found a way to solve this (thanks to Zereges for the idea):
$(RGAOBJ): $(RGASRC)
$(CC) $(CFLAGS) -I/src/app/app.h -c \
$(addprefix src/app/,$(notdir $(#:.o=.cpp))) -o $#
I think there is a better way to do.
So any other pointer will be helpful.
The $< variable picks up the first dependency. It is used with generic targets which have variable targets and produce different results. The compile target would match a pattern as target and have a generic dependency. The first target doesn't change in your case.
Your constraint of not being able to use a generic rule is entirely defeating the purpose of the $< variable. A somewhat naive work-around is to translate the destination name back into the source, e.g.,
$(OBJ): $(SRC)
$(CC) $(CFLAGS) -I/src/app/app.h -c $(#:%.o=%.cpp) -o $#
The problem with that approach is that no all object files depend on all source files. As a result, every time one of the source files is changed all object files are produced. For tiny projects and source that may be viable. On anything which I'd consider a real project neither of these conditions holds.
My understanding on your statement on not being able to use pattern rules is that you already have rules for the same pattern but you need to build some targets with some special rules. A work around for that situation is to build targets with a custom suffix which actually build something different and just use a marker file to prevent unnecessary rebuilds. For example:
all: $(OBJ:%=%.custom)
%.o.custom: %.cpp
$(CC) $(CFLAGS) -W -I/src/app/app.h -c $< -o $(#:%.custom=%) && touch $#
I need help to create a proper makefile (supporting incremental compilation) for multiple .hpp and .cpp files.
I've been looking for information about how to create a proper makefile, but I'm not really sure on how to do it.
I have the following files:
2048.cpp, game.cpp, game.hpp, gameutils.cpp, gameutils.hpp, menu.cpp, menu.hpp, saveandback.cpp, saveandback.hpp and tile.hpp
Right now I'm using the following makefile:
all: 2048.cpp tile.hpp menu.hpp menu.cpp gameutils.hpp gameutils.cpp saveandback.hpp saveandback.cpp game.hpp game.cpp
g++ -g -W -Wall --pedantic -DNDEBUG 2048.cpp -o power
clean:
$(RM) power
Thank you for your help.
Caveat: I haven't used make in a while so I may be a little rusty on POSIX vs. GNU-make specific stuff. There may also be new features released in the last few years that I'm not aware of. Please feel free to give corrections. Also most of this is from memory.
There are a few things missing from your knowledge set here that you can use to create a decent makefile that only re-compiles things when needed:
Generic Rules - These can be used to provide a generic rule for building a filename with one suffix from another. E.g. the following defines a rule for creating any *.o from its corresponding *.cpp:
%.o: %.cpp
stuff
In POSIX make these rules are actually specified as:
.cpp.o:
stuff
I'm using GNU syntax below but you can (and might want to) replace with POSIX syntax (moot if you leave them out and use the implicit rules, though, see below).
Automatic Variables
$< will expand to the input of the rule.
$# will expand to the target of the rule.
Variables - You can declare variables and give them values, e.g.:
SOURCES=2048.cpp gameutils.cpp saveandback.cpp
Etc.
Text Replacement - You can use text replacement functions to replace suffixes, e.g.:
OBJECTS=$(SOURCES:.cpp=.o)
Will set OBJECTS equal to SOURCES but with the .cpp's changed to .o.
Multiple Rules - If multiple rules are specified for the same target, their prerequisites are merged.
Phony Targets
Putting that all together you can get a start, leaving out header dependencies for now:
SOURCES=2048.cpp menu.cpp gameutils.cpp saveandback.cpp game.cpp
OBJECTS=$(SOURCES:.cpp=.o)
power: $(OBJECTS)
g++ $(OBJECTS) -o $#
%.o: %.cpp
g++ -c $< -o $#
And it's traditional to define an all rule, which is a phony target since there isn't actually a file named "all":
.PHONY: all
SOURCES=2048.cpp menu.cpp gameutils.cpp saveandback.cpp game.cpp
OBJECTS=$(SOURCES:.cpp=.o)
all: power
power: $(OBJECTS)
g++ $(OBJECTS) -o $#
%.o: %.cpp
g++ -c $< -o $#
Now, make actually has some default rules already, including one for %.o: %.cpp, and also it has some default variables. So you can reduce the above to this if you'd like (personally I prefer to explicitly specify rules, but that's just me):
.PHONY: all
SOURCES=2048.cpp menu.cpp gameutils.cpp saveandback.cpp game.cpp
OBJECTS=$(SOURCES:.cpp=.o)
all: power
power: $(OBJECTS)
$(CXX) $(CXXFLAGS) $(OBJECTS) -o $#
Now, as for your headers, keeping in mind the multiple rules thing, you can simply add those prerequisites by hand based on their includes, e.g.:
.PHONY: all
SOURCES=2048.cpp menu.cpp gameutils.cpp saveandback.cpp game.cpp
OBJECTS=$(SOURCES:.cpp=.o)
all: power
power: $(OBJECTS)
$(CXX) $(CXXFLAGS) $(OBJECTS) -o $#
2048.o: menu.hpp game.hpp
menu.o: menu.hpp
game.o: game.hpp
And so on. You probably also want a "clean" rule, another phony target, and it doesn't hurt to put your binary name in a variable since you use it in a few places, e.g.:
.PHONY: all clean
SOURCES=2048.cpp menu.cpp gameutils.cpp saveandback.cpp game.cpp
OBJECTS=$(SOURCES:.cpp=.o)
BINARY=power
all: $(BINARY)
clean:
$(RM) $(BINARY) $(OBJECTS)
$(BINARY): $(OBJECTS)
$(CXX) $(CXXFLAGS) $(OBJECTS) -o $#
And actually if you pass -MM to gcc it'll generate Makefile dependencies automatically for you, based on the source file's includes. See here for details and an example.
My make file is failing to find my include directory when it tries to remake object files. For example, when I call make tests I get the output:
g++ -c -o sdl_class.o sdl_class.cpp
sdl_class.cpp:9:23: fatal error: sdl_class.h: No such file or directory
#include <sdl_class.h>
^
compilation terminated.
make: *** [sdl_class.o] Error 1
My Makefile is this:
#Originally from: http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
#But will be heavily modified
IDIR =../include
CC=g++
CFLAGS=-w -I$(IDIR)
#ODIR=obj
LDIR =../lib
LIBS=-lSDL2
_DEPS = sdl_class.h SDL_image.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
OBJ = sdl_class.o tests.o
#OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
%.o: %.cpp $(DEPS)
$(CC) -c -o $# $< $(CFLAGS) $(LIBS)
tests: sdl_class.o tests.o
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
all: $(OBJ)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f *.o *~ core $(IDIR)/*~
My understanding is that when I call make tests, that it should attempt to remake the sdl_class.o file. This should then call the %.o rule, which should try to make the object file by calling something like:
g++ -c -o sdl_class.o sdl_class.cpp -w -I../include -lSDL2
However, this is not the case as it looks like it is calling $(CC) -c -o $# $< $(CFLAGS) $(LIBS), as you can see from above.
Do I have a fundamental misunderstanding about how make builds its rules? Seems likely, this is my first Makefile. Perhaps I am confused on how compilation works in general, as I'm somewhat new to that as well.
I would say that the problem is that one or more of the files ../include/sdl_class.h or ../include/SDL_image.h does not exist. Because of that, make is deciding that your pattern rule does not match (because not all the prerequisites can be found or made) and it defaults to the built-in rule to create object files from .cpp files.
The built-in rules use the make variables CXX for the C++ compiler and CXXFLAGS for the C++ flags: the CC and CFLAGS variables are used for the C compiler. That's why your settings for CFLAGS are being ignored.
If you run make -d sdl_class.o you'll see which file make is looking for and why it decides to not use your pattern rule.
If you rewrite your rules like this it will work better:
%.o: %.cpp
$(CC) -c -o $# $< $(CFLAGS)
sdl_class.o tests.o: $(DEPS)
because make will now complain that the relevant files can't be found or created.
There are other issues, of course. You shouldn't be passing $(LIBS) to your compile command; that belongs only in your link line. And, you should probably stick to the standard variables CXX for the C++ compiler, CPPFLAGS for preprocessor flags like -I and -D, and CXXFLAGS for C++ compiler flags. Also, linker library flags like -L../lib go in LDFLAGS and linker libraries like -lSDL2 go in LDLIBS.
CC/CCFLAGS are for C compilation. You should use CXX and CXXFLAGS for C++. They are used in built-in rules and in the LINK.cc macro, making the Makefile much simpler, and thus less error prone.
CXXFLAGS = -Wall ...
prog : foo.o bar.o
$(LINK.cc) -o $# $^
see Default linker setting in Makefile for linking C++ object files
I've got a Makefile that works good so far. Although, as it started growing, recompiling all the sources every time began to take too long. Here's a snippet from the working version:
CC=$(CROSS_COMPILE)g++
CFLAGS=-Wall -I./include -pg -O2
VPATH=./src:./include
all: dotgazer.cpp dotgazer/Dot.cpp
$(CC) $(CFLAGS) $^ -o dotgazer.out `pkg-config --libs opencv`
There are a lot more dependencies, but these two are enough to show what the problem is. I'm trying to move the compilation stage of each cpp file to a separate target. When it comes to the top-level file (dotgazer.cpp) it's not a problem and a general rule %.o: %.cpp works fine. But I can't get the second dependency to work. Here's how it looks now:
CC=$(CROSS_COMPILE)g++
CFLAGS=-Wall -I./include -pg -O2
VPATH=./src:./include
all: dotgazer.o dotgazer/Dot.o
$(CC) $(CFLAGS) $^ -o dotgazer.out `pkg-config --libs opencv`
%.o: %.cpp
$(CC) -c $(CFLAGS) $^ -o $#
dotgazer/Dot.o: dotgazer/Dot.cpp
$(CC) -c $(CFLAGS) $^ -o $#
I've tried different variations of the Dot.o rule but none of them seems to work. The error I get with the one above is:
Fatal error: can't create dotgazer/Dot.o: No such file or directory
How should I do that? I'd most prefer to have the .o files in the same folders as their sources. Also, I'd be thankful for general rules (like %.o: %.cpp) as there are lots of source files and I don't want the Makefile to get too bloated. Thank you!
I think your Makefile is a bit to specific and thus error-prone. I suggest to look at my following example that is way more generic than yours.
My example takes advantage of make's catalouge of implicit rules. For cpp-files exists a generic implicit rule already. So why should one not use it!?
The reference manual describes it as follows:
Compiling C++ programs
n.o is made automatically from n.cc, n.cpp, or n.C with a recipe of the form $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c.
So if you have %.o files as prerequisites like in the rule dotgazer.out: $(OBJS) make applies above implicit rule to all those files automatically. Assumed you have set valid values for CXX, CPPFLAGS and/or CXXFLAGS.
Furthermore you usually don't need to add your sources by hand to a variable. Most of the time all the sources in your project's directory tree are needed to build the executable. If it's not the case you should consider to build a appropriate tree that reflects this.
Since find is responsible to assign the sources to CPPFILES we don't need to set VPATH either. Due to our usage of find and patsubst we have only one explicit file name in our Makefile. That make working on a real project with plenty of different sources much more smooth.
Of course you don't need the all and the clean rule. I just added these for convenience.
CXX=$(CROSS_COMPILE)g++
CPPFLAGS=-I./include
CXXFLAGS=-Wall -pg -O2
LDLIBS=`pkg-config --libs opencv`
CPPFILES=$(shell find . -name "*.cpp")
OBJS=$(patsubst %.cpp, %.o, $(CPPFILES))
all: dotgazer.out
#echo $(CPPFILES)
#echo $(OBJS)
dotgazer.out: $(OBJS)
$(CXX) $(CXXFLAGS) -o $# $^ $(LDLIBS)
clean:
rm -f $(OBJS)
I was looking for a solution on this site and also tried google for some time now, but somehow I can't get it to work.
My source should be in the src directory and the object files would be in the obj directory. Now I try to create a simple makefie but I either get an error that there is no rule, or I can't make it work to use the directories.
CC = /usr/bin/gcc
CXXFLAGS = -O2 -g -Wall -fmessage-length=0
SRC:= nohupshd.cpp \
task.cpp
OBJ:= nohupshd.o \
task.o
OBJDIR:= obj
SRCDIR:= src
DEP:= src/task.h
LIBS:=
TARGET:= nohupshd
all: $(TARGET)
$(TARGET): $(OBJ)
$(CC) -o $(TARGET) $(OBJ) $(LIBS)
clean:
rm -f $(OBJ) $(TARGET)
Variant 1:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
$(CC) -S $(SRCDIR)/$< -o $(OBJDIR)/$#
$(CC) -c $(SRCDIR)/$< -o $(OBJDIR)/$#
Variant 1a:
%.o: %.cpp
$(CC) -S $(SRCDIR)/$< -o $(OBJDIR)/$#
$(CC) -c $(SRCDIR)/$< -o $(OBJDIR)/$#
When I use this pattern I always get an error that there is no rule for nohupshd.o to build.
Variant 2:
$(OBJ) : $(OBJDIR)/%.o: $(SRCDIR)/%.cpp
$(CC) -S $(SRCDIR)/$< -o $(OBJDIR)/$#
$(CC) -c $(SRCDIR)/$< -o $(OBJDIR)/$#
When I use this variant, I can see that it tries to build, but I get errors saying that "file".o doesn't fit the target pattern.
Another issue is that "$<" doesn't give me the source name. According to several sites it should, but I can see in the output that there is nothing, so how can I fix this?
Update:
In the meantime my newest version looks like this:
$(OBJDIR)/$(OBJ) : $(OBJDIR)/%.o : $(SRCDIR)/%.cpp
$(CC) -S $< -o $(OBJDIR)/`basename $# .o`.asm
$(CC) -c $< -o $#
This now manages to compile the first objectfile (nohupshd.o) but when make tries to do the second file it fails again saying: target 'task.o' doesn't match a pattern.
You actually have a couple if incorrect things above.
First you write My error was, that I was assuming that the pattern %.o matches ANY pattern ending with .o which it doesn't; that's not true. The pattern does match any string ending in .o. However, the pattern character % that is matched on the target side is replaced on the prerequisite side with the identical string. So if you have a target obj/task.o and it matches the pattern %.o then the stem (what the manual calls it) will be obj/task, and when the prerequisite is %.c that means that make will look for a prerequisite obj/task.c. Since there isn't one, and make doesn't know how to build one, that rule is discarded as not applying. When writing pattern rules you must write them so ONLY the identical parts of the names match the pattern character (%). ALL non-identical parts, including directories, must be specified explicitly.
Second, the rule $(OBJ) : $(SRC) is really not right. That line says that each object file depends on all the source files, so whenever any single source file changes all the object files will be recompiled. That's really not what you want (if that IS what you want you don't need make: you can just write a simple shell script). I don't know what you mean by since the rules is empty it invokes the pattern rule; you don't need this to invoke the pattern rule. The target depends on $(OBJ), and each object file depends on its source file (due to the pattern). You don't need this line at all.
Third, I don't know why you are trying to construct .asm files rather than just compiling directly from source to object, but if you really want them it would be cleaner and more "make-like" to create a separate pattern rule to build them: create a pattern rule $(OBJDIR)/%.o : $(OBJDIR)/%.asm and a rule $(OBJDIR)/%.asm : $(SRCDIR)/%.c. If you want the ASM files to be products of the build you should declare them as a prerequisite of all or similar, otherwise they'll be deleted as intermediate files.
Fourth, using things like basename is unnecessary. There are lots of automatic make variables that can be used instead. For example, $* expands to the stem, so you could write $(OBJDIR)/$*.asm. Of course if you make a separate pattern rule for ASM files you can just use $# or $< directly. There are various make functions that can also be used; see the manual.
Fifth, you define a variable containing a header file, DEP, but then never use it. Because it's not used, if you change that file nothing would be rebuilt. If you know that all the source files include every header you can use $(OBJ) : $(DEP) to define that; but it does mean (as in the second point above) that any change to any header causes all objects to recompile. You would be better off auto-generating the prerequisites; since you're using GCC this is quite simple.
Sixth, you're using C++ files (xxx.cpp) but you're using the C compiler. This will not work (the link line will fail: although the compiler can see you're compiling a C++ file and do the right thing, even if you call gcc, when you link a bunch of objects together it has no idea if those were C objects or C++ objects (or FORTRAN or whatever) so you MUST use the C++ front-end to link or it won't pull in the right C++ libraries). You should be using the make variable CXX to build C++ code, not CC, and setting it to g++ not gcc.
Seventh, you don't need .SUFFIXES: .c .o to use pattern rules. They are only needed for suffix rules, which you don't have here. You can keep the plain .SUFFIXES: though to disable built-in pattern matching which is a slight performance improvement.
Finally, you'll note you don't actually need the $(SRC) variable because make can infer it from the pattern rules. However, if you wanted to have your makefile less onerous to change, you could construct the contents of the OBJ variable from the SRC variable, like SRC = nohupshd.cpp task.cpp then OBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(SRC)).
So, all-in, this is how I would recommend you write your makefile (I don't include the auto-generated dependencies here though):
.SUFFIXES:
CXX := g++
CXXFLAGS := -O2 -g -Wall -fmessage-length=0
OBJDIR := obj
SRCDIR := src
TARGET := nohupshd
SRC := nohupshd.cpp task.cpp
DEP := src/task.h
LIBS :=
# ----
OBJ := $(patsubst %.cpp,$(OBJDIR)/%.o,$(SRC))
ASM := $(patsubst %.cpp,$(OBJDIR)/%.asm,$(SRC))
.PHONY: all clean
all: $(TARGET) $(ASM)
$(TARGET): $(OBJ)
$(CXX) -o $# $^ $(LIBS)
clean:
rm -f $(OBJDIR)/* $(TARGET)
$(OBJDIR)/%.o : $(SRCDIR)/%.asm
$(CXX) $(CXXFLAGS) -c -x assembler-with-cpp $< -o $#
$(OBJDIR)/%.asm : $(SRCDIR)/%.cpp
$(CXX) $(CPPFLAGS) -S $< -o $#
Don't repeat the directory names in the compiler line. $< and $# already have the directory names.
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
$(CC) -S $< -o $#
$(CC) -c $< -o $#
So finally I found the answer on how to write this makefile, for an exaplanation of my mistakes look at the posting I marked as correct answer:
The resulting makefile looks like this, and for completeness I post it here including dependencies for header files (remove the ASM parts if you don't need 'em):
.SUFFIXES:
.SUFFIXES: .o .cpp
.SUFFIXES: .o .d
CC := g++
LNK:= ar
CXXFLAGS = -O2 -g -Wall -fmessage-length=0
OBJDIR:= obj
SRCDIR:= src
HDIR:= include
INCLUDE_PATHS:= -Iinclude -Iinclude/interfaces -Iinclude/support
CPP_FILES := propertyfile/propertyfile.cpp \
propertyfile/propertyitem.cpp \
propertyfile/propertyfactory.cpp
OBJ := $(patsubst %.cpp,$(OBJDIR)/%.o, $(CPP_FILES))
SRC := $(patsubst %.cpp,$(SRCDIR)/%.o, $(CPP_FILES))
ASM := $(patsubst %.cpp, $(OBJDIR)/$*.asm, $(CPP_FILES))
LIBS:=
TARGET:= libsupport.a
all: $(TARGET)
$(TARGET): $(OBJ)
#echo "Linking..."
#$(LNK) rvs $(TARGET) $(OBJ)
#cp $(TARGET) ../lib
#cp -r include ..
clean:
rm -f $(OBJ) $(ASM) $(TARGET)
-include $(patsubst %.cpp,$(OBJDIR)/%.d, $(CPP_FILES))
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp $(OBJDIR)/%.d
#mkdir -p `dirname $#`
$(CC) $(CXXFLAGS) -S $< -o $(OBJDIR)/$*.asm $(INCLUDE_PATHS)
$(CC) $(CXXFLAGS) -c $< -o $# $(INCLUDE_PATHS)
$(OBJDIR)/%.d: $(SRCDIR)/%.cpp
$(CC) $(CXXFLAGS) -MM -MT $# -MF $(OBJDIR)/$*.d -c $< $(INCLUDE_PATHS)
I hope this helps other user. All examples that I found were either extremly simple and listed multiple files individually and not part of a rule, but didn't really explain how it works, or were so complicated that I couldn't find out how it can help me.