Openwrt的SDk使用教程-英原文

本文介绍如何为OpenWrt创建软件包,包括定义包的基本属性、配置编译选项及安装脚本等内容。通过示例展示了如何针对不同类型的软件包进行定制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


原文连接:http://wiki.openwrt.org/doc/devel/packages

Creating packages
One of the things that we've attempted to do with OpenWrt's template system is make it incredibly easy to port software to OpenWrt. If you look at a typical package directory in OpenWrt you'll find two things:


package/Makefile
package/patches
The patches directory is optional and typically contains bug fixes or optimizations to reduce the size of the executable.


The package makefile is the important item because it provides the steps actually needed to download and compile the package.


Looking at one of the package makefiles, you'd hardly recognize it as a makefile. Through what can only be described as blatant disregard and abuse of the traditional make format, the makefile has been transformed into an object oriented template which simplifies the entire ordeal.


Here for example, is package/bridge/Makefile:


include $(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
  DEFAULT:=y
  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))
BuildPackage variables
As you can see, there's not much work to be done; everything is hidden in other makefiles and abstracted to the point where you only need to specify a few variables.


PKG_NAME -The name of the package, as seen via menuconfig and ipkg
PKG_VERSION -The upstream version number that we're downloading
PKG_RELEASE -The version of this package Makefile
PKG_BUILD_DIR -Where to compile the package
PKG_SOURCE -The filename of the original sources
PKG_SOURCE_URL -Where to download the sources from
PKG_MD5SUM -A checksum to validate the download
PKG_CAT -How to decompress the sources (zcat, bzcat, unzip)
PKG_BUILD_DEPENDS -Packages that need to be built before this package, but are not required at runtime. Uses the same syntax as DEPENDS below.
The PKG_* variables define where to download the package from; @SF is a special keyword for downloading packages from sourceforge. The md5sum is used to verify the package was downloaded correctly and PKG_BUILD_DIR defines where to find the package after the sources are uncompressed into $(BUILD_DIR).


At the bottom of the file is where the real magic happens, "BuildPackage" is a macro setup by the earlier include statements. BuildPackage only takes one argument directly – the name of the package to be built, in this case "bridge". All other information is taken from the define blocks. This is a way of providing a level of verbosity, it's inherently clear what the DESCRIPTION variable in Package/bridge is, which wouldn't be the case if we passed this information directly as the Nth argument to BuildPackage.


BuildPackage defines
Package/


  matches the argument passed to buildroot, this describes the package
 the menuconfig and ipkg entries. Within Package/ you can define the
 following variables:
SECTION - The type of package (currently unused)
CATEGORY - Which menu it appears in menuconfig
TITLE - A short description of the package
DESCRIPTION - (deprecated) A long description of the package
URL - Where to find the original software
MAINTAINER - (optional) Who to contact concerning the package
DEPENDS - (optional) Which packages must be built/installed before this package. See below for the syntax.
Package/conffiles (optional)


 A list of config files installed by this package, one file per line.
Package/description


 A free text description of the package
Build/Prepare (optional)


 A set of commands to unpack and patch the sources. You may safely leave this
 undefined.
Build/Configure (optional)


 You can leave this undefined if the source doesn't use configure or has a
 normal config script, otherwise you can put your own commands here or use
 "$(call Build/Configure/Default,)" as above to pass in additional
 arguments for a standard configure script.
Build/Compile (optional)


 How to compile the source; in most cases you should leave this undefined.
Package/install


 A set of commands to copy files out of the compiled source and into the ipkg
 which is represented by the $(1) directory.
Package/preinst


 The actual text of the script which is to be executed before installation. Dont forget
 to include the #!/bin/sh. If you need to abort installation have the script return false.
Package/postinst


 The actual text of the script which is to be executed after installation. Dont forget
 to include the #!/bin/sh. 
Package/prerm


 The actual text of the script which is to be executed before removal. Dont forget
 to include the #!/bin/sh. If you need to abort removal have the script return false.
Package/postrm


 The actual text of the script which is to be executed after removal. Dont forget
 to include the #!/bin/sh. 
The reason that some of the defines are prefixed by "Package/" and others are simply "Build" is because of the possibility of generating multiple packages from a single source. OpenWrt works under the assumption of one source per package makefile, but you can split that source into as many packages as desired. Since you only need to compile the sources once, there's one global set of "Build" defines, but you can add as many "Package/" defines as you want by adding extra calls to BuildPackage – see the dropbear package for an example.


Dependency Types
Various types of dependencies can be specified, which require a bit of explanation for their differences.


