OpenWRT Makefile分析

目录介绍

原始目录

  • config: 存放用于生成menuconfig的配置文件
  • include: 顾名思义,存放了许多OpenWRT的Makefile文件,以.mk结尾
  • scripts: 一些shell,perl脚本
  • package: target包,这些软件会根据选择安装在目标板上
  • toolchain:用于生成交叉编译工具
  • tools:编译本机工具如patch等

生成目录

  • bin:存放生成的二进制文件
  • build_dir: 构建目录,用户存放软件包和host以及交叉编译器的编译目录
  • dl:软件包的下载位置,这个位置可根据配置进行修改
  • tmp:存放临时文件
  • staging_dir: 存放编译好的host工具,交叉编译工具,已经开发过程用到的头文件

Makefile分析

因为原始的Makfele太繁琐,下面我们贴上一个裁剪过的Makefile文件

整个Makefile有两个分支,简化如下:

ifneq($(OPENWRT_BUILD), 1)
override OPENWRT_BUILD=1
...第一个分支
else
...第二个分支
endif

# 由于第一次没有定义OPENWRT_BUILD变量,因此走到一个分支去,当从第一个分支再次执行Make时,由于OPENWRT_BUILD已经定义,因此会走到第二个分支
# 主Makefile
# Makefile for OpenWrt
#
# Copyright (C) 2007 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#

TOPDIR:=${CURDIR}
LC_ALL:=C
LANG:=C
export TOPDIR LC_ALL LANG
# 定义变量,并且向外到处,也就是通过make -C 切进去的子目录也能看到这些变量

empty:=
space:= $(empty) $(empty)
$(if $(findstring $(space),$(TOPDIR)),$(error ERROR: The path to the OpenWrt directory must not include any spaces))
# 如果TOPDIR里面包含了空格则报错

world:
# world目标是终极目标

include $(TOPDIR)/include/host.mk
# 包含include的host.mk, host.mk主要目标是$(TMP_DIR)/.host.mk
# 在host.mk中回包含$(TMP_DIR)/.host.mk, 如下
# -include $(TMP_DIR)/.host.mk, Makefile中使用include指示符将这个
# 文件包含进来,在执行时,make会重建此文件,在host.mk可以看到
# PRECIOUS: $(TMP_DIR)/.host.mk
# $(TMP_DIR)/.host.mk: $(TOPDIR)/include/host.mk
# 最终生成$(TMP_DIR)/.host.mk并被包含在主Makefile中
# $(TMP_DIR)/.host.mk的主要内容如下:
# HOST_OS:=Linux
# HOST_ARCH:=x86_64
# GNU_HOST_NAME:=x86_64-linux-gnu
# FIND_L=find -L $(1)
# 定义了一些变量
#

# 如果没有定义OPENWRT_BUILD则进入第一个逻辑
# 也就是我们经常编译时Make V=s时的正常逻辑
ifneq ($(OPENWRT_BUILD),1)
  _SINGLE=export MAKEFLAGS=$(space);

# override为了防止OPENWRT_BUILD通过命令行传递,

  override OPENWRT_BUILD=1
  export OPENWRT_BUILD
  GREP_OPTIONS=
  export GREP_OPTIONS
# debug.mk主要定义一些调试的变量,如debug, warn debug_eval, warn_eval
# 在非调试模式下都为空
# 我们可以使用make DEBUG=all来分析Makefile的所有信息,DEBUG=all如下
# debug flags
# d: show subdirectory tree
# t: show added targets
# l: show legacy targets
# r: show autorebuild messages
# v: verbose (no .SILENCE for common targets)
# include/debug.mk
# ifeq($(DEBUG), all)
#    build_debug = dltvr
# else
#    build_debug = $(DEBUG)
# endif
#
#
  include $(TOPDIR)/include/debug.mk
# depends.mk 主要定义了rdep这个变量,后续分析
  include $(TOPDIR)/include/depends.mk
# 这个是最重要的, 在toplevel.mk定义了双引号目标,双引号目标根据GNU_Make手册4.13
# 当双引号规则没有依赖时,规则的命令会被无条件执行,命令如下:
# %::
#    @+(PREP_MK) $(NO_TRACE_MAKE) -r -s prereq
#    @+(SUBMAKE) -r $@

# PREP_MAKE定义在:toplevel.mk中,PREP_MK= OPENWRT_BUILD= QUIET=0,
# NO_TRACE_MAKE定义在verbose.mk中,NO_TRACE_MAKE := $(MAKE) V=s$(OPENWRT_VERBOSE)
# SUBMAKE定义在verbose.mk中为:SUBMAKE=$(MAKE) -w
# 因此上面的规则翻译为:
# %::
#    @+OPENWRT_BUILD= QUIET=0 make V=s -r -s prereq
#    @+make -w world,重新执行world目标,由于OPENWRT_BUILD已经定义,因此进入第二个逻辑,进行真正的编译
#

# 详见toplevel.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

# $(toolchain/stamp-install) 这些变量在target/Makefile, toolchain/Makefile通过调用subdir.mk生成
$(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)

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

# 终极目标,这个很简单执执行prepare对应的依赖和命令,以此类推, $(target/stamp-compile)是通过subdir.mk里面的函数自动生成,详见subdir.mk的分析
world: prepare $(target/stamp-compile) $(package/stamp-compile) $(package/stamp-install) $(target/stamp-install) FORCE
    $(_SINGLE)$(SUBMAKE) -r package/index

# PHONY是为了防止当前目录下有同名文件导致Make不执行具体的规则,而只更新文件的时间戳
.PHONY: clean dirclean prereq prepare world package/symlinks package/symlinks-install package/symlinks-clean

endif

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

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

导航