uboot-Makefile分析

本文详细解析了U-Boot Makefile配置过程,包括主机系统架构、操作系统类型、执行shell脚本的设置、编译输出目录的设定以及编译目标的实现。重点介绍了Makefile如何根据硬件平台依赖确定编译环境,生成各种镜像文件的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.chinaunix.net/uid-26470747-id-3026594.html

uboot-Makefile分析 (2011-11-24 09:41)
标签:   uboot详解  分类:  uboot学习


U-Boot开头有一些跟主机软硬件环境相关的代码,在每次执行make命令时这些代码都被执行一次。

 

1.      U-Boot 配置过程

1)定义主机系统架构

HOSTARCH := $(shell uname -m | /

       sed -e s/i.86/i386/ /

           -e s/sun4u/sparc64/ /

           -e s/arm.*/arm/ /

           -e s/sa110/arm/ /

           -e s/powerpc/ppc/ /

           -e s/ppc64/ppc/ /

           -e s/macppc/ppc/)

       “sed –e”表示后面跟的是一串命令脚本,而表达式“s/abc/def/”表示要从标准输入中,查找到内容为“abc”的,然后替换成“def”。其中“abc”表达式用可以使用“.”作为通配符。

       命令“uname –m”将输出主机CPU的体系架构类型。作者的电脑使用Intel Core2系列的CPU,因此“uname –m”输出“i686”。 “i686”可以匹配命令“sed -e s/i.86/i386/”中的“i.86”,因此在作者的机器上执行Makefile,HOSTARCH将被设置成“i386” 。

2)定义主机操作系统类型

HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | /

           sed -e 's//(cygwin/).*/cygwin/')

       “uname –s”输出主机内核名字,作者使用Linux发行版Ubuntu9.10,因此“uname –s”结果是“Linux”。“tr '[:upper:]' '[:lower:]'”作用是将标准输入中的所有大写字母转换为响应的小写字母。因此执行结果是将HOSTOS 设置为“linux”。

(补充:$ sed -e '1,5d' -e 's/test/check/' example-----(-e)选项允许在同一行里执行多条命令。如例子所示,第一条命令删除15行,第二条命令用check替换test。命令的执 行顺序对结果有影响。如果两个命令都是替换命令,那么第一个替换命令将影响第二个替换命令的结果。)

3)定义执行shell脚本的shell

# Set shell to bash if possible, otherwise fall back to sh

SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; /

       else if [ -x /bin/bash ]; then echo /bin/bash; /

       else echo sh; fi; fi)

       "$$BASH"的作用实质上是生成了字符串“$BASH”(前一个$号的作用是指明第二个$是普通的字符)。若执行当前Makefile的shell中定义了“$BASH”环境变量,且文件“$BASH”是可执行文件,则SHELL的值为“$BASH”。否则,若“/bin/bash”是可执行文件,则SHELL值为“/bin/bash”。若以上两条都不成立,则将“sh”赋值给SHELL变量。

       由于作者的机器安装了bash shell,且shell默认环境变量中定义了“$BASH”,因此SHELL 被设置为$BASH 。

4)设定编译输出目录

ifdef O

ifeq ("$(origin O)", "command line")

BUILD_DIR := $(O)

endif

endif

       函数$( origin, variable) 输出的结果是一个字符串,输出结果由变量variable定义的方式决定,若variable在命令行中定义过,则origin函数返回值为"command line"。假若在命令行中执行了“export BUILD_DIR=/tmp/build”的命令,则“$(origin O)”值为“command line”,而BUILD_DIR被设置为“/tmp/build”。

ifneq ($(BUILD_DIR),)

saved-output := $(BUILD_DIR)

 

# Attempt to create a output directory.

$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})

      -d选项判断${BUILD_DIR}这个目录存在与否。

   若${BUILD_DIR}表示的目录没有定义,则创建目录。

# Verify if it was successful.

BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd)

$(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist))

endif # ifneq ($(BUILD_DIR),)

执行cd命令,进入到新建的目录里,然后执行pwd命令来得到当前目录的真实位置。为什么需要这样做呢,因为前面的创建目录工作可能不成功,所以导致后面的cd命令也没有进去,所以需要后面的pwd命令来确认一下。      

if(a,b,c)这样的形式,执行步骤为,先判断a的真假,如果为真,则执行b,如果为假,则执行c。所以这里的意思就是判断目录建成没有建成,如果建成,则什么也不干,没建成,就使用error,输出错误信息且退出。