+<foo> Package will depend on package <foo> and will select it when selected.
<foo> Package will depend on package <foo> and will be invisible until <foo> is selected.
@FOO Package depends on the config symbol CONFIG_FOO and will be invisible unless CONFIG_FOO is set. This usually used for depending on certain Linux versions or targets, e.g. @TARGET_foo will make a package only available for target foo. You can also use boolean expressions for complex dependencies, e.g. @(!TARGET_foo&&!TARGET_bar) will make the package unavailable for foo and bar.
+FOO:<bar> Package will depend on <bar> if CONFIG_FOO is set, and will select <bar> when it is selected itself. The typical use case would be if there compile time options for this package toggling features that depend on external libraries.  Note that the + replaces the @.
@FOO:<bar> Package will depend on <bar> if CONFIG_FOO is set, and will be invisible until <bar> is selected when CONFIG_FOO is set.
Some typical config symbols for (conditional) dependencies are:


TARGET_<foo> Target <foo> is selected
TARGET_<foo>_<bar> If the target <foo> has subtargets, subtarget <foo> is selected. If not, profile <foo> is selected. This is in addition to TARGET_<foo>
TARGET_<foo>_<bar>_<baz> Target <foo> with subtarget <bar> and profile <baz> is selected.
LINUX_3_X Linux version used is 3.x.*
LINUX_2_6_X Linux version used is 2.6.x.* (:1: only used for backfire and earlier)
LINUX_2_4 Linux version is 2.4 ( only used in backfire and earlier, and only for target brcm-2.4)
USE_UCLIBC, USE_GLIBC, USE_EGLIBC To (not) depend on a certain libc.
BROKEN Package doesn't build or work, and should only be visible if "Show broken targets/packages" is selected. Prevents the package from failing builds by accidentally selecting it.
IPV6 IPv6 support in packages is selected.
NOTES


All variables in your pre/post install/removal scripts should have double ($$) instead of a single ($) string characters. This will inform "make" to not interpret the value as a variable, but rather just ignore the string and replace the double $$ by a single $ – More Info


After you've created your package Makefile, the new package will automatically show in the menu the next time you run "make menuconfig" and if selected will be built automatically the next time "make" is run.


DESCRIPTION is obsolete, use Package/PKG_NAME/description.


Adding configuration options
If you would like configure your package installation/compilation in the menuconfig you can do the following: Add MENU:=1 to your package definition like this:


define Package/mjpg-streamer
  SECTION:=multimedia
  CATEGORY:=Multimedia
  TITLE:=MJPG-streamer
  DEPENDS:=@!LINUX_2_4 +libpthread-stubs +jpeg
  URL:=http://mjpg-streamer.wiki.sourceforge.net/
  MENU:=1
endef
Create a config key in the Makefile:


define Package/mjpg-streamer/config
source "$(SOURCE)/Config.in"
endef
Create a Config.in file directory where the Makefile is located with the content like this:


# Mjpg-streamer configuration
menu "Configuration"
depends on PACKAGE_mjpg-streamer
config MJPEG_STREAMER_AUTOSTART
bool "Autostart enabled"
default n
menu "Input plugins"
depends on PACKAGE_mjpg-streamer
config MJPEG_STREAMER_INPUT_FILE
bool "File input plugin"
help 
You can stream pictures from jpg files on the filesystem
default n

config MJPEG_STREAMER_INPUT_UVC
bool "UVC input plugin"
help
You can stream pictures from an Universal Video Class compatible webcamera
default y

config MJPEG_STREAMER_FPS
depends MJPEG_STREAMER_INPUT_UVC
int "Maximum FPS"
default 15
config MJPEG_STREAMER_PICT_HEIGHT
depends MJPEG_STREAMER_INPUT_UVC
int "Picture height"
default 640
config MJPEG_STREAMER_PICT_WIDTH
depends MJPEG_STREAMER_INPUT_UVC
int "Picture width"
default 480
config MJPEG_STREAMER_DEVICE
depends MJPEG_STREAMER_INPUT_UVC
string "Device"
default /dev/video0


config MJPEG_STREAMER_INPUT_GSPCA
bool "GSPCA input plugin"
help
You can stream pictures from a gspca supported webcamera Note this module is deprecated, use the UVVC plugin instead
default n
endmenu


# ......


endmenu
Above you can see examples for various type config parameters.


And finally you can check your configuration parameters in your Makefile in the following way: (Note that you can reference to the parameters value with it name prefixed with CONFIG_)


