• 借助实例,轻松掌握 Makefile




    萌芽破土篇

    在这里插入图片描述

    实例1:hello world


    编辑 Makefile

    all:
    	echo "hello world"
    


    编译执行

    $ make
    $ make all 
    


    结果输出

    在这里插入图片描述


    语法说明

    • echo 前面必须只有 TAB(即你键盘上的 TAB键),且至少有一个 TAB,不能用空格代替。


    实例2:Makefile定义多个目标


    编辑 Makefile

    all:
    	echo "hello world"
    	
    test:
    	echo "hello test"
    


    编译执行

    $ make 
    $ make all
    $ make test 
    


    结果输出

    在这里插入图片描述


    语法说明

    • Makefile 中包含多个目标时,直接使用 make 编译省略模式下,默认编译第一个目标。


    实例3:Makefile注释


    编辑 Makefile

    all:
    	@echo "hello world"
    	
    test:
    	@echo "hello test"
    


    编译执行

    $ make 
    $ make all
    $ make test 
    


    结果输出

    在这里插入图片描述

    语法说明

    • 使用 @ 符号,告诉make在运行时不要将这一行命令显示出来。


    实例4:简单的依赖


    编辑 Makefile

    all:test
    	@echo "hello world"
    	
    test:
    	@echo "hello test"
    


    编译执行

    $ make 
    $ make test 
    


    结果输出

    在这里插入图片描述


    语法说明

    • all:test 告诉 make,all 目标依赖 test 目标,这一依目标在Makefile中又被称为先决条件。出现这种目标依赖关系时,make工具会按照从左到右的先后顺序先构建规则中的每一个目标。比如这里,如果要构建 all ,那么 make 会在构建它之前先构建 test 目标。


    实例5:simple程序编译

    foo.c 源码

    #include 
    void foo()
    {
    	printf("This is foo()!\n");
    }
    


    main.c 源码

    extern void foo();
    
    int main()
    {
    	foo();
    	return 0;
    }
    


    编辑 Makefile

    all: main.o foo.o
    	gcc -o simple main.o foo.o
    main.o: main.c
    	gcc -o main.o -c main.c
    foo.o: foo.c
    	gcc -o foo.o -c foo.c
    clean:
    	rm simple main.o foo.o
    


    编译执行

    $ make 
    


    结果输出

    在这里插入图片描述


    语法说明

    • 写 Makefile 文件的关键是理清文件之间的依赖关系。


    实例6:假目标

    实例 5 的 Makefile 中有一个clean文件,我们希望能够通过 clean 命令,清理历史文件。不过,在执行 clean 指令时候发现,没法对文件进行删除。这是因为 make 将 clean 当作条件,且在当前目录找到了这个文件,加上 clean 目标没有任何先决条件,所以,当我们要求 make 为我们构建 clean 目标时,它就会认为 clean 是最新的。

    在这里插入图片描述

    对于这种情况,可以通过 Makefile 中的假目标来解决,假目标可以通过关键字 .PHONY 定义。


    编辑 Makefile

    .PHONY:clean
    all: main.o foo.o
    	gcc -o simple main.o foo.o
    maiin.o: main.c
    	gcc -o main.o -c main.c
    foo.o: foo.c
    	gcc -o foo.o -c foo.c
    clean:
    	rm simple main.o foo.o
    


    编译执行

    $ make 
    $ ./simple
    $ make clean
    


    结果输出

    在这里插入图片描述


    语法说明

    • Makefile 假目标关键字 .PHONY


    实例7:Makefile变量


    编辑 Makefile

    .PHONY:clean
    CC = gcc
    RM = rm
    EXE = simple
    OBJS = main.o foo.o
    
    $(EXE):$(OBJS)
    	$(CC) -o $(EXE) $(OBJS)
    main.o:main.c
    	$(CC) -o main.o -c main.c
    foo.o:foo.c
    	$(CC) -o foo.o -c foo.c
    clean:
    	$(RM) $(EXE) $(OBJS)
    


    编译执行

    $ make 
    $ ./simple
    $ make clean
    


    结果输出

    在这里插入图片描述

    语法说明

    • 变量定义:变量名=变量值;
    • 变量引用:$(变量名) 或 ${变量名}


    实例8:Makefile自动变量


    编辑 Makefile

    .PHONY:clean
    CC = gcc
    RM = rm
    EXE = simple
    OBJS = main.o foo.o
    
    $(EXE):$(OBJS)
    	$(CC) -o $@ $^
    main.o:main.c
    	$(CC) -o $@ -c $^
    foo.o:foo.c
    	$(CC) -o $@ -c $^
    clean:
    	$(RM) $(EXE) $(OBJS)
    


    编译执行

    $ make 
    $ ./simple
    $ make clean
    


    结果输出

    在这里插入图片描述


    语法说明

    • $ @ 用于表示一个规则中的目标;当一个规则中目标有多个时,$ @指的是其中任何造成命令被运行的目标;
    • $ ^ 用于表示规则中的所有先决条件;
    • $ < 用于表示规则中的第一个先决条件。
    • 在Makefile中 ’ $ ’ 具有特殊的含义,因此如果需要采用 echo 输出 ’ $ ’ ,则需要用两个连着的 ‘ $ ’;同时 ‘$ @’ 对 Shell 也有特殊的意思,因此需要在 ‘$$@’ 前面增加一个脱字节 ‘ \ ’.


    附加实例

    //Makefile
    .PHONY: all
    all: first second third
    	@echo "\$$@ = $@"
    	@echo "$$^ = $^"
    	@echo "$$< = $<"
    first second third:
    
    //输出
    $make
    $@ = all
    $^ = first second third
    $< = first
    


    实例9:Makefile特殊变量


    1. MAKE

    编辑 Makefile

    .PHONY: all
    all: 
    	@echo "MAKE = $(MAKE)"
    


    编译执行

    $ make 
    


    结果输出
    在这里插入图片描述


    语法说明

    • MAKE 变量表示make命令名是什么;
    • 使用场景:当我们需要在Makefile中调用另外一个Makefile时需要用到它,采用这种方式有利于写一个容易移植的Makefile。



    2. MAKECMDGOALS

    编辑 Makefile

    .PHONY: all clean
    all clean: 
    	@echo "\$$@ = $@"
    	@echo "MAKECMDGOALS = $(MAKECMDGOALS)"
    


    编译执行

    $ make 
    $ make all
    $ make clean
    $ make all clean
    


    结果输出
    在这里插入图片描述


    语法说明

    • MAKECMDGOALS 表示是当前用户输入的 make 目标是什么。


    实例10:Makefile变量的类别


    1. 递归扩展变量

    编辑 Makefile

    .PHONY: all
    foo=$(var1)
    var1=-$(var2)
    var2=100
    
    all: 
    	@echo $(foo)
    


    编译执行

    $ make 
    


    结果输出在这里插入图片描述


    语法说明

    • = 符号定义的变量称之为递归扩展变量。



    2. 简单扩展变量

    编辑 Makefile

    .PHONY: all clean
    x = foo
    y = $(x) b
    x = later
    xx := foo
    yy := $(xx) b
    xx := later
    
    all:
    	@echo "x = $(y), xx = $(yy)"
    


    编译执行

    $ make 
    


    结果输出
    在这里插入图片描述


    语法说明

    • := 符号定义的变量称之为简单扩展变量。



    3. 条件赋值变量

    编辑 Makefile

    .PHONY: all clean
    foo = x
    foo ?= y
    bar ?= y
    
    all:
    	@echo "foo = $(foo), bar = $(bar)"
    


    编译执行

    $ make 
    


    结果输出
    在这里插入图片描述


    语法说明

    • ?= 符号定义的变量称之为条件赋值变量;
    • 含义:当变量以前没有定义,就定义它并将左边的值赋给它;如果先前已经定义过了,就不会改变它原来的值。


    实例11:Makefile高级变量引用功能

    编辑 Makefile

    .PHONY: all
    foo=a.o b.o c.o
    bar := $(foo:.o=.c)
    
    all: 
    	@echo "bar = $(bar)"
    


    编译执行

    $ make 
    


    结果输出在这里插入图片描述


    语法说明

    • 上面实例中变量引用的一种高级功能,在赋值的同时完成后缀替换。


    实例12:override指令

    编辑 Makefile

    .PHONY: all
    override foo=100
    
    all: 
    	@echo "foo = $(foo)"
    


    编译执行

    $ make 
    $ make foo=0
    


    结果输出

    在这里插入图片描述


    语法说明

    • override 可以使得定义变量的值不被覆盖。如上面:make foo=0 输出的值依然为100。


    实例13:Makefile模式

    编辑 Makefile

    .PHONY:clean
    CC = gcc
    RM = rm
    EXE = simple
    OBJS = main.o foo.o
    
    $(EXE):$(OBJS)
    	$(CC) -o $@ $^
    %.o:%.c
    	$(CC) -o $@ -c $^
    
    clean:
    	$(RM) $(EXE) $(OBJS)
    


    编译执行

    $ make 
    $ ./simple
    


    结果输出

    在这里插入图片描述


    语法说明

    • % 字符模式类似Windows操作系统中的通配符。


    实例14:addprefix函数

    编辑 Makefile

    .PHONY: all
    without_dir = foo.c bar.c main.o
    with_dir := $( addprefix objs/, $(without_dir))
    
    all:
    	@echo $(with_dir)
    


    编译执行

    $ make 
    


    结果输出

    在这里插入图片描述


    语法说明

    • addprefix 用于给字符串中每个子串前都加上一个前缀,形式:$(addprefix prefix, names…)


    实例15:filter 函数

    编辑 Makefile

    .PHONY: all
    text = a.c b.c c.s d.h
    text := $(filter %.c %.s, $(text))
    all:
    	@echo $(text)
    


    编译执行

    $ make 
    


    结果输出
    在这里插入图片描述


    语法说明

    • filter 用于从一个字符串中,根据模式得到满足模式的字符串,形式:$(filter pattern…, text)


    实例16:filter-out 函数

    编辑 Makefile

    .PHONY: all
    text = a.c b.c c.s d.h
    text := $(filter-out %.c %.s, $(text))
    all:
    	@echo $(text)
    


    编译执行

    $ make 
    


    结果输出

    在这里插入图片描述


    语法说明

    • filter-out 用于从一个字符串中,根据模式滤除一部分字符串,形式:$(filter-out pattern…, text)


    实例17:patsubst 函数

    编辑 Makefile

    .PHONY: all
    text = a.c b.c c.c
    text := $(patsubst %.c %.h, $(text))
    all:
    	@echo $(text)
    


    编译执行

    $ make 
    


    结果输出

    在这里插入图片描述


    语法说明

    • patsubst 用于字符串替换;同时patsubst函数可以使用模式,所以也可以用于替换前缀等;形式:$(patsubst pattern,replacement,text)


    实例18:strip 函数

    编辑 Makefile

    .PHONY: all
    src = a.c  b.c  c.c
    dst := $(strip $(src))
    all:
    	@echo "src = $(src)"
    	@echo "dst = $(dst)"
    


    编译执行

    $ make 
    


    结果输出

    在这里插入图片描述


    语法说明

    • patsubst 用于去除变量中多余的空格;形式:$(strip string)


    实例19:wildcard 函数

    编辑 Makefile

    //显示当前Makefile目录下所有 .c 文件
    .PHONY: all
    src = $(wildcard *.c)
    all:
    	@echo $(src)
    


    编译执行

    $ make 
    


    结果输出(默认Makefile所在目录中包含了foo.c main.c bar.c等文件)

    在这里插入图片描述


    语法说明

    • wildcard 通配符函数,类似于 Windows 或 linux 命令行中的 " * ";形式:$(wildcard pattern)
  • 相关阅读:
    JVM—Class类文件结构详解
    举报垃圾邮件有何作用?有专门的垃圾邮件举报通道吗?
    Hall定理(霍尔定理)证明及推广
    学习笔记(15)跨域
    微服务之——负载均衡和服务接口调用(Ribbon、openfeign)
    java spring cloud 工程企业管理软件-综合型项目管理软件-工程系统源码
    React整理总结(二、组件化开发)
    重新认识下JVM级别的本地缓存框架Guava Cache(2)——深入解读其容量限制与数据淘汰策略
    图像的数据类型
    计算机网络基础 ---- 动态路由---OSPF协议----详解
  • 原文地址:https://blog.csdn.net/locahuang/article/details/126966304