主Makefile分析

注:1)make -n可打印makefile执行的命令,而不执行。

2)可以在规则的命令中增加echo跟踪执行进度。

顶层目录的Makefile是openert的总Makefile,第一个编译目标world是make的默认编译目标。

world:

include $(TOPDIR)/include/host.mk

ifneq ($(OPENWRT_BUILD),)

_SINGLE=export MAKEFLAGS=$(space);

override OPENWRT_BUILD=

export OPENWRT_BUILD

GREP_OPTIONS=

export GREP_OPTIONS

include $(TOPDIR)/include/debug.mk

include $(TOPDIR)/include/depends.mk

include $(TOPDIR)/include/toplevel.mk

else

include rules.mk

include $(INCLUDE_DIR)/depends.mk

include $(INCLUDE_DIR)/subdir.mk

include target/Makefile

include package/Makefile

include tools/Makefile

include toolchain/Makefile

printdb:

@true

prepare: $(target/stamp-compile)

clean: FORCE

rm -rf $(BUILD_DIR) $(STAGING_DIR) $(BIN_DIR) $(BUILD_LOG_DIR)

dirclean: clean

rm -rf $(STAGING_DIR_HOST) $(TOOLCHAIN_DIR) $(BUILD_DIR_HOST) $(BUILD_DIR_TOOLCHAIN)

rm -rf $(TMP_DIR)

ifndef DUMP_TARGET_DB

$(BUILD_DIR)/.prepared: Makefile

@mkdir -p $$(dirname $@)

@touch $@

tmp/.prereq_packages: .config

unset ERROR; \

for package in $(sort $(prereq-y) $(prereq-m)); do \

$(_SINGLE)$(NO_TRACE_MAKE) -s -r -C package/$$package prereq || ERROR=; \

done; \

if [ -n "$$ERROR" ]; then \

echo "Package prerequisite check failed."; \

false; \

fi

touch $@

endif

# check prerequisites before starting to build

prereq: $(target/stamp-prereq) tmp/.prereq_packages

@if [ ! -f "$(INCLUDE_DIR)/site/$(ARCH)" ]; then \

echo 'ERROR: Missing site config for architecture "$(ARCH)" !'; \

echo ' The missing file will cause configure scripts to fail during compilation.'; \

echo ' Please provide a "$(INCLUDE_DIR)/site/$(ARCH)" file and restart the build.'; \

exit ; \

fi

prepare: .config $(tools/stamp-install) $(toolchain/stamp-install)

world: prepare $(target/stamp-compile) $(package/stamp-compile) $(package/stamp-install) $(target/stamp-install) FORCE

$(_SINGLE)$(SUBMAKE) -r package/index

.PHONY: clean dirclean prereq prepare world package/symlinks package/symlinks-install package/symlinks-clean

endif

编译逻辑可简化为:

world:

ifndef ($(OPENWRT_BUILD),)

# 第一逻辑

else

# 第二逻辑

endif

第一逻辑

make V=s时,$OPENWRT_BUILD没有定义赋值,所以总是执行“第一逻辑”,“第一逻辑”结束时再次执行make world,此时$OPENWRT_BUILD=1,所以执行“第二逻辑”。

toplevel.mk中%::解释world目标的规则。

prereq:: prepare-tmpinfo .config

@+$(NO_TRACE_MAKE) -r -s $@

WARN_PARALLEL_ERROR = $(if $(BUILD_LOG),,$(and $(filter
-j,$(MAKEFLAGS)),$(findstring s,$(OPENWRT_VERBOSE))))

ifeq ($(SDK),1)

%::

@+$(PREP_MK) $(NO_TRACE_MAKE) -r -s prereq

@./scripts/config/conf --defconfig=.config Config.in

@+$(ULIMIT_FIX) $(SUBMAKE) -r $@

else

%::

@+$(PREP_MK) $(NO_TRACE_MAKE) -r -s prereq

