makefile示例

 

一、Makefile 基本结构

  Makefile 是make读入的唯一配置文件,

i:由make工具创建的目标体(target),通常是目标文件或可执行文件

ii:要创建的目标体所依赖的文件(dependency_file)

iii:要创建每个目标体时需要运行的命令(command)

注意命令行前面必须是一个“TAB键”,否则编译错误为:*** missing separator.    Stop.

Makefile格式

target: dependency file
<TAB>command

例子:

hello.o: hello.c hello.h
    gcc -c hello.c -o hello.o

二:Makefile变量

 下面有一个例子:

temp:f1.o f2.o main.o
  gcc f1.o f2.o main.o -o temp
f1.o:f1.c f1.h
  gcc -Wall -O -g -c f1.c -o f1.o
f2.o:f2.c f2.h
  gcc -Wall -O -g -c f2.c -o f2.o
main.o:main.c
  gcc -Wall -O -g -c main.c -o main.o
.PHONY : clean
clean:
  rm *.o temp

注释:-Wall:表示允许发出gcc所有有用的报警信息

      -c:只是编译不链接,生成目标文件“ .o”

   -o file:表示把输出文件输出到file里

  更多的用man工具

1、变量定义

变量定义的方式: VAR=var       VAR:=var

变量使用: $(VAR)

类似于编程语言的宏;
如果你要使用真实的“$”字符,那么你需要写成“$$”
OBJS = f1.o f2.0 main.o
CC = gcc
CFLAGS = -Wall -O -g

temp:$(OBJS)
  $(CC) $(OBJS) -o temp
f1.o:f1.c f1.h
  $(CC) $(CFLAGS) -c f1.c -o f1.o
f2.o:f2.c f2.h
  $(CC) $(CFLAGS) -c $< -o $@
main.o:main.c
  $(CC) $(CFLAGS) -c main.c -o main.o
.PHONY : clean
clean:
  rm *.o temp


.PHONY : clean  
  比如“clean”这个目标,一个“伪目标”,我们并不生成“clean”这个文件。“伪目标”并不是一个文件,只是一个标签,由于“伪目标”

不是文件,所以make无法生成它的依赖关系和决定它是否要执行。我们只有通过显式地指明这个“目标”才能让其生效。

当然,“伪目标”的取名不能和文件名重名,不然其就失去了“伪目标”的意义了。

  当然,为了避免和文件重名的这种情况,我们可以使用一个特殊的标记“.PHONY”来显式地指明一个目标是“伪目标”,向make说明,

不管是否有这个文件,这个目标就是“伪目标”。

2、追加变量值

追加变量值:我们可以使用“+=”操作符给变量追加值
如果变量之前没有定义过,那么,“+=”会自动变成“=”,如果前面有变量定义,那么“+=”会继承于前次操作的赋值符。

OBJS = f1.o f2.0 main.o
OBJS += f3.o

3、自动化变量

$@   表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,"$@"就是匹配于目标中模式定义的集合。
$<   依赖目标中的第一个目标名字。如果依赖目标是以模式(即"%")定义的,那么"$<"将是符合模式的一系列的文件集。注意,其是一个一个取出来的。
$%   仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是"foo.a(bar.o)",那么,"$%"就是 "bar.o""$@"就是"foo.a"。如果目标
     不是函数库文件(Unix下是[.a],Windows下是[.lib]),那么,其值为空。
$?   所有比目标新的依赖目标的集合。以空格分隔。
$^   所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量会去除重复的依赖目标,只保留一份。
$+   这个变量很像"$^",也是所有依赖目标的集合。只是它不去除重复的依赖目标。

4、变量中的变量

foo = $(bar)
bar = $(ugh)
ugh = Huh?
$(foo)的值为Huh?
echo $(foo)来进行查看 

5、条件变量

还有一个比较有用的操作符是“?=”,先看示例: 

 FOO ?= bar

其含义是,如果FOO没有被定义过,那么变量FOO的值就是“bar”,如果FOO先前被定义过,那么这条语句将什么也不做,其等价于:

