日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

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

發(fā)布時(shí)間:2024/3/13 linux 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Linux】制作U-Boot烧写镜像到SD卡的过程(下篇:Makefile文件) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

上文講到,如果需求僅略微修改,整個(gè)從編譯到僅保留二進(jìn)制文件到添加HeaderInfo到燒寫到SD卡的一系列命令都需要重新再輸入一遍,這很繁瑣。

如何解決這個(gè)問題呢?

制作一個(gè)bash腳本文件

制作一個(gè)bash腳本文件,也就是制作一個(gè)批處理文件:

#!/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文件生成可執(zhí)行文件arm-linux-objcopy -O binary myboot myboot.bin //只保留二進(jìn)制文件./mkv210 u-boot.bin u-boot.16k //添加HeaderInfosudo dd iflag=dsync oflag=dsync if=u-boot.16k of=/dev/sdb seek=1 //燒寫到SD卡

然后運(yùn)行這個(gè)文件:

bash genmyboot.sh

雖然,這樣也能夠?qū)崿F(xiàn)功能,但是某種程度上可以看出并不智能。什么意思呢?可能某次修改,只修改了其中的某幾個(gè)文件,其他的很多文件都沒有修改。但如果運(yùn)行這個(gè)bash,所有的程序都要走一遍,也就是無論文件是否被修改,都會(huì)被處理,會(huì)浪費(fèi)很多的時(shí)間。

Makefile

無需畏懼Makefile

Makefile是一個(gè)能夠讓初學(xué)者很挫敗的文件,初看會(huì)讓人頭昏眼花,感覺在看“天書”。比如下面是U-Boot的Makefile中很少的一部分:

$(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

是不是很費(fèi)解?Makefile其實(shí)語法比較簡單,但復(fù)雜就復(fù)雜在其中運(yùn)用了許多shell腳本和各種正則表達(dá)式等,這些混雜在一起,就會(huì)讓人摸不著頭腦。

如果需要詳細(xì)了解Makefile的內(nèi)容,可以參考鏈接:跟我一起寫Makefile。

Makefile的基本語法

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

具體含義為:

  • target:可以是一個(gè)object file(目標(biāo)文件),也可以是一個(gè)執(zhí)行文件,還可以是一個(gè)標(biāo)簽(label);
  • prerequisites:生成該target所依賴的文件和/或target;
  • command:該target要執(zhí)行的命令(任意的shell命令)。

這是一個(gè)文件的依賴關(guān)系,也就是說,target這一個(gè)或多個(gè)的目標(biāo)文件依賴于prerequisites中的文件, 其生成規(guī)則定義在command中。說白一點(diǎn)就是說:prerequisites中如果有一個(gè)以上的文件比target文件要新的話,command所定義的命令就會(huì)被執(zhí)行

這就是Makefile的規(guī)則,也就是Makefile中最核心的內(nèi)容。

Makefile案例

既然大致了解了Makefile的規(guī)則,那么如何才能完成制作描述U-Boot燒寫鏡像到SD卡的過程的Makefile呢?

.s文件生成.o文件

先根據(jù)這個(gè)簡單的規(guī)則,寫一個(gè)簡單的Makefile。這里首先注明一下make命令的尋找優(yōu)先級(jí),make會(huì)在當(dāng)前目錄下尋找以下的Makefile文件,優(yōu)先級(jí)由高到低為:

GUNMakefile > makefile > Makefile

一般,文件命名為Makefile。

制作一個(gè)Makefile文件,用于將mystart.s匯編成mystart.o文件:

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

這很簡單,如果同時(shí)還需要將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

如果此時(shí),還是運(yùn)行Makefile,會(huì)發(fā)現(xiàn)只運(yùn)行了前一句指令,但后一句的指令并沒有被運(yùn)行。這是因?yàn)?#xff1a;Makefile只運(yùn)行第一個(gè)目標(biāo)target,其余的目標(biāo)target都不會(huì)被運(yùn)行

