A make file consists of a set of make rules. Each rule has three parts: a target, a set of zero or more dependencies, and a list of zero or more commands.
target: dependencies
(tab) command1
(tab) command2
Make is invoked by specifying a target on the command line. If no target is given, then the first target in the file is taken as the default. To compete a target, all dependencies are evaluated first. If a dependency is another target in the makefile, then those dependent targets are evaluated. If the dependency is not a target in the makefile, then the file system is checked for the existence of a file with the name of the dependency. If the file has been modified more recently than the file matching the target, then the commands for that target are run.
Consider the files:
main.c:
#include "bar.h"
void main() {
bar();
}
bar.c:
#include "bar.h"
void bar() {
}
bar.h:
void bar();
The corresponding naive makefile would be:
main.exe: main.o bar.o
(tab) gcc main.o bar.o -o main.exe
main.o: main.c bar.h
(tab) gcc -c man.c
bar.o: bar.c bar.h
(tab) gcc -c bar.c
clean:
(tab) rm *.o main.exe
Note: the "-o" flag specifies the name of the output file. The "-c" flag tells the compiler to stop after the "compile" stage and before the "link" stage, generating an object file as the output.
Typing "make" on the command line would build this project and produce an executable named "main.exe". Typing "make" again would do nothing since all of the dependencies would evaluate to false since none of the source files had changed. Changing any of the source files and then typing "make" would cause only the required segments of the project to be recompiled. The make utility knows what files need to be rebuilt based on the dependencies that we have given it, so it is important that these dependencies are correct.
See also: GNU make documentation.