ifeq ($(origin FOO), undefined)
  FOO = bar
endif

6、关于命令的变量

AR    函数库打包程序。默认命令是“ar”。
AS    汇编语言编译程序。默认命令是“as”。
CC    C语言编译程序。默认命令是“cc”。
CXX   C++语言编译程序。默认命令是“g++”。
CO    从 RCS文件中扩展文件程序。默认命令是“co”。
CPP   C程序的预处理器(输出是标准输出设备)。默认命令是“$(CC) –E”。
RM   删除文件命令。默认命令是“rm –f”

7、关于命令参数的变量

ARFLAGS    函数库打包程序AR命令的参数。默认值是“rv”。
ASFLAGS    汇编语言编译器参数。(当明显地调用“.s”或“.S”文件时)。
CFLAGS     C语言编译器参数。
CXXFLAGS   C++语言编译器参数。
COFLAGS    RCS命令参数。
CPPFLAGS   C预处理器参数。( C 和 Fortran 编译器也会用到)
LDFLAGS   链接器参数。(如:“ld”)

如下面的例子:

CROSS_COMPILE =                             #指定编译器种类,为空,使用的就是gcc;类似于arm_linux_gnu_
LDFLAGS := -lm -lfreetype -lvga                         #指定编译器链接(根据实际项目手动修改)
TARGET := show_file #编译后的程序名(根据实际项目手动修改)
CFLAGS = -Wall -O -g

CC = $(CROSS_COMPILE)gcc
STRIP = $(CROSS_COMPILE)strip #优化工具
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
OBJS:= $(patsubst %.c, %.o, $(SRC))
all :$(OBJS)
  $(CC) $(OBJS) -o $(TARGET) $(LDFLAGS)  #将编译好的 .o文件链接生成我们的目标文件
%.o: %.c
  $(CC) $(CFLAGS) -c $< -o $@
.PHONY : clean
clean:
  rm *.o temp

目标中的"%"定义表示对文件名的匹配,"%"表示长度任意的非空字符串。例如:"%.c"表示以".c"结尾的文件名

三、make参数

“-I <dir>” 指定一个被包含 makefile 的搜索目标。可以使用多个“-I”参数来指定多个目录

CFLAGS += -I include

Makefile里面获取相对路径必须在pwd前面加shell,然后把shell pwd当一个变量来引用,书写形式是:$(shell pwd),比如说:

CFLAGS  += -I$(shell pwd)/include

 

 

 

四、关键字

 1、模式字符串替换函数——patsubst

$(patsubst <pattern>,<replacement>,<text>) 
  • 功能:查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式< pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通配符 “%”,表示任意长度的字串。如果<replacement>中也包含“%”,那么,<replacement>中的这个 “%”将是<pattern>中的那个“%”所代表的字串。(可以用“\”来转义,以“\%”来表示真实含义的“%”字符)
  • 返回:函数返回被替换过后的字符串
$(patsubst %.c,%.o,x.c bar.c)

把字串“x.c bar.c”符合模式 %.c 的单词替换成 %.o ,返回结果是“x.o bar.o”

 2、扩展通配符------wildcard

在Makefile规则中,通配符会被自动展开。但在变量的定义和函数引用时,通配符将失效。这种情况下如果需要通配符有效,就需要使用函数“wildcard”

一般我们可以使用“$(wildcard *.c)”来获取工作目录下的所有的.c文件列表。

可以使用“$(patsubst%.c,%.o,$(wildcard *.c))”,首先使用“wildcard”函数获取工作目录下的.c文件列表;之后将列表中所有文件名的后缀.c替换为.o

这样我们就可以得到在当前目录可生成的.o文件列表。

SRC = $(wildcard *.c)  $(wildcard app/*.c)
OBJS:= $(patsubst %.c, %.o, $(SRC))

 

 

 

 

推荐好文:跟我一起写Makefile

 

posted @ 2020-05-06 21:34  listxue  阅读(885)  评论(0编辑  收藏  举报