若$(BUILD_DIR)为空,则将其赋值为当前目录路径(源代码目录)。并检查$(BUILD_DIR)目录是否存在。

OBJTREE           := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))

SRCTREE          := $(CURDIR)

TOPDIR              := $(SRCTREE)

LNDIR                 := $(OBJTREE)

… …

MKCONFIG      := $(SRCTREE)/mkconfig

… …

ifneq ($(OBJTREE),$(SRCTREE))

obj := $(OBJTREE)/

src := $(SRCTREE)/

else

obj :=

src :=

endif

       CURDIR变量指示Make当前的工作目录,由于当前Make在U-Boot顶层目录执行Makefile,因此CURDIR此时就是U-Boot顶层目录。

OBJTREE和LNDIR为存放生成文件的目录,TOPDIR与SRCTREE为源码所在目录。

变量MKCONFIG:这个变量指向一个脚本,即顶层目录的mkconfig。

       执行完上面的代码后, SRCTREE,src变量就是U-Boot代码顶层目录,而OBJTREE,obj变量就是输出目录,若没有定义BUILD_DIR环境变量,则SRCTREE,src变量与OBJTREE,obj变量都是U-Boot源代码目录。而MKCONFIG则表示U-Boot根目录下的mkconfig脚本。

#########################################################################

 ifeq ($(OBJTREE)/include/config.mk,$(wildcard $(OBJTREE)/include/config.mk))

wildcardMakefile中的关键字,它的作用是让通配符在变量中展开。

这句的封闭语句为else
all $(obj)u-boot.hex $(obj)u-boot.srec $(obj)u-boot.bin /
$(obj)u-boot.img $(obj)u-boot.dis $(obj)u-boot /
$(SUBDIRS) version gdbtools updater env depend /
dep tags ctags etags $(obj)System.map:
 @echo "System not configured - see README" >&2
 @ exit 1
endif

 

首先,它判断$(OBJTREE)/include/config.mk与$(wildcard $(OBJTREE)/include/config.mk)得到的值是否一样。$(wildcard PATTERN)的使用就是查找到与PATTERN相符合的,并且是存在的,以空格分开的文件列表。说白了,这句话就是判 断$(OBJTREE)/include/config.mk文件是否存在。如果存在,则执行咱们忽略的内容,如果不存在,则执行咱们没有忽略的内容。
先看不存在的情况。不存在的时候,就把所有目标,都指向到一条依赖上了

 @echo "System not configured - see README" >&2
 @ exit 1

然后不管执行make xxx命令,都会显示System not configured - see README,然后它把这个输出输到标准错误输出文件里了,退出了执行。

 

所以这里就明说了,如果$(OBJTREE)/include/config.mk文件不存在,则编译不能进行下去了。

如果直接运行make的话,u-boot是编译不过去的,因为缺少$(OBJTREE)/include/config.mk这个文件。然后出错提示让去看README,那咱们就去看看这个README里面写的是什么东西。
这个README文件里介绍了一下u-boot这个工程,然后说明了一下好些个参数是做什么用的,其中有一句话是包含跟咱们编译有关的信息的

make <board_name>_config

也就是说,编译的时候,make后面是需要跟参数的,那么根据make的语法,这个<board_name>_config肯定是在Makefile里定义了的一个target了。

然后再看一下Makefile文件,果然以_config结尾的target很多。因为我的板子是仿制三星的S3C2440的,所以与我最接近的,让我在移植的时候代码改动量最小的,就是smdk2410_config这个target了。如果是新手,对自己没有什么信心,那就可以直接使用这个target来编译,直接修改与这个target相关的源码就可以了。其实我个人倒是建议另外给自己的板子取一个名字,然后在Makefile里给自己的板子按着相应的规则给加一条target。然后把自己需要的与现在板子的环境最接近的板子的相关的文件都拷到相应的位置,然后慢慢修改它们就可以了。

 

# load ARCH, BOARD, and CPU configuration
include $(OBJTREE)/include/config.mk
export ARCH CPU BOARD VENDOR SOC

