首页 > 其他分享 >轻松玩转makefile | 变量与模式

轻松玩转makefile | 变量与模式

时间:2023-03-02 12:33:38浏览次数:23  
标签:gcc 变量 makefile Makefile PHONY 玩转 fun main

前言

本文通过简单的几个示例,以及对同一个Makefile进行几个版本的迭代,帮助快速的理解变量和模式规则的使用。

1、回顾

在上一篇文章中,我们使用Makefile编译fun.c和main.c这两个文件,最终生成名为app的可执行文件。

fun.c的内容

#include <stdio.h>

void fun()
{
	printf("This is fun()!\n");
}

main.c的内容

extern void fun(); 

int main()
{ 
	fun(); 
	return 0; 
}

第一版Makefile

.PHONY:clean

all: main.o fun.o
	gcc -o app main.o fun.o
main.o : main.c 
	gcc -o main.o -c main.c
fun.o : fun.c 
	gcc -o fun.o -c fun.c
clean:
	rm app main.o fun.o

可以发现,Makefile里面有很多重复的内容,我们可以利用变量和模式规则对其进行优化。

2、自动变量

$@:用于表示一个规则中的目标。当有多个目标时,$@指的是其中任何导致规则命令被运行的自标。

$^:表示的是规则中的所有先决条件。

$<:表示的是规则中的第一个先决条件。

是不是看得有点晕?没关系,我们基于上面的Makefile,做一点点修改,把这些东西都打印出来看一下,就很清楚了。

.PHONY:clean

all: main.o fun.o
	gcc -o app main.o fun.o
	
	@echo "\$$@ = $@"
	@echo "$$^ = $^"
	@echo "$$< = $<"
	
main.o : main.c 
	gcc -o main.o -c main.c
fun.o : fun.c 
	gcc -o fun.o -c fun.c
clean:
	rm app main.o fun.o

运行make,终端打印如下内容

gcc -o app main.o fun.o
$@ = all
$^ = main.o fun.o
$< = main.o

了解到这些之后,我们再次修改

第二版Makefile

.PHONY:clean

all: main.o fun.o
	gcc -o app $^
	
main.o : main.c 
	gcc -o $@ -c $^
fun.o : fun.c 
	gcc -o $@ -c $^
clean:
	rm app main.o fun.o

3、变量的类别与赋值

变量的类别有递归扩展变量简单扩展变量

3.1 递归扩展变量

这种只用一个“=”符号定义的变量被称为递归扩展变量

.PHONY:all

goal = $(mid)
mid = $(fun)
fun = test

all:
	@echo "goal = $(goal)"

运行make命令 ,打印如下

goal = test

3.2 简单扩展变量

用“:=”操作符来定义的,make只对其进行一次展开。

.PHONY:all

goal_A = hello 
mid_A  = $(goal_A) world
goal_A = test

goal_B := hello
mid_B  := $(goal_B) world
goal_B := test

all:
	@echo "mid_A = $(mid_A),mid_B= $(mid_B)"

运行make命令 ,打印如下

mid_A = test world,mid_B= hello world

3.3 变量条件赋值

用“?=”操作符来定义,如果变量没有被定义,将右边的值赋值给它,如果变量已经定义了,则不改变其原值。

.PHONY:all

funA = original
funA ?= replacement

funB ?= replacement
all:
	@echo "funA = $(funA),funB = $(funB)"

运行make命令 ,打印如下

funA = original,funB = replacement

3.4 变量追加赋值

通过“+=”实现追加赋值

.PHONY:all

objects = main.o fun.o
objects += append.o

all:
	@echo "objects = $(objects)"

运行make命令 ,打印如下

objects = main.o fun.o append.o

3.5 高级变量引用功能

在赋值的同时,完成文件名后缀替换操作

.PHONY:all

src = a.c b.c c.c
objs := $(src:.c=.o)

all:
	@echo "objs = $(objs)"

运行make命令 ,打印如下

objs = a.o b.o c.o

注意,src:.c=.o 冒号后面不能有空格,如果加了空格变成src: .c=.o ,运行make,打印的结果如下

objs = a.c b.c c.c

4、模式规则

一个模式规则的格式为:

%.o : %.c 
	command...

我们利用模式规则对第二版的Makefile进行优化

第三版Makefile


