当前位置:首页 > 汽车电子1 > 糖果Autosar
[导读]一初识Makefilemake是一种用于项目编译的应用程序,本质是一种脚本。而Makefile则是对make脚本的规则描述。仅仅是写脚本编译项目的话shell脚本也是可以做的,用make的原因在于,make可以解析源文件之间的依赖,根据依赖关系自动维护编译工作。执行宿主操作系统中...


一 初识Makefile

make是一种用于项目编译的应用程序,本质是一种脚本。而Makefile则是对make脚本的规则描述。
仅仅是写脚本编译项目的话shell脚本也是可以做的,用make的原因在于,make可以解析源文件之间的依赖,根据依赖关系自动维护编译工作。执行宿主操作系统中的各种命令。
Makefile是一个描述文件,定义一系列的规则来指定源文件之间的调用先后顺序。有自己特定的语法规则,可以定义函数及函数调用。可以集成各种系统命令。Makefile用于指导make程序如何完成工作。


Makefile示例:


sayhello:
echo "hello world!"
  • 1


  • 2



其中sayhello称为目标,下方的 echo “hello world!” 是实现目标的命令。其中echo前面是TAB制表符,而不能是空格。
对于文件名,可以叫Makefile或makefile,也可以自定义名称。对于是否自定义Makefile文件名的区别在于使用方式不同。


采用默认名称makefile或Makefile:有两种方法,我们的Makefile文件名为Makefile


make -f 文件名 目标名
  • 1




make -f Makefile sayhello
  • 1



或者


make 目标名
  • 1




make -f make.txt sayhello
  • 1



如果不指定目标名字,则默认执行最前面的目标。



makefile三要素:目标;依赖;命令


makefile执行原理:从上到下建立依赖关系;从下到上执行


makefile建立

通过实现一个加减乘除方法作为例子,文件结构如图所示



src中文件如图所示:



然后编写src中Makefile文件


最简单的makefile

  1. app:add.c jian.c cheng.c chu.c main.c


  2. gcc add.c jian.c cheng.c chu.c main.c -I../include -o app



makefile进阶

  1. app:add.o jian.o cheng.o chu.o main.o


  2. gcc add.o jian.o cheng.o chu.o main.o -o app


  3. add.o:add.c


  4. gcc -c add.c -I../include


  5. jian.o:jian.c


  6. gcc -c jian.c -I../include


  7. cheng.o:cheng.c


  8. gcc -c cheng.c -I../include


  9. chu.o:chu.c


  10. gcc -c chu.c -I../include


  11. main.o:main.c


  12. gcc -c main.c -I../include



makefile优化

(1)常用的变量名(约定俗成的):

CC:表示c编译器版本


CFLAGS:表示编译时参数


CPPFLAGS:表示预处理参数


CXX:表示C 编译器版本


CXXFLAGS:表示c 编译时参数


LDFLAGS:表示库参数库选项


INCLUDE:表示头文件目录


TARGET:表示目标名


RM:删除选项


(2)一些特殊字符

$(变量):对变量取值


@:只显示命令结果,忽略命令本身


-:如果当前命令出错,忽略错误,继续执行


%:通配符,通配符是以遍历的方式实现的


(3)特殊变量

用于当前目标:


$@:代表目标


$<:代表依赖中的第一个


$^:代表所有依赖


(4)makefile内置函数

wildcard:按照指定格式获取当前目录下的所有文件名


例:SOURCEFILE=$(wildcard *.c):获取.c后缀的所有文件并返回赋值给SOURCEFILE


patsubst:根据指定的格式进行替换(字符串替换)


例:DEFFILE=(SOURCEFILE))


代码

  1. .PHONY:clean #伪目标


  2. CC=gcc


  3. INCLUDE=-I../include


  4. CFLAGS=-c -g -Wall $(INCLUDE) #-g增加调试信息 -Wall严格编译


  5. CPPFLAGS=-E -D #-E头文件展开 -D编译时定义宏


  6. CXX=g


  7. LDFLAGS=-L../lib -lpthread #这只是个例子,并没用到该库。-l库名


  8. TARGET=app


  9. RM=rm -rf



  10. SRCFILE=$(wildcard *.c)


  11. DEFFILE=$(patsubst %.c,%.o,$(SRCFILE))



  12. $(TARGET):$(DEFFILE)


  13. $(CC) $^ -o $(TARGET)


  14. %.o:%.c


  15. $(CC) $(CFLAGS) $<



  16. clean:


  17. -$(RM) $(TARGET) $(DEFFILE)


  18. install:


  19. sudo cp $(TARGET) /usr/bin


  20. uninstall:


  21. sudo $(RM) /usr/bin/$(TARGET)




二、Makefile基本结构与依赖

Makefile由一个个规则组成,一个规则的结构大致如下:


