我是靠谱客的博主 复杂金针菇,最近开发中收集的这篇文章主要介绍OpenWrt makefile 分析编译总体过程顶层Makefile分析,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

编译总体过程

  1. 编译host工具
  2. 编译交叉工具链
  3. 编译内核模块
  4. 编译ipk
  5. 安装ipk到文件系统
  6. 编译内核
  7. 将内核和文件系统组合成最终binary

顶层Makefile分析

在顶层Makefile里比较麻烦的是,将Makefile分为了两个主要分支,第一个部分主要是执行编译前的准备,第二个部分是执行编译。在每个分支里通过include载入相应的文件,在这些文件里包含相应的目标执行命令,在命令中多次用make+目标+参数的方式,则会再次执行Makefile文件,就形成了Makefile的嵌套执行。在嵌套执行的过程中,通过变量OPENWRT_BUILD来区分是执行顶层Makefile的那个部分,如果在make命令行中有OPENWRT_BUILD为0,则执行第一个部分,没有加OPENWRT_BUILD变量则执行第二个部分。
由于OPENWRT_BUILD是make命令行参数,所以在Makefile中如果要改变它的值,就用到了override指示符。

target/Makefile、package/Makefile、tools/Makefile、toolchain/Makefile这四个子目录下的Makefile实际上是不能独立执行。主要利用$(INCLUDE_DIR)/subdir.mk动态建立规则,诸如$(toolchain/stamp-install)目标是靠$(INCLUDE_DIR)/subdir.mk的stampfile函数动态建立。

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

这类使用变量命名的目标,其变量的赋值位置在$(INCLUDE_DIR)/subdir.mk的stampfile函数中。目标只有依赖关系,可能说明其工作顺序,在$(INCLUDE_DIR)/subdir.mk的stampfile函数中有进一步说明其目标执行的命令,并为目标建立一个空文件,即使用变量命名的目标为真实的文件。

top Makefile: $(package/stamp-compile): $(target/stamp-compile) $(package/stamp-cleanup)
package_makefile:  $(eval $(call stampfile,$(curdir),package,compile,$(TMP_DIR)/.build))
subdir.mk:  
define stampfile     # Parameters: <subdir> <name> <target> <depends> <config options> <stampfile location>
      $(1)/stamp-$(3):=$(if $(6),$(6),$(STAGING_DIR))/stamp/.$(2)_$(3)$(5)
      $$($(1)/stamp-$(3)): $(TMP_DIR)/.build $(4)

$(1)=$(curdir)   $(2)=package   $(3)=compile   
$(package/stamp-compile):=$(STAGING_DIR)/stamp/.package_compile

prereq应该是预请求目标,在OpenWrt执行Makefile时好像都要先执行prereq目标。
prepare应该是准备目标,是world依赖的一个伪目标。依赖于文件.config和$(tools/stamp-install) $(toolchain/stamp-install)目标。

top Makefile:  // second part
prereq: $(target/stamp-prereq) tmp/.prereq_packages
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
toplevel.mk:
prereq:: prepare-tmpinfo .config
        @+$(NO_TRACE_MAKE) -r -s $@                    (@make  tmp/.prereq-build)

%::
        @+$(PREP_MK) $(NO_TRACE_MAKE) -r -s prereq         
        @+$(ULIMIT_FIX) $(SUBMAKE) -r $@

除了少数在toplevel中被定义的目标外, 其他编译目标都会走到这里.将之简化后:
%::
make prereq
make $@
首先执行prereq, 然后再执行我们指定的目标或者默认目标world.

NO_TRACE_MAKE := $(MAKE) V=99
上面的 “%::” 用于解释world目标的规则
%是通配符,加上双冒号规则,此组合表示任何目标去无条件执行下面的命令

在执行@+$(PREP_MK) $(NO_TRACE_MAKE) -r -s prereq命令的时候,在make命令行里有$(PREP_MK)变量,而由于OPENWRT_BUILD的值为0,在verbose.mk文件里NO_TRACE_MAKE := $(MAKE) V=99,所以会执行顶层目录的Makefile第一个分支部分的目标prereq,即toplevel.mk文件中的目标prereq

最后

以上就是复杂金针菇为你收集整理的OpenWrt makefile 分析编译总体过程顶层Makefile分析的全部内容,希望文章能够帮你解决OpenWrt makefile 分析编译总体过程顶层Makefile分析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部