makefile入门

给一个简单的makefile,下面对其进行分析

.PHONY:clean #显示指定clean为伪目标
main:main.o add.o sub.o
	gcc -Wall -g main.o add.o sub.o -o main
main.o:main.o
	gcc -Wall -g -c main.c -o main.o
add.o:add.h add.c
	gcc -Wall -g -c add.c -o add.o
sub.o:sub.h sub.c
	gcc -Wall -g -c sub.c -o sub.o
clean:
	rm -f main main.o add.o sub.o

makefile的基本操作

TARGET … : DEPENDENCIES …
   COMMAND

(1)目标(TARGET)程序产生的文件,如可执行文件和目标文件;目标也可以是要执行的动作,如clean,也称为伪目标。目标可以有多个
(2)依赖(DEPENDENCIES)是用来产生目标的输入文件列表,一个目标通常依赖于多个文件。
(3)命令(COMMAND)是make执行的动作(命令是shell命令或是可在shell下执行的程序)。注意:每个命令行的起始字符必须为TAB字符!
注意:如果DEPENDENCIES中有一个或多个文件更新的话,COMMAND就要执行,这就是Makefile最核心的内容
(4)makefile自动化变量

选项名 作用
$@ 规则的目标文件名
$< 规则的第一个依赖文件名
$^ 规则的所有依赖文件列表
#通过自动化变量,对上面的例子进行改写
.PHONY:clean #显示指定clean为伪目标
CC    	= gcc
CFLAGS	= -Wall -g
BIN		= main
OBJECTS	= main.o add.o sub.o
$(BIN):$(OBJECTS)
	$(CC) $(CFLAGS) S^ -o $@
.c.o:
	$(CC) $(CFLAGS) -c $< -o $@
clean:
	rm -f $(BIN) $(OBJECTS)

(5)makefile编译多个可执行文件
模式规则:%.o:%.c
后缀规则:.c.o:
(6)make常用内嵌函数
函数调用的基本形式:$(function arguments)

函数调用 含义 例子
$(wildcard PATTERN) 当前目录下匹配模式的文件 src=$(wildcard *.c)
$(patsubst PATTERN,REPLACEMENT,TEXT) 模式替换函数 $(patsubst %.c,%.o,$src) 等价于$(src:.c=.o)
shell函数 执行shell命令 $(shell ls –d */)列出当前目录下的子目录
#使用make常用内嵌函数编写makefile
.PHONY:clean
CC		= gcc
CFLAGS	= -Wall -g
BIN		= main
SUBDIR	= $(shell ls -d */)						#当前目录中的子目录,使用shell命令,将子文件夹保存到SUBDIR这个变量中
ROOTSRC	= $(wildcard *.c)						#当前目录下的所有.c文件,使用make自带的函数wildcard将当前文件夹中匹配到的.c文件保存到ROOTSRC这个变量中
ROOTOBJ = $(ROOTSRC:%.c=%.o)					#当前目录下的.o文件,将ROOTSRC中的.c文件名列表替换为.o文件名,并将.o文件名列表保存到ROOTOBJ这个变量中
SUBSRC	= $(shell find $(SUBDIR) -name '*.c')	#子目录中所有.c文件,在子文件夹中查找所有.c文件,并将文件名列表保存到SUBOBJ中
SUBOBJ	= $(SUBSRC:%.c=%.o)						#子目录中所有.o文件

$(BIN):$(ROOTOBJ) $(SUBOBJ)
	$(CC) $(CFLAGS) -o $(BIN) $(ROOTOBJ) $(SUBOBJ)
.c.o:
	$(CC) $(CFLAGS) -c $< -o $@

clean:
	rm -f $(BIN) $(ROOTOBJ) $(SUBOBJ)

(7)多级目录makefile
使用父目录下的makefile文件,编译子目录中的可执行文件

文件树如下
├── makefile
├── test1
│   ├── makefile
│   ├── test1
│   ├── test1.c
│   └── test1.o
└── test2
    ├── makefile
    ├── test2
    ├── test2.cpp
    └── test2.o
#在子目录test1和test2中生成可执行文件test1、test2
SUBDIRS = test1 test2				# 父目录下的两个子目录test1 test2
.PHONY:default all clean $(SUBDIRS)
default:all

all clean:
	$(MAKE) $(SUBDIRS) TARGET=$@	#$(MAKE)表示make命令,$@表示目标all或clean
$(SUBDIRS):							
	$(MAKE) -C $@ $(TARGET)			#-C表示进入test1或test2目录
CC		= gcc
BIN		= test1
OBJS	= test1.o
.PHONY:all clean print
all:print $(BIN)

print:
	@echo "----- make all in $(PWD) -----"	#$(PWD)表示当前工作路径
	
$(BIN):$(OBJS)
	$(CC) $(OBJS) -o $@
	
%.o:%.c
	$(CC) -c $<
	
clean:
	@echo "---- make clean in $(PWD) -----"	
	rm -f $(BIN) $(OBJS)
CXX		= g++
BIN		= test2
OBJS	= test2.o
CPPFLAGS= -Wall -g
.PHONY: all clean print
all:print $(BIN)

print:
	@echo "----- make all in $(PWD) -----"	#$(PWD)表示当前工作路径
	
$(BIN):$(OBJS)
	$(CXX) $(CPPFLAGS) $(OBJS) -o $@
	
%.o:%.cpp
	$(CXX) -c $<
	
clean:
	@echo "---- make clean in $(PWD) -----"	
	rm -f $(BIN) $(OBJS)
posted @ 2017-02-10 20:35  west000  阅读(160)  评论(0编辑  收藏  举报