@( \

cp .config tmp/.config; \

./scripts/config/conf --defconfig=tmp/.config -w tmp/.config
Config.in > /dev/null 2>&1; \

if ./scripts/kconfig.pl '>' .config tmp/.config | grep -q
CONFIG; then \

printf "$(_R)WARNING: your configuration is out of
sync. Please run make menuconfig, oldconfig or defconfig!$(_N)\n"
>&2; \

fi \

)

@+$(ULIMIT_FIX) $(SUBMAKE) -r $@ $(if $(WARN_PARALLEL_ERROR), ||
{ \

printf "$(_R)Build failed - please re-run with -j1 to
see the real error message$(_N)\n" >&2; \

false; \

} )

endif

执行make
V=s时,上面规则简化为:

prereq:: prepare-tmpinfo .config

@make V=ss -r -s prereq

%::

@make V=s -r -s prereq

@make -w -r world

第二逻辑

首先就引入了target,
package, tools, toolchain这四个关键目录里的Makefile文件。

include target/Makefile

include package/Makefile

include tools/Makefile

include toolchain/Makefile

这些子目录里的Makefile使用include/subdir.mk里定义的两个函数来动态生成规则,这两个函数是subdir和stampfile。

subdir命令包

# Parameters: <subdir>

define subdir

$(call warn,$(1),d,D $(1))

