添加自定义的package

https://blog.csdn.net/teddy99999/article/details/17537545

 

OpenWrt是一个比较完善的嵌入式Linux开发平台,在无线路由器应用上已有100多个软件包。人们可以在其基础上增加软件包,以扩大其应用范围。OpenWrt在增加软件方面使用极其方便,按照OpenWrt的约定就可以很简单完成。
        加入的软件包可以是网上可下载的开源软件或自行开发的软件。為加入软件包需要在package目錄下创建一个目录,以包含软件包的各种信息和与OpenWrt建立联系的文件。然后创建一个Makefile与OpenWrt建立联系,Makefile需要遵循OpenWrt的约定。另外可以創建一個patchs目錄保存patch文件,對下載的源代碼進行適量修改。下面主要介紹Makefile的基本約定。
1、引入文件
OpenWrt使用三个makefile的子文件,分别为:
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk
include $(INCLUDE_DIR)/package.mk
        由這些makefile子文件確立軟件包加入OpenWrt的方式和方法。$(TOPDIR)/rules.mk一般在Makefile的開頭,$(INCLUDE_DIR)/kernel.mk文件對於軟件包為內核時不可缺少,$(INCLUDE_DIR)/package.mk一般在軟件包的基本信息完成後再引入。
2、编写软件包的基本信息,这些软件包的信息均以PKG_开头,其意思和作用如下:
PKG_NAME表示软件包名称,将在menuconfig和ipkg可以看到。
PKG_VERSION表示软件版本号。
PKG_RELEASE表示Makefile的版本号
PKG_SOURCE表示源代码的文件名。
PKG_SOURCE_URL表示源代码的下载网站位置。@SF表示在sourceforge网站,@GNU表示在GNU网站,還有@GNOME、@KERNEL。獲取方式可以為:git、svn、cvs、hg、bzr等。有關下載方法可參考$(INCLUDE_DIR)/download.mk和$(SCRIPT_DIR)/download.pl。
PKG_MD5SUM表示源代码文件的效验码。用于核对软件包是否正确下载。
PKG_CAT表示源代码文件的解压方法。包括zcat, bzcat, unzip等。
PKG_BUILD_DIR表示软件包编译目录。它的父目录为$(BUILD_DIR)。如果不指定,默认为$(BUILD_DIR)/$( PKG_NAME)$( PKG_VERSION)。
還有一些有關源代碼的定義。
PKG_SOURCE_SUBDIR
PKG_SOURCE_PROTO
PKG_SOURCE_MIRROR
PKG_MIRROR_MD5SUM
PKG_SOURCE_VERSION

3、编译包定义
用户程序和内核模块的定义不一样。用戶態軟件包使用Package,內核模塊使用KernelPackage。
3.1用户程序编译包定义
用户程序的编译包以Package/开头,然后接着软件名,在Package定义中的软件名可以与软件包名不一样,而且可以多个定义。下面使用$(PKG_NAME)只是做一个标示,并非真正使用$(PKG_NAME)。

Package/$(PKG_NAME)
SECTION表示包的类型,预留。
CATEGORY表示分类,在menuconfig的菜单下将可以找到。
TITLE用于软件包的简短描述
DESCRIPTION用于软件包的详细描述,已放弃使用。如果使用DESCRIPTION將會提示“error DESCRIPTION:= is obsolete, use Package/PKG_NAME/description”。
URL表示软件包的下载位置。
MAINTAINER表示维护者,选项。
DEPENDS表示与其他软件的依赖。即如编译或安装需要其他软件时需要说明。如果存在多個依賴,則每個依賴需用空格分開。依賴前使用+號表示默認顯示,即對象沒有選中時也會顯示,使用@則默認為不顯示,即當依賴對象選中後才顯示。
在用戶態的軟件包中沒有內核模塊的AUTOLOAD參數。如果軟件需要在boot時自動運行,則需要在/etc/init.d增加相應的腳本文件。腳本文件需要START參數,說明在boot時的優先級,如果在boot過程啟動後在關閉,則需要進一步設置STOP參數。如果STOP參數存在,其值必須大於START。腳本文件需要start()和stop()兩個函數,start()是執行程序,stop()是關閉程序。關閉程序一般需要執行killall命令。由/etc/rc.d/S10boot知道,裝載內核模塊的優先級為10,需要使用自己設計的內核模塊的程序其START的值必須大於10. 同樣由/etc/rc.d/S40network知道,使用網絡通信的程序其START的值必須大於40。

Package/$(PKG_NAME)/conffiles
本包安裝的配置文件,一行一個。如果文件結尾使用/,則表示為目錄。用於備份配置文件說明,在sysupgrade命令執行時將會用到。

Package/$(PKG_NAME)/description
软件包的详细描述,取代前面提到的DESCRIPTION详细描述。

Build/Prepare
编译准备方法,对于网上下载的软件包不需要再描述。对于非网上下载或自行开发的软件包必须说明编译准备方法。一般的准备方法为:
define 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
自行开发的软件包可以考虑使用下面的定义。
define Build/Compile
        $(MAKE) -C $(PKG_BUILD_DIR) \
                $(TARGET_CONFIGURE_OPTS) CFLAGS=”$(TARGET_CFLAGS) -I$(LINUX_DIR)/include”
