添加自定义的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/
AUTOLOAD:=$(call AutoLoad, $(PRIORITY),$(AUTOLOAD_MODS))
要把自己的程序加入到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