-compileargs = -Wall -Wextra -Wpedantic
-linkargs = -L/usr/local/lib -lGL -lglut -lassimp
-objects = out/main.o out/debugutil.o out/glut_janitor.o out/render.o \
- out/tga.o out/level.o
-
-shadowclad : $(objects)
- gcc -o out/shadowclad $(objects) $(linkargs)
-
-run : shadowclad
- LD_LIBRARY_PATH=/usr/local/lib out/shadowclad
-
-out/main.o : main.c debugutil.h glut_janitor.h render.h
- gcc -c -o out/main.o main.c $(compileargs)
-
-out/debugutil.o : debugutil.c
- gcc -c -o out/debugutil.o debugutil.c $(compileargs)
-
-out/glut_janitor.o : glut_janitor.c
- gcc -c -o out/glut_janitor.o glut_janitor.c $(compileargs)
-
-out/render.o : render.c render.h typedefs.h
- gcc -c -o out/render.o render.c $(compileargs)
-
-out/tga.o : tga.c tga.h
- gcc -c -o out/tga.o tga.c $(compileargs)
-
-out/level.o : level.c level.h tga.h
- gcc -c -o out/level.o level.c $(compileargs)
+CFLAGS ::= -g -std=c99 -Wall -Wextra -Wpedantic $(CFLAGS)
+LDFLAGS ::= $(LDFLAGS)
+LDLIBS ::= -L/usr/local/lib -lGL -lGLEW -lglut -lassimp $(LDLIBS)
+
+# Prefix all object file names with the compilation directory
+objects ::= $(addprefix out/, \
+ main.o level.o logger.o \
+ performance.o render.o tga.o ui.o)
+
+# Set executable extension for the platform
+ifeq ($(OS),Windows_NT)
+ binext ::= .exe
+else
+ binext ::=
+endif
+binary ::= out/shadowclad$(binext)
+
+# Default target: build executable
+$(binary) : $(objects) | out
+ @echo "###### Linking executable..."
+ $(CC) $(LDFLAGS) -o $(binary) $(objects) $(LOADLIBES) $(LDLIBS)
+
+# Alias for default target
+shadowclad : $(binary)
+.PHONY : shadowclad
+
+# Build and run
+run : $(binary)
+ @echo
+ LD_LIBRARY_PATH=/usr/local/lib $(binary)
+.PHONY : run
+
+# Create compilation directory
+out :
+ mkdir out/
+
+# Alias for 'out'
+init : out
+.PHONY : init
+
+# Generate dependencies
+out/%.make : %.c Makefile | out
+ $(CPP) -MM -MT out/$*.o -MF $@ $(CPPFLAGS) $<
+
+# Include generated rules
+-include $(addsuffix .make, $(basename $(objects)))
+
+# Build compilation units
+out/%.o : %.c out/%.make | out
+ $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
+
+# Delete build output
+clean : out
+ rm -f $(binary) out/*.o out/*.make
+ rm -d out/
+.PHONY : clean