ifndef CROSS_COMPILE
ifeq ($(HOSTARCH),ppc)
CROSS_COMPILE =
else
ifeq ($(ARCH),ppc)
CROSS_COMPILE = powerpc-linux-
endif
ifeq ($(ARCH),arm)
CROSS_COMPILE = arm-linux-
endif
ifeq ($(ARCH),i386)
ifeq ($(HOSTARCH),i386)
CROSS_COMPILE =
else
CROSS_COMPILE = i386-linux-
endif
endif
ifeq ($(ARCH),mips)
CROSS_COMPILE = mips_4KC-
endif
ifeq ($(ARCH),nios)
CROSS_COMPILE = nios-elf-
endif
ifeq ($(ARCH),nios2)
CROSS_COMPILE = nios2-elf-
endif
ifeq ($(ARCH),m68k)
CROSS_COMPILE = m68k-elf-
endif
ifeq ($(ARCH),microblaze)
CROSS_COMPILE = mb-
endif
ifeq ($(ARCH),blackfin)
CROSS_COMPILE = bfin-elf-
endif
ifeq ($(ARCH),avr32)
CROSS_COMPILE = avr32-
endif
endif
endif

export CROSS_COMPILE

# load other configuration
include $(TOPDIR)/config.mk

 

上面为加入编译环境,根据CPU类型来为交叉编译工具加上相应的前缀

开 头一句中的include,它是把后面跟的文件内容给加到它出现的地方,这里就是把$(OBJTREE)/include/config.mk文件的内容 加入到了这里,所以就得到了ARCH,BOARD与CPU的值,如果VENDOR与SOC也定义了,也会得到它们的值。

下面为U-boot需要的目标文件。 顺序很重要,start.o必须放第一位。

 

 #########################################################################

else

all $(obj)u-boot.hex $(obj)u-boot.srec $(obj)u-boot.bin /

$(obj)u-boot.img $(obj)u-boot.dis $(obj)u-boot /

$(SUBDIRS) version gdbtools updater env depend /

dep tags ctags etags $(obj)System.map:

    @echo "System not configured - see README" >&2

    @ exit 1

endif

 

.PHONY : CHANGELOG

CHANGELOG:

    git log --no-merges U-Boot-1_1_5.. | /

    unexpand -a | sed -e 's//s/s*$$//' > $@

 

OBJS  = cpu/$(CPU)/start.o
ifeq ($(CPU),i386)
OBJS += cpu/$(CPU)/start16.o
OBJS += cpu/$(CPU)/reset.o
endif
ifeq ($(CPU),ppc4xx)
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),mpc83xx)
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),mpc85xx)
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),mpc86xx)
OBJS += cpu/$(CPU)/resetvec.o
endif
ifeq ($(CPU),bf533)
OBJS += cpu/$(CPU)/start1.o cpu/$(CPU)/interrupt.o cpu/$(CPU)/cache.o
OBJS += cpu/$(CPU)/cplbhdlr.o cpu/$(CPU)/cplbmgr.o cpu/$(CPU)/flush.o
endif
OBJS := $(addprefix $(obj),$(OBJS))
LIBS  = lib_generic/libgeneric.a
LIBS += board/$(BOARDDIR)/lib$(BOARD).a
LIBS += cpu/$(CPU)/lib$(CPU).a
ifdef SOC
LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a
endif
LIBS += lib_$(ARCH)/lib$(ARCH).a
LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a /
 fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a
LIBS += net/libnet.a
LIBS += disk/libdisk.a
LIBS += rtc/librtc.a
LIBS += dtt/libdtt.a
LIBS += drivers/libdrivers.a
LIBS += drivers/nand/libnand.a
LIBS += drivers/nand_legacy/libnand_legacy.a
LIBS += drivers/sk98lin/libsk98lin.a
LIBS += post/libpost.a post/cpu/libcpu.a
LIBS += common/libcommon.a
LIBS += $(BOARDLIBS)

LIBS := $(addprefix $(obj),$(LIBS))
.PHONY : $(LIBS)
# Add GCC lib
PLATFORM_LIBS += -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc 

 # The "tools" are needed early, so put this first
# Don't include stuff already done in $(LIBS)
SUBDIRS = tools /
   examples /
   post /
   post/cpu
.PHONY : $(SUBDIRS)

ifeq ($(CONFIG_NAND_U_BOOT),y)
NAND_SPL = nand_spl
U_BOOT_NAND = $(obj)u-boot-nand.bin
endif

__OBJS := $(subst $(obj),,$(OBJS))
__LIBS := $(subst $(obj),,$(LIBS))

       以上为UBOOT需要的库文件。

