上文讲到,如果需求仅略微修改,整个从编译到仅保留二进制文件到添加HeaderInfo到烧写到SD卡的一系列命令都需要重新再输入一遍,这很繁琐。

如何解决这个问题呢?

制作一个bash脚本文件

制作一个bash脚本文件,也就是制作一个批处理文件

#!/bin/basharm-linux-gcc -c mystart.s
arm-linux-gcc -c mylowlevel_init.s          //.s文件生成.o文件arm-linux-ld -T myboot.lds -o myboot mystart.o mylowlevel_init.o    //.o文件生成可执行文件arm-linux-objcopy -O binary myboot myboot.bin          //只保留二进制文件./mkv210 u-boot.bin u-boot.16k                    //添加HeaderInfosudo dd iflag=dsync oflag=dsync if=u-boot.16k of=/dev/sdb seek=1     //烧写到SD卡

然后运行这个文件:

bash genmyboot.sh

虽然,这样也能够实现功能,但是某种程度上可以看出并不智能。什么意思呢?可能某次修改,只修改了其中的某几个文件,其他的很多文件都没有修改。但如果运行这个bash,所有的程序都要走一遍,也就是无论文件是否被修改,都会被处理,会浪费很多的时间。

Makefile

无需畏惧Makefile

Makefile是一个能够让初学者很挫败的文件,初看会让人头昏眼花,感觉在看“天书”。比如下面是U-BootMakefile中很少的一部分:

$(obj)u-boot.img:    $(obj)u-boot.bin$(obj)tools/mkimage -A $(ARCH) -T firmware -C none \-O u-boot -a $(CONFIG_SYS_TEXT_BASE) -e 0 \-n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \sed -e 's/"[  ]*$$/ for $(BOARD) board"/') \-d $< $@$(obj)u-boot.ubl:       $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin$(OBJCOPY) ${OBJCFLAGS} --pad-to=$(PAD_TO) -O binary $(obj)spl/u-boot-spl $(obj)spl/u-boot-spl-pad.bincat $(obj)spl/u-boot-spl-pad.bin $(obj)u-boot.bin > $(obj)u-boot-ubl.bin$(obj)tools/mkimage -n $(UBL_CONFIG) -T ublimage \-e $(CONFIG_SYS_TEXT_BASE) -d $(obj)u-boot-ubl.bin $(obj)u-boot.ublrm $(obj)u-boot-ubl.binrm $(obj)spl/u-boot-spl-pad.bin$(obj)u-boot.ais:       $(obj)spl/u-boot-spl.bin $(obj)u-boot.img$(obj)tools/mkimage -s -n $(if $(CONFIG_AIS_CONFIG_FILE),$(CONFIG_AIS_CONFIG_FILE),"/dev/null") \-T aisimage \-e $(CONFIG_SPL_TEXT_BASE) \-d $(obj)spl/u-boot-spl.bin \$(obj)spl/u-boot-spl.ais$(OBJCOPY) ${OBJCFLAGS} -I binary \--pad-to=$(CONFIG_SPL_MAX_SIZE) -O binary \$(obj)spl/u-boot-spl.ais $(obj)spl/u-boot-spl-pad.aiscat $(obj)spl/u-boot-spl-pad.ais $(obj)u-boot.img > \$(obj)u-boot.ais

是不是很费解?Makefile其实语法比较简单,但复杂就复杂在其中运用了许多shell脚本和各种正则表达式等,这些混杂在一起,就会让人摸不着头脑。

如果需要详细了解Makefile的内容,可以参考链接:跟我一起写Makefile。

Makefile的基本语法

target ... : prerequisites ...command......

具体含义为:

  • target:可以是一个object file(目标文件),也可以是一个执行文件,还可以是一个标签(label);
  • prerequisites:生成该target所依赖的文件和/或target;
  • command:该target要执行的命令(任意的shell命令)。

这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件, 其生成规则定义在command。说白一点就是说:prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行

这就是Makefile的规则,也就是Makefile中最核心的内容。

Makefile案例

既然大致了解了Makefile的规则,那么如何才能完成制作描述U-Boot烧写镜像到SD卡的过程的Makefile呢?

.s文件生成.o文件

先根据这个简单的规则,写一个简单的Makefile。这里首先注明一下make命令的寻找优先级,make会在当前目录下寻找以下的Makefile文件,优先级由高到低为:

GUNMakefile > makefile > Makefile

一般,文件命名为Makefile

制作一个Makefile文件,用于将mystart.s汇编成mystart.o文件:

mystart.o: mystart.sarm-linux-gcc -c mystart.s

这很简单,如果同时还需要将mylowlevel_init.s汇编成mylowlevel_init.o文件:

mystart.o: mystart.sarm-linux-gcc -c mystart.smylowlevel_init.o: mylowlevel_init.sarm-linux-gcc -c mylowlevel_init.s

如果此时,还是运行Makefile,会发现只运行了前一句指令,但后一句的指令并没有被运行。这是因为:Makefile只运行第一个目标target,其余的目标target都不会被运行

