KernelPackage是OpenWrt用来编译内核模块的函数,其实KernelPackage后面会调用BuildPackage,这里会一块将BuildPackage也顺便分析,本文以gpio-button-hotplug驱动模块为例,讲解整个编译过程。
gpio-button-hotplug驱动编译命令如下:
make package/kernel/gpio-button-hotplug/compile V=s
由前面的文章介绍了subdir的作用后,我们可以知道,subdir会将make package/kernel/gpio-button-hotplug/compile V=s命令转换为如下命令:
make -C package/kernel/gpio-button-hotplug compile
make会去到package/kernel/gpio-button-hotplug下找Makfile,并且找其中的compile目标运行,gpio-button-hotplug的Makefile如下:
- include $(TOPDIR)/rules.mk
- include $(INCLUDE_DIR)/kernel.mk
-
- PKG_NAME:=gpio-button-hotplug
- PKG_RELEASE:=3
- PKG_LICENSE:=GPL-2.0
-
- include $(INCLUDE_DIR)/package.mk
-
- define KernelPackage/gpio-button-hotplug
- ......
- endef
- ......
- MAKE_OPTS:= $(KERNEL_MAKE_FLAGS) M="$(PKG_BUILD_DIR)"
-
- define Build/Compile
- $(MAKE) -C "$(LINUX_DIR)" $(MAKE_OPTS) modules
- endef
-
- $(eval $(call KernelPackage,gpio-button-hotplug))
可以看到,这里会调用到KernelPackage,KernelPackage内容如下:
- include/kernel.mk:
- define KernelPackage
- NAME:=$(1)
- $(eval $(call Package/Default))
- $(eval $(call KernelPackage/Defaults))
- $(eval $(call KernelPackage/$(1)))
- $(eval $(call KernelPackage/$(1)/$(BOARD)))
- $(eval $(call KernelPackage/$(1)/$(BOARD)/$(if $(SUBTARGET),$(SUBTARGET),generic)))
-
- define Package/kmod-$(1)
- TITLE:=$(TITLE)
- SECTION:=kernel
- CATEGORY:=Kernel modules
- DESCRIPTION:=$(DESCRIPTION)
- EXTRA_DEPENDS:=kernel (=$(LINUX_VERSION)-$(LINUX_RELEASE)-$(LINUX_VERMAGIC))
- VERSION:=$(LINUX_VERSION)$(if $(PKG_VERSION),+$(PKG_VERSION))-$(if $(PKG_RELEASE),$(PKG_RELEASE),$(LINUX_RELEASE))
- PKGFLAGS:=$(PKGFLAGS)
- $(call KernelPackage/$(1))
- $(call KernelPackage/$(1)/$(BOARD))
- $(call KernelPackage/$(1)/$(BOARD)/$(if $(SUBTARGET),$(SUBTARGET),generic))
- endef
-
- ifdef KernelPackage/$(1)/conffiles
- define Package/kmod-$(1)/conffiles
- $(call KernelPackage/$(1)/conffiles)
- endef
- endif
-
- ifdef KernelPackage/$(1)/description
- define Package/kmod-$(1)/description
- $(call KernelPackage/$(1)/description)
- endef
- endif
-
- ifdef KernelPackage/$(1)/config
- define Package/kmod-$(1)/config
- $(call KernelPackage/$(1)/config)
- endef
- endif
-
- $(call KernelPackage/depends)
- $(call KernelPackage/hooks)
-
- ifneq ($(if $(filter-out %=y %=n %=m,$(KCONFIG)),$(filter m y,$(foreach c,$(filter-out %=y %=n %=m,$(KCONFIG)),$($(c)))),.),)
- define Package/kmod-$(1)/install
- @for mod in $$(call version_filter,$$(FILES)); do \
- if grep -q "$$$$$$$${mod##$(LINUX_DIR)/}" "$(LINUX_DIR)/modules.builtin"; then \
- echo "<<2>>" \
- echo "NOTICE: module '$$$$$$$$mod' is built-in."; \
- elif [ -e $$$$$$$$mod ]; then \
- echo "<<3>> $$$$$$$$mod" ; \
- mkdir -p $$(1)/$(MODULES_SUBDIR) ; \
- $(CP) -L $$$$$$$$mod $$(1)/$(MODULES_SUBDIR)/ ; \
- else \
- echo "ERROR: module '$$$$$$$$mod' is missing." >&2; \
- exit 1; \
- fi; \
- done;
- $(call ModuleAutoLoad,$(1),$$(1),$(filter-out 0-,$(word 1,$(AUTOLOAD))-),$(filter-out 0,$(word 2,$(AUTOLOAD))),$(sort $(wordlist 3,99,$(AUTOLOAD))))
- $(call KernelPackage/$(1)/install,$$(1))
- endef
- $(if $(CONFIG_PACKAGE_kmod-$(1)),
- else
- compile: $(1)-disabled
- $(1)-disabled:
- @echo "WARNING: kmod-$(1) is not available in the kernel config - generating empty package" >&2
-
- define Package/kmod-$(1)/install
- echo "<<1>>"
- true
- endef
- )
- endif
- $$(eval $$(call BuildPackage,kmod-$(1)))
-
- $$(IPKG_kmod-$(1)): $$(wildcard $$(call version_filter,$$(FILES)))
-
- endef
细节先不分析,先找compile目标,可以看到KernelPackage下没有compile目标,原因如下:
ifneq ($(if $(filter-out %=y %=n %=m,$(KCONFIG)),$(filter m y,$(foreach c,$(filter-out %=y %=n %=m,$(KCONFIG)),$($(c)))),.),)
如上代码KCONFIG变量(package/kernel/linux/modules/*.mk才有定义)为空,所以以上表达式可以写为ifneq (.,),结果为真,执行上面的分支,上面分支没有compile目标。
此时,就要到BuildPackage里面寻找了。BuildPackage代码如下:
- define BuildPackage
- $(eval $(Package/Default))
- $(eval $(Package/$(1)))
-
- ifdef DESCRIPTION
- $$(error DESCRIPTION:= is obsolete, use Package/PKG_NAME/description)
- endif
-
- ifndef Package/$(1)/description
- define Package/$(1)/description
- $(TITLE)
- endef
- endif
-
- BUILD_PACKAGES += $(1)
- $(STAMP_PREPARED): $$(if $(QUILT)$(DUMP),,$(call find_library_dependencies,$(1)))
-
- $(foreach FIELD, TITLE CATEGORY SECTION VERSION,
- ifeq ($($(FIELD)),)
- $$(error Package/$(1) is missing the $(FIELD) field)
- endif
- )
-
- $(if $(DUMP), \
- $(if $(CHECK),,$(Dumpinfo/Package)), \
- $(foreach target, \
- $(if $(Package/$(1)/targets),$(Package/$(1)/targets), \
- $(if $(PKG_TARGETS),$(PKG_TARGETS), ipkg) \
- ), $(BuildTarget/$(target)) \
- ) \
- )
- $(if $(PKG_HOST_ONLY),,$(call Build/DefaultTargets,$(1)))
- endef
这里也没有compile目标。我们分析里面如下代码:
$(if $(DUMP), \
$(if $(CHECK),,$(Dumpinfo/Package)), \
$(foreach target, \
$(if $(Package/$(1)/targets),$(Package/$(1)/targets), \
$(if $(PKG_TARGETS),$(PKG_TARGETS), ipkg) \
), $(BuildTarget/$(target)) \
) \
)
以上代码不难分析,结果为$(BuildTarget/ipkg)。接下来分析BuildTarget/ipkg,代码如下:
- define BuildTarget/ipkg
- ABIV_$(1):=$(call FormatABISuffix,$(1),$(ABI_VERSION))
- PDIR_$(1):=$(call FeedPackageDir,$(1))
- IPKG_$(1):=$$(PDIR_$(1))/$(1)$$(ABIV_$(1))_$(VERSION)_$(PKGARCH).ipk
- IDIR_$(1):=$(PKG_BUILD_DIR)/ipkg-$(PKGARCH)/$(1)
- KEEP_$(1):=$(strip $(call Package/$(1)/conffiles))
-
- ifeq ($(BUILD_VARIANT),$$(if $$(VARIANT),$$(VARIANT),$(BUILD_VARIANT)))
- do_install=
- ifdef Package/$(1)/install
- do_install=yes
- endif
- ifdef Package/$(1)/install-overlay
- do_install=yes
- endif
- ifdef do_install
- ifneq ($(CONFIG_PACKAGE_$(1))$(DEVELOPER),)
- IPKGS += $(1)
- $(_pkg_target)compile: $$(IPKG_$(1)) $(PKG_INFO_DIR)/$(1).provides $(PKG_BUILD_DIR)/.pkgdir/$(1).installed
- prepare-package-install: $$(IPKG_$(1))
- compile: $(STAGING_DIR_ROOT)/stamp/.$(1)_installed
- else
- $(if $(CONFIG_PACKAGE_$(1)),$$(info WARNING: skipping $(1) -- package not selected))
- endif
-
- .PHONY: $(PKG_INSTALL_STAMP).$(1)
- ifeq ($(CONFIG_PACKAGE_$(1)),y)
- compile: $(PKG_INSTALL_STAMP).$(1)
- endif
- $(PKG_INSTALL_STAMP).$(1): prepare-package-install
- echo "$(1)" >> $(PKG_INSTALL_STAMP)
- else
- $(if $(CONFIG_PACKAGE_$(1)),$$(warning WARNING: skipping $(1) -- package has no install section))
- endif
- endif
-
- DEPENDS:=$(call PKG_FIXUP_DEPENDS,$(1),$(DEPENDS))
- IDEPEND_$(1):=$$(call filter_deps,$$(DEPENDS))
- IDEPEND += $$(patsubst %,$(1):%,$$(IDEPEND_$(1)))
- $(FixupDependencies)
- $(FixupReverseDependencies)
-
- $(eval $(call BuildIPKGVariable,$(1),conffiles))
- $(eval $(call BuildIPKGVariable,$(1),preinst,,1))
- $(eval $(call BuildIPKGVariable,$(1),postinst,-pkg,1))
- $(eval $(call BuildIPKGVariable,$(1),prerm,-pkg,1))
- $(eval $(call BuildIPKGVariable,$(1),postrm,,1))
-
- $(PKG_BUILD_DIR)/.pkgdir/$(1).installed : export PATH=$$(TARGET_PATH_PKG)
- $(PKG_BUILD_DIR)/.pkgdir/$(1).installed: $(STAMP_BUILT)
- rm -rf $$@ $(PKG_BUILD_DIR)/.pkgdir/$(1)
- mkdir -p $(PKG_BUILD_DIR)/.pkgdir/$(1)
- $(call Package/$(1)/install,$(PKG_BUILD_DIR)/.pkgdir/$(1))
- $(call Package/$(1)/install_lib,$(PKG_BUILD_DIR)/.pkgdir/$(1))
- touch $$@
-
- $(STAGING_DIR_ROOT)/stamp/.$(1)_installed: $(PKG_BUILD_DIR)/.pkgdir/$(1).installed
- mkdir -p $(STAGING_DIR_ROOT)/stamp
- $(if $(ABI_VERSION),echo '$(ABI_VERSION)' | cmp -s - $(PKG_INFO_DIR)/$(1).version || { \
- echo '$(ABI_VERSION)' > $(PKG_INFO_DIR)/$(1).version; \
- $(foreach pkg,$(filter-out $(1),$(PROVIDES)), \
- cp $(PKG_INFO_DIR)/$(1).version $(PKG_INFO_DIR)/$(pkg).version; \
- ) \
- } )
- $(call locked,$(CP) $(PKG_BUILD_DIR)/.pkgdir/$(1)/. $(STAGING_DIR_ROOT)/,root-copy)
- touch $$@
-
- Package/$(1)/DEPENDS := $$(call mergelist,$$(foreach dep,$$(filter-out @%,$$(IDEPEND_$(1))),$$(dep)$$(call GetABISuffix,$$(dep))))
- ifneq ($$(EXTRA_DEPENDS),)
- Package/$(1)/DEPENDS := $$(EXTRA_DEPENDS)$$(if $$(Package/$(1)/DEPENDS),$$(comma) $$(Package/$(1)/DEPENDS))
- endif
-
- $(_define) Package/$(1)/CONTROL
- Package: $(1)$$(ABIV_$(1))
- Version: $(VERSION)
- $$(call addfield,Depends,$$(Package/$(1)/DEPENDS)
- )$$(call addfield,Conflicts,$$(call mergelist,$(CONFLICTS))
- )$$(call addfield,Provides,$$(call mergelist,$$(filter-out $(1)$$(ABIV_$(1)),$(PROVIDES)$$(if $$(ABIV_$(1)), $(1) $(foreach provide,$(PROVIDES),$(provide)$$(ABIV_$(1))))))
- )$$(call addfield,Alternatives,$$(call mergelist,$(ALTERNATIVES))
- )$$(call addfield,Source,$(SOURCE)
- )$$(call addfield,SourceName,$(1)
- )$$(call addfield,License,$(LICENSE)
- )$$(call addfield,LicenseFiles,$(LICENSE_FILES)
- )$$(call addfield,Section,$(SECTION)
- )$$(call addfield,Require-User,$(USERID)
- )$$(call addfield,SourceDateEpoch,$(PKG_SOURCE_DATE_EPOCH)
- )$$(if $$(ABIV_$(1)),ABIVersion: $$(ABIV_$(1))
- )$(if $(PKG_CPE_ID),CPE-ID: $(PKG_CPE_ID)
- )$(if $(filter hold,$(PKG_FLAGS)),Status: unknown hold not-installed
- )$(if $(filter essential,$(PKG_FLAGS)),Essential: yes
- )$(if $(MAINTAINER),Maintainer: $(MAINTAINER)
- )Architecture: $(PKGARCH)
- Installed-Size: 0
- $(_endef)
-
- $$(IPKG_$(1)) : export CONTROL=$$(Package/$(1)/CONTROL)
- $$(IPKG_$(1)) : export DESCRIPTION=$$(Package/$(1)/description)
- $$(IPKG_$(1)) : export PATH=$$(TARGET_PATH_PKG)
- $$(IPKG_$(1)) : export PKG_SOURCE_DATE_EPOCH:=$(PKG_SOURCE_DATE_EPOCH)
- $(PKG_INFO_DIR)/$(1).provides $$(IPKG_$(1)): $(STAMP_BUILT) $(INCLUDE_DIR)/package-ipkg.mk
- @rm -rf $$(IDIR_$(1)); \
- $$(call remove_ipkg_files,$(1),$$(call opkg_package_files,$(call gen_ipkg_wildcard,$(1))))
- mkdir -p $(PACKAGE_DIR) $$(IDIR_$(1))/CONTROL $(PKG_INFO_DIR)
- $(call Package/$(1)/install,$$(IDIR_$(1)))
- $(if $(Package/$(1)/install-overlay),mkdir -p $(PACKAGE_DIR) $$(IDIR_$(1))/rootfs-overlay)
- $(call Package/$(1)/install-overlay,$$(IDIR_$(1))/rootfs-overlay)
- -find $$(IDIR_$(1)) -name 'CVS' -o -name '.svn' -o -name '.#*' -o -name '*~'| $(XARGS) rm -rf
- @( \
- find $$(IDIR_$(1)) -name lib\*.so\* -or -name \*.ko | awk -F/ '{ print $$$$NF }'; \
- for file in $$(patsubst %,$(PKG_INFO_DIR)/%.provides,$$(IDEPEND_$(1))); do \
- if [ -f "$$$$file" ]; then \
- cat $$$$file; \
- fi; \
- done; $(Package/$(1)/extra_provides) \
- ) | sort -u > $(PKG_INFO_DIR)/$(1).provides
- $(if $(PROVIDES),@for pkg in $(filter-out $(1),$(PROVIDES)); do cp $(PKG_INFO_DIR)/$(1).provides $(PKG_INFO_DIR)/$$$$pkg.provides; done)
- $(CheckDependencies)
-
- $(RSTRIP) $$(IDIR_$(1))
-
- ifneq ($$(CONFIG_IPK_FILES_CHECKSUMS),)
- (cd $$(IDIR_$(1)); \
- ( \
- find . -type f \! -path ./CONTROL/\* -exec mkhash sha256 -n \{\} \; 2> /dev/null | \
- sed 's|\([[:blank:]]\)\./| \1/|' > $$(IDIR_$(1))/CONTROL/files-sha256sum \
- ) || true \
- )
- endif
- (cd $$(IDIR_$(1))/CONTROL; \
- ( \
- echo "$$$$CONTROL"; \
- printf "Description: "; echo "$$$$DESCRIPTION" | sed -e 's,^[[:space:]]*, ,g'; \
- ) > control; \
- chmod 644 control; \
- ( \
- echo "#!/bin/sh"; \
- echo "[ \"\$$$${IPKG_NO_SCRIPT}\" = \"1\" ] && exit 0"; \
- echo "[ -s "\$$$${IPKG_INSTROOT}/lib/functions.sh" ] || exit 0"; \
- echo ". \$$$${IPKG_INSTROOT}/lib/functions.sh"; \
- echo "default_postinst \$$$$0 \$$$$@"; \
- ) > postinst; \
- ( \
- echo "#!/bin/sh"; \
- echo "[ -s "\$$$${IPKG_INSTROOT}/lib/functions.sh" ] || exit 0"; \
- echo ". \$$$${IPKG_INSTROOT}/lib/functions.sh"; \
- echo "default_prerm \$$$$0 \$$$$@"; \
- ) > prerm; \
- chmod 0755 postinst prerm; \
- $($(1)_COMMANDS) \
- )
-
- ifneq ($$(KEEP_$(1)),)
- @( \
- keepfiles=""; \
- for x in $$(KEEP_$(1)); do \
- [ -f "$$(IDIR_$(1))/$$$$x" ] || keepfiles="$$$${keepfiles:+$$$$keepfiles }$$$$x"; \
- done; \
- [ -z "$$$$keepfiles" ] || { \
- mkdir -p $$(IDIR_$(1))/lib/upgrade/keep.d; \
- for x in $$$$keepfiles; do echo $$$$x >> $$(IDIR_$(1))/lib/upgrade/keep.d/$(1); done; \
- }; \
- )
- endif
-
- $(INSTALL_DIR) $$(PDIR_$(1))
- $(FAKEROOT) $(SCRIPT_DIR)/ipkg-build -m "$(FILE_MODES)" $$(IDIR_$(1)) $$(PDIR_$(1))
- @[ -f $$(IPKG_$(1)) ]
-
- $(1)-clean:
- $$(call remove_ipkg_files,$(1),$$(call opkg_package_files,$(call gen_ipkg_wildcard,$(1))))
-
- clean: $(1)-clean
-
- endef
里面一段一段分析,如下:
ifeq ($(BUILD_VARIANT),
(VARIANT),$$(VARIANT),$(BUILD_VARIANT)))( i f " role="presentation" style="text-align: center; position: relative;">
do_install=
ifdef Package/$(1)/install
do_install=yes
endif
ifdef Package/$(1)/install-overlay
do_install=yes
endif
ifdef do_install
ifneq ($(CONFIG_PACKAGE_$(1))$(DEVELOPER),)
IPKGS += $(1)
$(_pkg_target)compile:(IPKG_$(1))( I P K G $ ( 1 ) ) $ ( P K G I N F O D I R ) / $ ( 1 ) . p r o v i d e s $ ( P K G B U I L D D I R ) / . p k g d i r / $ ( 1 ) . i n s t a l l e d p r e p a r e − p a c k a g e − i n s t a l l : " role="presentation" style="position: relative;">
compile: $(STAGING_DIR_ROOT)/stamp/.$(1)_installed
else
$(if $(CONFIG_PACKAGE_$(1)),$$(info WARNING: skipping $(1) -- package not selected))
endif.PHONY: $(PKG_INSTALL_STAMP).$(1)
ifeq ($(CONFIG_PACKAGE_$(1)),y)
compile: $(PKG_INSTALL_STAMP).$(1)
endif
$(PKG_INSTALL_STAMP).$(1): prepare-package-install
echo "$(1)" >> $(PKG_INSTALL_STAMP)
else
$(if $(CONFIG_PACKAGE_$(1)),$$(warning WARNING: skipping $(1) -- package has no install section))
endif
endif
由于BUILD_VARIANT和VARIANT都未定义,都为空,自然相等,所以条件成立。
由于Package/$(1)/install定义在include/kernel.mk中,如下:
- include/kernel.mk:
- define Package/kmod-$(1)/install
- @for mod in $$(call version_filter,$$(FILES)); do \
- if grep -q "$$$$$$$${mod##$(LINUX_DIR)/}" "$(LINUX_DIR)/modules.builtin"; then \
- echo "NOTICE: module '$$$$$$$$mod' is built-in."; \
- elif [ -e $$$$$$$$mod ]; then \
- mkdir -p $$(1)/$(MODULES_SUBDIR) ; \
- $(CP) -L $$$$$$$$mod $$(1)/$(MODULES_SUBDIR)/ ; \
- else \
- echo "ERROR: module '$$$$$$$$mod' is missing." >&2; \
- exit 1; \
- fi; \
- done;
- $(call ModuleAutoLoad,$(1),$$(1),$(filter-out 0-,$(word 1,$(AUTOLOAD))-),$(filter-out 0,$(word 2,$(AUTOLOAD))),$(sort $(wordlist 3,99,$(AUTOLOAD))))
- $(call KernelPackage/$(1)/install,$$(1))
- endef
所以do_install变量的值是yes。以上的结果可以通过$(warning $(Package/$(1)/install))打印出来证实。
由于,do_install=yes,此时,可以找到compile目标了,这里有两个compile目标,两个compile目标会依次运行,compile目标和为什么这么运行的例子如下:
- include/package-ipkg.mk:
- compile: $(STAGING_DIR_ROOT)/stamp/.$(1)_installed
- ......
- compile: $(PKG_INSTALL_STAMP).$(1)
-
- example:
- act1:
- @echo act1;
- act2:
- @echo act2;
-
- compile: act1
- compile: act2
-
- all: compile
- @echo all
-
- result:
- act1
- act2
- all
$(STAGING_DIR_ROOT)/stamp/.$(1)_installed依赖于$(PKG_BUILD_DIR)/.pkgdir/$(1).installed,实现如下:
- include/package-ipkg.mk:
- $(STAGING_DIR_ROOT)/stamp/.$(1)_installed: $(PKG_BUILD_DIR)/.pkgdir/$(1).installed
- mkdir -p $(STAGING_DIR_ROOT)/stamp
- $(if $(ABI_VERSION),echo '$(ABI_VERSION)' | cmp -s - $(PKG_INFO_DIR)/$(1).version || { \
- echo '$(ABI_VERSION)' > $(PKG_INFO_DIR)/$(1).version; \
- $(foreach pkg,$(filter-out $(1),$(PROVIDES)), \
- cp $(PKG_INFO_DIR)/$(1).version $(PKG_INFO_DIR)/$(pkg).version; \
- ) \
- } )
- $(call locked,$(CP) $(PKG_BUILD_DIR)/.pkgdir/$(1)/. $(STAGING_DIR_ROOT)/,root-copy)
- touch $$@
$(PKG_BUILD_DIR)/.pkgdir/$(1).installed依赖于STAMP_BUILT,实现如下:
- include/package-ipkg.mk:
- $(PKG_BUILD_DIR)/.pkgdir/$(1).installed: $(STAMP_BUILT)
- rm -rf $$@ $(PKG_BUILD_DIR)/.pkgdir/$(1)
- mkdir -p $(PKG_BUILD_DIR)/.pkgdir/$(1)
- $(call Package/$(1)/install,$(PKG_BUILD_DIR)/.pkgdir/$(1))
- $(call Package/$(1)/install_lib,$(PKG_BUILD_DIR)/.pkgdir/$(1))
- touch $$@
STAMP_BUILT定义在Build/CoreTargets,Build/CoreTargets实现如下:
- include/package.mk:
- define Build/CoreTargets
- STAMP_PREPARED:=$$(STAMP_PREPARED)
- STAMP_CONFIGURED:=$$(STAMP_CONFIGURED)
-
- $(if $(QUILT),$(Build/Quilt))
- $(call Build/Autoclean)
- $(call DefaultTargets)
-
- $(DL_DIR)/$(FILE): FORCE
-
- download:
- $(foreach hook,$(Hooks/Download),
- $(call $(hook))$(sep)
- )
-
- $(STAMP_PREPARED) : export PATH=$$(TARGET_PATH_PKG)
- $(STAMP_PREPARED): $(STAMP_PREPARED_DEPENDS)
- @-rm -rf $(PKG_BUILD_DIR)
- @mkdir -p $(PKG_BUILD_DIR)
- touch $$@_check
- $(foreach hook,$(Hooks/Prepare/Pre),$(call $(hook))$(sep))
- $(Build/Prepare)
- $(foreach hook,$(Hooks/Prepare/Post),$(call $(hook))$(sep))
- touch $$@
-
- $(call Build/Exports,$(STAMP_CONFIGURED))
- $(STAMP_CONFIGURED): $(STAMP_PREPARED) $(STAMP_CONFIGURED_DEPENDS)
- rm -f $(STAMP_CONFIGURED_WILDCARD)
- $(CleanStaging)
- $(foreach hook,$(Hooks/Configure/Pre),$(call $(hook))$(sep))
- $(Build/Configure)
- $(foreach hook,$(Hooks/Configure/Post),$(call $(hook))$(sep))
- touch $$@
-
- $(call Build/Exports,$(STAMP_BUILT))
- $(STAMP_BUILT): $(STAMP_CONFIGURED) $(STAMP_BUILT_DEPENDS)
- rm -f $$@
- touch $$@_check
- $(foreach hook,$(Hooks/Compile/Pre),$(call $(hook))$(sep))
- $(Build/Compile)
- $(foreach hook,$(Hooks/Compile/Post),$(call $(hook))$(sep))
- $(Build/Install)
- $(foreach hook,$(Hooks/Install/Post),$(call $(hook))$(sep))
- touch $$@
-
- $(STAMP_INSTALLED) : export PATH=$$(TARGET_PATH_PKG)
- $(STAMP_INSTALLED): $(STAMP_BUILT)
- rm -rf $(TMP_DIR)/stage-$(PKG_DIR_NAME)
- mkdir -p $(TMP_DIR)/stage-$(PKG_DIR_NAME)/host $(STAGING_DIR)/packages
- $(foreach hook,$(Hooks/InstallDev/Pre),\
- $(call $(hook),$(TMP_DIR)/stage-$(PKG_DIR_NAME),$(TMP_DIR)/stage-$(PKG_DIR_NAME)/host)$(sep)\
- )
- $(call Build/InstallDev,$(TMP_DIR)/stage-$(PKG_DIR_NAME),$(TMP_DIR)/stage-$(PKG_DIR_NAME)/host)
- $(foreach hook,$(Hooks/InstallDev/Post),\
- $(call $(hook),$(TMP_DIR)/stage-$(PKG_DIR_NAME),$(TMP_DIR)/stage-$(PKG_DIR_NAME)/host)$(sep)\
- )
- if [ -f $(STAGING_DIR)/packages/$(STAGING_FILES_LIST) ]; then \
- $(SCRIPT_DIR)/clean-package.sh \
- "$(STAGING_DIR)/packages/$(STAGING_FILES_LIST)" \
- "$(STAGING_DIR)"; \
- fi
- if [ -d $(TMP_DIR)/stage-$(PKG_DIR_NAME) ]; then \
- (cd $(TMP_DIR)/stage-$(PKG_DIR_NAME); find ./ > $(TMP_DIR)/stage-$(PKG_DIR_NAME).files); \
- $(call locked, \
- mv $(TMP_DIR)/stage-$(PKG_DIR_NAME).files $(STAGING_DIR)/packages/$(STAGING_FILES_LIST) && \
- $(CP) $(TMP_DIR)/stage-$(PKG_DIR_NAME)/* $(STAGING_DIR)/; \
- ,staging-dir); \
- fi
- rm -rf $(TMP_DIR)/stage-$(PKG_DIR_NAME)
- touch $$@
-
- ifdef Build/InstallDev
- $(_pkg_target)compile: $(STAMP_INSTALLED)
- endif
-
- $(_pkg_target)prepare: $(STAMP_PREPARED)
- $(_pkg_target)configure: $(STAMP_CONFIGURED)
- $(_pkg_target)dist: $(STAMP_CONFIGURED)
- $(_pkg_target)distcheck: $(STAMP_CONFIGURED)
-
- ifneq ($(CONFIG_AUTOREMOVE),)
- compile:
- -touch -r $(PKG_BUILD_DIR)/.built $(PKG_BUILD_DIR)/.autoremove 2>/dev/null >/dev/null
- $(FIND) $(PKG_BUILD_DIR) -mindepth 1 -maxdepth 1 -not '(' -type f -and -name '.*' -and -size 0 ')' -and -not -name '.pkgdir' | \
- $(XARGS) rm -rf
- endif
- endef
-
-
- define Build/DefaultTargets
- $(if $(USE_SOURCE_DIR)$(USE_GIT_TREE)$(USE_GIT_SRC_CHECKOUT),,$(if $(strip $(PKG_SOURCE_URL)),$(call Download,default)))
- $(if $(DUMP),,$(Build/CoreTargets))
-
- define Build/DefaultTargets
- endef
- endef
-
- define BuildPackage
- ......
-
- $(if $(PKG_HOST_ONLY),,$(call Build/DefaultTargets,$(1)))
- endef
其中
$(STAMP_BUILT): $(STAMP_CONFIGURED) $(STAMP_BUILT_DEPENDS)
rm -f@_check@ t o u c h " role="presentation" style="text-align: center; position: relative;">
$(foreach hook,$(Hooks/Compile/Pre),$(call $(hook))$(sep))
$(Build/Compile)
$(foreach hook,$(Hooks/Compile/Post),$(call $(hook))$(sep))
$(Build/Install)
$(foreach hook,$(Hooks/Install/Post),$(call $(hook))$(sep))
touch $$@
STAMP_BUILT依赖于STAMP_CONFIGURED和STAMP_BUILT_DEPENDS,STAMP_CONFIGURED实现如下:
$(STAMP_CONFIGURED): $(STAMP_PREPARED) $(STAMP_CONFIGURED_DEPENDS)
rm -f $(STAMP_CONFIGURED_WILDCARD)
$(CleanStaging)
$(foreach hook,$(Hooks/Configure/Pre),$(call $(hook))$(sep))
$(Build/Configure)
$(foreach hook,$(Hooks/Configure/Post),$(call $(hook))$(sep))
touch $$@
STAMP_CONFIGURED依赖于STAMP_PREPARED,STAMP_PREPARED实现如下:
(STAMP_PREPARED) : export PATH=
@_check( T A R G E T P A T H P K G ) $ ( S T A M P P R E P A R E D ) : $ ( S T A M P P R E P A R E D D E P E N D S ) @ − r m − r f $ ( P K G B U I L D D I R ) @ m k d i r − p $ ( P K G B U I L D D I R ) t o u c h " role="presentation" style="position: relative;">
$(foreach hook,$(Hooks/Prepare/Pre),$(call $(hook))$(sep))
$(Build/Prepare)
$(foreach hook,$(Hooks/Prepare/Post),$(call $(hook))$(sep))
touch $$@
经过这几个步骤,kmod-*.ipkg的代码就编译好了。步骤分别是BUild/Prepare,CleanStaging,Build/Configure,Build/Compile和Build/Install。
在之后,执行如下代码
- include/package-ipkg.mk:
- $(PKG_BUILD_DIR)/.pkgdir/$(1).installed : export PATH=$$(TARGET_PATH_PKG)
- $(PKG_BUILD_DIR)/.pkgdir/$(1).installed: $(STAMP_BUILT)
- rm -rf $$@ $(PKG_BUILD_DIR)/.pkgdir/$(1)
- mkdir -p $(PKG_BUILD_DIR)/.pkgdir/$(1)
- $(call Package/$(1)/install,$(PKG_BUILD_DIR)/.pkgdir/$(1))
- $(call Package/$(1)/install_lib,$(PKG_BUILD_DIR)/.pkgdir/$(1))
- touch $$@
实际运行代码:
- rm -rf /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/.pkgdir/kmod-gpio-button-hotplug.installed /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/.pkgdir/kmod-gpio-button-hotplug
- mkdir -p /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/.pkgdir/kmod-gpio-button-hotplug
- mkdir -p /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/.pkgdir/kmod-gpio-button-hotplug/etc/modules.d; ( echo "gpio-button-hotplug"; ) > /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/.pkgdir/kmod-gpio-button-hotplug/etc/modules.d/30-gpio-button-hotplug; mkdir -p /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/.pkgdir/kmod-gpio-button-hotplug/etc/modules-boot.d; ln -sf ../modules.d/30-gpio-button-hotplug /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/.pkgdir/kmod-gpio-button-hotplug/etc/modules-boot.d/;
- touch /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/.pkgdir/kmod-gpio-button-hotplug.installed
创建build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/.pkgdir/kmod-gpio-button-hotplug.installed文件。
- $(STAGING_DIR_ROOT)/stamp/.$(1)_installed: $(PKG_BUILD_DIR)/.pkgdir/$(1).installed
- mkdir -p $(STAGING_DIR_ROOT)/stamp
- $(if $(ABI_VERSION),echo '$(ABI_VERSION)' | cmp -s - $(PKG_INFO_DIR)/$(1).version || { \
- echo '$(ABI_VERSION)' > $(PKG_INFO_DIR)/$(1).version; \
- $(foreach pkg,$(filter-out $(1),$(PROVIDES)), \
- cp $(PKG_INFO_DIR)/$(1).version $(PKG_INFO_DIR)/$(pkg).version; \
- ) \
- } )
- $(call locked,$(CP) $(PKG_BUILD_DIR)/.pkgdir/$(1)/. $(STAGING_DIR_ROOT)/,root-copy)
- touch $$@
执行如下:
mkdir -p /root/mt7981/openwrt/staging_dir/target-aarch64_cortex-a53_musl/root-mediatek/stamp
SHELL= flock /root/mt7981/openwrt/tmp/.root-copy.flock -c 'cp -fpR /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/.pkgdir/kmod-gpio-button-hotplug/. /root/mt7981/openwrt/staging_dir/target-aarch64_cortex-a53_musl/root-mediatek/'
touch /root/mt7981/openwrt/staging_dir/target-aarch64_cortex-a53_musl/root-mediatek/stamp/.kmod-gpio-button-hotplug_installed
至此,第一个compile目标就分析完成了,接下来第二个compile主要是生成ipkg包。
第二个compile代码如下:
- include/package-ipkg.mk:
- compile: $(PKG_INSTALL_STAMP).$(1)
$(PKG_INSTALL_STAMP).$(1)依赖于prepare-package-install,prepare-package-install代码如下:
- include/package-ipkg.mk:
- prepare-package-install: $$(IPKG_$(1))
$$(IPKG_$(1))的定义如下:
- include/package-ipkg.mk:
- $$(IPKG_$(1)) : export CONTROL=$$(Package/$(1)/CONTROL)
- $$(IPKG_$(1)) : export DESCRIPTION=$$(Package/$(1)/description)
- $$(IPKG_$(1)) : export PATH=$$(TARGET_PATH_PKG)
- $$(IPKG_$(1)) : export PKG_SOURCE_DATE_EPOCH:=$(PKG_SOURCE_DATE_EPOCH)
- $(PKG_INFO_DIR)/$(1).provides $$(IPKG_$(1)): $(STAMP_BUILT) $(INCLUDE_DIR)/package-ipkg.mk
- @rm -rf $$(IDIR_$(1)); \
- $$(call remove_ipkg_files,$(1),$$(call opkg_package_files,$(call gen_ipkg_wildcard,$(1))))
- mkdir -p $(PACKAGE_DIR) $$(IDIR_$(1))/CONTROL $(PKG_INFO_DIR)
- $(call Package/$(1)/install,$$(IDIR_$(1)))
- $(if $(Package/$(1)/install-overlay),mkdir -p $(PACKAGE_DIR) $$(IDIR_$(1))/rootfs-overlay)
- $(call Package/$(1)/install-overlay,$$(IDIR_$(1))/rootfs-overlay)
- -find $$(IDIR_$(1)) -name 'CVS' -o -name '.svn' -o -name '.#*' -o -name '*~'| $(XARGS) rm -rf
- @( \
- find $$(IDIR_$(1)) -name lib\*.so\* -or -name \*.ko | awk -F/ '{ print $$$$NF }'; \
- for file in $$(patsubst %,$(PKG_INFO_DIR)/%.provides,$$(IDEPEND_$(1))); do \
- if [ -f "$$$$file" ]; then \
- cat $$$$file; \
- fi; \
- done; $(Package/$(1)/extra_provides) \
- ) | sort -u > $(PKG_INFO_DIR)/$(1).provides
- $(if $(PROVIDES),@for pkg in $(filter-out $(1),$(PROVIDES)); do cp $(PKG_INFO_DIR)/$(1).provides $(PKG_INFO_DIR)/$$$$pkg.provides; done)
- $(CheckDependencies)
-
- $(RSTRIP) $$(IDIR_$(1))
-
- ifneq ($$(CONFIG_IPK_FILES_CHECKSUMS),)
- (cd $$(IDIR_$(1)); \
- ( \
- find . -type f \! -path ./CONTROL/\* -exec mkhash sha256 -n \{\} \; 2> /dev/null | \
- sed 's|\([[:blank:]]\)\./| \1/|' > $$(IDIR_$(1))/CONTROL/files-sha256sum \
- ) || true \
- )
- endif
- (cd $$(IDIR_$(1))/CONTROL; \
- ( \
- echo "$$$$CONTROL"; \
- printf "Description: "; echo "$$$$DESCRIPTION" | sed -e 's,^[[:space:]]*, ,g'; \
- ) > control; \
- chmod 644 control; \
- ( \
- echo "#!/bin/sh"; \
- echo "[ \"\$$$${IPKG_NO_SCRIPT}\" = \"1\" ] && exit 0"; \
- echo "[ -s "\$$$${IPKG_INSTROOT}/lib/functions.sh" ] || exit 0"; \
- echo ". \$$$${IPKG_INSTROOT}/lib/functions.sh"; \
- echo "default_postinst \$$$$0 \$$$$@"; \
- ) > postinst; \
- ( \
- echo "#!/bin/sh"; \
- echo "[ -s "\$$$${IPKG_INSTROOT}/lib/functions.sh" ] || exit 0"; \
- echo ". \$$$${IPKG_INSTROOT}/lib/functions.sh"; \
- echo "default_prerm \$$$$0 \$$$$@"; \
- ) > prerm; \
- chmod 0755 postinst prerm; \
- $($(1)_COMMANDS) \
- )
-
- ifneq ($$(KEEP_$(1)),)
- @( \
- keepfiles=""; \
- for x in $$(KEEP_$(1)); do \
- [ -f "$$(IDIR_$(1))/$$$$x" ] || keepfiles="$$$${keepfiles:+$$$$keepfiles }$$$$x"; \
- done; \
- [ -z "$$$$keepfiles" ] || { \
- mkdir -p $$(IDIR_$(1))/lib/upgrade/keep.d; \
- for x in $$$$keepfiles; do echo $$$$x >> $$(IDIR_$(1))/lib/upgrade/keep.d/$(1); done; \
- }; \
- )
- endif
-
- $(INSTALL_DIR) $$(PDIR_$(1))
- $(FAKEROOT) $(SCRIPT_DIR)/ipkg-build -m "$(FILE_MODES)" $$(IDIR_$(1)) $$(PDIR_$(1))
- @[ -f $$(IPKG_$(1)) ]
逐行代码分析,
- @rm -rf $$(IDIR_$(1)); \
- $$(call remove_ipkg_files,$(1),$$(call opkg_package_files,$(call gen_ipkg_wildcard,$(1))))
这句指令实际执行命令如下:
rm -rf /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/ipkg-aarch64_cortex-a53/kmod-gpio-button-hotplug;
删除ipkg目录。
mkdir -p $(PACKAGE_DIR) $$(IDIR_$(1))/CONTROL $(PKG_INFO_DIR)
实际执行命令如下:
mkdir -p /root/mt7981/openwrt/bin/targets/mediatek/mt7981/packages /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/ipkg-aarch64_cortex-a53/kmod-gpio-button-hotplug/CONTROL /root/mt7981/openwrt/staging_dir/target-aarch64_cortex-a53_musl/pkginfo
新建ipkg以及其下面的目录。
$(call Package/$(1)/install,$$(IDIR_$(1)))
实际执行命令如下:
mkdir -p /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/ipkg-aarch64_cortex-a53/kmod-gpio-button-hotplug/etc/modules.d; ( echo "gpio-button-hotplug"; ) > /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/ipkg-aarch64_cortex-a53/kmod-gpio-button-hotplug/etc/modules.d/30-gpio-button-hotplug; mkdir -p /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/ipkg-aarch64_cortex-a53/kmod-gpio-button-hotplug/etc/modules-boot.d; ln -sf ../modules.d/30-gpio-button-hotplug /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/ipkg-aarch64_cortex-a53/kmod-gpio-button-hotplug/etc/modules-boot.d/;
其上面的命令都在include/kernel.mk的Package/kmod-$(1)/install中的ModuleAutoLoad实现的。
- -find $$(IDIR_$(1)) -name 'CVS' -o -name '.svn' -o -name '.#*' -o -name '*~'| $(XARGS) rm -rf
- @( \
- find $$(IDIR_$(1)) -name lib\*.so\* -or -name \*.ko | awk -F/ '{ print $$$$NF }'; \
- for file in $$(patsubst %,$(PKG_INFO_DIR)/%.provides,$$(IDEPEND_$(1))); do \
- if [ -f "$$$$file" ]; then \
- cat $$$$file; \
- fi; \
- done; $(Package/$(1)/extra_provides) \
- ) | sort -u > $(PKG_INFO_DIR)/$(1).provides
实际执行命令如下:
find /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/ipkg-aarch64_cortex-a53/kmod-gpio-button-hotplug -name 'CVS' -o -name '.svn' -o -name '.#*' -o -name '*~'| xargs -r rm -rf
删除掉ipkg目录下一些无关的文件。
$(RSTRIP) $$(IDIR_$(1))
实际执行命令如下:
export CROSS="aarch64-openwrt-linux-musl-" NO_RENAME=1 ; NM="aarch64-openwrt-linux-musl-nm" STRIP="/root/mt7981/openwrt/staging_dir/host/bin/sstrip -z" STRIP_KMOD="/root/mt7981/openwrt/scripts/strip-kmod.sh" PATCHELF="/root/mt7981/openwrt/staging_dir/host/bin/patchelf" /root/mt7981/openwrt/scripts/rstrip.sh /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/ipkg-aarch64_cortex-a53/kmod-gpio-button-hotplug
rstrip.sh: /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/ipkg-aarch64_cortex-a53/kmod-gpio-button-hotplug/lib/modules/5.4.203/gpio-button-hotplug.ko: relocatable
去掉ipkg中文件的符号表。
- (cd $$(IDIR_$(1))/CONTROL; \
- ( \
- echo "$$$$CONTROL"; \
- printf "Description: "; echo "$$$$DESCRIPTION" | sed -e 's,^[[:space:]]*, ,g'; \
- ) > control; \
- chmod 644 control; \
- ( \
- echo "#!/bin/sh"; \
- echo "[ \"\$$$${IPKG_NO_SCRIPT}\" = \"1\" ] && exit 0"; \
- echo "[ -s "\$$$${IPKG_INSTROOT}/lib/functions.sh" ] || exit 0"; \
- echo ". \$$$${IPKG_INSTROOT}/lib/functions.sh"; \
- echo "default_postinst \$$$$0 \$$$$@"; \
- ) > postinst; \
- ( \
- echo "#!/bin/sh"; \
- echo "[ -s "\$$$${IPKG_INSTROOT}/lib/functions.sh" ] || exit 0"; \
- echo ". \$$$${IPKG_INSTROOT}/lib/functions.sh"; \
- echo "default_prerm \$$$$0 \$$$$@"; \
- ) > prerm; \
- chmod 0755 postinst prerm; \
- $($(1)_COMMANDS) \
- )
实际执行命令如下:
(cd /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/ipkg-aarch64_cortex-a53/kmod-gpio-button-hotplug/CONTROL; ( echo "$CONTROL"; printf "Description: "; echo "$DESCRIPTION" | sed -e 's,^[[:space:]]*, ,g'; ) > control; chmod 644 control; ( echo "#!/bin/sh"; echo "[ \"\${IPKG_NO_SCRIPT}\" = \"1\" ] && exit 0"; echo "[ -s "\${IPKG_INSTROOT}/lib/functions.sh" ] || exit 0"; echo ". \${IPKG_INSTROOT}/lib/functions.sh"; echo "default_postinst \$0 \$@"; ) > postinst; ( echo "#!/bin/sh"; echo "[ -s "\${IPKG_INSTROOT}/lib/functions.sh" ] || exit 0"; echo ". \${IPKG_INSTROOT}/lib/functions.sh"; echo "default_prerm \$0 \$@"; ) > prerm; chmod 0755 postinst prerm; )
生成ipkg下的control,postinst和prerm文件。
$(INSTALL_DIR) $$(PDIR_$(1))
实际执行命令如下:
install -d -m0755 /root/mt7981/openwrt/bin/targets/mediatek/mt7981/packages
创建bin下的packages目录。
$(FAKEROOT) $(SCRIPT_DIR)/ipkg-build -m "$(FILE_MODES)" $$(IDIR_$(1)) $$(PDIR_$(1))
实际执行命令如下:
/root/mt7981/openwrt/staging_dir/host/bin/fakeroot /root/mt7981/openwrt/scripts/ipkg-build -m "" /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/ipkg-aarch64_cortex-a53/kmod-gpio-button-hotplug /root/mt7981/openwrt/bin/targets/mediatek/mt7981/packages
Packaged contents of /root/mt7981/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/gpio-button-hotplug/ipkg-aarch64_cortex-a53/kmod-gpio-button-hotplug into /root/mt7981/openwrt/bin/targets/mediatek/mt7981/packages/kmod-gpio-button-hotplug_5.4.203-3_aarch64_cortex-a53.ipk
调用ipkg-build命令生成ipkg文件。
echo "$(1)" >> $(PKG_INSTALL_STAMP)
实际执行命令如下:
echo "kmod-gpio-button-hotplug" >> /root/mt7981/openwrt/staging_dir/target-aarch64_cortex-a53_musl/pkginfo/gpio-button-hotplug.default.install
毫无疑问,它们都必须包含ipkg的基本元素,符合ipkg的规范,有CONTROL目录,CONTROL目录下有对应的control,postinst和prerm文件,还有其他的目录,例如内核驱动有etc和lib目录,应用程序有usr目录等等。
它们都要调用include/package.mk中的BuildPackage,再调用到include/package-ipkg.mk的BuildTarget/ipkg,BuildPackage的子功能定义编译ipkg源代码的一整套流程,Prepare,Configure,Compile和Install步骤,虽然两者区别是其中一个一些步骤会省略(Build/xxx为空),例如,kmod就不需要Configure。
编译kmod和普通应用的代码方式不一样。这个就体现在Build/Compile中,kmod的Makefile需要在自己的Makefile中定义这个宏,表示如何编译kmod,而应用代码Build/Compile是不推荐自定义的。
安装的方式不一样。kmod需要etc/modules.d/这样的目录,而应用程序不需要,在kmod的安装中,include/package-ipkg.mk中$(call Package/$(1)/install,$$(IDIR_$(1)))会调用到include/kernel.mk中的Package/kmod-$(1)/install,而如果再有需要,由于KernelPackage/$(1)/install定义在Package/kmod-$(1)/install,kmod的Makefile可以自定义KernelPackage/$(1)/install,做一些特殊处理。但是普通应用程序要在自己的Makefile中定义Package/$(1)/install,做一些自己需要的操作。