OpenWrt是一个比较完善的嵌入式Linux开发平台,人们可以在其基础上增加软件包,以扩大其应用范围。OpenWrt在增加软件方面使用极其方便,按照OpenWrt的约定就可以很简单完成。
加入的软件包可以是网上可下载的开源软件或自行开发的软件。为加入软件包需要在package目录下创建一个目录,以包含软件包的各种信息和与OpenWrt建立联系的文件。然后创建一个Makefile与OpenWrt建立联系,Makefile需要遵循OpenWrt的约定。另外可以创建一個patchs目录保存patch文件,对下载的源代码进行适量修改。下面主要介紹Makefile的基本约定。
引入文件
OpenWrt使用三个makefile的子文件,分别为:
include(TOPDIR)/rules.mk
include(INCLUDE_DIR)/.kernel.mk
include(INCLUDE_DIR)/package.mk
由这些makefile子文件确立软件包加入Openwrt的方法和方式。
include(TOPDIR)/rules.mk一般在Makefile的开头
include(INCLUDE_DIR)/kernel.mk文件对于软件包为内核时不可缺少
include(INCLUDE_DIR)/package.mk一般在软件包的基本信息完成后引入
编写软件包的基本信息,这些软件包的开头均以PKG_开头,其意义和作用如下:
-PKG_NAME -软件包的名字, 在 menuconfig 和 ipkg 显示
-PKG_VERSION -软件包的版本,主干分支的版本正是我们要下载的
-PKG_RELEASE -这个 makefile 的版本
-PKG_BUILD_DIR -编译软件包的目录
-PKG_SOURCE -要下载的软件包的名字,一般是由 PKG_NAME 和 PKG_VERSION 组成
-PKG_SOURCE_URL -下载这个软件包的链接,@SF表示在sourceforge网站,@GNU表示在GNU网站
-PKG_MD5SUM -软件包的 MD5 值
-PKG_CAT -解压软件包的方法 (zcat, bzcat, unzip)
-PKG_BUILD_DEPENDS -需要预先构建的软件包,但只是在构建本软件包时,而不是运行的时候。它的语法和下面的DEPENDS一样
编译包定义
用户程序和内核模块的定义不一样。用户态软件包使用Package,內核模块使用KernelPackage。
用户程序的编译包以Package/开头,然后接着软件名,在Package定义中的软件名可以与软件包名不一样,而且可以多个定义。下面使用$(PKG_NAME)只是做一个标示,并非真正使用它。
Package/$(PKG_NAME)
-SECTION - 软件包类型 (尚未使用)
-CATEGORY - menuconfig中软件包所属的一级目录,如Network
-SUBMENU - menuconfig中软件包所属的二级目录,如dial-in/up
-TITLE - 软件包标题
-DESCRIPTION - 软件包的详细说明
-URL - 软件的原始位置,一般是软件作者的主页
-MAINTAINER - (optional) 软件包维护人员
-DEPENDS - (optional) 依赖项,运行本软件依赖的其他包,如果存在多个依赖,则每个依赖需用空格分开。依赖前使用+号表示默认显示,即对象沒有选中时也会显示,使用@则默认为不显示,即当依赖对象选中后才显示。
Package/$(PKG_NAME)/conffiles
本包安装的配置文件,一行一个。如果文件结尾使用/,则表示为目录。用于备份配置文件说明,在sysupgrade命令执行时将会用到。
Package/$(PKG_NAME)/description
软件包的详细描述,取代前面提到的DESCRIPTION详细描述。
Build/Prepare
编译准备方法,对于网上下载的软件包不需要再描述。对于非网上下载或自行开发的软件包必须说明编译准备方法。一般的准备方法为:
1
2
3
4
1
2
3
4define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
按OpenWrt的习惯,一般把自己设计的程序全部放在src目录下。
Build/Configure
在Automake中需要进行./configure,所以本配置方法主要针对需要配置的软件包而设计,一般自行开发的软件包可以不在这里说明。需要使用本定义的情况,可参考dropbear。
Build/Compile
编译方法,没有特别说明的可以不予以定义。如果不定义将使用默认的编译方法Build/Compile/Default
自行开发的软件包可以考虑使用下面的定义。
1
2
3
4
1
2
3
4define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
$(TARGET_CONFIGURE_OPTS) CFLAGS="$(TARGET_CFLAGS) -I$(LINUX_DIR)/include"
Endef
Package/$(PKG_NAME)/install
软件包的安装方法,包括一系列拷贝编译好的文件到指定位置。调用时会带一个参数,就是嵌入系統的镜像文件系統目录,因此$(1)表示嵌入系统的镜像目录。一般可以采用下面的方法:
1
2
3
4
1
2
3
4define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ $(PKG_NAME) $(1)/usr/bin/
endef
INSTALL_DIR、INSTALL_BIN在 $(TOPDIR)/rules.mk文件定义,所以本Makefile必须引入该文件
INSTALL_DIR :=install -d -m0755 意思创建所属用户可读写即执行,其他用户可读可执行的目录。
INSTALL_BIN:=install -m0755意思编译好的文件到镜像文件目录。
如果用户态软件在boot时要自动运行,则需要在安装方法说明中增加自动运行的脚本文件安装和配置文件安装方法
例如:
1
2
3
4
5
6
7
1
2
3
4
5
6
7define Package/mountd/install
$(INSTALL_DIR) $(1)/sbin/ $(1)/etc/config/ $(1)/etc/init.d/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/mountd $(1)/sbin/
$(INSTALL_DATA) ./files/mountd.config $(1)/etc/config/mountd
$(INSTALL_BIN) ./files/mountd.init $(1)/etc/init.d/mountd
endef
安装文件放在files子目录下,不要和源代码文件目录src混在一起,以提高可读性。
使用清晰的文件扩展名,更方便安装识別文件。
Package/preinst
软件安装之前被执行的脚本,别忘了在第一句加上#!/bin/sh。如果脚本执行完毕要取消安装过程,直接让它返回false即可。
Package/postinst
软件安装之后被执行的脚本,别忘了在第一句加上#!/bin/sh。
Package/prerm
软件删除之前被执行的脚本,别忘了在第一句加上#!/bin/sh。如果脚本执行完毕要取消删除过程,直接让它返回false即可。
Package/postrm
软件删除之后被执行的脚本,别忘了在第一句加上#!/bin/sh。
OK,对于软件包的定义已经讲完啦,现在我们来看一个例子:
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
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
38include $(TOPDIR)/rules.mk
PKG_NAME:=bridge
PKG_VERSION:=1.0.6
PKG_RELEASE:=1
PKG_BUILD_DIR:=$(BUILD_DIR)/bridge-utils-$(PKG_VERSION)
PKG_SOURCE:=bridge-utils-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=@SF/bridge
PKG_MD5SUM:=9b7dc52656f5cbec846a7ba3299f73bd
PKG_CAT:=zcat
include $(INCLUDE_DIR)/package.mk
define Package/bridge
SECTION:=base
CATEGORY:=Network
TITLE:=Ethernet bridging configuration utility
#DESCRIPTION:=This variable is obsolete. use the Package/name/description define instead!
URL:=http://bridge.sourceforge.net/
endef
define Package/bridge/description
Ethernet bridging configuration utility
Manage ethernet bridging; a way to connect networks together to
form a larger network.
endef
define Build/Configure
$(call Build/Configure/Default,--with-linux-headers=$(LINUX_DIR))
endef
define Package/bridge/install
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/brctl/brctl $(1)/usr/sbin/
endef
$(eval $(call BuildPackage,bridge))
是不是很容易就看懂了呢?接下来就是创建自己想要的软件包了,下一篇我们会说一下Openwrt创建内核模块软件包的方法。