openwrt サブディレクトリ関数の分析

I.はじめに

        厳密に言えば、subdir はコマンド パッケージであり、この記事の残りの部分では関数と呼ばれます。openwrt の subdir 関数は非常に重要です。openwrt/include/subdir.mk ファイルの下にあります。ツール、ツールチェーン、ターゲット、およびパッケージ モジュールは、次のように subdir を使用してコンパイルされます。

openwrt/tools/Makefile

curdir:=tools
......

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

openwrt/toolchain/Makefile

curdir:=toolchain
.....

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

        openwrt/package/Makefile と openwrt/target/Makefile も同じ形式であるため、ここでは例は示しません。次に、subdir 関数の動作原理を大まかに分析します。

2. サブディレクトリ分析 

        subdir は openwrt/include/subdir.mk にあり、ソースコードは次のとおりです。

# Parameters: <subdir>
define subdir
  $(call warn,$(1),d,D $(1))
  $(foreach bd,$($(1)/builddirs),
    $(call warn,$(1),d,BD $(1)/$(bd))
    $(foreach target,$(SUBTARGETS) $($(1)/subtargets),
      $(foreach btype,$(buildtypes-$(bd)),
        $(call warn_eval,$(1)/$(bd),t,T,$(1)/$(bd)/$(btype)/$(target): $(if $(NO_DEPS)$(QUILT),,$($(1)/$(bd)/$(btype)/$(target)) $(call $(1)//$(btype)/$(target),$(1)/$(bd)/$(btype))))
		  $(call log_make,$(1)/$(bd),$(target),$(btype),$(filter-out __default,$(variant))) \
			$(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 $(NO_DEPS)$(QUILT),,$($(1)/$(bd)/$(target)) $(call $(1)//$(target),$(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 $(BUILD_LOG),@mkdir -p $(BUILD_LOG_DIR)/$(1)/$(bd)/$(filter-out __default,$(variant)))
			$(if $($(1)/autoremove),$(call rebuild_check,$(1)/$(bd),$(target),,$(filter-out __default,$(variant))))
			$(call log_make,$(1)/$(bd),$(target),,$(filter-out __default,$(variant))) \
				$(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) $($(1)/subtargets),$(call subtarget,$(1),$(target)))
endef

        分析の前に、現在ツールをコンパイルしていると仮定し、ツールの下のbison を例として取り上げます。

次に、ソース コードを 1 行ずつ分析します。

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

        この行は warn 関数を呼び出します。warn 関数は openwrt/include/debug.mk にあります。この文はデバッグに使用されるため、無視してかまいません。

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

        この行の foreach 関数の末尾のかっこは、subdir 関数の最後から 3 番目の行のかっこです。$(1) は tools を意味するので、 $(foreach bd,$(tools/builddirs)) と展開され、 tools/Makefile の解析から、 tools/builddirs の値は次のようになります。

gmp mpfr mpc libelf m4 libtool autoconf automake flex bison pkg-config sed mklibs sstrip make-ext4fs e2fsprogs mtd-utils mkimage ファームウェア-ユーティリティ パッチイメージ パッチキルト yaffs2 flock Padjffs2 mm-macros missing-macros xz cmake scons bc findutils gengetopt patchelf lzma squashfs4 wrt350nv2-builder upslug2 upx qemu elftosb mtools dosfstools lzma-old squashfs b43-tools ppl cloog sparse

        したがって、bdは上記の各ツールの名前です。

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

        この行はデバッグ情報であり、一時的にスキップすることもできます。

$(foreach target,$(SUBTARGETS) $($(1)/subtargets),
......
)

        この行の foreach 関数の末尾のかっこは、subdir 関数の最後から 2 番目の行のかっこです。SUBTARGETS:=$(DEFAULT_SUBDIR_TARGETS) であるため、DEFAULT_SUBDIR_TARGETS の定義は次のように openwrt/rules.mk にあります。

DEFAULT_SUBDIR_TARGETS:=clean download prepare compile update refresh prereq dist distcheck configure check check-depends

        ツール/サブターゲットが定義されていないため、空です。したがって、そのコード行は次のように展開されます。

$(foreach target,clean download prepare compile update refresh prereq dist distcheck configure check check-depends,
......
)

        ターゲットは順番にクリーンになり、チェックに応じてダウンロードされます。

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

        ここでは、bd は bison を例として $(foreach btype,$(buildtypes-bison)) に展開しますが、buildtypes-bison が定義されていないため、ここでは foreach 関数が空に展開されます。

        注: openwrt/tmp/.packageinfo ファイルには、Build-Types のフィールドがあり、パッケージの $(buildtype-$(package)) は空ではありません。具体的なメカニズムは後で分析します。

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

        warn_eval 関数は、openwrt/include/debug.mk ファイルで次のように定義されています。

define warn_eval
$(call warn,$(1),$(2),$(3)	$(4))
$(4)
endef

        warn_eval 関数は warn 関数と 4 番目のパラメーターで構成されているため、ここでは 4 番目のパラメーターのみに注意する必要があります。NO_DEPS と QUILT が定義されていないため、コード全体は次のように展開されます。

tools/bison/compile: $(tools/bison/compile) $(call tools//compile,tools/bison)

        openwrt/tools/Makefile を分析すると、tools/bison/compile=tools/flex/install tools/patch/install であることがわかります。tools//compile=$(STAGING_DIR)/.prepared $(STAGING_DIR_HOST)/.prepared。STAGING_DIR=openwrt/staging_dir/target-mipsel_24kc_musl/、STAGING_DIR_HOST=openwrt/staging_dir/host。STAGING_DIR と STAGING_DIR_HOST は両方とも絶対パスであることに注意してください。したがって、文全体は次のように展開されます。

tools/bison/compile: tools/flex/install tools/patch/install openwrt/staging_dir/target-mipsel_24kc_musl openwrt/staging_dir/host

        これは、bison をコンパイルする前に、最初に flex と patch をコンパイルする必要があり、staging_dir/target_xxx と staging_dir/host が存在することを意味します。

$(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))),
......
)

        ここでは、BUILD_VARIANT が空なので、ここを展開します。

$(foreach variant, $(if $(strip $(tools/bison/variants)),$(tools/bison/variants),$(if tools/bison/default-variant),$(tools/bison/default-variant),default))

        上記のコードは、tools/bison/variants が定義されている場合は tools/bison/variants 変数の値を取得し、そうでない場合は tools/bison/default-variant 変数に値があるかどうかを確認し、ない場合は __default を取得することを示しています。 bison の場合は、__default を選択します。

$(if $(BUILD_LOG),@mkdir -p $(BUILD_LOG_DIR)/$(1)/$(bd)/$(filter-out __default,$(variant)))

        BUILD_LOG は、rule.mk で定義され、CONFIG_BUILD_LOG 変数によって制御されます。CONFIG_BUILD_LOG が定義されていないため、このコード行は無視されます。

$(if $($(1)/autoremove),$(call rebuild_check,$(1)/$(bd),$(target),,$(filter-out __default,$(variant))))

        bison/autoremove が定義されていない場合、このコード行は実行されません。

$(call log_make,$(1)/$(bd),$(target),,$(filter-out __default,$(variant)))

        次のように展開されます。

$(call log_make,tools/bison,compile,,)

log_make は次のように定義されます。

log_make = \
	 $(if $(call debug,$(1),v),,@)+ \
	 $(if $(BUILD_LOG), \
		set -o pipefail; \
		mkdir -p $(BUILD_LOG_DIR)/$(1)$(if $(4),/$(4));) \
	$(SCRIPT_DIR)/time.pl "time: $(1)$(if $(4),/$(4))/$(if $(3),$(3)-)$(2)" \
	$$(SUBMAKE) $(subdir_make_opts) $(if $(3),$(3)-)$(2) \
		$(if $(BUILD_LOG),SILENT= 2>&1 | tee $(BUILD_LOG_DIR)/$(1)$(if $(4),/$(4))/$(if $(3),$(3)-)$(2).txt)

        デバッグ機能は無視され、BUILD_LOG が定義されていないため、time.pl の処理は無視されます。subdir_make_opts は次のように定義されます

subdir_make_opts = \
	-r -C $(1) \
		BUILD_SUBDIR="$(1)" \
		BUILD_VARIANT="$(4)"

        したがって、コード行全体は次のように展開されます。

make -r -C tools/bison compile
$(foreach target,$(SUBTARGETS) $($(1)/subtargets),$(call subtarget,$(1),$(target)))

        このコード行は、ターゲットを指定せずに直接 make するために使用されます。サブターゲットの定義は次のとおりです。

define subtarget
  $(call warn_eval,$(1),t,T,$(1)/$(2): $($(1)/) $(foreach bd,$(call subtarget-default,$(1),$(2)),$(1)/$(bd)/$(2)))
endef

        subtarget-default の定義は次のとおりです。

subtarget-default = $(filter-out ., \
	$(if $($(1)/builddirs-$(2)),$($(1)/builddirs-$(2)), \
	$(if $($(1)/builddirs-default),$($(1)/builddirs-default), \
	$($(1)/builddirs))))

        この行は、tools/builddirs-compile が空でない場合、subtarget-default の値が $(tools/builddirs-compile) であることを示します。それ以外の場合は、tools/builddirs-default が空かどうか、および subtarget-default の値が空かどうかを確認します。デフォルトは $(tools/builddirs-default)、それ以外の場合は $(tools/builddirs)。

        したがって、コード全体は次のように展開されます。

tools/clean: .config prereq tools/gmp/clean tools/mpfr/clean tools/mpc/clean tools/libelf/clean tools/expat/clean tools/m4/clean tools/libtool/clean tools/autoconf/clean tools/automake/clean tools/flex/clean tools/bison/clean tools/pkg-config/clean tools/mklibs/clean tools/zlib/clean tools/sstrip/clean tools/make-ext4fs/clean tools/e2fsprogs/clean tools/mtd-utils/clean tools/mkimage/clean tools/firmware-utils/clean tools/patch-image/clean tools/quilt/clean tools/padjffs2/clean tools/mm-macros/clean tools/missing-macros/clean tools/cmake/clean tools/scons/clean tools/bc/clean tools/findutils/clean tools/gengetopt/clean tools/patchelf/clean tools/mtools/clean tools/dosfstools/clean tools/libressl/clean tools/lzma/clean tools/squashfskit4/clean tools/zip/clean tools/tar/clean tools/xz/clean tools/patch/clean tools/flock/clean tools/sed/clean
tools/download: .config prereq tools/gmp/download tools/mpfr/download tools/mpc/download tools/libelf/download tools/expat/download tools/m4/download tools/libtool/download tools/autoconf/download tools/automake/download tools/flex/download tools/bison/download tools/pkg-config/download tools/mklibs/download tools/zlib/download tools/sstrip/download tools/make-ext4fs/download tools/e2fsprogs/download tools/mtd-utils/download tools/mkimage/download tools/firmware-utils/download tools/patch-image/download tools/quilt/download tools/padjffs2/download tools/mm-macros/download tools/missing-macros/download tools/cmake/download tools/scons/download tools/bc/download tools/findutils/download tools/gengetopt/download tools/patchelf/download tools/mtools/download tools/dosfstools/download tools/libressl/download tools/lzma/download tools/squashfskit4/download tools/zip/download tools/tar/download tools/xz/download tools/patch/download tools/flock/download tools/sed/download
tools/prepare: .config prereq tools/gmp/prepare tools/mpfr/prepare tools/mpc/prepare tools/libelf/prepare tools/expat/prepare tools/m4/prepare tools/libtool/prepare tools/autoconf/prepare tools/automake/prepare tools/flex/prepare tools/bison/prepare tools/pkg-config/prepare tools/mklibs/prepare tools/zlib/prepare tools/sstrip/prepare tools/make-ext4fs/prepare tools/e2fsprogs/prepare tools/mtd-utils/prepare tools/mkimage/prepare tools/firmware-utils/prepare tools/patch-image/prepare tools/quilt/prepare tools/padjffs2/prepare tools/mm-macros/prepare tools/missing-macros/prepare tools/cmake/prepare tools/scons/prepare tools/bc/prepare tools/findutils/prepare tools/gengetopt/prepare tools/patchelf/prepare tools/mtools/prepare tools/dosfstools/prepare tools/libressl/prepare tools/lzma/prepare tools/squashfskit4/prepare tools/zip/prepare tools/tar/prepare tools/xz/prepare tools/patch/prepare tools/flock/prepare tools/sed/prepare
tools/compile: .config prereq tools/gmp/compile tools/mpfr/compile tools/mpc/compile tools/libelf/compile tools/expat/compile tools/m4/compile tools/libtool/compile tools/autoconf/compile tools/automake/compile tools/flex/compile tools/bison/compile tools/pkg-config/compile tools/mklibs/compile tools/zlib/compile tools/sstrip/compile tools/make-ext4fs/compile tools/e2fsprogs/compile tools/mtd-utils/compile tools/mkimage/compile tools/firmware-utils/compile tools/patch-image/compile tools/quilt/compile tools/padjffs2/compile tools/mm-macros/compile tools/missing-macros/compile tools/cmake/compile tools/scons/compile tools/bc/compile tools/findutils/compile tools/gengetopt/compile tools/patchelf/compile tools/mtools/compile tools/dosfstools/compile tools/libressl/compile tools/lzma/compile tools/squashfskit4/compile tools/zip/compile tools/tar/compile tools/xz/compile tools/patch/compile tools/flock/compile tools/sed/compile

        tools/$(target) は、次のように stampfile 関数によって呼び出されます。

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

        $(1)/$(3) が tools/compile の場合、subdir のターゲットが呼び出されます。

3. まとめ

        一般に、subdir は 2 層の foreach ループを使用して、bd のすべてのターゲットをすべてのターゲットに追加し、ツール、ツールチェーン、パッケージ、ターゲットなど、それぞれの完全なターゲットと依存関係を確立します。最後にプロジェクト全体をコンパイルします。

おすすめ

転載: blog.csdn.net/to_be_better_wen/article/details/130307193