OpenWrt添加软件包之一概述

参考 openwrt 官方文档

下面用<BUILDROOT>表示 Openwrt 源码树顶层目录。Openwrt 所有的软件包都都保存在<BUILDROOT>/package目录下,一个软件包占一个子目录。

软件包目录结构

例如: helloworld,如下所示
<BUILDROOT>/package/helloworld/Makefile重点,它定义了如何构建一个
Openwrt 软件包,包括从哪里下载源码,怎样编译和安装。
<BUILDROOT>/package/helloworld/files/可选,一般存放配置文件和启动脚本。
<BUILDROOT>/package/helloworld/patches/可选,一般存放 bug 修复或者程序优化的补丁。
两种软件包目录格式:
1、没有源码的 Openwrt 软件包目录下,构建 Openwrt 软件包的第一步是从指定的 URL 下载指定的源码包,
这个 URL 在 Makefile 中定义,如下所示:
PKG_SOURCE:=helloworld.tar.gz
PKG_SOURCE_URL:=http://www.example.com/
PKG_MD5SUM:=e06c222e186f7cc013fd272d023710cb 用于验证下载的软件包的完整性。
下载的helloworld.tar.gz 一般存放在<BUILDROOT>/dl/目录,后
解压到<BUILDROOT>/build_dir/target-xxx/$(PKG_BUILD_DIR)

2、自己写的代码构建 Openwrt 软件包的方式是在<BUILDROOT>/package/helloworld/目录下创
建一个子目录 src,用来保存自己写的源码文件,如下所示:
<BUILDROOT>/helloworld/src/
<BUILDROOT>/helloworld/src/helloworld.c
<BUILDROOT>/helloworld/src/Makefile
这种方式没有任何源码包需要从 Web 下载,这里的<BUILDROOT>/helloworld/src/Makefile 和通常的 GNU Makefile语法一样

Makefile

每个包都包含一个Makefile,内容也大致相同,首先导入几个文件进来,它们定义了一些变量、规则、函数
include $(TOPDIR)/rules.mk
PKG_*自定义软件包的一些信息
include $(INCLUDE_DIR)/package.mk对PKG_*没有定义到的基本信息补充,以及其他mk文件的导入。最重要的是定义BuildPackage宏在 Makefile 的最后一行被引用。
include $(INCLUDE_DIR)/kernel.mk 定义内核模块时才需要
include $(INCLUDE_DIR)/cmake.mk 使用 cmake 构建软件时才需要

Makefile详解
PKG_*

PKG_*定义了软件包相关的一些基本信息,如下所示:
PKG_NAME -包的名称。
PKG_VERSION -下载的或者自己写的软件包的版本号(必须)
PKG_RELEASE -当前的编译版本,可能根据不同需求,编译方式不同。
PKG_BUILD_DIR - 在 哪个目录下编译该软件包, 默 认 为 $(BUILD_DIR) /$( PKG_NAME)-$(PKG_VERSION)
PKG_SOURCE -要从网上下载的的源码包的文件名
PKG_SOURCE_URL -从哪里下载源码包
PKG_MD5SUM-用于验证下载的源码包的完整性
PKG_CAT -怎样解压源码包 (zcat, bzcat,unzip等)
PKG_BUILD_DEPENDS -定义需要在该软件包之前编译的软件包或者一些版本的依赖。和下面的DEPENDS 语法相同。

define Package/xxx

描述软件包在 menuconfig 和 ipkg 中的条目(其中的 xxx要S与PKG_NAME一致, 即出现在 menuconfig 中的标签以及.config 中的CONFIG_PACKAGE_xxx=y)如下图:

左边PKG_NAME包名字,右边是如下说的TITLE描述内容
在这里插入图片描述

