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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

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

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

上文講到,如果需求僅略微修改,整個從編譯到僅保留二進制文件到添加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-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

是不是很費解?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.o和mylowlevel_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-Boot的Makefile肯定比本文的要復雜得多的多,之后的博文會對此進行詳細分析。

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。