当前位置:首页 > 汽车电子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



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

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