targets : prerequisites
commands


targets可以有多个目标,目标之间空格隔开,prerequisites可以包含多个依赖项,依赖项之间空格隔开。


其中 target 为我们要构建的目标,prerequisite为构建目标的依赖项。command为构建目标所需的命令。


举例子来说明,有两个c语言程序文件,func.c和main.c:


func.c文件


//func.c
#include
void func()
{
printf("hello world!\n");
}
  • main.c文件


//main.c
extern void func();
int main()
{
func();
return 0;
}
Makefile文件:


all main : main.o func.o
gcc main.o func.o -o main







main.o : main.c
gcc -o main.o -c main.c



func.o : func.c
gcc -o func.o -c func.c



目标依赖规则:


  • 当目标不存在时,执行对应命令。


  • 当依赖在时间上比目标更新时,执行对应命令。


  • 当依赖关系连续存在时,要依次向上回溯每个目标。


上面那个Makefile中,all和main都是目标。all是没有规则的终极目标,他可以用作生成多个目标。把main和all写在一起的话,make就会检查main的依赖,如果main是最新的就不会执行编译。


上述Makefile文件,执行make all或 make 命令的时候,先检查,main是否存在,如果不存在则检查main的依赖项,main.o和func.o这两个目标,依次向上检查,生成目标。
如果目标存在,但依赖项比目标时间要新,则也要向上检查,生成目标。


三 伪目标的引入

Makefile中的目标指什么?


  • Makefile中目标一般对应着一个文件


  • make比较目标文件和依赖之间的新旧关系,如果依赖新则执行命令


  • make以文件处理作为第一优先级


为什么需要引入伪目标?


一个场景是,Makefile文件中有一个名为clean的目标。对应的命令是清除相应目标文件。如果当前工作目录下没有名为clean的文件,这样是没问题的。但是如果当前目录下存在名为clean的文件,那么make每次检查这个目标的时候就会发现这个文件已经存在了,clean是最新的,导致clean目标对应的清除命令不会执行。



四 Makefile中变量的定义及使用



  1. CC := gcc


  2. TAGRET := hello.out



  3. $(TARGET): func.o main.o


  4. $(CC) -o $(TARGET) func.O



上述Makefile中第一二行依次定义了变量CC、TARGET,第四五行引用了这两个变量,引用变量采用"变量名或者{变量名}"的形式。



Makefile中的变量只能是字符串类型。


Makefile中变量有四种赋值方式:


1,简单赋值( := ) 编程语言中常规理解的赋值方式,只对当前语句的变量有效


2,递归赋值( = )赋值语句可能影响多个变量,所有目标变量相关的其他变量都受影响


3,条件赋值( ?= )如果变量未定义,则使用符号中的值定义变量。如果该变量已经赋值,则该赋值语句无效。


4,追加赋值( = )原变量用空格隔开的方式追加一个新值



用例子来了解一下各个赋值的差别:



简单赋值



  1. x := foo


  2. y := $(x)b


  3. x := new



  4. .PHONY : test


  5. test:


  6. @echo "y => $(y)"


  7. @echo "x => $(x)"


输出值:


x => new


y => foob



递归赋值


  1. x = foo


  2. y = $(x)b


  3. x = new



  4. .PHONY : test


  5. test:


  6. @echo "y => $(y)"


  7. @echo "x => $(x)"


输出值:


y = > newb


x => new



条件赋值


  1. x := foo


  2. y := $(x)b


  3. x ?= new



  4. .PHONY : test


  5. test:


  6. @echo "y => $(y)"


  7. @echo "x => $(x)"


输出值:


y => foob


x = foo



追加赋值


  1. x := foo


  2. y := $(x)b


  3. x = $(y)



  4. .PHONY : test


  5. test:


  6. @echo "y => $(y)"


  7. @echo "x => $(x)"


输出结果:


y => foob


x => foo foob



递归赋值就是一个连锁反应,只要之前与该变量直接产生过关联的变量都会有影响。


条件赋值,第一次为变量赋值的时候推荐条件赋值。



五 Makefile中的变量值的替换



1.使用指定字符串替换变量中的后缀字符(串)


格式:{var:a=b}


注意:替换表达式中不能有空格】


例:


  1. src := acc bcc ccc


  2. obj := $(src:cc=o)


  3. test:


  4. @echo "obj => $(obj)"


make test输出结果:


ao bo co



2.变量的模式替换


使用%保留变量值中的指定字符串,替换替他字符


格式:{var:a%b=x%y}


注意:替换表达式中不能有空格


例:


  1. src := a123b.c a234b.c ajkhb.c


  2. obj := $(src:a%b.c=x%y)


  3. test:


  4. @echo "obj => $(obj)"



