A Simple Makefile Tutorial

What is Makefile

Makefile is a simple way to organize code compilation. 

Why we need Makefile

Assuming that we have the following three files:

1: hellomake.c

#include <hellomake.h>

int main(){
  myPrint("hello");
  return 0;
} 

2: hellofunc.c

#include <hellomake.h>
#include <stdio.h>

void myPrint(char* str){
  myPrint("%s", &str);
  return;
} 

3: hellomake.h

void myPrint(char* str);

Normally, you would compile this collection of code by executing the following command:
gcc -o hellomake hellomake.c hellofunc.c -I

tips:

  1. -o hellomake means that the name of compiled executable file is hellomake
  2. -I is included so that gcc will look in the current directory (.) for the include file hellomake.h

The downfalls of compiling using command line are:

  1. you have to retype the compile command (without using the up arrow in a terminal), which is inefficient
  2. if you make change to one .c file, you need to recompiling them every time, which is also inefficient

How to create a Makefile

Let’s start off with a simple example to better understand what is Makefile and how to write your own Makefile.

the simplest makefile that we can create looks like:

Makefile 1

hellomake: hellomake.c hellofunc.c
	gcc -o hellomake hellomake.c hellofunc.c -I

hellomake: hellomake.c hellofunc.c tells make that the dependency list of hellomake is hellomake.c and hellofunc.c
when you type the command line make, it will execute gcc -o hellomake hellomake.c hellofunc.c -I
(note: there is a tab before gcc command in the makefile)

Makefile 2

CC = gcc
CFLAGS = -I.

hellomake: hellomake.o hellofunc.o
	$(CC) -o hellomake hellomake.o hellofunc.o

Macro CC is the C compiler to use
Macro CFLAGS is the list of flags to pass to the compilation command
hellomake: hellomake.o hellofunc.o means that by putting together the .o object files (in this example, they are hellomake.o and hellofunc.o) in the dependency list, make knows it must first compile the .c versions individually, and then build the executable hellomake
(using this form of Make file is sufficient for small projects, but there is one thing missing: dependency on the include files. If you were to make a change to the hellomake.h, make would not recompile the .c files)

Makefile 3

CC = gcc
CFLAGS = -I.
DEPS = hellomake.h

%.o: %.c $(DEPS)
	$(CC) -c -o $@ $< $(CFLAGS)

hellomake: hellomake.o hellofunc.o
	$(CC) -o hellomake hellomake.o hellofunc.o

Macro CC is the C compiler to use
Macro CFLAGS is the list of flags to pass to the compilation command
Macro DEPS is the set of .h files on which .c files depend
Then we define a rule that applies to all files ending in .o suffix.
First part of the rule %.o: %.c $(DEPS) says that the .o file depends upon the .c version of the file and the .h files included in DEPS. Second part of the rule $(CC) -c -o $@ $< $(CFLAGS) says that to generate the .o files, make needs to compile the .c file using the compiler CC. flag -c says to generate the object file, -o $@ says to put the output of the compilation in the file named on the left side of the :(i.e., %.o). The $< is the first item in the dependencies list.
hellomake: hellomake.o hellofunc.o means that by putting together the .o object files (in this example, they are hellomake.o and hellofunc.o) in the dependency list, make knows it must first compile the .c versions individually, and then build the executable hellomake

(notes: $@, $^ and $< are special macros. $@ is left side of :, $^ is right side of :, $< is the first prerequisite (usually the source file, respectively. )

Makefile 4

CC = gcc
CFLAGS = -I.
DEPS = hellomake.h
OBJ = hellomake.o hellofunc.o

%.o: %.c $(DEPS)
	$(CC) -c -o $@ $< $(CFLAGS)

hellomake: $(OBJ)
	$(CC) -o $@ $^ $(CFLAGS)

In this file, all the files are listed as macro (all include files are listed as part of the macro DEPS, all of the object files are listed as part of the macro OBJ), which makes the overall compilation rule more general.

Makefile 5

IDIR = ../include
CC = gcc
CFLAGS = -I$(IDIR)

ODIR = obj
LDIR = ../lib

LIBS = -lm

_DEPS = hellomake.h
DEPS = &(patsubst %, $(IDIR) /%, $(_DEPS))

_OBJ = hellomake.o hellofunc.o
OBJ = $(patsubst %, $(ODIR) /%, $(_OBJ))

(ODIR)%.o: %.c $(DEPS)
	$(CC) -c -o $@ $< $(CFLAGS)

hellomake: $(OBJ)
	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)

.PHONY: clean

clean:
	rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~

If we want to put our .h files in an include directory, our source code in a src directory, some local libraries in a lib directory, and hide the annoying .o files that hang around all over the place, the Makefile 5 is an example about how to achieve them.

note:
$(patsubst pattern, replacement, text)
Finds whitespace-separated words in text that match pattern and replaces them with replacement. Here pattern may contain a ‘%’ which acts as a wildcard, matching any number of any characters within a word. If replacement also contains a ‘%’, the ‘%’ is replaced by the text that matched the ‘%’ in pattern. Only the first ‘%’ in the pattern and replacement is treated this way, any subsequent ‘%’ is unchanged.

for example:
$(patsubst %.c, %.o, x.c.c bar.c)
produces: ‘x.c.o bar.o’

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值