$(foreach bd,$($(1)/builddirs),

$(call warn,$(1),d,BD $(1)/$(bd))

$(foreach target,$(SUBTARGETS),

$(foreach btype,$(buildtypes-$(bd)),

$(call
warn_eval,$(1)/$(bd),t,T,$(1)/$(bd)/$(btype)/$(target): $(if
$(QUILT),,$($(1)/$(bd)/$(btype)/$(target)) $(call
$(1)//$(btype)/$(target),$(1)/$(bd)/$(btype))))

$(if $(call debug,$(1)/$(bd),v),,@)+$$(SUBMAKE) -r -C
$(1)/$(bd) $(btype)-$(target) $(if $(findstring
$(bd),$($(1)/builddirs-ignore-$(btype)-$(target))), || $(call
ERROR,$(1), ERROR: $(1)/$(bd) [$(btype)] failed to build.))

$(if $(call diralias,$(bd)),$(call
warn_eval,$(1)/$(bd),l,T,$(1)/$(call
diralias,$(bd))/$(btype)/$(target): $(1)/$(bd)/$(btype)/$(target)))

)

$(call warn_eval,$(1)/$(bd),t,T,$(1)/$(bd)/$(target): $(if
$(QUILT),,$($(1)/$(bd)/$(target)) $(call
$(1)//$(target),$(1)/$(bd))))

$(if $(BUILD_LOG),@mkdir -p $(BUILD_LOG_DIR)/$(1)/$(bd))

$(foreach variant,$(if $(BUILD_VARIANT),$(BUILD_VARIANT),$(if
$(strip $($(1)/$(bd)/variants)),$($(1)/$(bd)/variants),$(if
$($(1)/$(bd)/default-variant),$($(1)/$(bd)/default-variant),__default))),

$(if $(call debug,$(1)/$(bd),v),,@)+$(if $(BUILD_LOG),set
-o pipefail;) $$(SUBMAKE) -r -C $(1)/$(bd) $(target)
BUILD_VARIANT="$(filter-out __default,$(variant))" $(if
$(BUILD_LOG),SILENT= 2>&1 | tee
$(BUILD_LOG_DIR)/$(1)/$(bd)/$(target).txt) $(if $(findstring
$(bd),$($(1)/builddirs-ignore-$(target))), || $(call ERROR,$(1),
ERROR: $(1)/$(bd) failed to build$(if $(filter-out
__default,$(variant)), (build variant: $(variant))).))

)

$(if $(PREREQ_ONLY)$(DUMP_TARGET_DB),,

# aliases

$(if $(call diralias,$(bd)),$(call
warn_eval,$(1)/$(bd),l,T,$(1)/$(call diralias,$(bd))/$(target):
$(1)/$(bd)/$(target)))

)

)

)

$(foreach target,$(SUBTARGETS),$(call subtarget,$(1),$(target)))

endef

subdir会遍历参数子目录,执行make
-C操作。

stampfile命令包

# Parameters: <subdir> <name>
<target> <depends> <config options> <stampfile
location>

define stampfile

$(1)/stamp-$(3):=$(if
$(6),$(6),$(STAGING_DIR))/stamp/.$(2)_$(3)$(5)

$$($(1)/stamp-$(3)): $(TMP_DIR)/.build $(4)

@+$(SCRIPT_DIR)/timestamp.pl -n $$($(1)/stamp-$(3)) $(1) $(4) ||
\

$(MAKE) $(if $(QUIET),--no-print-directory)
$$($(1)/flags-$(3)) $(1)/$(3)

@mkdir -p $$$$(dirname $$($(1)/stamp-$(3)))

@touch $$($(1)/stamp-$(3))

$$(if $(call debug,$(1),v),,.SILENT: $$($(1)/stamp-$(3)))

.PRECIOUS: $$($(1)/stamp-$(3)) # work around a make bug

$(1)//clean:=$(1)/stamp-$(3)/clean

$(1)/stamp-$(3)/clean: FORCE

@rm -f $$($(1)/stamp-$(3))

endef

target/Makefile中调用:

curdir:=target

$(curdir)/builddirs:=linux sdk imagebuilder toolchain

$(curdir)/builddirs-default:=linux

$(curdir)/builddirs-install:=linux $(if $(CONFIG_SDK),sdk) $(if
$(CONFIG_IB),imagebuilder) $(if $(CONFIG_MAKE_TOOLCHAIN),toolchain)

$(curdir)/imagebuilder/install:=$(curdir)/linux/install

$(eval $(call
stampfile,$(curdir),target,prereq,.config))

$(eval $(call
stampfile,$(curdir),target,compile,$(TMP_DIR)/.build))

$(eval $(call
stampfile,$(curdir),target,install,$(TMP_DIR)/.build))

$($(curdir)/stamp-install): $($(curdir)/stamp-compile)

$(eval $(call subdir,$(curdir)))

$(eval
$(call stampfile,$(curdir),target,prereq,.config))

会生成规则:

target/stamp-prereq:=$(STAGING_DIR)/stamp/.target_prereq

$$(target/stamp-prereq): $(TMP_DIR)/.build .config

@+$(SCRIPT_DIR)/timestamp.pl -n $$(target/stamp-prereq) target
.config || \

make $$(target/flags-prereq) target/prereq

@mkdir -p $$$$(dirname $$(target/stamp-prereq))

@touch $$(target/stamp-prereq)

$$(if $(call debug,target,v),,.SILENT: $$(target/stamp-prereq))

.PRECIOUS: $$(target/stamp-prereq) # work around a make bug

target//clean:=target/stamp-prereq/clean

target/stamp-prereq/clean: FORCE

@rm -f $$(target/stamp-prereq)

所以可以简单的看作:
$(eval
$(call stampfile,$(curdir),target,prereq,.config)) 生成了目标
$(target/stamp-prereq)

  • 对于target分别生成了:$(target/stamp-prereq),
    $(target/stamp-compile),
    $(target/stamp-install)

  • toolchain
    : $(toolchain/stamp-install)

  • package
    : $(package/stamp-prereq),$(package/stamp-cleanup), $(package/stamp-compile),$(package/stamp-install)

  • tools
    : $(tools/stamp-install)

倚赖关系如下:

$(toolchain/stamp-install):
$(tools/stamp-install)

$(target/stamp-compile):
$(toolchain/stamp-install) $(tools/stamp-install)
$(BUILD_DIR)/.prepared

$(package/stamp-compile):
$(target/stamp-compile) $(package/stamp-cleanup)

$(package/stamp-install):
$(package/stamp-compile)

$(target/stamp-install):
$(package/stamp-compile) $(package/stamp-install)

基本上就是toolchain依赖tools,target依赖toolchain,package依赖target,最后target/stamp-install倚赖于package。

kernel编译

kernel编译可运行命令:make
target/linux/{prepare,compile,install} V=s

target/linux/Makefile

include $(TOPDIR)/rules.mk

include $(INCLUDE_DIR)/target.mk

export TARGET_BUILD=1

prereq clean download prepare compile install menuconfig nconfig
oldconfig update refresh: FORCE

@+$(NO_TRACE_MAKE) -C $(BOARD) $@

target/linux/ipq806x/Makefile

include $(TOPDIR)/rules.mk

ARCH:=arm

BOARD:=ipq806x

BOARDNAME:=Qualcomm Atheros IPQ806X

FEATURES:=ubifs squashfs

CPU_TYPE:=cortex-a7

MAINTAINER:=John Crispin <blogic@openwrt.org>

KERNELNAME:=zImage Image dtbs

KERNEL_PATCHVER:=3.14

include $(INCLUDE_DIR)/target.mk

$(eval $(call BuildTarget))

BuildTarget在include/target.mk中:

include $(INCLUDE_DIR)/kernel.mk

ifeq ($(TARGET_BUILD),1)

include $(INCLUDE_DIR)/kernel-build.mk

BuildTarget?=$(BuildKernel)

endif

BuildKernel在include/kernel-build.mk中:

define BuildKernel

$(if $(QUILT),$(Build/Quilt))

$(if $(LINUX_SITE),$(call Download,kernel))

define BuildKernel

endef

download: $(if $(LINUX_SITE),$(DL_DIR)/$(LINUX_SOURCE))

prepare: $(STAMP_CONFIGURED)

compile: $(LINUX_DIR)/.modules

$(MAKE) -C image compile TARGET_BUILD=

oldconfig menuconfig nconfig: $(STAMP_PREPARED) $(STAMP_CHECKED)
FORCE

rm -f $(STAMP_CONFIGURED)

$(LINUX_RECONF_CMD) > $(LINUX_DIR)/.config

$(_SINGLE)$(MAKE) -C $(LINUX_DIR) $(KERNEL_MAKEOPTS) $$@

$(LINUX_RECONF_DIFF) $(LINUX_DIR)/.config >
$(LINUX_RECONFIG_TARGET)

install: $(LINUX_DIR)/.image

+$(MAKE) -C image compile install TARGET_BUILD=

clean: FORCE

rm -rf $(KERNEL_BUILD_DIR)

image-prereq:

@+$(NO_TRACE_MAKE) -s -C image prereq TARGET_BUILD=

prereq: image-prereq

endef

至此编译kernel时clean/prepare/compile/install目标规则出现,涉及的Makefile包括:include/kernel-build.mk,include/kernel-defaults.mk.

1)触发make
vmlinux命令生成vmlinux:
install --> $(LINUX_DIR)/.image -->
$(KERNEL_BUILD_DIR)/symtab.h --> `$(MAKE) $(KERNEL_MAKEOPTS)
vmlinux`

2)对vmlinux做objcopy,
strip操作:
$(LINUX_DIR)/.image --> $(Kernel/CompileImage) --> $(call
Kernel/CompileImage/Default) --> $(call Kernel/CopyImage)

define Kernel/CopyImage

$(KERNEL_CROSS)objcopy -O binary $(OBJCOPY_STRIP) -S
$(LINUX_DIR)/vmlinux $(LINUX_KERNEL)$(1)

$(KERNEL_CROSS)objcopy $(OBJCOPY_STRIP) -S $(LINUX_DIR)/vmlinux
$(KERNEL_BUILD_DIR)/vmlinux$(1).elf

$(CP) $(LINUX_DIR)/vmlinux $(KERNEL_BUILD_DIR)/vmlinux$(1).debug

$(foreach k, \

$(if $(KERNEL_IMAGES),$(KERNEL_IMAGES),$(filter-out
dtbs,$(KERNELNAME))), \

$(CP)
$(LINUX_DIR)/arch/$(LINUX_KARCH)/boot/$(IMAGES_DIR)/$(k)
$(KERNEL_BUILD_DIR)/$(k)$(1); \

)

endef

3)内核config处理

prepare -->
$(STAMP_CONFIGURED) --> $(Kernel/Configure) --> $(call
Kernel/Configure/Default)

define Kernel/Configure

$(call Kernel/Configure/Default)

endef

define Kernel/Configure/Default

$(LINUX_CONF_CMD) > $(LINUX_DIR)/.config.target

# copy CONFIG_KERNEL_* settings over to .config.target

awk
'/^(#[[:space:]]+)?CONFIG_KERNEL/{sub("CONFIG_KERNEL_","CONFIG_");print}'
$(TOPDIR)/.config >> $(LINUX_DIR)/.config.target

echo "# CONFIG_KALLSYMS_EXTRA_PASS is not set" >>
$(LINUX_DIR)/.config.target

echo "# CONFIG_KALLSYMS_ALL is not set" >>
$(LINUX_DIR)/.config.target

echo "# CONFIG_KALLSYMS_UNCOMPRESSED is not set" >>
$(LINUX_DIR)/.config.target

$(SCRIPT_DIR)/metadata.pl kconfig $(TMP_DIR)/.packageinfo
$(TOPDIR)/.config $(KERNEL_PATCHVER) >
$(LINUX_DIR)/.config.override

$(SCRIPT_DIR)/kconfig.pl 'm+' '+' $(LINUX_DIR)/.config.target
/dev/null $(LINUX_DIR)/.config.override > $(LINUX_DIR)/.config

$(call Kernel/SetNoInitramfs)

rm -rf $(KERNEL_BUILD_DIR)/modules

$(_SINGLE) [ -d $(LINUX_DIR)/user_headers ] || $(MAKE)
$(KERNEL_MAKEOPTS) INSTALL_HDR_PATH=$(LINUX_DIR)/user_headers
headers_install

$(SH_FUNC) grep '=[ym]' $(LINUX_DIR)/.config | LC_ALL=C sort |
md5s > $(LINUX_DIR)/.vermagic

endef

firmware编译

firmware由kernel和rootfs两个部分组成,要对两个部分先分别处理,然后再合并成一个.bin文件。

target/linux/ipq806x/image/Makefile中最后定义了生成image的规则:

$(eval $(call BuildImage))

本文件中也定义了生成Image镜像(包含ubifs镜像)的规则。

同时注意:编译kernel的compile或install时也会执行image下的compile和install。

include/image.mk定义BuildImage命令包:

define BuildImage

download:

prepare:

compile:

clean:

image_prepare:

ifeq ($(IB),)

.PHONY: download prepare compile clean image_prepare mkfs_prepare
kernel_prepare install

compile:

$(call Build/Compile)

clean:

$(call Build/Clean)

image_prepare: compile

mkdir -p $(KDIR)/tmp

$(call Image/Prepare)

else

image_prepare:

mkdir -p $(KDIR)/tmp

endif

mkfs_prepare: image_prepare

$(call Image/mkfs/prepare)

kernel_prepare: mkfs_prepare

$(call Image/BuildKernel)

$(if $(CONFIG_TARGET_ROOTFS_INITRAMFS),$(if $(IB),,$(call
Image/BuildKernel/Initramfs)))

$(call Image/InstallKernel)

$(foreach device,$(TARGET_DEVICES),$(call Device,$(device)))

$(foreach fs,$(TARGET_FILESYSTEMS) $(fs-subtypes-y),$(call
BuildImage/mkfs,$(fs)))

$$(sort $$(_KERNEL_IMAGES)):

@touch $$@

install: kernel_prepare

$(foreach fs,$(TARGET_FILESYSTEMS),

$(call Image/Build,$(fs))

)

$(call Image/mkfs/ubifs)

$(call Image/Checksum,md5sum --binary,md5sums)

$(call Image/Checksum,openssl dgst -sha256,sha256sums)

endef

至此编译firmware时clean/prepare/compile/install目标规则出现,但只有install起作用。测试中发现直接运行make
target/linux/ipq806x/image/install V=s出错,需要运行make
target/linux/install V=s。

kernel处理

install-->kernel_prepare
-->mkfs_prepare -->image_prepare --> $(call Image/Prepare)

kernel_prepare: mkfs_prepare

$(call Image/BuildKernel)

$(if $(CONFIG_TARGET_ROOTFS_INITRAMFS),$(if $(IB),,$(call
Image/BuildKernel/Initramfs)))

$(call Image/InstallKernel)

$(foreach device,$(TARGET_DEVICES),$(call Device,$(device)))

$(foreach fs,$(TARGET_FILESYSTEMS) $(fs-subtypes-y),$(call
BuildImage/mkfs,$(fs)))

$$(sort $$(_KERNEL_IMAGES)):

@touch $$@

mkfs_prepare: image_prepare

$(call Image/mkfs/prepare)

image_prepare: compile

mkdir -p $(KDIR)/tmp

$(call Image/Prepare)

define Image/Prepare

$(CP) $(LINUX_DIR)/vmlinux $(KDIR)/$(IMG_PREFIX)-vmlinux.elf

endef

主要处理命令包为:Image/BuildKernel,将设备树和镜像打包成FIT镜像树文件:openwrt-ipq806x-fit-uImage.itb。

define Image/BuildKernel

$(call Image/BuildKernel/template,FIT)

$(call
Image/BuildKernel/GenericFIT,qcom-ipq40xx,$(IPQ40XX_KERNEL_LOADADDR))

$(call Image/BuildKernel/MultiDTBFIT,qcom-ipq40xx-ap.dkxx, \

$(call FindDeviceTrees, qcom-ipq40??-ap) $(call
FindDeviceTrees, qcom-ipq40??-db), \

$(IPQ40XX_KERNEL_LOADADDR))

endef

rootfs处理

  1. 对文件系统处理(include/image.mk)

install-->kernel_prepare
-->mkfs_prepare -->$(call Image/mkfs/prepare)

define Image/mkfs/prepare/default

# Use symbolic permissions to avoid clobbering SUID/SGID/sticky
bits

- $(FIND) $(TARGET_DIR) -type f -not -perm /0100 -not -name
'ssh_host*' -not -name 'shadow' -print0 | $(XARGS) -0 chmod
u+rw,g+r,o+r

- $(FIND) $(TARGET_DIR) -type f -perm /0100 -print0 | $(XARGS) -0
chmod u+rwx,g+rx,o+rx

- $(FIND) $(TARGET_DIR) -type d -print0 | $(XARGS) -0 chmod
u+rwx,g+rx,o+rx

$(INSTALL_DIR) $(TARGET_DIR)/tmp $(TARGET_DIR)/overlay

chmod 1777 $(TARGET_DIR)/tmp

chmod 700 $(TARGET_DIR)/usr/bin/scvt

test -e $(TARGET_DIR)/etc/cert && chmod 0700
$(TARGET_DIR)/etc/cert || echo ok

test -e $(TARGET_DIR)/etc/init.d/cert && chmod 0700
$(TARGET_DIR)/etc/init.d/cert || echo ok

test -e $(TARGET_DIR)/.ocloud/ && chmod 0700
$(TARGET_DIR)/.ocloud/ || echo ok

test -e $(TARGET_DIR)/.ocloud/ && chmod 0600
$(TARGET_DIR)/.ocloud/* || echo ok

test -e $(TARGET_DIR)/etc/root.secret && chmod 0600
$(TARGET_DIR)/etc/root.secret || echo ok

test -e $(TARGET_DIR)/etc/rsync.pass && chmod 0600
$(TARGET_DIR)/etc/rsync.pass || echo ok

endef

define Image/mkfs/prepare/pub_cfgs

[ -d $(TARGET_DIR)/etc/cfm/config/config-pub ] || mkdir -p
$(TARGET_DIR)/etc/cfm/config/config-pub

cp $(TARGET_DIR)/etc/config/*
$(TARGET_DIR)/etc/cfm/config/config-pub

- mv $(TARGET_DIR)/etc/cfm/config/config-pub/network
$(TARGET_DIR)/etc/cfm/config/config-priv/

(cd $(TARGET_DIR)/etc/cfm/config/config-pub; md5sum * >
pub-cfg-md5)

endef

define Image/mkfs/prepare

$(call Image/mkfs/prepare/default)

$(call Image/mkfs/prepare/pub_cfgs)

endef

  1. squashfs处理

install-->kernel_prepare
-->$(call BuildImage/mkfs,$(fs))

define BuildImage/mkfs

install: mkfs-$(1)

.PHONY: mkfs-$(1)

mkfs-$(1): mkfs_prepare

$(Image/mkfs/$(1))

$(call Build/mkfs/default,$(1))

$(call Build/mkfs/$(1),$(1))

$(KDIR)/root.$(1): mkfs-$(1)

endef

define Image/mkfs/squashfs

$(STAGING_DIR_HOST)/bin/mksquashfs4 $(TARGET_DIR)
$(KDIR)/root.squashfs -nopad -noappend -root-owned -comp
$(SQUASHFSCOMP) $(SQUASHFSOPT) -processors $(if
$(CONFIG_PKG_BUILD_JOBS),$(CONFIG_PKG_BUILD_JOBS),1)

endef

  1. squashfs打补丁

install--> $(call
Image/Build,$(fs))

define Image/Build/squashfs

$(call prepare_generic_squashfs,$(KDIR)/root.squashfs)

endef

define Image/Build

$(call Image/Build/$(1),$(1))

dd if=$(KDIR)/root$(2).$(1)
of=$(BIN_DIR)/$(IMG_PREFIX)$(2)-$(1)-root$(3).img bs=2k conv=sync

endef

# pad to 4k, 8k, 16k, 64k, 128k, 256k and add jffs2 end-of-filesystem
mark

define prepare_generic_squashfs

$(STAGING_DIR_HOST)/bin/padjffs2 $(1) 4 8 16 64 128 256

endef

至此生成squashfs文件系统镜像openwrt-ipq806x-squashfs-root.img(root.squashfs)。

4)ubifs处理

intall --> $(call
Image/mkfs/ubifs)

将文件系统格式化为ubifs格式:openwrt-ipq806x-ubifs-root.img(root.ubifs)。

镜像打包

intall --> $(call
Image/mkfs/ubifs)

将kernel处理后的FIT镜像openwrt-ipq806x-fit-uImage.itb和rootfs处理后的root.squashfs打包成ubi格式的ubi镜像openwrt-ipq806x-ubi-root.img。此镜像可直接在uboot下烧写和运行,也就是常说的factory.bin。

build_img.sh通过工具mkimage将ubi镜像增加firmware镜像头后生成sysupgrade.bin以支持sysupgrade升级使用

参考:

1. openwrt: Makefile 框架分析

2. An introduction to Buildroot-ng

openwrt固件编译过程的更多相关文章

  1. (二)我的Makefile学习冲动&&编译过程概述

    前言 一 年轻的冲动 二 学习曲线 1 Makefile基本语法 2 bash基础 3 world 三 编译过程概述 1 主机预装工具 2 编译host工具 3 编译交叉工具链 4 编译内核模块 5 ...

  2. 转:小白编译openwrt固件教程

    原文地址 编译openwrt固件并没有想象的那么复杂,我也是个小白,以下内容是我将网络上的编译教程稍微进行了一下整合.因为我发现很多编译教程没有说明如何更改flash相关配置.   安装ubuntu, ...

  3. 搭建OpenWrt开发环境(包括编译过程)

    OpenWrt是一个高度模块化.高度自动化的嵌入式linux发行版,其编译和安装过程比普通的linux发行版而言,要简单太多了.如果您是新手,您那恐惧的心大可放到肚子里,呵呵.对于新手来说最麻烦的恐怕 ...

  4. 编译树莓派2代B型OpenWrt固件实现无线路由器及nodogsplash认证功能

    最终功能: 无线路由器的主要功能,网口WAN接入,USB无线网卡AP热点输出,连上wifi之后跳转到认证页面,点击认证方可上网,有效时间10分钟,认证成功之后自动访问指定网址. 文章结尾有编译好的刷机 ...

  5. 初玩OpenWRT之编译TP-Link WR841N V8固件

    0x00 安装依赖 安装git以下载OpenWrt源码.安装编译工具以进行交叉编译: sudo apt-get update sudo apt-get install build-essential ...

  6. 编译适用于TP-Link WR703N的OpenWRT固件

    编译适用于TP-Link WR703N TP-Link MR11U 以及使用AR9331芯片组的单WAN/LAN复用口的路由. 注:刷机有风险,刷机需谨慎.一般情况下是不会失败的,若无法通过捅Rese ...

  7. 编译 OpenWrt/LEDE 基本过程

    说明 前段时间花 110 从闲鱼淘了个 Newifi D1,这个路由的 Soc 是 MT7621AT,性能强劲,于是又开始折腾编译固件了,重新记录一下编译基本过程. 步骤 安装必要的软件包 sudo ...

  8. (四) openwrt单个ipk编译过程

    Tags : Makefile 本周是成胖子每周一博的第五周. 更好的阅读体验,请点击这里 [TOC] 前言 前一篇博客中,我们已经知道整个openwrt的编译顺序,本文我们来探讨与开发者息息相关的单 ...

  9. debian下编译openwrt固件

    参考文章:Ubuntu下编译OpenWRT固件 我买的路由器是RG100A-AA,采用了bcm63xx系列的芯片. 下载openwrt源码: svn co svn://svn.openwrt.org/ ...

随机推荐

  1. Windows 无法验证此设备所需的驱动程序的数字签名。某软件或硬件最近有所更改,可能安装了签名错误或损毁的文件,或者安装的文件可能是来路不明的恶意软件。(代码52)

    由未签名驱动导致的键鼠装无法使用的问题 usb 问题失效. 要是win 10的话  导致的结果就是 无线键鼠套装无法使用. 解决办法是 1.按下shift 按键 点击重启按钮 重启后 2.疑难解答-- ...

  2. NHibernate官方文档中文版--只读实体类型(Read-only entities)

    重点 NHIbernate处理只读对象的方式可能和你在别处看到的不同.不正确的使用方式可能造成不可预料的结果. 当一个实体是只读的时候: NHIbernate不会对实体的简单属性和单向关联数据检查数据 ...

  3. "0" 并不一定是 假 (false)

    写习惯C/C++系代码的人应该很习惯看见类似这样的代码: 1 2 3 4 5 int i = 0; ...... if(i){    //这里代码不会被执行 } 因此写习惯以后会想当然地觉得其他语言里 ...

  4. JVM Object Query Language (OQL) 查询语言

    Object Query Language (OQL) OQL is SQL-like query language to query Java heap. OQL allows to filter/ ...

  5. iOS:地图笔记

    地图笔记 01. CLLocation -------------------------------------------------------- CLLocationManager 定位管理者 ...

  6. FL2440 ubifs文件系统烧录遇到的问题——内核分区的重要性

    之前用的文件系统是initramfs的,这种文件系统是编译进内核里的,而开机之后内核是写在内存中的,所以每次掉电之后写进文件系统中的东西都会丢失.所以决定换成ubifs的文件系统.这种文件系统是跟内核 ...

  7. FL2440 rt3070模块station模式动态获取IP地址

    ---------------------------------------------------------------------------------------------------- ...

  8. JS组件系列——自己封装一个上传文件组件

    页面调用: $('#fileUpload').cemsUpload({ errorEmpty:'<s:text name="cupgrade.view.tip.upload.file. ...

  9. IDEA默认VIM模式

    Intellij Idea, 每次打开文件都进入了vim模式,必须输入i才可编辑,实在是非常困扰. 终于找到了解决办法:取消Vim Emulator的选择:

  10. [Angular] Angular Custom Change Detection with ChangeDetectorRef

    Each component has its own ChangeDetectorRef, and we can inject ChangeDetectorRef into constructor: ...