根据上面的include/config.mk文件定义的ARCH、CPU、BOARD、SOC这些变量。硬件平台依赖的目录文件可以根据这些定义来确定。SMDK2410平台相关目录及对应生成的库文件如下。
board/smdk2410/        :库文件board/smdk2410/libsmdk2410.a
cpu/arm920t/              :库文件cpu/arm920t/libarm920t.a
cpu/arm920t/s3c24x0/ :  库文件cpu/arm920t/s3c24x0/libs3c24x0.a
lib_arm/                     : 库文件lib_arm/libarm.a
include/asm-arm/       :下面两个是头文件。
include/configs/smdk2410.h

下面是最终生成的各种镜像文件:

 这 里就是定义了各种目标的target。我们最终想要的目标就是$(obj)u-boot,然后看后面的,它都信赖了好多其它的目标,然后这些个目标,也是 在此处定义的,然后有相应的$(MAKE)来执行相应的操作,所以这样就实现了一个Makefile文件,套很多个其它的Makefile文件来编译整个 工程的情况。

 

#########################################################################
#########################################################################

ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND)

all:  $(ALL)

$(obj)u-boot.hex: $(obj)u-boot
  $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@

$(obj)u-boot.srec: $(obj)u-boot
  $(OBJCOPY) ${OBJCFLAGS} -O srec $< $@

$(obj)u-boot.bin: $(obj)u-boot
  $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@