分析:原串 a123b.c按照a%b.c进行模式匹配的时候a与b.c中间的123就会被%匹配到,后边就会被保留下来,a和b.c就会被x和y取代。其他的类似。


make test执行结果:


x123y x234y xjkhy



3.规则中的模式替换


targets:target-pattern:prereq-pattern


command1


command2


意义:通过target-pattern从targets中匹配子目标,再通过prereq-pattern从子目标生成依赖,进而构成完整规则。


例:


  1. objs := func.o main.o


  2. $(objs): %.o : %.c


  3. gcc -o $@ -c $^


分析:


上述第二行,通过%.o匹配objs中的func.o,通过func.c生成依赖,再匹配main.o生成main.c依赖。


上述第二行会被make程序解析成


  1. func.o: func.c


  2. gcc -o $@ -c $^


  3. main.o: main.c


  4. gcc -o $@ -c $^




4.变量的嵌套引用


一个变量名中可以包含对其他变量的引用


嵌套引用的本质是使用一个变量表示另外一个变量


例:


  1. x := y


  2. y := z


  3. a := $($(x))


分析: 这个很好理解,上述第三行可以解析为


a := $(y) ==> a := z
5.命令行变量


在shell中运行make的时候,在命令行中定义变量


命令行变量可以默认覆盖Makefile中定义的变量。


例:


  1. hm := hello makefile


  2. test:


  3. @echo "hm => $(hm)"



shell中执行 make hm = cmd


执行结果: hm => cmd



6.override关键字


override关键字用于保护Makefile中的变量不被覆盖。


  1. override var := dest


  2. test:


  3. @echo "var => $(var)"


shell中执行 make hm = cmd


执行结果: var =>dest


这个类似于C 中的const关键字



7.define关键字


define关键字用于在Makefile中定义多行变量


变量定义从变量名开始到endef结束


define定义的变量等价于使用 = 定义的变量(递归赋值)


例:


  1. define ade


  2. Jack!


  3. Tom!


  4. endef


可以加上override 修饰



  1. over define cmd


  2. @echo "Run cmd ls..."


  3. @ls


  4. endif



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

业内消息,近日高通公司宣布推出针对桌面平台的全新骁龙 X Plus 处理器。

关键字: 高通 骁龙 X Plus 处理器

近日,台积电在圣克拉拉年度技术研讨会上宣布首个“埃级”制程技术:A16。A16 是台积电首次引入背面电源输送网络技术,计划于 2026 年下半年开始量产。同时,台积电也在重新命名工艺节点,标志着「埃级」时代的开始。

关键字: 台积电 A16

4 月 25 日消息,4 月 25 日,国际数据公司(IDC)发布 2024 年第一季度中国手机市场跟踪报告,荣耀以 17.1% 的市场份额拿下第一,华为占 17.0% 位列第二,OPPO、苹果和 vivo 分别位列第三...

关键字: 荣耀 华为

业内消息, 近日华为全新Pura 70系列手机正式开售引发广大 数码爱好者追捧,但是有网友注意到这款手机的“AI修图”功能,竟然可以将照片中的人物衣服消除,并拍成视频发布网络。

关键字: 华为Pura70 华为

据韩媒报道,近日韩国多位军方人士透露,韩国军方正在考虑全面禁止在军事建筑内使用苹果手机,军方担心敏感信息通过录音泄露。

关键字: iPhone 苹果

据韩媒《朝鲜日报》消息,三星集团已确认已决定将适用于三星电子等部分关联公司的“高管每周工作 6 天”扩大到整个集团。三星子公司的人力资源团队直接通过口头、群聊和电子邮件向高管传达了这一新政,而非正式信函的形式。

关键字: 三星

4月23日,深圳传音控股股份有限公司发表了2023年年度报告。数据显示,2023年,该公司手机整体出货量约1.94亿部。

关键字: 传音 智能手机

最新消息,美国参议院以 79 票赞成、18 票反对的压倒性多数,通过了一项可能导致 TikTok 在美国被禁的法案,该法案要求字节跳动公司出售 TikTok,否则将面临禁令。TikTok 最多有 12 个月的时间从母公司...

关键字: 美国 TikTok 字节跳动

业内消息,近日数码博主@手机晶片达人在社交媒体发文表示,苹果公司正在研发自家的 AI 服务器芯片,采用台积电的 3nm 工艺,预估将于 2025 年下半年量产。台积电是苹果最重要的合作伙伴,目前苹果的大部分 3nm 产能...

关键字: 苹果 AI服务器芯片 台积电 3nm

业内消息,近日苹果公司公布了2023财年供应链名单。其中,中国大陆地区新进8家企业,有4家企业被剔除;中国台湾地区供应商新进2家企业,同样有4家企业被剔除。

关键字: 苹果 供应链
关闭
关闭