Создание пакетов
Одной из целей, которые мы хотели достичь с помощью системы шаблонов OpenWrt, было желание сделать процесс портирования программного обеспечения под OpenWrt максимально простым. Если вы посмотрите на обычный каталог пакета в OpenWrt вы найдете две составляющие:
- package/Makefile
- package/patches
Каталог patches не является обязательным и обычно содержит исправления ошибкок или оптимизацию размера исполняемого файла. Makefile пакета является важной составляющей и описывает шаги необходимые чтобы получить исходный код и скомпилировать пакет.
Глядя на Makefile из какого либо пакета, вы вряд ли узнаете в нем обычный Makefile. Это может быть охарактеризовано как вопиющее пренебрежение и жестокое обращение с традиционным форматом make, однако, преобразование Makefile пакета в объектно-ориентированный шаблон позволило упростить весь процесс портирования приложений.
Ниже для примера приведен 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
Как вы можете видеть, необходимо сделать совсем не много. Все скрыто в других make-файлах и вам нужно только определить несколько переменных.
- PKG_NAME -Название пакета, которое будет видно в конфигурационном меню и ipkg
- PKG_VERSION -Версия пакета, которую необходимо загрузить из репозитория проекта
- PKG_RELEASE -Версия данного Makefile
- PKG_BUILD_DIR -Каталог для сборки пакета
- PKG_SOURCE -Названия архива с исходным кодом
- PKG_SOURCE_URL -Адрес, с которого необходимо загрузить архив с исходным кодом
- PKG_MD5SUM -Контрольная сумма архива с исходным кодом
- PKG_CAT -Метод разархивирования исходного кода (zcat, bzcat, unzip)
- PKG_BUILD_DEPENDS -Пакеты, которые необходимо собрать перед сборкой данного пакета (не используются во время работы на устройстве). Использеутся тот же синтаксис что и для DEPENDS (см. ниже).
Переменные PKG_* определяют откуда загружать исходный код; @SF - это ключевое слово для загрузки исходников с sourceforge. Контрольная сумма md5sum используется для проверки корректности загрузки архива, а PKG_BUILD_DIR определяет где находится исходный код после разархивирования полученного архива в $(BUILD_DIR).
В конце файла происходит настоящее волшебство: функция “BuildPackage” настраивает процесс сборки пакета на основании ранее определенных переменных. BuildPackage принимает только один аргумент напрямую - имя пакета, который будет собран, в данном случае “bridge”. Вся остальная информация берется из блоков define. Это способ позволяет обеспечить необходимый уровень читаемости кода, как следствие остается ясным значение переменной DESCRIPTION в Package/bridge, а не теряется как в случае, если бы мы передали эту информацию непосредственно в N-ый аргумент BuildPackage.
Блоки define BuildPackage
Package/
соответствует аргументу передоваемому в buildroot, описание пакета для menuconfig и ipkg. В блоке Package/ вы можете определить следующие переменные:
- SECTION - Тип пакета (в данный момент не используется)
- CATEGORY - В каком пункте menuconfig отображать данный пакет
- TITLE - Краткое описание пакета
- DESCRIPTION - (устарело) Полное описание пакета
- URL - Ссылка на сайт пакета
- MAINTAINER - (опционально) Кто поддерживает пакет
- DEPENDS - (опционально) Какие пакеты должны быть собраны и установлены перед текущим пакетом
Package/conffiles (опционально)
Перечень конфигурационных файлов устанавливаемых данным пакетом, каждый файл на отдельной строке.
Package/description
Полное описание пакета
Build/Prepare (опционально)
Перечень команд необходимых для разархивирования и наложения патчей на исходный код. Можно не определять.
Build/Configure (опционально)
Можно не определять, если не используется configure или есть стандартный конфигурационный скрипт, иначе можно прописать необходимые команды или использовать "$(call Build/Configure/Default,)" чтобы передать дополнительные параметры стандартному конфигурационному скрипту.
Build/Compile (опционально)
Перечень команд необходимых для компиляции исходного кода; в большинстве случаев не нужно определять.
Package/install
Перечень команд необходимых для копирования собранных файлов в ipkg, который представлен как директория $(1).
Package/preinst
Текст скрипта выполняемого перед установкой. Не забудьте написать #!/bin/sh. Если необхомо прервать установку, скрипт должен вернуть false.
Package/postinst
Текст скрипта выполняемого после установки. Не забудьте написать #!/bin/sh.
Package/prerm
Текст скрипта выполняемого перед удалением. Не забудьте написать #!/bin/sh. Если необхомо прервать удаление, скрипт должен вернуть false.
Package/postrm
Текст скрипта выполняемого после удаления. Не забудьте написать #!/bin/sh.
Причина того, что некоторые из блоков define имеют префикс “Package/”, а другие просто “Build” заключается в возможности получения нескольких пакетов из одного Makefile. OpenWrt работает в предположении, что одному исходному коду соответствует один Makefile пакета, но вы можете повторно использовать этот исходный код для нескольких пакетов. Так как вам нужно собрать исходный код один раз, то есть один глобальный набор блоков define “Build”, но вы можете добавить несколько блоков define “Package/”, по одному для каждого вызова BuildPackage - см. пакет dropbear для примера.
ПРИМЕЧАНИЯ
Все переменные в ваших pre/post install/removal скриптах должны начинаться с двух символов ($$) вместо одного символа ($). Это будет информировать “make”, чтобы он не интерпретировал строку как переменную и соответственно не подставлял значение, а просто заменял две $$ на один $ -- Подробнее
После того как вы создали свой Makefile пакета, новый пакет будет автоматически отображаться в меню настройки дистрибутива при следующем запуске “make menuconfig”, и в случае включения будет собран автоматически при следующем запуске “make”.
Переменная DESCRIPTION устарела, используйте Package/PKG_NAME/description.
Добавление конфигурационных опций
Если вы хотите иметь возможность конфигурировать сборку или установку пакета через menuconfig, вы можете сделать следующее: Добавьте MENU:=1 в блок define Package пакета:
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
Создайте блок config в Makefile:
define Package/mjpg-streamer/config source "$(SOURCE)/Config.in" endef
Создайте файл Config.in в том же каталоге, где находлится Makefile, с аналогичным содержанием:
# 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
Выше вы можете видеть примеры конфигурируемых параметров различных типов.
Далее вы можете проверить ваши конфигурируемые параметры в Makefile следующим образом: (Заметьте, что обращение к параметрам выполняется с префисом CONFIG_)
ifeq ($(CONFIG_MJPEG_STREAMER_INPUT_UVC),y) $(CP) $(PKG_BUILD_DIR)/input_uvc.so $(1)/usr/lib endif
Создание пакетов для модулей ядра
Модуль ядра - это дополнительный программный модуль, который расширяет возможности ядра Linux. Модуль ядра загружается после самого ядра, (например, с помощью insmod). Многие модули ядра включены в дистрибутив исходников Linux; обычно сборка ядра может быть сконфигурирована для каждого программного модуля:
- скомпилировать его в ядро, как встроенный,
- скомпилировать его как загружаемый модуль ядра, или
- игнорировать его.
Чтобы включить один из этих программных модулей, как загружаемый модуль, выберите соответствующую опцию ядра в конфигурации OpenWRT (см. Build Configuration). Если ваш любимый модуль ядра не появляется в меню конфигурации OpenWRT, необходимо добавить строку в однин из файлов в каталоге package/kernel/modules. Вот пример взятый из 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))
Вы также можете добавить модули ядра, которые не являются частью дистрибутива исходников Linux. В этом случае модуль ядра появляется в каталоге package/ так же как любой другой пакет. В package/Makefile используются блоки
KernelPackage/xxx
вместо
Package/xxx
. Например, 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))
ПРИМЕЧАНИЯ
Параметры INSTALL_DIR, INSTALL_BIN, INSTALL_DATA используются для создания каталогов, копирования исполняемых и обычных файлов. Атрибут +x выставляется для файла при использовании INSTALL_BIN, вне зависимости от атрибутов файла в сборочной системе.
Из большого документа:
Package/<name>/install:
Набор команд для копирования файлов из сборочного каталога в ipkg, который представлен в виде каталога $(1). Обратите внимание, что в настоящее время существует 4 макроса для установки:
INSTALL_DIR install -d -m0755 INSTALL_BIN install -m0755 INSTALL_DATA install -m0644 INSTALL_CONF install -m0600