怎么解决呢?利用Makefile生成一个伪目标target,再利用伪目标target去生成接下来的两个目标target。方式如下:

.PHONY:all               //注明all为伪目标(可写可不写)
all: mystart.o mylowlevel_init.omystart.o: mystart.sarm-linux-gcc -c mystart.smylowlevel_init.o: mylowlevel_init.sarm-linux-gcc -c mylowlevel_init.s

make的时候,目标all本身不运行任何命令,但是它依赖于mystart.omylowlevel_init.o。但当前目录下并没有这两个文件,因此它就会自动在当前Makefile中寻找是否存在目标target,如果存在,就自动执行该目标的命令。

其余步骤

.PHONY:all               //注明all为伪目标(可写可不写)
all: mystart.o mylowlevel_init.oarm-linux-ld -T myboot.lds -o myboot mystart.o mylowlevel_init.oarm-linux-objcopy -O binary myboot myboot.bin./mkv210 u-boot.bin u-boot.16kmystart.o: mystart.sarm-linux-gcc -c mystart.smylowlevel_init.o: mylowlevel_init.sarm-linux-gcc -c mylowlevel_init.s

由于烧写到SD卡的命令,需要SD卡已经插入的状态,一般而言,不会将它和这些命令都写在一起。但是,每次都输入这么麻烦的代码,也是很麻烦的事情。于是,可以用另一种方式:

.PHONY:all               //注明all为伪目标(可写可不写)
all: mystart.o mylowlevel_init.oarm-linux-ld -T myboot.lds -o myboot mystart.o mylowlevel_init.oarm-linux-objcopy -O binary myboot myboot.bin./mkv210 u-boot.bin u-boot.16kmystart.o: mystart.sarm-linux-gcc -c mystart.smylowlevel_init.o: mylowlevel_init.sarm-linux-gcc -c mylowlevel_init.s.PHONY:mksd
mksd:sudo dd iflag=dsync oflag=dsync if=u-boot.16k of=/dev/sdb seek=1

创造一个伪目标,专门用于烧写镜像到SD卡中。但是,一般情况下,这句伪目标是运行不到的。那怎么样才能只运行这句伪目标呢?

只需要在make的时候,人为地指定伪目标即可:

make mksd

Makefile的改进

尽管此时Makefile的运行没有问题,但是还是会发现一个问题。如果修改了mylowlevel_init.s文件,只会将mylowlevel_init.s文件会变成mylowlevel_init.o文件,mystart.s并不会重新汇编,这很不错;但是如果两个都不修改,此时两个.s文件都不会会变成.o文件,但是后面链接、只保留二进制文件、添加HeaderInfo三句依然还是会运行!

这是为什么呢?

由于all是一个伪目标,没有办法进行目标与依赖之间的新旧关系,因此就会一直都会运行后面的三句。

改进后的代码为:

.PHONY:all               //注明all为伪目标(可写可不写)
all: mybootmystart.o: mystart.sarm-linux-gcc -c mystart.smylowlevel_init.o: mylowlevel_init.sarm-linux-gcc -c mylowlevel_init.smyboot: mystart.o mylowlevel_init.o myboot.ldsarm-linux-ld -T myboot.lds -o myboot mystart.o mylowlevel_init.oarm-linux-objcopy -O binary myboot myboot.bin./mkv210 u-boot.bin u-boot.16k.PHONY:mksd
mksd:sudo dd iflag=dsync oflag=dsync if=u-boot.16k of=/dev/sdb seek=1

如此便好,也就是说,最好让伪目标没有命令可以执行

Makefile的自动化变量

尽管上文的Makefile看起来比较“优雅”了,但是还是存在问题的:如果存在100个.s文件需要汇编成.o文件,那么需要写100条类似于如下的代码。

mystart.o: mystart.sarm-linux-gcc -c mystart.s

这想一想,也是非常繁琐。于是,Makefile就引进了:

  • 自动化变量:$@(所有目标target集合)、$^(所有依赖集合)、$<(所有依赖集合中的第一个)
  • 模式匹配:%.x(当前目录下所有.x结尾的文件)

有了自动化变量和模式匹配,就可以写出更加简洁的Makefile了:

.PHONY:all               //注明all为伪目标(可写可不写)
all: myboot%.o: %.sarm-linux-gcc -c $<myboot: mystart.o mylowlevel_init.o myboot.ldsarm-linux-ld -T myboot.lds -o myboot mystart.o mylowlevel_init.oarm-linux-objcopy -O binary myboot myboot.bin./mkv210 u-boot.bin u-boot.16k.PHONY:mksd
mksd:sudo dd iflag=dsync oflag=dsync if=u-boot.16k of=/dev/sdb seek=1

同样,可以使用变量来代替某些内容,有点类似于宏定义的样子。一般采用:=来赋值,引用的时候需要用$()来引用

CC := arm-linux-gcc.PHONY:all               //注明all为伪目标(可写可不写)
all: myboot%.o: %.s$(CC) -c $<myboot: mystart.o mylowlevel_init.o myboot.ldsarm-linux-ld -T myboot.lds -o myboot mystart.o mylowlevel_init.oarm-linux-objcopy -O binary myboot myboot.bin./mkv210 u-boot.bin u-boot.16k.PHONY:mksd
mksd:sudo dd iflag=dsync oflag=dsync if=u-boot.16k of=/dev/sdb seek=1