Endef

Package/$(PKG_NAME)/install
软件包的安装方法,包括一系列拷贝编译好的文件到指定位置。調用時會帶一個參數,就是嵌入系統的鏡像文件系統目錄,因此$(1)表示嵌入系统的镜像目录。一般可以采用下面的方法:
define 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必须引入$(TOPDIR)/rules.mk文件。
INSTALL_DIR :=install -d -m0755 意思創建所屬用戶可讀寫即執行,其他用戶可讀可執行的目錄。
INSTALL_BIN:=install -m0755意思編譯好的文件到鏡像文件目錄。
如果用戶態軟件在boot時要自動運行,則需要在安裝方法說明中增加自動運行的腳本文件安裝和配置文件安裝方法。
例如:
define 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/$(PKG_NAME)/preinst
软件包安装前处理方法,使用脚本语言,因此定义的第一行需要下面的格式
#!/bin/sh
調用時帶入的參數為嵌入式系統的鏡像目錄。
Package/$(PKG_NAME)/postinst
软件包安装后处理方法,使用脚本语言。
Package/$(PKG_NAME)/prerm
软件包删除前处理方法,使用脚本语言
Package/$(PKG_NAME)/postrm
软件包删除后处理方法,使用脚本语言
3.2内核模块包定义
Linux分为内核态和用户态。开发者开发的内核部分可以直接加入Linux的Kernel程序,也可以生成内核模块以便需要时装入内核。OpenWrt一般希望开发者生成内核模块,在Linux启动后自动装载或手工使用insmod命令装载。内核模块使用KernelPackage开头,其他与一般软件包基本相同。
在内核模块定义中增加
SUBMENU表示子菜单位置,在$(INCLUDE)/kernel.mk对内核模块定义了CATEGORY为kernel modules,所以内核模块在menuconfig中的主菜单为kernel modules,然后有下一级子菜单$(SUBMENU)。在子菜单下可以看到以kmod-$( PKG_NAME)项目。
DEFAULT表示直接编入内核或产生内核模块,y表示直接编入内核,m表示产生内核模块。
AUTOLOAD表示自动装入内核,一般表示方法为:

AUTOLOAD:=$(call AutoLoad, $(PRIORITY),$(AUTOLOAD_MODS))

AutoLoad的第一个参数$(PRIORITY)为优先级,01为最优先,99为最后装载。有关自动装载可以在/etc/modules.d目录下看到,第二个参数$(AUTOLOAD_MODS)模块名,每个模块名以空格符分隔。即可同时装载多个内核模块。
在开发过程最好不要使用自动装载,經過嚴格調試後再使用,可以減輕調試的工作量。
 
4、使用定义
完成前面定义后,必须使用eval函数实现各种定义。其格式为:
对于一般软件包
$(eval $(call Package,$(PKG_NAME)))
或对于内核模块
$(eval $(call KernelPackage,$(PKG_NAME)))
       如果一個軟件包有多個程序,例如:一個應用程序有自己的內核模塊,上面使用的PKG_NAME需要靈活變通。eval函數可能設計多個。也可以當成多個軟件包處理。

 

要把自己的程序加入到openwrt中有两个方法,1)固件是自己编译的,那可以在package目录下下面添加自定义的包
2)固件不是自己编译的话,那可以用openwrt的编译工具链将自己的程序编译成可运行在openwrt上面的可执行程序。

 

一、添加自定义的package
下面通过我自己做的一个实例来说明。我的程序主要是C语言程序。
1)目录结构图如下图所示
http_upgrade/
├── config
│   └── http_url
├── init.d
│   └── get_route_data
├── Makefile
├── rc.d
│   └── S110http_upgrade
└── src
    ├── client.c
    ├── client.h
    ├── debug.c
    ├── debug.h
    ├── http_upgrade.c
    ├── Makefile
    ├── safe.c
    ├── safe.h
    ├── system_status.c
    └── system_status.h

4 directories, 14 files

(可选)config目录主要是放置程序的配置文件
(可选)init.d目录主要是放置自定义的脚本,可以运行程序这些
(可选)rc.d目录主要是放置开机运行程序,我这里是需要将自定义的程序开机启动
(可选)src目录主要是放置源码以及编译源码的makefile文件
(必选)Makefile 这里最关键的就是makefile文件了

2)package下面的makefile详解(我这里写的比较简单,可以参照网上详解和openwrt的源码)

#
# Copyright (C) 2012 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#

include $(TOPDIR)/rules.mk

PKG_NAME:=http_upgrade  ——-包的名字,在make menuconfig中看到的
PKG_RELEASE:=1

PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)

include $(INCLUDE_DIR)/package.mk

define Package/http_upgrade    —————包的目录
  SECTION:=utils
  CATEGORY:=Utilities —————————包放到哪个目录下,这里放到Utilities 下
  TITLE:=ZK contral x86 remote upgrade firmware  ——包的描述
  DEPENDS:=+libpthread +jansson +libcurl   ————–包需要的依赖库
