there are several little 'oops' in the posted makefile.
Note: the :=
for the macro definitions, so they are only evaluated once.
Note: could use: SRC := $(wildcard *.c)
then OBJ := $(SRC:.c=.o)
to get the list of object files. However, there must not be any stray *.c files in the current directory
Note: library files are only needed at link time.
Note: when compiling should always enable all warnings, then fix those warnings.
Note: The order of items on the command line, when linking is important. Always place the library path, followed by the 'short' library names last
Note: When ever a 'target' rule does not actually create a file with the same name, always proceed the rule with: .PHONY : target
Note: when calling system functions, it is (almost) always better to define a macro then invoke that macro. This results in better flexibility and less chance of an error. See the RM
and CC
macros for examples
Note: it is better to not define macros that will not be used: for instance the DEP
macro
You might want to use something similar to this for compiling and linking as it does not invoke the shell functionality echo
and it results in a better looking output
game.o : game.c field.h GUI.h
#
# ========= START $< TO $@ =========
$(CC) $(CFLAGS) -c $< -o $@ -I.
# ========= END $< TO $@ =========
#
By using something like: (note: gcc
has a parameter that can also do this)
%.d: %.c
#
# ========= START $< TO $@ =========
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
# ========= END $< TO $@ =========
plus this:
%.o: %.c %.d
#
# ========= START $< TO $@ =========
$(CC) $(CCFLAGS) -c $< -o $@ -I.
# ========= END $< TO $@ =========
#
and this: (with a DEP
macro)
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif
then make
would generate all the dependency information so it would not have to be hardcoded into the makefile and all the compile statements would collapse into a single:
%.o: %.c %.d
#
# ========= START $< TO $@ =========
$(CC) $(CCFLAGS) -c $< -o $@ -I.
# ========= END $< TO $@ =========
#
The above will not make much difference for this project, but when the project contains hundreds of files, it is a MAJOR savings in time and debugging effort
The proposed makefile corrects all the obvious problems and allows running by:
make
or
make game
or
make all
or for individual file compilation
make <objectFileName>
Here is the proposed makefile
RM := /usr/bin/rm
CC := /usr/bin/gcc
CFLAGS := -c -fmessage-length=0 -D_SDL_main_h
#a better CFLAGS would be:
#CFLAGS := -fmessage-length=0 -D_SDL_main_h -std=c99 -Wall -Wextra -pedantic -Wconversion -c
LFLAGS :=
LIBS := -L/usr/lib/x86_64-linux-gnu -lSDL -lSDL_ttf -lSDL_gfx
# DEPS := game.h field.h cell.h allocate_field.h GUI.h
OBJ := game.o field.o allocate_field.o GUI.o
OUTPUT := game
.PHONY : all
all: $(OUTPUT)
$(OUTPUT): $(OBJ)
@echo Programma aanmaken
$(CC) $(LFLAGS) -o $@ $(OBJ) $(LIBS)
game.o : game.c field.h GUI.h
@echo Bezig met game.o te compileren
$(CC) $(CFLAGS) -c $< -o $@ -I.
field.o : field.c allocate_field.h cell.h
@echo Bezig met field.o te compileren
$(CC) $(CFLAGS) -c $< -o $@ -I.
allocate_field.o : allocate_field.c cell.h
@echo Bezig met allocate_field.o te compileren
$(CC) $(CFLAGS) -c $< -o $@ -I.
GUI.o : GUI.c field.h cell.h
@echo Bezig met GUI.o te compileren
$(CC) $(CFLAGS) -c $< -o $@ -I.
.PHONY : clean
clean:
@echo Cleaning... Object files verwijderen
$(RM) -f *.o
$(RM) -f $(OUTPUT)