当然,U-BootMakefile肯定比本文的要复杂得多的多,之后的博文会对此进行详细分析。

【Linux】制作U-Boot烧写镜像到SD卡的过程(下篇:Makefile文件)相关推荐

  1. 【Linux】制作U-Boot烧写镜像到SD卡的过程(中篇:LDS文件)

    上一篇文章,讲述了制作U-Boot烧写镜像到SD卡的过程,其中运用make的方式来进行将.s文件编译成.bin文件,那make是什么意思?它主要实现了什么? 先讲一下,如果不采用make的方式该怎样实 ...

  2. 【Linux】制作U-Boot烧写镜像到SD卡的过程(上篇)

    在嵌入式Linux操作系统中,需要将三样东西(BootLoader.内核kernel.根文件系统)传输到目标板中.一般而言,U-Boot烧写到SD卡中,而内核.根文件系统都采用TFTP的方式传输到目标 ...

  3. raspberry 烧写镜像到SD卡

    刚开始接触树莓派,需要烧写系统镜像到SD卡,网上找了些资料,记录于此. raspberry镜像下载: https://www.raspberrypi.org/downloads/ 烧写工具: wid3 ...

  4. x210项目重新回顾之十四烧写镜像到SD卡

    九鼎公司提供的sd_fusing.sh默认只生成一个分区,这在在sd_fdisk.c中可见前3行被注释, //encode_partitionInfo(partInfo[0], &mbr[0x ...

  5. pcDuino入门指南+如何烧写系统(SD卡-卡刷)

    第一章:初识pcDuino 一.概述: pcDuino是一款高性能的,性价比极高的迷你PC平台,它能运行像 Linux 3.0和Ubuntu 12.10这样的操作系统.通过内置HDMI接口即可直接输出 ...

  6. 【烧写Uboot到SD卡,打开 SD-bl1-8k.bin 失败,failed to open‘SD-bl1-8k.bin】

    烧写Uboot到SD卡,打开 SD-bl1-8k.bin 失败,failed to open'SD-bl1-8k.bin 在进行X210烧入镜像时出现了一下错误,之前烧入时是正常的,不知道为什么就报错 ...

  7. Jetson-Xavier-NX使用教程(这里说插上烧好镜像的SD卡上电就可以直接用了)

    这里说插上烧好镜像的SD卡上电就可以直接用了,似乎是不需要特意更改或者设置什么的. 转载自:https://mp.weixin.qq.com/s/Lhm9FFctl7BShdnBwmCV4w Jets ...

  8. 【Tiny4412】烧写Android系统(SD卡)

    00. 目录 文章目录 00. 目录 01. 编译内核 02. 安装dnw工具 03. 安装Android_tools 04. 烧写Android系统 05. 问题解决 06. 附录 01. 编译内核 ...

  9. rockpi4b 烧写固件到SD卡

    rockpi官方烧写文档 点我直达 烧写自己编译的固件 1.选择固件 Y:\RK3399_ROCKPI4B_ANDROID11_USERDEBUG_RK3399-ROCKPI-4B_ENG-20220 ...

最新文章

  1. 2019年第一个工作日!
  2. linux | 网卡驱动
  3. verilog扰码器设计及仿真
  4. python 多继承的问题
  5. android 用户界面教程实例汇总
  6. Encapsulate Field
  7. 调制方式性能比较--BER,频带效率的极限
  8. 微信小程序服装商城+后台管理系统
  9. 猿创征文|计算机专业硕博研究生提高效率的10款科研工具
  10. 解决复制网页文本多一个空格的问题
  11. C语言小技巧之如何求平均数
  12. java第十一次作业
  13. 2020年个人年终总结
  14. 高考临近,各地考点附近1公里范围内的酒店房量处于紧张状态
  15. 以下是两段c语言代码 函数arith(),第二章习题-ddg.doc
  16. 通过Windows批处理脚本批量修改DNS
  17. 加载Glove预训练词向量到字典
  18. [转载]扩展Log4Net中的ILog实现自定义日志字段
  19. linux系统编程3—文件存储函数
  20. Java Web 开发实战经典 基础篇(1)

热门文章

  1. matlab图像处理代码实例,MATLAB图像处理375例-程序代码
  2. 软件测试面试题:你们公司的测试流程是怎么样的?
  3. android启动其他apk,Android 启动apk的常用方法
  4. 常见python爬虫模板_常见的Python爬虫框架有几个?
  5. opengl 读取obj模型
  6. Redisson(2-2)分布式锁实现对比 VS Java的ReentrantLock之带超时时间的tryLock
  7. PADS如何导出BOM清单
  8. 手机下载神器批量下载图片教程
  9. 统一认证授权平台keycloak太牛了,我要搞一搞
  10. 计算机教程文档,计算机应用基础教程-20210323002444.doc-原创力文档