So I've been working on a simple C++ project which requires the following command to build:

g++ -Wall -o game game.cpp main.cpp -lncurses -I.


game is the output executable, game.* and main.cpp are the source files and ncurses is a library whuch must be linked in with the -l switch. The -I switch along with the dot, will cause g++ to look in the current directory for game.h. The -Wall switch (short for Warning all) tells the compiler to output all possible warnings if any.
If I change just one source file, I have to recompile the whole lot, this can be extremely time consuming. Obviously this method of building software is not very flexible, and can be seriously cumbersome as the project increases in size and complexity.
Enter makefiles.....

If I create a file called 'makefile', and put it in the sourcefile directory with the following:

game: game.cpp main.cpp
g++ -Wall -o game game.cpp game.h main.cpp -lncurses

then all I need to do in type 'make' at the command line instead of using the up arrow on the keyboard all the time.

The first line in the makefile specifies the target. Usually you would specify the target you want to run with make, so you would do make game, but in this case we have only one target, so make will just go for the first one on the list.

After the target name and semicolon you specify the files that need to be compiled if any of them change, in this case game.cpp and main.cpp
This solves the problem of having to recompile all the source files each time because make now knows to just compile the source files that have changed.
Finally its important to note that make requires a tab to be inserted before the compiler command. Make requires a tab to be in place before any command, and will get cranky if it isn't there.

The is fine but we could do with being a little more specific and succinct in how we instruct the compiler. First of all we can define some macros.

We define CC as referring the the compiler we are using, then we define a macro CXXFLAGS to specify all the switches we use in the command, next is the DEPS macro, which lists all the header files, that the .cpp files depend on. Finally we have LIBS, which specifies the library or librtaries that we include when we link.

CC=g++
CXXFLAGS=-I.
DEPS = game.h
LIBS=-lncurses

Now we generalize the syntax of our command to make it more portable.
We create

%.o: %.cpp $(DEPS)
$(CC) -c -o $@ $< $(CXXFLAGS)


game: $(OBJ)
$(CC) -o $@ $^ $(CXXFLAGS) $(LIBS)

The first target is the compile stage, an instruction to g++ to compile all the cpp files. Our target here is '%.o' and the dependencies are '%.cpp' and '$(DEPS)', i.e. game.h in this case.
The second line is the command to be issued. The first term in the command is the dereferenced CC macro, i.e. g++, then we have the -c switch to compile only, the -o switch to specify the output file, which is '$@' (that which is specified on the left side of the semicolon, in this case %.o) then the files to be compiled, '$<' (that which is specified on the left side of the semicolon, in this case %.o)and finally $(CXXFLAGS).

The second target, is the link stage, where it takes the object files created in the compile stage and generates the executable file, game in this case. Its pretty much the same as the compile stage except the '-c' switch is ommitted as we want to link the files. Also, the LIBS macro is dereferenced here as we want to linnk ht encurses library.

So thats cool, we now have a set up where we can build the files using a simple command, make, we can easily add additional libraries if needs be, and for neatness we have separated out he compile and link stages. But we can refine this further. We might like to put the source and header files in separate directories, we might also want to clean out all unwanted intermediary files like object files etc.

So to do this we will lay out a simple project directory structure. If we want to create a project called testproj1, then we create that directory and everything will go inside it. The source files go into a directory called 'src' and the header files go into 'include'. The object files will go into 'obj', which will be a subdirectory under 'src'. We will also have a target 'clean' which removes all the object files etc.

IDIR =../include
CC=g++
CXXFLAGS=-I$(IDIR)
ODIR=obj
LIBS=-lncurses

_DEPS = game.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))

_OBJ = game.o main.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))


$(ODIR)/%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)

game: $(OBJ)
gcc -o $@ $^ $(CFLAGS) $(LIBS)

#This is just to stop make trying to do something with a file called 'clean'
.PHONY: clean

clean:
rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~

This will do for now....Really need to have the makefile at the project root as well as the executable binary.
Also need to create a bash script that will set up the project directories and generate the makefile automatically