Even in a small project with just a few files, as the example above, it starts to be tricky figuring out the dependencies between files.
In this case gcc can help us to create targets and prerequisites:
main.o: main.c
cc -c main.c# TAB before command!printhelloworld.o: printhelloworld.c hello.h world.h
cc -c printhelloworld.c# TAB before command!hello.o: hello.c hello.h
cc -c hello.c# TAB before command!world.o: world.c world.h
cc -c world.c# TAB before command!
...and finally add the helloworld and clean targets, and we're done:
# The executable 'helloworld' depends on all object fileshelloworld: main.o printhelloworld.o hello.o world.o
cc -o helloworld main.o printhelloworld.o hello.o world.o# TAB before command!main.o: main.c
cc -c main.c# TAB before command!printhelloworld.o: printhelloworld.c hello.h world.h
cc -c printhelloworld.c# TAB before command!hello.o: hello.c hello.h
cc -c hello.c# TAB before command!world.o: world.c world.h
cc -c world.c# TAB before command!# Remove object files, executables (UNIX/Windows), Emacs backup files, and core files.PHONY : clean
clean:
rm -rf *.o helloworld helloworld.exe *~ *.core core# TAB before command!
As we see in the rule of the target helloworld, the list of object files grows.
To not repeat typing the list (besides beeing good for the lazy ones like me, it may avoid typos) we can substitute it (or any text) with a variable...