$ gcc -c file1.c $ gcc -c file2.c $ gcc -c main.c $ gcc -o myprogram file1.o file2.o file3.o
That would get old fast. You'd have to remember which .o files were current with respect to their sources, and you'd have to know whether the executable was current with respect to the objects.
Make automates this. By default, it knows how to build a .o file from a .c file. All you need to tell it is that myprogram depends on three object files:
# Makefile for myprogram
myprogram : file1.o file2.o main.o
gcc -o $@ $^
Make's not limited to programming. How 'bout this for counting url hits and hosts from our web server access log:
# Makefile for access_logs
LOG:=/local/httpd/logs/access_log
default : host.counts url.counts
host.list : ${LOG}
cut -f1 -d' ' $< >$@
url.list : ${LOG}
perl -ne 'm/"GET (\S+)/ && print($$1,"\n")' $< >$@
%.sorted : %.list
sort $< >$@
%.counts : %.sorted
uniq -c $< >$@