Lab 3 — Makefiles
Slides. How to compile a C program with multiple source code files with Make.
Live-coding examples
main.c
main.c is a C source code file that contains a function named main. Every C program requires one such function as an entry-point into the program.
The third line includes the even.h header file with the definition for is_even. Header files are required to expose
functions defined in one source file to other source files. In this example, including even.h in main.c makes the function
is_even usable there, even though it is defined in even.c.
#include <stdio.h>
#include "even.h"
int main() {
int n = 5;
if (is_even(n)) {
printf("%d is even\n", n);
} else {
printf("%d is odd\n", n);
}
}
even.c
#include "even.h"
int is_even(int n) {
if (n % 2 == 0) {
return 1;
} else {
return 0;
}
}
even.h
The first two lines and the last line are preprocessor directives that protect against the header being included multiple times in one file. #include is very simplistic: it just copies the contents of one file into another during compilation.
#ifndef __EVEN_H__
#define __EVEN_H__
int is_even(int n);
#endif /* __EVEN_H__ */
Sequence of commands to create an executable
To compile the two .c files into an executable, I ran this sequence of commands to create the file program which can then be run with: $ ./program. The $ at the start of each line means that what follows is shell input, and if you're running this for yourself you wouldn't write the $.
$ gcc even.c -c # -c compiles a .o object
$ gcc main.c -c
$ gcc main.o even.o -o program # -o compiles an executable
Equivalent makefile
This makefile runs the equivalent of the commands above to compile main.c and even.c together into an executable.
# set the compiler and compiler flags
CC := gcc
CFLAGS := -Wall # -Wall means turn on all warnings
# compile prog from a list of object files
# if you have different source files, rename these
prog: main.o even.o
$(CC) $(CFLAGS) $^ -o $@
# how to transform source files to object files
%.o: %.c
$(CC) $(CFLAGS) $< -c
# clean up the directory. -f here makes rm not print
# an error if the file doesn't exist
.PHONY: clean
clean:
rm -f *.o
rm -f prog