#替换掉这部分
#main.o : main.c 
#	gcc -o $@ -c $^
#fun.o : fun.c 
#	gcc -o $@ -c $^

.PHONY:clean

all: main.o fun.o
	gcc -o app $^
%.o : %.c
	gcc -o $@ -c $^
clean:
	rm app main.o fun.o

这里将两条构建目标文件的规则变成了一条

" % " 类似于通配符,%.c匹配所有以".c "结尾的文件,采用了模式以后,不管有多少个源文件,都可以用同一条规则,可以极大的简化Makefile

5、利用变量和模式规则优化Makefile

我们再对第三版的Makefile进行优化,将编译器,目标等都用变量替代,这样以后修改只需要改动变量部分就好了

第四版Makefile

.PHONY:clean

CC = gcc
RM = rm

TARGET = app
OBJS = main.o fun.o

$(TARGET) : $(OBJS)
	$(CC) -o $@ $^
%.o : %.c
	$(CC) -o $@ -c $^
clean:
	$(RM) $(TARGET) $(OBJS)

到这里,Makefile已经得到了很大的改善,但是我们可以看到OBJS = xxxx 这里,如果文件数量多,得一个个书写,还是不够智能。

下一篇文章,将介绍Makefile函数的使用,利用函数可以轻松管理好源文件和目标文件。
————————————————————————————————

码字不易,点个赞再走吧!

欢迎关注我的同名公众号,这里有更多好料等着你哦!

标签:gcc,变量,makefile,Makefile,PHONY,玩转,fun,main
From: https://www.cnblogs.com/Wayne123/p/17171384.html

相关文章

  • 4-连续型随机变量、常见分布
    1回顾:23解题就是要用它的那两个性质,这里采用归一性最好了。45这个分布函数是连续的,极限等于函数值。这部分的内容跟离散型是不一样的。离散型是离散......
  • 数组元素的指针变量
    数组元素的指针变量和数组名(作为地址)等价  在使用中,[]就是*()的缩写 为啥arr==&arr[0]&arr[0]==&*(arr+0)==arr+0==arr指向......
  • Matlab中的偏最小二乘法(PLS)回归模型,离群点检测和变量选择|附代码数据
    全文下载:http://tecdat.cn/?p=22319最近我们被客户要求撰写关于偏最小二乘法(PLS)回归的研究报告,包括一些图形和统计输出。本文建立偏最小二乘法(PLS)回归(PLSR)模型,以及预测性......
  • makefile
    makefile一、gccgcc是用来编译代码的编译器编译完后有一些常见的输出文件.a 静态库(文档).c 需要预处理的C语言源代码.h C语言源代码的头文件.i 经过预处理......
  • 两个线程交替打印一个共享变量
    首先给出基本框架#include<iostream>#include<thread>usingnamespacestd;intmain(){intn=100;inti=0;//创建两个线程threadnewThre......
  • jmeter跨线程组调用变量-以token为例
    跨线程组调用变量的解决方法:在beanshell取样器中使用setProperty函数设置全局变量,其他线程组用P函数调用全局变量 跨线程组调用变量的步骤:以token为例跨线程组调用有两......
  • 轻松玩转Makefile | 基础用法
    前言本文通过几个简单的示例,可以快速了解Makefile的基本使用方法,适用于编译我们平时练习所编写的小量代码。1.make命令Makefile文件内容:all为目标,这里没有依赖的文......
  • IDEA在编译的时候报Error: java: 找不到符号符号: 变量 log lombok失效问题
    setting-->Build,Execution,Deployment 点击complier 在SharedbuildprocessVMoptions:中添加配置  -Djps.track.ap.dependencies=false ......
  • makefile中PHONY的重要性
       伪目标是这样一个目标:它不代表一个真正的文件名,在执行make时可以指定这个目标来执行所在规则定义的命令,有时也可以将一个伪目标称为标签。伪目标通过  PHONY来......
  • 《爆肝整理》保姆级系列教程-玩转Charles抓包神器教程(9)-Charles如何修改请求参数和
    1.简介宏哥之前一直用postman调接口比较多(web端),也非常容易上手和操作。但有时候想要去修改APP的页面展示,造数据又会比较麻烦,你自己造相对还好些,要是让开发造,还得低眉顺眼......