OpenWRT scan.mk

简述

单纯分析scan.mk太死板,本文以make命令的执行过程重点说明scan.mk的工作机制,总体来说,scan.mk用于扫描package和target目录, 生成用于menuconfig的Config.in文件和其他临时信息

Makefile

根据Mafile分析我们知道,Make最终的目标如下:

# SDK相关我们忽略

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, #通过这一行行我们知道我们需要先执行prereq目标对应的依赖和命令, preqre定义在在topdir.mk中
    @( \
        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 preqreq

# 我们依赖与prepare-tmpinfo和.config文件,.config依赖script/config/conf程序,
# 通过defconfig或者menuconfig生成TOPDIR下的.config,我们重点分析prepare-tmpinfo命令

prereq:: prepare-tmpinfo .config 170     
    @+$(NO_TRACE_MAKE) -r -s $@

Make prepare-tmpinfo

prepare-tmpinfo: FORCE
    @+$(MAKE) -r -s staging_dir/host/.prereq-build $(PREP_MK)
    mkdir -p tmp/info
    make -j1 -r -s -f include/scan.mk SCAN_TARGET="packageinfo" SCAN_DIR="package" SCAN_NAME="package" SCAN_DEPS="$(TOPDIR)/include/package*.mk $(TOPDIR)/overlay/*/*.mk" SCAN_DEPTH=5 SCAN_EXTRA=""
    make -j1 -r -s -f include/scan.mk SCAN_TARGET="targetinfo" SCAN_DIR="target/linux" SCAN_NAME="target" SCAN_DEPS="profiles/*.mk $(TOPDIR)/include/kernel*.mk $(TOPDIR)/include/target.mk" SCAN_DEPTH=2 SCAN_EXTRA="" SCAN_MAKEOPTS="TARGET_BUILD=1"
    for type in package target; do \ #生成tmp/.config-package.in和tmp/.config-target.in用于menuconfig图形化配置
        f=tmp/.$${type}info; t=tmp/.config-$${type}.in; \
        [ "$$t" -nt "$$f" ] || ./scripts/metadata.pl $${type}_config "$$f" > "$$t" || { rm -f "$$t"; echo "Failed to build $$t"; false; break;     }; \
    done
    [ tmp/.config-feeds.in -nt tmp/.packagefeeds ] || ./scripts/feeds feed_config > tmp/.config-feeds.in
    ./scripts/metadata.pl package_mk tmp/.packageinfo > tmp/.packagedeps || { rm -f tmp/.packagedeps; false; }
    ./scripts/metadata.pl package_feeds tmp/.packageinfo > tmp/.packagefeeds || { rm -f tmp/.packagefeeds; false; }
    touch $(TOPDIR)/tmp/.build

 

scan.mk

终于看到scan.mk被调用的地方,先看看scan.mk的源码

在分析之前我们可以知道,通过调用scan.mk传递的变量如下

1, SCAN_TARGET = "packageinfo"

2, SCAN_DIR = "package"

3, SCAN_NAME = "package"

4, SCAN_DEPENDS = "$(TOPDIR)/include/package*.mk $(TOPDIR)/overlay/*/*.mk" 

5, SCAN_DEPETH = 5

6, SCAN_EXTRA = ""

include $(TOPDIR)/include/verbose.mk
TMP_DIR:=$(TOPDIR)/tmp

#替换一下; all: tmp/.packageinfo
all: $(TMP_DIR)/.$(SCAN_TARGET)
include $(TOPDIR)/include/host.mk

SCAN_TARGET ?= packageinfo
SCAN_NAME ?= package
SCAN_DIR ?= package

# TARGET_STAMP = tmp/info/.files-packgeinfo.stamp
# SCAN_COOKIE?=$(shell echo $$$$)表示当前make的进程号,FILELIST = tmp/info/.files-packageinfo-xxxx
# OVERRIDELIST = tmp/info/.overrides-packageinfo-xxxx

TARGET_STAMP:=$(TMP_DIR)/info/.files-$(SCAN_TARGET).stamp
FILELIST:=$(TMP_DIR)/info/.files-$(SCAN_TARGET)-$(SCAN_COOKIE)
OVERRIDELIST:=$(TMP_DIR)/info/.overrides-$(SCAN_TARGET)-$(SCAN_COOKIE) # OVER

ifeq ($(IS_TTY),1)
  define progress
    printf "\033[M\r$(1)" >&2;
  endef
else
  define progress
    :;
  endef
endif

define feedname
$(if $(patsubst feeds/%,,$(1)),,$(word 2,$(subst /, ,$(1))))
endef

# 以$(eval $(call PackageDir,base-files,base-files,))为例展开如下:
# tmp/.packageinfo : tmp/info/.packageinfo-base-files
# tmp/info/.packageinfo-base-files: package/base-files/Makefile ...产生依赖
#        $(call progress, Collecting package info: package/base-files) \
#        echo Source-Makefile: package/base-files/Makefile
#        make -r DUMP=1 FEED= -C package/base-files $(SCAN_MAKEOPTS) 2>/dev/null > tmp/info/.packageinfo-base-files
# 如果发生错误则记录错误到logs/package/base-files/dump.txt中
# 生成的tmp/info/.packageinfo-base-files内容如下:
-------------------------------------------------------------------------
tmp/info/.packageinfo-base-files

  1 Source-Makefile: package/base-files/Makefile
  2 Package: base-files
  3 Version: 157.2-unknown
  4 Depends: +libc +SSP_SUPPORT:libssp +USE_GLIBC:librt +USE_GLIBC:libpthread +netifd +procd +jsonfilter +SIGNED_PACKAGES:usign
  5 Conflicts:
  6 Menu-Depends:
  7 Provides:
  8 Build-Depends: opkg/host usign/host
  9 Section: base
 10 Category: Base system
 11 Title: Base filesystem for OpenWrt
 12 Maintainer:
 13 Source:
 14 License: GPL-2.0
 15 Type: ipkg
 16 Description:  This package contains a base filesystem and system scripts for OpenWrt.
 17 http://openwrt.org/
 18
 19 @@
-------------------------------------------------------------------------

define PackageDir
  $(TMP_DIR)/.$(SCAN_TARGET): $(TMP_DIR)/info/.$(SCAN_TARGET)-$(1)
  $(TMP_DIR)/info/.$(SCAN_TARGET)-$(1): $(SCAN_DIR)/$(2)/Makefile $(SCAN_STAMP) $(foreach DEP,$(DEPS_$(SCAN_DIR)/$(2)/Makefile) $(SCAN_DEPS),$(wildcard $(if $(filter /%,$(DEP)),$(DEP),$(SCAN_DIR)/$(2)/$(DEP))))
    { \
        $$(call progress,Collecting $(SCAN_NAME) info: $(SCAN_DIR)/$(2)) \
        echo Source-Makefile: $(SCAN_DIR)/$(2)/Makefile; \
        $(if $(3),echo Override: $(3),true); \
        $(NO_TRACE_MAKE) --no-print-dir -r DUMP=1 FEED="$(call feedname,$(2))" -C $(SCAN_DIR)/$(2) $(SCAN_MAKEOPTS) 2>/dev/null || { \
            mkdir -p "$(TOPDIR)/logs/$(SCAN_DIR)/$(2)"; \
            $(NO_TRACE_MAKE) --no-print-dir -r DUMP=1 FEED="$(call feedname,$(2))" -C $(SCAN_DIR)/$(2) $(SCAN_MAKEOPTS) > $(TOPDIR)/logs/$(SCAN_DIR)/$(2)/dump.txt 2>&1; \
            $$(call progress,ERROR: please fix $(SCAN_DIR)/$(2)/Makefile - see logs/$(SCAN_DIR)/$(2)/dump.txt for details\n) \
            rm -f $$@; \
        }; \
        echo; \
    } > $$@ || true
endef

$(OVERRIDELIST):
    rm -f $(TMP_DIR)/info/.overrides-$(SCAN_TARGET)-*
    touch $@

ifeq ($(SCAN_NAME),target)
  GREP_STRING=BuildTarget
else
  GREP_STRING=(Build/DefaultTargets|BuildPackage|.+Package)
endif

#FILELIST为tmp/info/.files-packageinfo-xxx
#FILELIST依赖与OVERRIDELIST, OVERRIDELIST如上,删除旧的/tmp/info/.overrides-packageinfo-*, 重建新的tmp/info/.overrides-packageinfo-xxxx
#依赖处理完成后,执行删除tmp/info/.file-packageinfo-*的所有文件,如/tmp/info/.files-packageinfo-59016
$(FILELIST): $(OVERRIDELIST)
    rm -f $(TMP_DIR)/info/.files-$(SCAN_TARGET)-*

# 翻译一下下面的语句:
# find -L package -mindepth 1 -maxdepth 5 -name Makefile | xargs grep -aHE "(Build/DefaultTargets|BuildPackage|.+Package)" | \
# sed -e 's#^package/##' -e 's#/Makefile:.*##' | uniq | awk -v of=/tmp/gg -f include/scan.awk > tmp/info/.files-packageinfo-xxxx
# 生成的文件如下
-------------------------------------------------------------------------
utils/px5g-standalone
utils/robocfg
utils/spidev_test
utils/ubi-utils
utils/ugps
utils/usbmode
utils/usbreset
utils/usbutils
utils/util-linux
utils/xfsprogs
feeds/alljoyn/alljoyn
feeds/alljoyn/alljoyn-config
feeds/alljoyn/alljoyn-controlpanel
feeds/alljoyn/alljoyn-notification
feeds/alljoyn/alljoyn-onboarding
feeds/alljoyn/alljoyn-sample_apps
feeds/alljoyn/alljoyn-services_common
feeds/bluetopia/bluetopia
-------------------------------------------------------------------------
    $(call FIND_L, $(SCAN_DIR)) $(SCAN_EXTRA) -mindepth 1 $(if $(SCAN_DEPTH),-maxdepth $(SCAN_DEPTH)) -name Makefile | \
    xargs grep -aHE 'call $(GREP_STRING)' | sed -e 's#^$(SCAN_DIR)/##' -e 's#/Makefile:.*##' | uniq | awk -v of=$(OVERRIDELIST) -f include/scan.awk > $@

 

# tmp/info/.files-packageinfo.mk: tmp/info/.files-packageinfo-xxxx
# 通过脚本生成/tmp/info/.files-packageinfo.mk, 生成的文件内容如下:
-------------------------------------------------------------------------
1 DEPS_package/firmware/linux-firmware/Makefile=*.mk
2 DEPS_package/kernel/linux/Makefile=modules/*.mk $(TOPDIR)/target/linux/*/modules.mk $(TOPDIR)/include/netfilter.mk
3 $(eval $(call PackageDir,base-files,base-files,))
4 $(eval $(call PackageDir,boot_apex,boot/apex,))
-------------------------------------------------------------------------

$(TMP_DIR)/info/.files-$(SCAN_TARGET).mk: $(FILELIST)
    ( \
        cat $< | awk '{print "$(SCAN_DIR)/" $$0 "/Makefile" }' | xargs grep -HE '^ *SCAN_DEPS *= *' | awk -F: '{ gsub(/^.*DEPS *= */, "", $$2); print "DEPS_" $$1 "=" $$2 }'; \
        awk -F/ -v deps="$$DEPS" -v of="$(OVERRIDELIST)" ' \
        BEGIN { \
            while (getline < (of)) \
                override[$$NF]=$$0; \
            close(of) \
        } \
        { \
            info=$$0; \
            gsub(/\//, "_", info); \
            dir=$$0; \
            pkg=""; \
            if($$NF in override) \
                pkg=override[$$NF]; \
            print "$$(eval $$(call PackageDir," info "," dir "," pkg "))"; \
        } ' < $<; \
        true; \
    ) > $@

-include $(TMP_DIR)/info/.files-$(SCAN_TARGET).mk #include tmp/info/.files-packageinfo.mk

# 第一条命令重建FILELIST, FILELIST重建完成后的文件为tmp/info/.files-packageinfo-xxxx
# 然后将此文件进行md5sum计算,删除文件tmp/info/.files-packgeinfo.stamp*
# 重建建立文件tmp/info/.files-packageinfo.stamp和tmp/info/.files-packageinfo.stamp.$(md5sums FILELIST)文件

$(TARGET_STAMP)::
    +( \
        $(NO_TRACE_MAKE) $(FILELIST); \
        MD5SUM=$$(cat $(FILELIST) $(OVERRIDELIST) | (md5sum || md5) 2>/dev/null | awk '{print $$1}'); \
        [ -f "$@.$$MD5SUM" ] || { \
            rm -f $@.*; \
            touch $@.$$MD5SUM; \
            touch $@; \
        } \
    )

# tmp/.packageinfo最终目标,依赖$(TARGET_STAMP) = tmp/info/.files-packgeinfo.stamp $(SCAN_STAMP)为空
# 合并tmp/info/.packageinfo-base-files ...等所有的软件包到/tmp/.packageinfo中形成最终的文件
# 内容如下:
-------------------------------------------------------------------------
     1 Source-Makefile: package/base-files/Makefile
     2 Package: base-files
     3 Version: 157.2-unknown
     4 Depends: +libc +SSP_SUPPORT:libssp +USE_GLIBC:librt +USE_GLIBC:libpthread +netifd +procd +jsonfilter +SIGNED_PACKAGES:usign
     5 Conflicts:
     6 Menu-Depends:
     7 Provides:
     8 Build-Depends: opkg/host usign/host
     9 Section: base
    10 Category: Base system
    11 Title: Base filesystem for OpenWrt
    12 Maintainer:
    13 Source:
    14 License: GPL-2.0
    15 Type: ipkg
    16 Description:  This package contains a base filesystem and system scripts for OpenWrt.
    17 http://openwrt.org/
    18
    19 @@
    20
    21
    22 Source-Makefile: package/boot/apex/Makefile
    23 Package: apex
    24 Default: y
    25 Version: 1.6.9-1
    26 Depends: +libc +SSP_SUPPORT:libssp +USE_GLIBC:librt +USE_GLIBC:libpthread @TARGET_ixp4xx
    27 Conflicts:
    28 Menu-Depends:
    29 Provides:
    30 Section: boot
    31 Category: Boot Loaders
    32 Title: Boot loader for NSLU2, FSG3, NAS100D and others
    33 Maintainer:
    34 Source: apex-1.6.9.tar.gz
    35 Type: bin
    36 Description: Boot loader for NSLU2, FSG3, NAS100D and others
    37 http://wiki.buici.com/wiki/Apex_Bootloader
    38
    39 @@
-------------------------------------------------------------------------
# SCAN_TARGET = packageinfo
# TARGET_STAMP = tmp/info/.files-packgeinfo.stamp
# SCAN_STAMP为空 $(TMP_DIR)/.$(SCAN_TARGET): $(TARGET_STAMP) $(SCAN_STAMP) $(call progress,Collecting $(SCAN_NAME) info: merging...) -cat $(FILELIST) | awk '{gsub(/\//, "_", $$0);print "$(TMP_DIR)/info/.$(SCAN_TARGET)-" $$0}' | xargs cat > $@ 2>/dev/null $(call progress,Collecting $(SCAN_NAME) info: done) echo FORCE: .PHONY: FORCE .NOTPARALLEL:

总结:

1,当我们输入make命令时,Makefile进入第一个分支并执行make -r -s prereq进行准备

2,make -r -s prereq 会进行prepare-tmpinfo目标执行和.config文件的准备

3,prepare-tmpinfo会传递参数并制定scan.mk进行工作(后面以package目录为例)

4,prepare-tmpinfo的最终目标是tmp/.packageinfo,其依赖tmp/info/.files-packageinfo.stamp(此文件为空文件,仅用于记录更新时间戳)

  tmp/.packageinfo的内容为:包含了所有系统内的软件包信息,包括feeds,这些文件是有tmp/info/.packageinfo-base-files这些文件合成一个文件形成

1 Source-Makefile: package/base-files/Makefile
2 Package: base-files
3 Version: 157.2-unknown
4 Depends: +libc +SSP_SUPPORT:libssp +USE_GLIBC:librt +USE_GLIBC:libpthread +netifd +procd +jsonfilter +SIGNED_PACKAGES:usign
5 Conflicts:
6 Menu-Depends:
7 Provides:
8 Build-Depends: opkg/host usign/host
9 Section: base
10 Category: Base system
11 Title: Base filesystem for OpenWrt
12 Maintainer:
13 Source:
14 License: GPL-2.0
15 Type: ipkg
16 Description:  This package contains a base filesystem and system scripts for OpenWrt.
17 http://openwrt.org/
18
19 @@
20
21
22 Source-Makefile: package/boot/apex/Makefile
23 Package: apex
24 Default: y
25 Version: 1.6.9-1
26 Depends: +libc +SSP_SUPPORT:libssp +USE_GLIBC:librt +USE_GLIBC:libpthread @TARGET_ixp4xx
27 Conflicts:

5, tmp/info/.files-packageinfo.stamp是一个双引号目标,会永远被执行,

  这个文件主要生成FILELIST文件(tmp/info/.files-packageinfo-xxxx),tmp/info/.files-packageinfo.stamp,tmp/info/.files-packageinfo.stamp.$(md5sums FILELIST)

  tmp/info/.files-packageinfo.stamp,tmp/info/.files-packageinfo.stamp.$(md5sums FILELIST)都没有实际内容,仅用于记录时间戳

  FILELIST(tmp/info/.files-packageinfo-xxxx)的格式为,是系统所有软件包的列表:

 

utils/px5g-standalone
utils/robocfg
utils/spidev_test
utils/ubi-utils
utils/ugps
utils/usbmode
utils/usbreset
utils/usbutils
utils/util-linux
utils/xfsprogs
feeds/alljoyn/alljoyn
feeds/alljoyn/alljoyn-config
feeds/alljoyn/alljoyn-controlpanel
feeds/alljoyn/alljoyn-notification
feeds/alljoyn/alljoyn-onboarding
feeds/alljoyn/alljoyn-sample_apps
feeds/alljoyn/alljoyn-services_common
feeds/bluetopia/bluetopi

 

6,目标tmp/info/.files-packageinfo.mk: tmp/info/.files-packageinfo-xxxx根据规则生成如下文件

1 DEPS_package/firmware/linux-firmware/Makefile=*.mk
2 DEPS_package/kernel/linux/Makefile=modules/*.mk $(TOPDIR)/target/linux/*/modules.mk $(TOPDIR)/include/netfilter.mk
3 $(eval $(call PackageDir,base-files,base-files,))
4 $(eval $(call PackageDir,boot_apex,boot/apex,))

PackageDir展开如下

tmp/.packageinfo : tmp/info/.packageinfo-base-files
tmp/info/.packageinfo-base-files: package/base-files/Makefile ...产生依赖
    $(call progress, Collecting package info: package/base-files) \
    echo Source-Makefile: package/base-files/Makefile
    make -r DUMP=1 FEED= -C package/base-files $(SCAN_MAKEOPTS) 2>/dev/null > tmp/info/.packageinfo-base-files

7,tmp/info/.packageinfo-base-files文件的格式为:

1 Source-Makefile: package/base-files/Makefile
2 Package: base-files
3 Version: 157.2-unknown
4 Depends: +libc +SSP_SUPPORT:libssp +USE_GLIBC:librt +USE_GLIBC:libpthread +netifd +procd +jsonfilter +SIGNED_PACKAGES:usign
5 Conflicts:
6 Menu-Depends:
7 Provides:
8 Build-Depends: opkg/host usign/host
9 Section: base

8,然后toplevel.mk的prepare-tmpinfo目标中使用scripts/metadata.pl生成tmp/.config-package.in和tmp/.config-target.in用于进行menuconfig的配置,并使用此脚本生成tmp/.config-feeds.in,tmp/.packagedeps,tmp/.packagefeeds

tmp/.packageinfo包含了所有软件信息
tmp/info/.files-packageinfo-xxxx 软件的简单列表文件
tmp/info/.files-packageinfo.stamp 空文件,仅用于记录时间戳
tmp/info/.files-packageinfo.stamp.$(md5sums tmp/info/.files-packageinfo-xxxx)用于记录软件是否发生变化
tmp/info/.packaginfo-base-files 单一软件的详细信息,有多少软件就有多少文件
tmp/info/.files-packageinfo.mk 临时Makefile主要用于产生tmp/info/.packaginfo-base-files的依赖

以base-files为例,其依赖关系为
world: prepare-tmpinfo

prepare-tmpinfo:FORCE
  make -f include/scan.mk,scan.mk的终极目标为tmp/.packageinfo

tmp/.packageinfo: tmp/info/.files-packageinfo.stamp

tmp/info/.files-packageinfo.stamp::
  tmp/info/.files-packageinfo-xxxx 一个简单的软件列表
  touch tmp/info/.files-packageinfo.stamp
  touch tmp/info/.files-packageinfo.stamp.$(md5sum tmp/info/.files-packageinfo-xxxx)

tmp/info/.files-packageinfo.mk: tmp/info/.files-packageinfo-xxxx
  
  

 

本文原创,转载请注明出处 !

posted on 2022-03-04 15:07  sudochen  阅读(358)  评论(0编辑  收藏  举报

导航