endef

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

define Build/Configure
endef

define Build/Compile
        $(MAKE) -C $(PKG_BUILD_DIR) \
                CC=”$(TARGET_CC)” \
                CFLAGS=”$(TARGET_CFLAGS) -Wall” \
                LDFLAGS=”$(TARGET_LDFLAGS)”
endef

define Package/http_upgrade/install  ————–安装过程
        $(INSTALL_DIR) $(1)/etc/init.d   ————–安装目录
        $(INSTALL_BIN) ./init.d/* $(1)/etc/init.d —–将包init.d目录下的文件安装到openwrt下的init.d目录下

        $(INSTALL_DIR) $(1)/usr/sbin
        $(INSTALL_BIN) $(PKG_BUILD_DIR)/http_upgrade $(1)/usr/sbin/  ——-将http_upgrade文件安装到openwrt下的/usr/sbin/目录下

        $(INSTALL_DIR) $(1)/etc/config
        $(INSTALL_DATA) ./config/* $(1)/etc/config   ————————–将包下config目录下面的文件安装到openwrt的/etc/config/目录下

        $(INSTALL_DIR) $(1)/etc/rc.d
        $(INSTALL_BIN) ./rc.d/* $(1)/etc/rc.d   ———————————-将包下rc.d目录下面的文件安装到openwrt的/etc/rc.d目录下
endef

$(eval $(call BuildPackage,http_upgrade))

2)src目录下的makefile(这个就是c语言的makefile)

all: http_upgrade

http_upgrade:
        $(CC) $(CFLAGS) -o $@ debug.c safe.c system_status.c client.c http_upgrade.c $(LDFLAGS) -lpthread -ljansson -lcurl

clean:
        rm -f http_upgrade

将上面的包添加到openwrt编译目录的package目录下面以后,
make menuconfig 就可以看到自定义的包,将它选上,就可以编译出自定义的ipk了

二、使用openwrt的编译工具链生成可执行文件(这个比较麻烦,需要有automake的基础)

这个automake网上教程很多,可以自行百度,我这里要讲的就是怎么用openwrt的工具链来编译

首先在项目目录下新建一个.sh脚本

将automake的步骤都写在脚本中并在脚本中指定编译工具链

#!/bin/sh

rm -rf /tmp/test

#指定编译工具链
export STAGING_DIR=/home/zyw/work/chaos_calmer/staging_dir
export PATH=$STAGING_DIR/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin:$PATH
export TOOLCHAIN_DIR=$STAGING_DIR/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2
export LDCFLAGS=$TOOLCHAIN_DIR/lib/
export LD_LIBRARY_PATH=$TOOLCHAIN_DIR/lib/

STAGING_DIR_TMP=${STAGING_DIR}/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2
CLFS_TARGET=mipsel-openwrt-linux
export CC=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-gcc
export CXX=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-c++
export AR=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-ar
export AS=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-as
export LD=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-ld
export NM=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-nm
export OBJDUMP=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-objdump
export RANLIB=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-ranlib
export STRIP=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-strip
export CC_FOR_TARGET=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-gcc
export CXX_FOR_TARGET=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-c++
export AR_FOR_TARGET=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-ar
export AS_FOR_TARGET=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-as
export LD_FOR_TARGET=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-ld
export NM_FOR_TARGET=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-nm
export OBJDUMP_FOR_TARGET=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-objdump
export RANLIB_FOR_TARGET=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-ranlib
export STRIP_FOR_TARGET=${STAGING_DIR_TMP}/bin/${CLFS_TARGET}-strip

#automake
cd /home/zyw/work/http_client
make clean
./autogen.sh
[ $? -ne 0 ] && echo “autogen失败” && exit 1
./configure –host=mipsel-openwrt-linux –prefix=/usr –sysconfdir=/etc/config
make
make DESTDIR=/tmp/test install

通过执行上面的脚本就可以通过openwrt的编译工具链生成可执行文件,拷贝到openwrt路由器上就可以运行了。

********如果编译的时候遇到依赖库不存在,这个时候就需要手动复制到指定目录下

例子:编译的时候提示curl库不存在,解决办法
根据上面指定的工具链是mips还是i386

cd /work/chaos_calmer/build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/curl-7.40.0/ipkg-install/usr 目录下
1)将上面usr下的include目录下的所有文件拷贝到指定目录
cd include
cp -R * /home/zyw/work/chaos_calmer/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/include/
cp -R * /home/zyw/chaos_calmer/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/usr/include/

2)将上面usr下的lib目录下的所有文件拷贝到指定目录
cd lib
cp -R * /home/zyw/chaos_calmer/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/usr/lib
cp -R * /home/zyw/barrier_breaker/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/lib

******如果执行的时候提示lib*不存在,解决办法是将对应lib的ipk安装到openwrt路由器上面,如果安装不上,就只能手动复制到/usr/lib目录下。

 

============= End

 

原文地址:http://www.cnblogs.com/lsgxeva/p/16864358.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性