CONFIG_PACKAGE_xxx=y
SECTION - 软件包的类型如(net、utilities等)
CATEGORY - 该软件包出现在 menuconfig 中的哪个菜单下,如果是第一次使用,则 menuconfig 中会新创建一个菜单,如图:
在这里插入图片描述
TITLE- 对该软件包的一个简短描述,如第一张图右半部分。
URL - 在哪里可以找到该软件包的源码包
MAINTAINER -定义该软件包的维护者的联系方式
DEPENDS - 定义需要在该软件包之前编译/安装的软件包,或者其他一些依赖条件,比如版本依赖等,多个依赖之间使用空格分隔,下面列出其具体语法:

  • DEPENDS:=+foo 当前软件包和 foo 都会出现在 menuconfig 中,当前软件包被选中时,其依赖的软件
    包 foo 也被自动选中;如果依赖额软件包 foo 先前没有选中而当前软件包取消选中时,其依赖分软
    件包 foo 也会被取消选中。
  • DEPENDS:=foo 只有当其依赖的软件包 foo 被选中时,当前软件包才会出现在 menuconfig 中。
  • DEPENDS:=@FOO 软件包依赖符号 CONFIG_FOO,只有当符号 CONFIG_FOO 被设置时,该软件包才会
    出现在 menuconfig 中。通常用于依赖于某个特定的 Linux 版本或目标(比如 CONFIG_LINUX_3_10、
    CONFIG_TARGET_ramips)。
  • DEPENDS:=+FOO:bar 当前软件包和软件包 bar 都会出现在 menuconfig 中。如果符号 CONFIG_FOO 被
    设置,则当前软件包依赖于软件包 bar,否则不依赖
  • DEPENDS:=@FOO:bar如果符号 CONFIG_FOO 被设置,则当前软件包依赖于软件包 bar,否则不依赖,
    并且只有其依赖包 bar 被选中时,当前软件包才会出现在 menuconfig 中
define KernelPackage/xxx

描述内核模块在 menuconfig 和 ipk 中的条目(在 menuconfig 中看到的标签为 kmod-xxx)
SUBMENU – 该模块出现在 menuconfig 中的 Kernel modules 菜单下的哪个子菜单。
TITLE – 对该模块的一个简短描述
FILES – 模块名称(全路径),多个模块文件之间用空格分开
AUTOLOAD – 自动加载,例如:AUTOLOAD:=$(call AutoLoad,40,timesync can)表示自动加载 timesync.ko
和 can.ko,其加载的优先级为 40

define Build/Prepare

定义一组指令,比如用于给源码打补丁,创建编译目录,拷贝自己的源码到编译目录。对于从网上下载源
码包一般不需要定义,对于从自己写的代码构建软件包,一般按如下方式定义:

define Build/Prepare
         mkdir -p $(PKG_BUILD_DIR)
         $(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Configure

对于需要通过执行./ configure 的软件包可以在这里自定义。可参考 package/libs/openssl/Makefile

define Build/Compile

如何编译源码,一般不用定义。可参考 package/libs/openssl/Makefile。但对于内核模块需要这样定义

define Build/Compile
	$(MAKE) -C "$(LINUX_DIR)" \
		ARCH="$(LINUX_KARCH)" \
		CROSS_COMPILE="$(TARGET_CROSS)" \
		SUBDIRS="$(PKG_BUILD_DIR)" \
		EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
		$(EXTRA_KCONFIG) \
	modules
endef
define Package/xxx/install

如何安装软件包。定义了一组命令,用来在嵌入式文件系统中创建目录或者拷贝相关文件到嵌入式文件系统或者 ipk。例如:

define Package/helloworld/install
	echo "Here is Package/install"
	$(INSTALL_DIR) $(1)/bin
	$(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/bin/
endef

这里的$(1)表示嵌入式根文件系统 rootfs 的根目录
$(INSTALL_DIR) $(1)/bin表示在嵌入式根文件系统中创建目录 bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/bin/表示将可执行程序$(PKG_BUILD_DIR)/helloworld 拷贝到嵌入式根文件系统的 bin 目录下
INSTALL_XXX<BUILDROOT>/rules.mk中定义
在这里插入图片描述
INSTALL_DIR 用来安装目录,安装的目录权限为所属用户可读/写/执行,其他用户可读/执行。
INSTALL_DATA 用来安装数据文件,其权限为所属用户可读/写,其他用户可读
INSTALL_CONF 用来安装配置文件,其权限为所属用户可读/写,其他用户不能读/写/执行。

Package/xxx/preinst

定义一段需要在软件包安装前执行的脚本。例如

define Package/helloworld/preinst
	#!/bin/sh
	echo 'before install $(PKG_NAME)'
endef

Package/xxx/postinst 定义一段需要在软件包安装后执行的脚本
Package/xxx/prerm 定义一段需要在软件包删除前执行的脚本
Package/xxx/postrm 定义一段需要在软件包删除后执行的脚本
注意:这些脚本必须可以同时在嵌入式设备和主机上都能执行

最后需要调用$(eval $(call BuildPackage,xxx))或者$(eval $(call KernelPackage,xxx))

前者用于应用程序,后者用于内核模块,如果有多个软件包需要针对每个软件包调用。
helloworld实例
hellokernel实例

发布了73 篇原创文章 · 获赞 39 · 访问量 6811

猜你喜欢

转载自blog.csdn.net/hzlarm/article/details/102970236