ifeq ($(CONFIG_MJPEG_STREAMER_INPUT_UVC),y)
$(CP) $(PKG_BUILD_DIR)/input_uvc.so $(1)/usr/lib
endif
Creating packages for kernel modules
A kernel module is an installable program which extends the behavior of the linux kernel. A kernel module gets loaded after the kernel itself, (e.g. using insmod).


Many kernel programs are included in the linux source distribution; typically the kernel build may be configured to, for each program,


compile it into the kernel as a built-in,
compile it as a loadable kernel module, or
ignore it.
See FIX:Customizingthekerneloptions customizing the kernel options for including it in the kernel.


To include one of these programs as a loadable module, select the corresponding kernel option in the OpenWrt configuration (see Build Configuration). If your favorite kernel module does not appear in the OpenWrt configuration menus, you must add a stanza to one of the files in the package/kernel/modules directory. Here is an example extracted from package/kernel/modules/block.mk:


define KernelPackage/loop
  SUBMENU:=$(BLOCK_MENU)
  TITLE:=Loopback device support
  KCONFIG:= \
        CONFIG_BLK_DEV_LOOP \
        CONFIG_BLK_DEV_CRYPTOLOOP=n
  FILES:=$(LINUX_DIR)/drivers/block/loop.ko
  AUTOLOAD:=$(call AutoLoad,30,loop)
endef


define KernelPackage/loop/description
 Kernel module for loopback device support
endef


$(eval $(call KernelPackage,loop))
You can also add kernel modules which are not part of the linux source distribution. In this case, a kernel module appears in the package/ directory, just as any other package does. The package/Makefile uses


KernelPackage/xxx
definitions in place of
Package/xxx
. For example, here is package/madwifi/Makefile:
#
# Copyright (C) 2006 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
# $Id$


include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk


PKG_NAME:=madwifi
PKG_VERSION:=0.9.2
PKG_RELEASE:=1


PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
PKG_SOURCE_URL:=@SF/$(PKG_NAME)
PKG_MD5SUM:=a75baacbe07085ddc5cb28e1fb43edbb
PKG_CAT:=bzcat


PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)


include $(INCLUDE_DIR)/package.mk


RATE_CONTROL:=sample


ifeq ($(ARCH),mips)
  HAL_TARGET:=mips-be-elf
endif
ifeq ($(ARCH),mipsel)
  HAL_TARGET:=mips-le-elf
endif
ifeq ($(ARCH),i386)
  HAL_TARGET:=i386-elf
endif
ifeq ($(ARCH),armeb)
  HAL_TARGET:=xscale-be-elf
endif
ifeq ($(ARCH),powerpc)
  HAL_TARGET:=powerpc-be-elf
endif


BUS:=PCI
ifneq ($(CONFIG_LINUX_2_4_AR531X),)
  BUS:=AHB
endif
ifneq ($(CONFIG_LINUX_2_6_ARUBA),)
  BUS:=PCI AHB # no suitable HAL for AHB yet.
endif


BUS_MODULES:=
ifeq ($(findstring AHB,$(BUS)),AHB)
  BUS_MODULES+=$(PKG_BUILD_DIR)/ath/ath_ahb.$(LINUX_KMOD_SUFFIX)
endif
ifeq ($(findstring PCI,$(BUS)),PCI)
  BUS_MODULES+=$(PKG_BUILD_DIR)/ath/ath_pci.$(LINUX_KMOD_SUFFIX)
endif


MADWIFI_AUTOLOAD:= \
wlan \
wlan_scan_ap \
wlan_scan_sta \
ath_hal \
ath_rate_$(RATE_CONTROL) \
wlan_acl \
wlan_ccmp \
wlan_tkip \
wlan_wep \
wlan_xauth


ifeq ($(findstring AHB,$(BUS)),AHB)
MADWIFI_AUTOLOAD += ath_ahb
endif
ifeq ($(findstring PCI,$(BUS)),PCI)
MADWIFI_AUTOLOAD += ath_pci
endif


define KernelPackage/madwifi
  SUBMENU:=Wireless Drivers
  DEFAULT:=y if LINUX_2_6_BRCM |  LINUX_2_6_ARUBA |  LINUX_2_4_AR531X |  LINUX_2_6_XSCALE, m if ALL
  TITLE:=Driver for Atheros wireless chipsets
  DESCRIPTION:=\
This package contains a driver for Atheros 802.11a/b/g chipsets.
  URL:=http://madwifi.org/
  VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE)
  FILES:= \