$(obj)u-boot.img: $(obj)u-boot.bin
  ./tools/mkimage -A $(ARCH) -T firmware -C none /
  -a $(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.dis: $(obj)u-boot
  $(OBJDUMP) -d $< > $@

$(obj)u-boot:  depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT)
  UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed  -n -e 's/.*/(__u_boot_cmd_.*/)/-u/1/p'|sort|uniq`;/
  cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) /
   --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) /
   -Map u-boot.map -o u-boot

$(OBJS):
  $(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@))

$(LIBS):
  $(MAKE) -C $(dir $(subst $(obj),,$@))

$(SUBDIRS):
  $(MAKE) -C $@ all

$(NAND_SPL): version
  $(MAKE) -C nand_spl/board/$(BOARDDIR) all

$(U_BOOT_NAND): $(NAND_SPL) $(obj)u-boot.bin
  cat $(obj)nand_spl/u-boot-spl-16k.bin $(obj)u-boot.bin > $(obj)u-boot-nand.bin

version:
  @echo -n "#define U_BOOT_VERSION /"U-Boot " > $(VERSION_FILE); /
  echo -n "$(U_BOOT_VERSION)" >> $(VERSION_FILE); /
  echo -n $(shell $(CONFIG_SHELL) $(TOPDIR)/tools/setlocalversion /
    $(TOPDIR)) >> $(VERSION_FILE); /
  echo "/"" >> $(VERSION_FILE)

gdbtools:
  $(MAKE) -C tools/gdb all || exit 1

updater:
  $(MAKE) -C tools/updater all || exit 1

env:
  $(MAKE) -C tools/env all || exit 1

depend dep:
  for dir in $(SUBDIRS) ; do $(MAKE) -C $$dir _depend ; done

tags ctags:
  ctags -w -o $(OBJTREE)/ctags `find $(SUBDIRS) include /
    lib_generic board/$(BOARDDIR) cpu/$(CPU) lib_$(ARCH) /
    fs/cramfs fs/fat fs/fdos fs/jffs2 /
    net disk rtc dtt drivers drivers/sk98lin common /
   /( -name CVS -prune /) -o /( -name '*.[ch]' -print /)`

etags:
  etags -a -o $(OBJTREE)/etags `find $(SUBDIRS) include /
    lib_generic board/$(BOARDDIR) cpu/$(CPU) lib_$(ARCH) /
    fs/cramfs fs/fat fs/fdos fs/jffs2 /
    net disk rtc dtt drivers drivers/sk98lin common /
   /( -name CVS -prune /) -o /( -name '*.[ch]' -print /)`

$(obj)System.map: $(obj)u-boot
  @$(NM) $< | /
  grep -v '/(compiled/)/|/(/.o$$/)/|/( [aUw] /)/|/(/./.ng$$/)/|/(LASH[RL]DI/)' | /
  sort > $(obj)System.map

smdk2410_config : unconfig
 @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0

首先我们看到,这个target首先需要执行一个unconfig操作,然后再执行后面的操作。然后我们查到unconfig操作的具体内容如下:

unconfig:
 @rm -f $(obj)include/config.h $(obj)include/config.mk /
  $(obj)board/*/config.tmp $(obj)board/*/*/config.tmp

看得出来,它是删掉了包括$(obj)include/config.mk文件在内的,几个在编译的时候生成的配置文件,这个$(obj)include/config.mk$(OBJTREE)/include/config.mk是同一个文件。这样做是为了保证重新生成文件的纯粹性。

执行完unconfig后,就执行:

 @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0

这里的$(MKCONFIG)就会被替换成上文中所说的$(SRCTREE)/mkconfig文件路径,相关于是把这个文件的内容,当可执行程序执行了,其实,它就是一个shell脚本。

一定要注意这句$(@:_config=),其实这里是用了一个比较高级的Makefile语法,$(a:patternA=patternB),这样的语法表示把a变量里的形式为patternA的换成为patternB,然后输出。那么在这个例子里,a变量换成了@,它的意思与shell@的意思是一样的,就是输入进来的所有的参数,但是中间不用环境变量IFS所定义的分隔符分开。patternA就是_configpatternB就是空。然后再看看咱们执行这个Makefile的时候输入的语句:

 make smdk2410_config

那么在这里的话,传到$(SRCTREE)/mkconfig这个脚本里的参数实际上就是 smdk2410 arm arm920t smdk2410 NULL s3c24x0


<think>好的,我现在需要帮用户优化一个Shell脚本,使其支持add和remove参数。用户提供的原始脚本分为两个部分:添加和移除uboot相关文件。用户希望将其改造成带参数的脚本,通过参数控制执行添加或移除操作。 首先,我需要理解原始脚本的功能。添加部分是将一些自定义的脚本和配置文件复制到uboot的源码目录中,而移除部分则是删除这些文件,并恢复原始的Makefile。看起来用户可能在开发或定制uboot时,需要频繁地切换这些文件,可能是为了测试不同的配置或维护多个版本。 接下来,我需要考虑如何将这两个部分转化为带参数的脚本。通常,Shell脚本可以通过位置参数(如$1)来接收参数,例如使用add或remove作为参数。因此,脚本应该检查第一个参数,决定执行添加还是移除操作。 在优化过程中,需要注意以下几点: 1. **参数处理**:脚本需要接受add或remove作为参数,并可能提供帮助信息。如果参数不正确,应该提示用法。 2. **函数化**:将添加和移除的逻辑封装成函数,提高代码的可读性和可维护性。 3. **错误处理**:在复制或删除文件时,检查操作是否成功,例如使用cp和rm的返回状态,并在失败时给出提示。 4. **路径处理**:确保所有文件路径正确,特别是相对路径的使用。可能需要使用绝对路径或基于脚本所在目录的路径,避免执行脚本时路径错误。 5. **恢复原始Makefile**:在移除操作中,用户不仅删除了自定义文件,还复制了origin目录下的Makefile回去。需要确保这个origin目录的位置正确,并且在复制时不会出错。 6. **可扩展性**:如果以后需要添加更多的文件或操作,脚本应该容易修改。 现在,我需要考虑用户可能的深层需求。用户可能希望简化部署流程,通过脚本快速切换不同的uboot配置,减少手动操作带来的错误。此外,用户可能希望脚本具备一定的健壮性,比如在文件不存在时不会报错,或者能够提示用户具体的错误原因。 在编写函数时,可以为add和remove分别创建函数。在add函数中,逐一复制文件,并在每一步检查是否成功。如果某个文件复制失败,可以输出错误信息并退出,或者继续执行但提示警告。同样,在remove函数中,删除文件时如果文件不存在,可能需要忽略错误,或者提示用户。 关于路径问题,原始脚本中的路径使用了相对路径,比如../uboot-master/,这依赖于脚本执行的位置。如果用户在其他目录执行脚本,可能会导致路径错误。因此,可能需要使用脚本所在的目录作为基准,或者要求用户在特定目录下执行脚本。不过,考虑到用户提供的原始脚本使用的是相对路径,可能在他们的工作流程中已经固定了目录结构,因此暂时保持相对路径,但可以在脚本中添加注释,提醒用户需要在正确的目录下运行。 另一个需要注意的点是,在移除操作中,用户不仅删除了自定义文件,还恢复了原始的Makefile。这里的cp命令是从./uboot/origin/Makefile复制到目标位置。需要确保./uboot/origin/Makefile存在,否则会导致错误。在脚本中应该检查这个文件是否存在,如果不存在则报错。 此外,为了提高脚本的友好性,可以添加帮助信息,当用户输入无效参数或使用-h/--help时显示用法。 总结步骤: 1. 解析参数,判断是add、remove还是其他。 2. 定义add和remove函数,分别处理文件复制和删除。 3. 在函数中添加错误检查,确保每一步操作成功。 4. 处理路径问题,确保文件在正确的位置。 5. 添加帮助信息和错误处理,提升脚本的健壮性。</think>以下是优化后的脚本,支持通过`add`和`remove`参数控制文件操作: --- ```bash #!/bin/bash # 定义路径变量(根据实际路径调整) UBOOT_DIR="../uboot-master" DTS_MAKEFILE_ORIGIN="./uboot/origin/Makefile" # 添加文件的函数 add_files() { echo "添加 U-Boot 相关文件..." # 复制构建脚本 cp -v ./build/54_build.sh ../ || { echo "复制 54_build.sh 失败"; exit 1; } # 复制 U-Boot 脚本和配置 cp -v ./uboot/54_make_clean_uboot.sh $UBOOT_DIR/ || exit 1 cp -v ./uboot/54_make_uboot.sh $UBOOT_DIR/ || exit 1 cp -v ./uboot/54_evb_defconfig $UBOOT_DIR/configs/ || exit 1 cp -v ./uboot/54_evb.h $UBOOT_DIR/include/configs/ || exit 1 cp -v ./uboot/54-evb.dts $UBOOT_DIR/arch/arm/dts/ || exit 1 cp -v ./uboot/Makefile $UBOOT_DIR/arch/arm/dts/Makefile || exit 1 echo "✅ 文件添加完成" } # 移除文件的函数 remove_files() { echo "移除 U-Boot 相关文件..." # 删除构建脚本 rm -vf ../54_build.sh # 删除 U-Boot 脚本和配置 rm -vf $UBOOT_DIR/54_make_clean_uboot.sh rm -vf $UBOOT_DIR/54_make_uboot.sh rm -vf $UBOOT_DIR/configs/54_evb_defconfig rm -vf $UBOOT_DIR/include/configs/54_evb.h rm -vf $UBOOT_DIR/arch/arm/dts/54-evb.dts # 恢复原始 Makefile if [ -f "$DTS_MAKEFILE_ORIGIN" ]; then cp -v $DTS_MAKEFILE_ORIGIN $UBOOT_DIR/arch/arm/dts/Makefile || exit 1 else echo "❌ 原始 Makefile 不存在: $DTS_MAKEFILE_ORIGIN" exit 1 fi echo "✅ 文件移除完成" } # 参数处理 case "$1" in "add") add_files ;; "remove") remove_files ;; *) echo "用法: $0 [add|remove]" echo " add - 添加 U-Boot 定制文件" echo " remove - 移除 U-Boot 定制文件并恢复原始配置" exit 1 ;; esac ``` --- ### **优化说明** 1. **参数化操作**: - 通过`add`和`remove`参数控制文件操作,避免手动注释代码。 - 示例用法: ```bash ./script.sh add # 添加文件 ./script.sh remove # 移除文件 ``` 2. **错误处理**: - 使用 `|| exit 1` 确保单步失败时脚本立即退出。 - 检查原始 Makefile 是否存在,避免无效覆盖。 3. **路径集中管理**: - 定义 `UBOOT_DIR` 和 `DTS_MAKEFILE_ORIGIN` 变量,便于批量修改路径。 4. **友好输出**: - 添加 `-v` 参数显示操作详情(如 `cp -v`、`rm -v`)。 - 使用 ✅/❌ 符号标识操作结果。 --- ### **使用注意事项** 1. **权限问题**: - 若提示权限不足,运行前添加执行权限: ```bash chmod +x script.sh ``` 2. **路径验证**: - 确保 `UBOOT_DIR` 和 `DTS_MAKEFILE_ORIGIN` 与实际路径匹配。 3. **日志记录**: - 可将关键操作重定向到日志文件: ```bash ./script.sh add > setup.log 2>&1 ``` 此脚本通过模块化设计提高了可维护性,同时降低了误操作风险。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值