Understand the dependency levels of makefiles
I have not divided up the header files into their .h and .c files because they are very small header files. 


I would advice against this. Dividing into header and source files is just something you do. If something deserves an own source file, it also deserves an own header file. If nothing else, future readers of your code will expect .h files to only contain declarations. If you really don't want to split them up, then include the .c files instead. That's not good, but at least you're not hiding what you're doing.

Also, I don't really see the need to manually write dependencies. If your project is big, look into CMake or something. If it is small, use a generic Makefile. Here is a small example that basically contains everything you'll ever need before it's time to move on to CMake:

# Configuration

EXE = play
CFLAGS = -g -Wall -Wextra -std=c11
LDLIBS = -lm
LDFLAGS =

# Don't touch anything below

# Every .c is a source file (dough)
SRC = $(wildcard *.c)
# Every source file should be compiled to an object file
OBJ = $(SRC:.c=.o)
# Every object file should have a dependency file
DEP = $(OBJ:.o=.d)

# Link the exe from the object files
$(EXE): $(OBJ)
    $(CC) $(LDFLAGS) $^ -o $@ $(LDLIBS)

# Generate dependencies for the object files
%.o: %.c
    $(CC) -MMD -MP -c $&lt; -o $@

# https://stackoverflow.com/q/2145590/6699433
.PHONY: clean

clean:
    $(RM) $(OBJ) $(DEP) $(EXE) *~

# Include the generated dependencies
-include $(DEP)


Note that you don't need to pass $(CFLAGS) to the CC commands. It's done automatically.

I used the above Makefile on this:

$ cat *.c *.h
/* bar.c */

#include "bar.h"
#include &lt;math.h&gt;

int bar(int a, int b) { return a*pow(b,3); }
/* foo.c */

#include "foo.h"
#include "bar.h"

int foo(int a, int b) { return a+bar(a,b); }
/* main.c */

#include "foo.h"

int main() { foo(1,2); }
/* bar.h */

#ifndef __BAR_H__
#define __BAR_H__

int bar(int a, int b);

#endif
/* foo.h */

#ifndef __FOO_H__
#define __FOO_H__

int foo(int, int);

#endif


I sacrificed a bit of readability to keep number of lines down. After running make I have a couple of .d files.

$ cat *.d
bar.o: bar.c bar.h

bar.h:
foo.o: foo.c foo.h bar.h

foo.h:

bar.h:
main.o: main.c foo.h

foo.h: