查找package/compile
package/compile
目标没有明确的Makefile定义。所以我们考虑通过顶层Makefile中include进来的package/Makefile找到突破口。
该文件中直接定义的只有cleanup、rootfs-prepare、index三个目标。文件最后以package作为参数调用了subdir函数。根据之前文章中关于subdir函数作用的分析,我们可以得出结论:任何非直接定义的package/xxx目标,都依赖于其特定子目录的对应目标。特定子目录的读取规则参考前文,这里直接列出结论:
install
目标依赖于配置了CONFIG_PACKAGE_xxx
为y的包目录prereq
目标依赖于CONFIG_PACKAGE_xxx
为y或者m的包目录- 其他目标依赖于
CONFIG_PACKAGE_xxx
为y或者m的包目录
深入package/包名/
进入到具体的包,每个包的Makefile内容都各不一样。但是大体上都包含以下几个部分:
include
顶层的rules.mk文件- 定义名称、版本、下载地址、依赖等包信息
include
顶层include/package.mk文件- 定义该软件包的一些非通用的函数(
Package/包名/操作
)。 - 以包名为参数调用
BuildPackage
函数。
前面几步都没有什么特别的,最后一步的BuildPackage
函数调用非常关键。该函数定义在前面include进来的顶层include/pacakge.mk文件中。
深入BuildPackage函数
定义在顶层include/package.mk文件的该函数,内容不多。主要包含:
- 读取顶层
overlay/*/包名.mk
文件里定义的特殊规则 - 读取默认的
Package/Default
、Package/包名
函数以导入软件包的相关变量。 - 检查必要的变量名是否正确定义。
- 重要通过遍历,构建目标规则。
- 以$1作为参数调用
Build/DefaultTargets
函数设置一些默认目标规则。该函数就在本文件中定义
遍历构造规则部分,主要是遍历列表内容作为target变量的值,然后调用BuildTarget/$(target)
。遍历的列表分为集中情况:
- 当定义了
Package/包名/targets
时,将其作为遍历的内容。 - 否则检查是否存在
PKG_TARGETS
变量,如果有,则将其作为遍历内容。 - 否则将
ipkg
作为遍历的内容,如果CONFIG_DEBUG_DIR变量设置的话,将debug也添加为遍历的内容。
由此可见,默认情况下就是调用的BuildTarget/ipkg
函数,该函数定义在package.mk
前面include进来的include/package-ipkg.mk
文件中。
Build/DefaultTargets
函数主要定义了prepare、configure、dist、distclean这些准备性的目标,及其关联的目标stamp文件目标。
BuildTarget/ipkg
函数定义了compile、install两个重要的目标,及其关联的依赖目标。需要注意的这两个目标定义,在Package/包名/install
函数有定义的前提下才有效。而这个函数必须要自己定义。
所以,执行package/compile实质上执行的就是include/package-ipkg.mk中定义的compile目标。
package/包名/compile的依赖分析
每个软件包的compile目标,都依赖于IPKG_包名
、$(STAGING_DIR_ROOT)/stamp/.$(1)_installed
两个目标。前者主要是编译打包成ipkg。后者主要调用Package/包名/install
和Package/包名/install_lib
两个方法,将软件包安装到STAGING_DIR_ROOT
(staging_dir/target-mips_uClibc-0.9.30.1/root-wndr4500v3/
)中。
IPKG_包名
这个目标的执行体主要包括三个功能:
- 生成ipkg所需要的软件包的元数据
- 调用
Package/包名/install
安装软件包到临时目录build_dir/target-mips_uClibc-0.9.30.1/包名/ipkg-wndr4500v3/包名
- 把临时目录、元数据打包成ipkg格式的软件包,放在
bin/packages/wndr4500v3_uClibc-0.9.30.1/
。
IPKG_包名
同时依赖于$(STAMP_BUILT)
目标,该目标定义在include/package.mk中。
$(STAMP_BUILT)
的执行体,主要调用Build/Compile
、Build/Install
两个函数,以及相关的Hooks。这两个函数分别是等价于在include/pacakge-defaults.mk中定义的Build/Compile/Default
、Build/Install/Default
。
$(STAMP_BUILT)
依赖于$(STAMP_CONFIGURED)
。类似地,这个目标调用的是Build/Configure/Default
。并依赖于$(STAMP_PREPARED)
目标,这个目标同样类似的调用的是Build/Prepare/Default
。
上面被最终调用的,定义在include/package-defaults.mk中的默认目标分别是:
Build/Prepare/Default
:调用PKG_UNPACK
解压代码并调用Build/Patch
打补丁Build/Configure/Default
:带参数执行默认的./configure
Build/Compile/Default
:带参数执行默认的make
Build/Install/Default
:带参数执行默认的make install
package/包名/install
该目标依赖于IPKG_包名
目标,也就是说他也需要先将软件包打包成ipkg格式。该目标的执行体最简单,直接调用ipkg命令安装打包好的ipkg文件。需要注意的是ipkg命令本身设置了几个环境变量:
IPKG_TMP
安装所需临时目录,值为tmp/ipkg
IPKG_INSTROOT
安装目录,值为build_dir/target-mips_uClibc-0.9.30.1/root-wndr4500v3/
IPKG_CONF_DIR
配置目录,值为staging_dir/target-mips_uClibc-0.9.30.1/etc
IPKG_OFFLINE_ROOT
离线安装目录,值为build_dir/target-mips_uClibc-0.9.30.1/root-wndr4500v3