package是target之外的另一个概念,它表示一个包,比如busybox是一个package。package在package/目录下,比如busybox的路径为:package/utils/busybox。每个package都有一个Makefile,来定义这个package。
添加一个package:package/my/webcgi,添加Makefile文件:package/webcgi/my/Makefile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | include $(TOPDIR)/rules.mk PKG_NAME:=webcgi PKG_VERSION:=1.0.0 PKG_RELEASE:=1 include $(INCLUDE_DIR)/package.mk define Package/webcgi CATEGORY:=My package TITLE:=webcgi DEPENDS := +libnl +libblobmsg-json +libubus endef define Build/Prepare mkdir -p $(PKG_BUILD_DIR)/{lib,cgi} endef define Build/Compile CFLAGS="$(TARGET_CFLAGS)" LDFLAGS="$(TARGET_LDFLAGS)" make -C src/ \ O=$(PKG_BUILD_DIR)/ CC=$(TARGET_CC) endef define Package/webcgi/install $(INSTALL_DIR) $(1)/web/cgi-bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/webcgi $(1)/web/cgi-bin endef $(eval $(call BuildPackage,webcgi)) |
执行 make prepare-tmpinfo,生成了 tmp/info/.package-webcgi包信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | Source-Makefile: package/my/webcgi/Makefile Package: webcgi Version: 1.0.0-1 Depends: +libc +USE_GLIBC:librt +USE_GLIBC:libpthread +libnl +libblobmsg-json +libubus Conflicts: Menu-Depends: Provides: Section: My section Category: My package Repository: base Title: webcgi Maintainer: Source: Type: ipkg Description: webcgi @@ |
配置文件 tmp/.config-package.in包含了这个包的配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | menu "My package" config PACKAGE_webcgi tristate "webcgi............................................................ webcgi" default y if DEFAULT_webcgi default m if ALL select PACKAGE_libnl select PACKAGE_libblobmsg-json select PACKAGE_libpthread if USE_GLIBC select PACKAGE_libc select PACKAGE_libubus select PACKAGE_librt if USE_GLIBC help webcgi endmenu |
定义中的CATEGORY变量,表示是哪个menu。还可以定义SUBMENU变量,指定二级目录。
依赖通过DEPENDS变量定义。规则如下:
+foo | 选中foo这个package,翻译为config为: select PACKAGE_foo |
foo | 依赖foo这个package,翻译为config为: depends on PACKAGE_foo |
@foo | 依赖配置项CONFIG_foo,翻译为config为:depends on foo |
+foo:bar | 如果配置项CONFIG_foo开启,则选中bar这个package, 翻译为config为:select PACKAGE_bar if foo |
@foo:bar | 如果CONFIG_foo开启,则依赖CONFIG_bar。 翻译为config为:depends on !(foo) || bar 这里有问题和openwrt的文档描述不符。查看openwrt的package,没有这么用的。 |
还可以通过定义Package/xxx/config变量,来直接定义配置项:
define Package/webcgi/config
config webcgi_name
string "name of webcgi"
depends on PACKAGE_webcgi
endef
生成的依赖文件tmp/.packagedeps包含如下webcgi的定义:
package-$(CONFIG_PACKAGE_webcgi) += my/webcgi
$(curdir)/my/webcgi/compile += $(curdir)/libs/libnl/compile $(curdir)/libs/toolchain/compile
$(if $(CONFIG_USE_GLIBC),$(curdir)/libs/toolchain/compile)
在package/Makefile中的$(eval $(call subdir,$(curdir)))生成了编译包的信息:
1 2 3 4 5 6 7 8 | package/my/webcgi/compile: package/libs/libnl/compile package/libs/toolchain/compile @+ /work/openwrt/scripts/time.pl "time: package/my/webcgi/compile" $(SUBMAKE) -r \ -C package/my/webcgi BUILD_SUBDIR="package/my/webcgi" BUILD_VARIANT="" compile \ || ( printf "\\033[33m%s\\033[m\n" " \ ERROR: package/my/webcgi failed to build." >&8; exit 1;) # aliases package/webcgi/compile: package/my/webcgi/compile |
可以看到有alias的支持,所以编译package/webcgi/compile,等价于:package/my/webcgi/compile。
一个Makefile里面是可以定义多个包的。比如修改package/my/webcgi/Makefile如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | PKG_NAME:=webcgi2 PKG_VERSION:=1.0.0 PKG_RELEASE:=1 include $(INCLUDE_DIR)/package.mk define Package/webcgi3 CATEGORY:= My package TITLE:=webcgi3 DEPENDS := +libnl VARIANT:=3 endef define Package/webcgi4 CATEGORY:= My package TITLE:=webcgi4 DEPENDS := +libubus VARIANT:=4 endef define Build/Prepare mkdir -p $(PKG_BUILD_DIR)/{lib,cgi} endef define Build/Compile touch $(PKG_BUILD_DIR)/webcgi endef define Package/webcgi3/install $(INSTALL_DIR) $(1)/web/cgi-bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/webcgi $(1)/web/cgi-bin endef define Package/webcgi4/install $(INSTALL_DIR) $(1)/web/cgi-bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/webcgi $(1)/web/cgi-bin endef $(eval $(call BuildPackage,webcgi3)) $(eval $(call BuildPackage,webcgi4)) |
可以看到Prepare和Compile是共用的,package定义和install是独立的。定义里面多了一个VARIANT变量来区分。
解析的包属性如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | $ cat tmp/info/.packageinfo-my_webcgi Source-Makefile: package/my/webcgi/Makefile Package: webcgi3 Version: 1.0.0-1 Depends: +libc +USE_GLIBC:librt +USE_GLIBC:libpthread +libnl Conflicts: Menu-Depends: Provides: Build-Variant: 3 Section: opt Category: My package Repository: base Title: webcgi3 Maintainer: Source: Type: ipkg Description: webcgi3 @@ Package: webcgi4 Version: 1.0.0-1 Depends: +libc +USE_GLIBC:librt +USE_GLIBC:libpthread +libubus Conflicts: Menu-Depends: Provides: Build-Variant: 4 Section: opt Category: My package Repository: base Title: webcgi4 Maintainer: Source: Type: ipkg Description: webcgi4 @@ |
可以看到PKG_NAME定义的webcgi2,并没有出现解析结果中,实际上编译的时候的包名是Makefile所在目录的名称,PKG_NAME只是用来生成默认的PKG_BUILD_DIR等变量。但是通常PKG_NAME和Makefile所在目录名称相同。
生成的配置信息包含如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | menu "My package" config PACKAGE_webcgi3 tristate "webcgi3.......................................................... webcgi3" default y if DEFAULT_webcgi3 default m if ALL select PACKAGE_libpthread if USE_GLIBC select PACKAGE_librt if USE_GLIBC select PACKAGE_libnl select PACKAGE_libc help webcgi3 config PACKAGE_webcgi4 tristate "webcgi4.......................................................... webcgi4" default y if DEFAULT_webcgi4 default m if ALL select PACKAGE_librt if USE_GLIBC select PACKAGE_libc select PACKAGE_libpthread if USE_GLIBC select PACKAGE_libubus help webcgi4 endmenu |
可以看到,包括了两个包,是可以独立选择的。
生成的tmp/.packagedeps包含如下:
1 2 3 4 5 6 7 8 9 10 11 | package-$(CONFIG_PACKAGE_webcgi3) += my/webcgi $(curdir)/my/webcgi/variants += $(if $(CONFIG_PACKAGE_webcgi3),3) package-$(CONFIG_PACKAGE_webcgi4) += my/webcgi $(curdir)/my/webcgi/variants += $(if $(CONFIG_PACKAGE_webcgi4),4) $(curdir)/my/webcgi/default-variant := 3 $(curdir)/my/webcgi/compile += $(curdir)/libs/libnl/compile \ $(curdir)/libs/toolchain/compile $(curdir)/system/ubus/compile \ $(if $(CONFIG_USE_GLIBC),$(curdir)/libs/toolchain/compile) |
可以看到,webcgi3/4选中的都是my/webcgi,实际上是同一个目标。但是会更新variants变量。
可以看到依赖是多个VARIANT的并集。选中两个包后,再看package/Makefile生成的编译信息:
1 2 3 4 5 6 7 8 9 10 11 | package/my/webcgi/compile: package/libs/libnl/compile package/libs/toolchain/compile \ package/system/ubus/compile @+ /work/openwrt/scripts/time.pl "time: package/my/webcgi/3/compile" $(SUBMAKE) -r \ -C package/my/webcgi BUILD_SUBDIR="package/my/webcgi" BUILD_VARIANT="3" compile @+ /work/openwrt/scripts/time.pl "time: package/my/webcgi/4/compile" $(SUBMAKE) -r \ -C package/my/webcgi BUILD_SUBDIR="package/my/webcgi" BUILD_VARIANT="4" compile # aliases package/webcgi/compile: package/my/webcgi/compile |
可以看到,实际上编译了两次,BUILD_VARIANT不同而已。通常不同的VARIANT,其PKG_BUILD_DIR不同,如果相同,编译一次后,编译另外一个VARIANT,OPENWRT检测到没有变化,就不会重新编译。就没有意义了。
从上面生成的信息可以看到,编译,实际上是进入到package/my/webcgi里面,执行compile。prepare、configure、compile比较简单,这里重点强调下安装。
首先,必须定义install,否则不会编译,并告警:
$(warning WARNING: skipping webcgi4 -- package has no install section)
第一步:
编译产物安装的stamp文件是:$(PKG_BUILD_DIR)/.pkgdir/webcgi4.installed
安装目录是:$(PKG_BUILD_DIR)/.pkgdir/webcgi4/
第二步:
然后staging里面有个root目录:/work/openwrt/staging_dir/target-mips_4kec_musl/root-realtek/
stamp文件:stamp/.webcgi4_installed
将第一步安装的文件安装到这个目录。
第三步:
安装ipkg,检查依赖等。
PDIR_webcgi4:=/work/openwrt/bin/packages/mips_4kec/base
IPKG_webcgi4:=$(PDIR_webcgi4)/webcgi4$(ABIV_webcgi4)_1.0.0-1_mips_4kec.ipk
IDIR_webcgi4:=$(PKG_BUILD_DIR)/ipkg-mips_4kec/webcgi4
.compile: $(IPKG_webcgi4) \
/work/openwrt/staging_dir/target-ips_4kec_musl/pkginfo/webcgi4.provides
$(IPKG_webcgi4) 和 provides执行的规则相同:
1 把文件安装到$(IDIR_webcgi4),然后生成provides。
2 生成provides
3 检查依赖,生成missing
4 执行strip
5 生成在$(IDIR_webcgi4)/CONTROL目录下,生成包信息
6 生成IPK文件
参考
https://openwrt.org/docs/guide-developer/packages
https://openwrt.org/docs/guide-developer/build-system/use-patches-with-buildsystem