怎么解決呢?利用Makefile生成一個(gè)偽目標(biāo)target,再利用偽目標(biāo)target去生成接下來的兩個(gè)目標(biāo)target。方式如下:

.PHONY:all //注明all為偽目標(biāo)(可寫可不寫) 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

當(dāng)make的時(shí)候,目標(biāo)all本身不運(yùn)行任何命令,但是它依賴于mystart.o和mylowlevel_init.o。但當(dāng)前目錄下并沒有這兩個(gè)文件,因此它就會(huì)自動(dòng)在當(dāng)前Makefile中尋找是否存在目標(biāo)target,如果存在,就自動(dòng)執(zhí)行該目標(biāo)的命令。

其余步驟

.PHONY:all //注明all為偽目標(biāo)(可寫可不寫) 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卡已經(jīng)插入的狀態(tài),一般而言,不會(huì)將它和這些命令都寫在一起。但是,每次都輸入這么麻煩的代碼,也是很麻煩的事情。于是,可以用另一種方式:

.PHONY:all //注明all為偽目標(biāo)(可寫可不寫) 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

創(chuàng)造一個(gè)偽目標(biāo),專門用于燒寫鏡像到SD卡中。但是,一般情況下,這句偽目標(biāo)是運(yùn)行不到的。那怎么樣才能只運(yùn)行這句偽目標(biāo)呢?

只需要在make的時(shí)候,人為地指定偽目標(biāo)即可:

make mksd

Makefile的改進(jìn)

盡管此時(shí)Makefile的運(yùn)行沒有問題,但是還是會(huì)發(fā)現(xiàn)一個(gè)問題。如果修改了mylowlevel_init.s文件,只會(huì)將mylowlevel_init.s文件會(huì)變成mylowlevel_init.o文件,mystart.s并不會(huì)重新匯編,這很不錯(cuò);但是如果兩個(gè)都不修改,此時(shí)兩個(gè).s文件都不會(huì)會(huì)變成.o文件,但是后面鏈接、只保留二進(jìn)制文件、添加HeaderInfo三句依然還是會(huì)運(yùn)行!

這是為什么呢?

由于all是一個(gè)偽目標(biāo),沒有辦法進(jìn)行目標(biāo)與依賴之間的新舊關(guān)系,因此就會(huì)一直都會(huì)運(yùn)行后面的三句。

改進(jìn)后的代碼為:

.PHONY:all //注明all為偽目標(biāo)(可寫可不寫) 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

如此便好,也就是說,最好讓偽目標(biāo)沒有命令可以執(zhí)行

Makefile的自動(dòng)化變量

盡管上文的Makefile看起來比較“優(yōu)雅”了,但是還是存在問題的:如果存在100個(gè).s文件需要匯編成.o文件,那么需要寫100條類似于如下的代碼。

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

這想一想,也是非常繁瑣。于是,Makefile就引進(jìn)了:

  • 自動(dòng)化變量:$@(所有目標(biāo)target集合)、$^(所有依賴集合)、$<(所有依賴集合中的第一個(gè))
  • 模式匹配:%.x(當(dāng)前目錄下所有.x結(jié)尾的文件)

有了自動(dòng)化變量和模式匹配,就可以寫出更加簡潔的Makefile了:

.PHONY:all //注明all為偽目標(biāo)(可寫可不寫) 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

同樣,可以使用變量來代替某些內(nèi)容,有點(diǎn)類似于宏定義的樣子。一般采用:=來賦值,引用的時(shí)候需要用$()來引用

CC := arm-linux-gcc.PHONY:all //注明all為偽目標(biāo)(可寫可不寫) 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

當(dāng)然,U-Boot的Makefile肯定比本文的要復(fù)雜得多的多,之后的博文會(huì)對(duì)此進(jìn)行詳細(xì)分析。

總結(jié)

以上是生活随笔為你收集整理的【Linux】制作U-Boot烧写镜像到SD卡的过程(下篇:Makefile文件)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。