• 系统移植Makefile&README文件分析


    Makefile介绍

    1. Makefile
    2. Makefile是一个工程管理文件,简化编译的流程,完成自动化编译的过程
    3. 在Makefile中,会把编译的过程分为两步,先生成.o文件,再对.o文件链接,生成可执行文件
    4. make工具
    5. make是一个GNU的工具,make会读入文件并完成自动化编译的过程,
    6. make默认读入文件是名为Makefile和makefile的文件,
    7. 如果makefile和Makefile同时存在,默认读入makefile
    8. 可以使用-f参数指定make工具的读入文件 ----->make -f Makefile clean
    9. Makefile的语法规则
    10. Makefile由变量,函数和规则构成
    11. Makefile中规则的构成
    12. 目标:依赖
    13. <tab>指令
    14. 注意事项:
    15. 1、一条规则必须有一个目标
    16. 2、一个目标可以有多个依赖
    17. 3、一条规则可以没有依赖,只完成相关的指令
    18. 4、一条规则可以没有指令,只描述依赖关系

    第一版Makefile

    1. all:fun #一般Mkefile会有一个all目标
    2. #该目标通常写在Makefile中的第一个位置,用于保证Makefile文件一定会生成一个可执行性文件
    3. main.o:main.c
    4. gcc -c main.c -o main.o
    5. fun:main.o fun.o
    6. gcc main.o fun.o -o fun
    7. fun.o:fun.c
    8. gcc -c -o fun.o fun.c
    9. clean:
    10. rm *.o fun

    引入Makfile中的变量,赋值

    1. =:递归赋值 ---->取变量最后一次的值
    2. +=:追加赋值 ---->把值追加到原有值的后面,并带空格
    3. :=:立即赋值 ---->在哪赋值在哪展开
    4. ?=:条件赋值 ---->如果前面出现过该变量,就不赋值否则赋值
    5. Makefile中的自动变量,都是针对一条规则而言的
    6. $@:所有目标
    7. $^:所有依赖
    8. $<:第一个依赖

    第二版Makefile

    1. EXE=fun #定义EXE表示可执行文件名
    2. OBJs+=main.o #定义中间代码文件(二进制文件)
    3. OBJs+=fun.o
    4. CC=gcc #定义编译器gcc为CC变量
    5. CFLAGs=-c -g -o #定义CFLAGs保存gcc的编译参数
    6. all:$(EXE) #一般Mkefile会有一个all目标
    7. #该目标通常写在Makefile中的第一个位置,用于保证Makefile文件一定会生成一个可执行性文件
    8. $(EXE):$(OBJs)
    9. $(CC) $^ -o $@
    10. main.o:main.c
    11. $(CC) $(CFLAGs) $@ $^
    12. fun.o:fun.c
    13. $(CC) $(CFLAGs) $@ $^
    14. clean:
    15. rm $(OBJs) $(EXE)

    第三版Makefile---->引入通配符

    1. 引入%通配符做模式匹配,能实现目标和依赖之间的唯一匹配关系
    2. EXE=fun #定义EXE表示可执行文件名
    3. OBJs+=main.o #定义中间代码文件(二进制文件)
    4. OBJs+=fun.o
    5. CC=gcc #定义编译器gcc为CC变量
    6. CFLAGs=-c -g -o #定义CFLAGs保存gcc的编译参数
    7. all:$(EXE) #一般Mkefile会有一个all目标
    8. #该目标通常写在Makefile中的第一个位置,用于保证Makefile文件一定会生成一个可执行性文件
    9. $(EXE):$(OBJs)
    10. $(CC) $^ -o $@
    11. %.o:%.c
    12. $(CC) $(CFLAGs) $@ $^
    13. clean:
    14. rm *.o $(EXE)
    15. %.o:%.c ----->会根据上面规则提供的依赖文件,找到OBJs里面的所有.o文件
    16. main.o ---->%会自动获取到main,并且继续匹配%.c--->%.c会被展开为main.c

    引入内置函数

    1. 使用以下内置函数时,要求工作路径下,只存在可执行文件需要的.c文件
    2. i)wildcard
    3. 获取当前工作路径下,所有满足格式的文件
    4. $(wildcard 指定的文件格式)
    5. $(wildcard *.c) ----->获取当前路径下的所有.c后缀的文件
    6. ii)patsubst
    7. 模式匹配,把指定格式符字符串替换为另一个格式
    8. $(patsubst 模式1,模式2,要转换的字符串)
    9. $(patsubst %c,%o,1.c 2.c 3.c····· )

    第四版Makefile

    1. 把用wildcard找到的所有.c文件文件名,转换成.o的字符串
    2. EXE=fun #定义EXE表示可执行文件名
    3. files=$(wildcard *.c) #使用内置函数wildcard获取当前路径下的所有.c文件
    4. OBJs=$(patsubst %.c,%.o,$(files))
    5. CC=gcc #定义编译器gcc为CC变量
    6. CFLAGs=-c -g -o #定义CFLAGs保存gcc的编译参数
    7. all:$(EXE) #一般Mkefile会有一个all目标
    8. #该目标通常写在Makefile中的第一个位置,用于保证Makefile文件一定会生成一个可执行性文件
    9. $(EXE):$(OBJs) #main.o fun.o
    10. $(CC) $^ -o $@
    11. %.o:%.c
    12. $(CC) $(CFLAGs) $@ $^
    13. .PHONY:clean #clean可以作为一个伪目标,这个目标不生成任何文件直接执行规则里的指令
    14. clean:
    15. rm *.o $(EXE)

    分析Makefile

    1. # 指定交叉编译工具链前缀变量
    2. CROSS_COMPILE = arm-linux-gnueabihf-
    3. #指定文件名字变量
    4. NAME = interface
    5. #=============================================================================#
    6. #-g:编译时添加gdb调试信息 -marm: 将程序编译生成arm指令集 -Wall:编译时显示所有警告信息
    7. #-O0:编译时添加优化等级 -O0:不优化 -O1:一级优化
    8. #-fno-builtin: 不使用linux操作系统,提供内置函数
    9. #-nostdinc: 不可以包含linux操作系统提供的头文件
    10. #-I:指定头文件路径
    11. CFLAGS += -g -marm -Wall -O0 -mabi=apcs-gnu -mfpu=neon -mfloat-abi=softfp -fno-builtin \
    12. -nostdinc -I./common/include -I./include
    13. #LD:链接命令
    14. LD = $(CROSS_COMPILE)ld
    15. #CC:编译命令
    16. CC = $(CROSS_COMPILE)gcc
    17. #NM:查看符号表信息
    18. NM = $(CROSS_COMPILE)nm
    19. #OBJCOPY:生成二进制文件
    20. OBJCOPY = $(CROSS_COMPILE)objcopy
    21. #OBJDUMP:生成反汇编文件
    22. OBJDUMP = $(CROSS_COMPILE)objdump
    23. #============================================================================#
    24. #wildcard是Makefile中内置函数
    25. #功能:将指定目录下,指定文件以字符串格式进行展开,并用空格隔开
    26. #参数:指定目录指定要展开文件
    27. #返回值:展开后的结果
    28. OBJSss := $(wildcard start/*.S) $(wildcard common/src/*.S) $(wildcard *.S)\
    29. $(wildcard start/*.c) $(wildcard common/src/*.c) \
    30. $(wildcard src/*.c) $(wildcard *.c)
    31. #patsubst是Makefile中内置函数
    32. #功能:将指定目录下某种格式,替换成另外一种格式
    33. #参数:1)源字符串格式 2)目标字符串格式 3)指定替换目录
    34. #返回值:替换后的结果
    35. OBJSs := $(patsubst %.S,%.o,$(OBJSss))
    36. OBJS := $(patsubst %.c,%.o,$(OBJSs))
    37. %.o: %.S
    38. @echo " AS $@"
    39. @# $(CC): 使用arm-linux-gnueabihf-gcc命令
    40. @$(CFLAGS): 指定编译参数
    41. @#-c:只编译不链接 $<:第一个依赖 $^:所有依赖 -o: 起别名 $@:目标
    42. @#将所有的.s文件根据指定参数,编译生成.o文件
    43. @$(CC) $(CFLAGS) -c $< -o $@
    44. %.o: %.c
    45. @echo " CC $@"
    46. @$(CC) $(CFLAGS) -c $< -o $@
    47. all:clean $(OBJS)
    48. @echo " LD Linking $(NAME).elf"
    49. @#将所有的.o文件,根据map.lds,通过LD链接生成.elf文件
    50. @$(LD) $(OBJS) -T map.lds -o $(NAME).elf
    51. @echo " OBJCOPY Objcopying $(NAME).bin"
    52. @#将.elf文件,通过OBJCOPY生成.bin文件
    53. @$(OBJCOPY) -O binary $(NAME).elf $(NAME).bin
    54. @echo " MAP Generating $(NAME).map"
    55. @#将.elf文件符号表信息,重定向到.map文件
    56. @$(NM) $(NAME).elf > $(NAME).map
    57. @echo " OBJDUMP Objdumping $(NAME).dis"
    58. @#将.elf文件,通过OBJDUMP生成反汇编文件,并且重定向到.dis文件
    59. @$(OBJDUMP) -DS $(NAME).elf > $(NAME).dis
    60. distclean clean:
    61. @rm -rf $(OBJS) *.elf *.bin *.dis *.map
    62. @echo " CLEAN complete."
    63. install:
    64. sudo cp $(NAME).bin /mnt/hgfs/share/

    uboot移植前准备工作/make _deconfig执行过程

    1. 1.进入uboot源码目录下,打开README文件,分析如下内容
    2. 193 For all supported boards there are ready-to-use default
    3. 194 configurations available; just type "make _defconfig".
    4. 对于所有支持的板,有现成的默认配置可用;只需键入“make <board_name>_defconfig”。
    5. 总结:通过以上分析可知,需要确定<board_name>名字,执行make <board_name>_defconfig这条命令就可以
    6. 问题:如何确定<board_name>
    7. 2.在uboot源码顶层目录下,执行make fsmp1a_defconfig
    8. 出现如下错误信息:
    9. ***
    10. *** Can't find default configuration "arch/../configs/fsmp1a_defconfig"! ===> 不能找到默认配置“arch/../configs/fsmp1a_defconfig”
    11. ***
    12. 3.进入uboot源码顶层目录下,进入configs目录下,查看和<board_name>_defconfig相关信息
    13. 4.在uboot源码顶层目录下,打开Mkaefile文件,搜索config,添加如下打印信息
    14. 563 %config: scripts_basic outputmakefile FORCE
    15. 569 $(MAKE) $(build)=scripts/kconfig $@ ===> 打印信息内容:make -f ./scripts/Makefile.build obj=scripts/kconfig fsmp1a_defconfig
    16. 分析执行语句:make -f ./scripts/Makefile.build obj=scripts/kconfig fsmp1a_defconfig ===> make obj=scripts/kconfig fsmp1a_defconfig
    17. 5.如何可以查看打印信息内容:在uboot源码顶层目录下,执行make fsmp1a_defconfig
    18. 6.进入uboot源码scripts/Kconfig目录下,打开Makefile文件,搜索:defconfig,添加如下内容打印信息
    19. %_defconfig: $(obj)/conf
    20. $< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
    21. ====> 打印信息内容:scripts/kconfig/conf --defconfig=arch/../configs/fsmp1a_defconfig Kconfig
    22. scripts/kconfig/conf:elf可执行文件
    23. --defconfig=arch/../configs/fsmp1a_defconfig:目标
    24. Kconfig:存放默认板子相关配置信息
    25. 总结:conf是一个可执行文件,目标和板子相关配置信息作为参数传递给conf

    uboot 非安全版本移植脚本文件

    使用脚本进行烧写 ./sdtools /dev/sdb

    make menuconfig执行过程

    1. 1.在uboot源码顶层目录下,打开Mkaefile文件,搜索menuconfig,发现无法找到目录,所以搜索config,找到目标之后,
    2. 563 %config: scripts_basic outputmakefile FORCE
    3. 569 $(MAKE) $(build)=scripts/kconfig $@ ===> 打印信息内容:make -f ./scripts/Makefile.build obj=scripts/kconfig menuconfig
    4. 分析执行语句:make -f ./scripts/Makefile.build obj=scripts/kconfig menuconfig
    5. ===> make obj=scripts/kconfig menuconfig
    6. 2.如何可以查看打印信息内容:在uboot源码顶层目录下,执行menuconfig
    7. 3.进入uboot源码scripts/Kconfig目录下,打开Makefile文件,搜索:menuconfig,添加如下内容打印信息
    8. 34 menuconfig: $(obj)/mconf
    9. 39 $< $(silent) $(Kconfig) =====> scripts/kconfig/mconf Kconfig
    10. 4.如何可以查看打印信息内容:在uboot源码顶层目录下,执行menuconfig
    11. 5.总结:make menuconfig执行内容
    12. =====> scripts/kconfig/mconf Kconfig
    13. scripts/kconfig/mconf :elf可执行文件
    14. Kconfig :存放默认相关图形化界面配置信息内容
    15. mconf是一个可执行文件,Kconfig作为参数传递给mconf,因为Kconfig文件存放默认相关图形化界面配置信息内容,所以执行这条命令,生成图形化界面信息

    make all执行过程

    1. 1.在uboot源码顶层目录下执行: make V=1 all
    2. //打印信息注解
    3. arm-linux-gnueabihf-objdump -t u-boot > u-boot.sym
    4. 解释:将u-boot可执行文件,通过objdump生成反汇编文件,将反汇编文件重定向到u-boot.sym
    5. arm-linux-gnueabihf-objcopy -O srec u-boot u-boot.srec
    6. 解释:将u-boot可执行文件,通过objcopy命令,生成u-boot.srec文件
    7. ./tools/mkimage -T stm32image -a 0xC0100000 -e 0xC0100000 -d u-boot.bin u-boot.stm32 >u-boot.stm32.log && cat u-boot.stm32.log
    8. 解释: mkimage - Generate image for U-Boot ====> 生成uboot镜像文件
    9. -T:设置镜像文件类型
    10. -a:设置加载地址
    11. -e:设置入口地址
    12. -d:指定使用哪一个镜像文件
    13. 使用mkimage工具,设置镜像文件类型stm32image,指定加载地址和入口地址0xC0100000
    14. 指定使用 u-boot.bin 和 u-boot.stm32 重定向到>u-boot.stm32.log文件 并且 回显u-boot.stm32.log文件内容
    15. cp u-boot-dtb.bin u-boot.bin ====> 解释:将u-boot-dtb.bin复制为u-boot.bin
    16. cat u-boot-nodtb.bin dts/dt.dtb > u-boot-dtb.bin ==> 解释:将u-boot-nodtb.bin和dts/dt.dtb进行拼接,重定向到u-boot-dtb.bin
    17. make -f ./scripts/Makefile.build obj=dts dtbs ===> 编译dts目录下设备树相关内容
    18. make -f ./scripts/Makefile.build obj=arch/arm/dts dtbs ===> 编译arch/arm/dts目录下设备树相关内容
    19. arm-linux-gnueabihf-objcopy -O binary u-boot u-boot-nodtb.bin ===> 将 u-boot可执行文件,通过objcopy生成u-boot-nodtb.bin
    20. arm-linux-gnueabihf-ld -Ttext 0xC0100000 -o u-boot -T u-boot.lds *.o
    21. 解释:将uboot源码目录下所有的.o文件,根据 u-boot.lds文件,指定链接地址0xC0100000,生成u-boot可执行文件

    TF-A 的 README文档

    1. 1、分析如下目录信息
    2. Compilation of TF-A (Trusted Firmware-A):
    3. 1. Pre-requisite ======> 准备工作
    4. 2. Initialise cross-compilation via SDK ======> 安装交叉编译工具链
    5. 3. Prepare tf-a source code ======> 准备tf-a源码
    6. 4. Management of tf-a source code ======> 管理tf-a源码
    7. 5. Compile tf-a source code ======> 编译tf-a源码
    8. 6. Update software on board ======> 烧写步骤
    9. 2、解压tf-a源码
    10. $> tar xfz tf-a-stm32mp-2.2.r2-r0.tar.gz
    11. 3、进入tf-a源码目录
    12. $> cd tf-a-stm32mp-2.2.r2
    13. 4、在tf-a源码目录下,执行打补丁命令
    14. $> for p in `ls -1 ../*.patch`; do patch -p1 < $p; done
    15. 5、编译tf-a源码命令
    16. $> make -f $PWD/../Makefile.sdk all
    17. 或者
    18. $ make -f $PWD/../Makefile.sdk TFA_DEVICETREE=stm32mp157c-ev1 TF_A_CONFIG=trusted ELF_DEBUG_ENABLE='1' all
    19. 6、生成镜像文件路径,以及名字
    20. #> ../build/*/tf-a-*.stm32

    分析Linux的README文档

    1. 1.分析README文档目录
    2. 1. Pre-requisite ======> 准备工作
    3. 2. Initialise cross-compilation via SDK ======> 安装交叉编译工具链
    4. 3. Prepare kernelsource code ======> 准备tf-a源码
    5. 4. Management of kernelsource code ======> 管理tf-a源码
    6. 5. Compile kernel source code ======> 编译tf-a源码
    7. 6. Update software on board ======> 烧写步骤
    8. 2.需要安装库
    9. sudo apt-get install u-boot-tools
    10. sudo apt-get install libyaml-dev
    11. 3.解压内核源码
    12. $> tar xfJ linux-5.10.61.tar.xz
    13. 4.进入内核源码目录下
    14. $> cd linux-5.10.61
    15. 5.打补丁命令
    16. $> for p in `ls -1 ../*.patch`; do patch -p1 < $p; done
    17. 6.配置补丁文件列表相关配置信息
    18. $ make ARCH=arm multi_v7_defconfig fragment*.config
    19. 7. 编译内核源码的命令
    20. $ make ARCH=arm uImage vmlinux dtbs LOADADDR=0xC2000000
    21. 解释:
    22. ARCH=arm :指定架构为arm架构
    23. uImage:编译生成uImage镜像文件
    24. vmlinux:内核源码目录下elf可执行文件
    25. dtbs:编译设备树
    26. LOADADDR=0xC2000000 :指定加载地址
    27. 8.内核采用模块化方式进行编译
    28. $ make ARCH=arm modules
    29. 9. 产生镜像文件名字和位置
    30. uImage镜像文件:$PWD/arch/arm/boot/uImage
    31. 设备树镜像文件:$PWD/arch/arm/boot/dts/st*.dtb

    驱动开发 动态编译的内核模块的Makefile

    1. #定义变量存放内核源码顶层路径
    2. #KERNELDIR:= /home/ubuntu/linux-5.10.61 #用于编译生成ARM架构的模块
    3. KERNELDIR := /lib/modules/$(shell uname -r)/build #用于生成x86架构的模块
    4. #定义变量保存模块化编译的文件的路径
    5. PWD:= $(shell pwd)
    6. all:
    7. #make modules是模块化编译的命令
    8. #make -C $(KERNELDIR)表示读取KERNELDIR路径下的Makefile进行make编译
    9. #M=$(PWD)指定模块化编译的路径
    10. make -C $(KERNELDIR) M=$(PWD) modules
    11. clean: #编译清除
    12. make -C $(KERNELDIR) M=$(PWD) clean
    13. obj-m:=demo.o #指定将demo.o独立链接生成内核模块文件

    驱动开发 动态编译的内核模块的Makefile通用版本

    使用这个Makefile编译的时候可以在命令行指定编译的架构以及编译的模块名

    1. modname?=demo #给定一个默认的模块名
    2. arch?=arm #给定一个架构的模块名
    3. ifeq ($(arch),arm)#判断要编译的架构进而使用不同的Makefile规则进行编译
    4. #定义变量存放内核源码顶层路径
    5. KERNELDIR:= /home/ubuntu/linux-5.10.61 #用于编译生成ARM架构的模块
    6. else
    7. KERNELDIR := /lib/modules/$(shell uname -r)/build #用于生成x86架构的模块
    8. endif
    9. #定义变量保存模块化编译的文件的路径
    10. PWD:= $(shell pwd)
    11. all:
    12. #make modules是模块化编译的命令
    13. #make -C $(KERNELDIR)表示读取KERNELDIR路径下的Makefile进行make编译
    14. #M=$(PWD)指定模块化编译的路径
    15. make -C $(KERNELDIR) M=$(PWD) modules
    16. clean: #编译清除
    17. make -C $(KERNELDIR) M=$(PWD) clean
    18. obj-m:=$(modname).o #指定将demo.o独立链接生成内核模块文件

  • 相关阅读:
    已解决xlrd.biffh.XLRDError: Excel xlsx file; not supported
    vulnhub EMPIRE: BREAKOUT靶机
    【Unity入门计划】基本概念(7)-Input Manager&Input类
    【多线程进阶】死锁问题
    SpringBoot + Nacos + K8s 优雅停机
    JavaEE中进程、线程的知识点
    香港免费主机空间哪里有
    【目标检测】YOLOv5模型从大变小,发生了什么?
    问题记录:GPU显卡提高后,代码总体运行效率没有提高
    采购供应链可见性的详细介绍(数智化采购供应链系统)
  • 原文地址:https://blog.csdn.net/MaGuangming001/article/details/132759631