makefile
As you know, in order to execute the program written in C, we need to do compilation and link to convert the c source code to an executable binary file. This compilation and link process would not be a big issue if you are handling a small number of c files and h files, but the process would go more and more complicated as the number of those files increases and you need to use more complicated compilation / link options. Repeating those compilation and link process over and over can be an annoying process. makefile is a kind of batch file (similar to shell program) that execute the predefined compilation/link procedure.
If you have tried to use any large scale programs (like those open source programs you can get from internet or github), you would noticed that most of the program source codes are provided with its own makefile and understanding the contents of the makefiles are not an easy task.
This note is intended to help you with understanding the contents of makefile provided with those programs and help you with creating makefiles for your own program.
Compile without makefile
hello.c
|
hello.h
|
#include "hello.h"
int main(void)
{
print_hello();
return 1;
}
|
#include <stdio.h>
void print_hello(void)
{
printf("Hello World \n");
}
|
Simplest makefile
hello.c
|
hello.h
|
#include "hello.h"
int main(void)
{
print_hello();
return 1;
}
|
#include <stdio.h>
void print_hello(void)
{
printf("Hello World \n");
}
|
Example 01 >
makefile |
hello:
gcc hello.c -o hello
|
Example 02 >
makefile |
hello:
gcc -o hello hello.c
|
Example 03 >
makefile |
hello: hello.c
gcc -o hello hello.c
|
Example 04 >
makefile |
hello: hello.c hello.h
gcc -o hello hello.c
|
All the example shown above gives the same result as shown below except the printout of 'make' command
Simplest makefile with Macro
hello.c
|
hello.h
|
#include "hello.h"
int main(void)
{
print_hello();
return 1;
}
|
#include <stdio.h>
void print_hello(void)
{
printf("Hello World \n");
}
|
Example 01 >
makefile |
CC=gcc
hello:
$(CC) hello.c -o hello
|
Example 02 >
makefile |
CC=gcc
hello:
$(CC) hello.c -o $@ # $@ represents 'target' ('hello' in this case)
|
Example 04 >
makefile |
CC=gcc
hello: hello.c hello.h
$(CC) $< -o $@ # $< represents the first items of the rule ('hello.c' in this case)
|
Example 05 >
makefile |
CC=gcc
hello: hello.c hello.h
$(CC) $^ -o $@ # $^ represents the all items of the rule ('hello.c hello.h' in this case)
|
Example 06 >
makefile |
CC=gcc
hello: hello.c hello.h
$(CC) -o $@ $^
|
All the example shown above gives the same result as shown below except the printout of 'make' command
Special Symbols
Symbol
|
Description
|
$@
|
file name indicating target |
$%
|
The target member name, when the target is an archive member
|
$<
|
The filename of the first prerequisite.
|
$?
|
The names of all the prerequisites that are newer than the target, with spaces between them
|
$^
|
The names of all the prerequisites, with spaces between them
|
$+
|
This is like ‘$^’, but prerequisites listed more than once are duplicated in the order they were listed in the makefile. This is primarily useful for use in linking commands where it is meaningful to repeat library file names in a particular order
|
$*
|
The stem with which an implicit rule matches (see How Patterns Match). If the target is dir/a.foo.b and the target pattern is a.%.b then the stem is dir/foo. The stem is useful for constructing names of related files.
|
Example 01 >
makefile |
hello.o: hello.c hello.h # hello.o is target, [hello.c hello.h] is prerequisite
gcc -c $< -o $@ # $@ indicates the target (hello.o in this case)
# $< indicates the first elements of the prerequisites (hello.c in this case)
|
Reference :
|