Makefile概述——常用操作记录

一、导入

1、编写文件a.c

#include <stdio.h>

int main(void)
{
	func();
	return 0;
}

2、编写文件b.c

#include <stdio.h>

void func(void)
{
	printf("Hello World.\n");
}

3、linux环境下执行命令:

gcc -o test a.c b.c	

 

4、在当前目录下会生成一个test的可执行文件,在linux环境下执行命令运行test

./test

5、分析:通过gcc -o test a.c b.c 命令行对a.c、b.c进行编译、链接生成test可执行程序还是比较简单的,这是因为文件数量少,可以这样用, 但是当文件数量很多时(如几千几万个量级), 没必要每次对所有文件都编译、链接,可以仅对改动的文件进行编译,生成.o文件, 然后再对所有.o文件进行链接生成可执行程序文件

6、上述分析,可以借助编写Makefile文件来实现。

 

 

二、Makefile语法及常用功能

1、Makefile的核心——规则:

目标:依赖1 依赖2...

[TAB]命令

 

2、执行场景:

当“目标文件”不存在,

某个依赖文件比目标文件“新”,

则:执行“命令”

 

3、对上述a.c b.c编写Makefile文件

1) 在与a.c、b.c同级目录下,新建Makefile文件,编写内容如下:

test : a.o b.o
	gcc -o test a.o b.o
	
a.o : a.c
	gcc -c -o a.o a.c
	
b.o : b.c
	gcc -c -o b.o b.c
	
clean:
	rm *.o test

 

 

 

2)linux环境下执行 make 和 make clean命令,观察目录内文件变化:

运行make命令后,目录内生成test可执行程序文件,通过./test命令即可运行该程序;

运行make clean 命令, 目录内左右 .o 和 test 文件被清除。

 

4、Makefile的语法

1)通配符:%.o

  •  $@ 表示目标
  •  $< 表示第一个依赖文件
  • $^ 表示所有依赖文件

使用通配符修改上述Makefile文件,如下:

 

test: a.o b.o
	gcc -o test $^
	
%.o : %.c 
	gcc -c -o $@ $<
	
clean:
	rm *.o test

问题及分析:当前文件夹中若有同名的clean文件时,make clean命令将不会被执行,可以使用假想目标:.PHONY来解决。

2) 假想目标:.PHONY

如下:

test: a.o b.o
	gcc -o test $^
	
%.o : %.c 
	gcc -c -o $@ $<
	
clean:
	rm *.o test
	
.PHONY: clean

 

说明:添加 .PHONY: clean 后,就不会判断名为clean的文件是否存在,而是直接执行make clean命令。

 

3)即时变量、延时变量,export

简单变量(即使变量):

A := xxx         # A的值即可确定,在定义时即确定

B = xxx          # B的值使用到时才确定

 

:=                   # 即时变量

=                    # 延时变量

?=                  # 延时变量,如果是第一次定义才起效果,如果在前面该变量已定义则忽略该句

+=                  # 附加, 它是即时变量还是延时变量取决于前面的定义

 

 

 

三、Makefile语法及常用功能

a.   $(foreach var, list, text)

b.   $(filter pattern..., text)                                                  #在text中取出符合pattern格式的值

      $(filter-out pattern..., text)                                            #在text中取出不符合pattern格式的值

c.   $(wildcard pattern)                                                       #pattern定义了文件名的格式,

                                                                                          #wildcard取出其中存在的文件

d.   $(patsubst pattern, replacement, $(var))                     #从列表中取出每一个值,

                                                                                          #如果符合pattern

                                                                                          #则替换为replacement

 

 

四、Makefile实例

1、改进:支持头文件依赖

(详细介绍可以参考这篇博客: http://blog.csdn.net/qq1452008/article/details/50855810)

gcc -M c.c                                      //打印出依赖

gcc -M -MF c.d c.c                        //把依赖写入文件c.d

gcc -c -o c.o c.c -MD -MF c.d        //编译c.o, 把依赖写入文件c.d

 

自动添加依赖文件, 举例:

objs = a.o b.o c.o

#从objs列表中取出符合%的值(此处取出所有),然后替换为替换为.%.d
dep_files := $(patsubst %, .%.d, $(objs))	

#取出dep_files中存在的文件,即取出所有依赖文件
dep_files := $(wildcard $(dep_files))  

test: $(objs)
	gcc -o test $^
	
#判断是否包含依赖文件,若不包含,则执行include包含依赖文件命令
ifneq ($(dep_files),)
include $(dep_files)
endif
	
c.o : c.c c.h

#编译%.o,把依赖写入文件%.d
%.o : %.c 
	gcc -c -o $@ $< -MD -MF [email protected]  
	
clean:
	rm *.o test
	
distclean:
	rm $(dep_files)
	
.PHONY: clean

 

2、添加CFLAGS

 

#将所有警告设置成错误提醒, 设置所有头文件路径到 ./ 即当前路径查找 CFLAGS = -Werror -I./

objs = a.o b.o c.o

#从objs列表中取出符合%的值(此处取出所有),然后替换为替换为.%.d
dep_files := $(patsubst %, .%.d, $(objs))	

#取出dep_files中存在的文件,即取出所有依赖文件
dep_files := $(wildcard $(dep_files))  

#将所有警告设置成错误提醒, 设置所有头文件路径到 ./ 即当前路径查找
CFLAGS = -Werror -I./	

test: $(objs)
	gcc -o test $^
	
#判断是否包含依赖文件,若不包含,则执行include包含依赖文件命令
ifneq ($(dep_files),)
include $(dep_files)
endif
	
c.o : c.c c.h

#编译%.o,把依赖写入文件%.d
%.o : %.c 
	gcc -c -o $@ $< -MD -MF [email protected]  
	
clean:
	rm *.o test
	
distclean:
	rm $(dep_files)
	
.PHONY: clean

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章