$(PKG_BUILD_DIR)/ath/ath_hal.$(LINUX_KMOD_SUFFIX) \
$(BUS_MODULES) \
$(PKG_BUILD_DIR)/ath_rate/$(RATE_CONTROL)/ath_rate_$(RATE_CONTROL).$(LINUX_KMOD_SUFFIX) \
$(PKG_BUILD_DIR)/net80211/wlan*.$(LINUX_KMOD_SUFFIX)
  AUTOLOAD:=$(call AutoLoad,50,$(MADWIFI_AUTOLOAD))
endef


MADWIFI_MAKEOPTS= -C $(PKG_BUILD_DIR) \
PATH="$(TARGET_PATH)" \
ARCH="$(LINUX_KARCH)" \
CROSS_COMPILE="$(TARGET_CROSS)" \
TARGET="$(HAL_TARGET)" \
TOOLPREFIX="$(KERNEL_CROSS)" \
TOOLPATH="$(KERNEL_CROSS)" \
KERNELPATH="$(LINUX_DIR)" \
LDOPTS=" " \
ATH_RATE="ath_rate/$(RATE_CONTROL)" \
DOMULTI=1


ifeq ($(findstring AHB,$(BUS)),AHB)
  define Build/Compile/ahb
$(MAKE) $(MADWIFI_MAKEOPTS) BUS="AHB" all
  endef
endif


ifeq ($(findstring PCI,$(BUS)),PCI)
  define Build/Compile/pci
$(MAKE) $(MADWIFI_MAKEOPTS) BUS="PCI" all
  endef
endif


define Build/Compile
$(call Build/Compile/ahb)
$(call Build/Compile/pci)
endef


define Build/InstallDev
$(INSTALL_DIR) $(STAGING_DIR)/usr/include/madwifi
$(CP) $(PKG_BUILD_DIR)/include $(STAGING_DIR)/usr/include/madwifi/
$(INSTALL_DIR) $(STAGING_DIR)/usr/include/madwifi/net80211
$(CP) $(PKG_BUILD_DIR)/net80211/*.h $(STAGING_DIR)/usr/include/madwifi/net80211/
endef


define KernelPackage/madwifi/install
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_DIR) $(1)/lib/modules/$(LINUX_VERSION)
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) ./files/madwifi.init $(1)/etc/init.d/madwifi
$(CP) $(PKG_BUILD_DIR)/tools/{madwifi_multi,80211debug,80211stats,athchans,athctrl,athdebug,athkey,athstats,wlanconfig} $(1)/usr/sbin/
endef


$(eval $(call KernelPackage,madwifi))
NOTES


INSTALL_DIR, INSTALL_BIN, INSTALL_DATA are used for creating a directory, copying an executable, or a data file. +x is set on the target file for INSTALL_BIN, independent of it's mode on the host.


From the big document:


Package/<name>/install:


A set of commands to copy files out of the compiled source and into the ipkg which is represented by the $(1) directory. Note that there are currently 4 defined install macros:


INSTALL_DIR 
install -d -m0755
INSTALL_BIN 
install -m0755
INSTALL_DATA 
install -m0644
INSTALL_CONF 
install -m0600
Packaging a service
If you want to install a service, (something that should start/stop at boot time, that has a /etc/init.d/blah script), you should make sure that the init.d script can be run on the host. At image build time, all init.d scripts found are run on the host, looking for the START=20/STOP=99 lines.


This is what installs the symlinks in /etc/rc.d, so they are only created when you rebuild the entire image. If you want the symlinks to be created when a package is installed, such as via opkg, you should add a postinstall script which runs


/etc/init.d/foo enable
if $IPKG_INSTROOT is empty. when $IPKG_INSTROOT is defined, you run within the buildroot, if it is empty you run on the target.
Example makefile snippet to install/remove symlinks.


define Package/mrelay/postinst
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
        echo "Enabling rc.d symlink for mrelay"
        /etc/init.d/mrelay enable
fi
exit 0
endef


define Package/mrelay/prerm
#!/bin/sh
# check if we are on real system
if [ -z "$${IPKG_INSTROOT}" ]; then
        echo "Removing rc.d symlink for mrelay"
        /etc/init.d/mrelay disable
fi
exit 0
endef
Very basic example of a suitable init.d script


#!/bin/sh /etc/rc.common


START=80
APP=mrelay
PID_FILE=/var/run/$APP.pid


start() {
        start-stop-daemon -S -x $APP -p $PID_FILE -m -b
}


stop() {
        start-stop-daemon -K -n $APP -p $PID_FILE -s TERM
        rm -rf $PID_FILE
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值