如何在OpenWrt平台新增一个package

发布时间 2023-11-29 15:36:33作者: 付时凡

如何在OpenWrt平台新增一个package

背景

OpenWrt的编译框架做得非常好,只需要在固定的目录下,放置通用的Makefile,其编译框架即可正常读取该Makefile,并用指定的toolchains开始编译。

自定义的pacakge可以放在SDK根目录下的这个位置openwrt/package

每个package的目录架构都是相似的:

package
├── files
├── Makefile
└── src
    ├── main.c
    └── Makefile

本文所描述的是上层的Makefile。

示例

既可以编译用户进态的模块,也可以编译内核模块。以下为具体示例。

用户态模块

#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#

include $(TOPDIR)/rules.mk

PKG_NAME:=app-monitor
PKG_VERSION:=1.0

include $(INCLUDE_DIR)/package.mk

define Package/app-monitor
  SECTION:=XXXX
  CATEGORY:=XXXX platform apps
  MAINTAINER:=XXXX
  DEPENDS:=
  TITLE:=App module test for XXXX
endef

define Package/app-monitor/Description
	This is a app module test for XXXX
endef

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

define Package/app-monitor/install
	$(INSTALL_DIR) $(1)/etc
	$(INSTALL_DATA) ./filesystem/etc/app-monitor.config $(1)/etc

	$(INSTALL_DIR) $(1)/usr/bin
	$(INSTALL_BIN) $(PKG_BUILD_DIR)/app-monitor $(1)/usr/bin
endef

$(eval $(call BuildPackage,app-monitor))

内核模块

#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#

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

PKG_NAME:=app-monitor
PKG_VERSION:=0.1

define KernelPackage/app-monitor
  SECTION:=XXXX
  CATEGORY:=XXXX platform apps
  MAINTAINER:=XXXX
  DEPENDS:=
  TITLE:=app-monitor
  FILES:=$(PKG_BUILD_DIR)/app_monitor.ko
  AUTOLOAD:=$(call AutoLoad,99,app_monitor)
endef

define KernelPackage/app-monitor/description
	This is a kernel package which used by xxx
endef

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

define Build/Compile
	$(MAKE) -C "$(LINUX_DIR)"		\
		CROSS_COMPILE="$(TARGET_CROSS)" \
		ARCH="$(LINUX_KARCH)"		\
		SUBDIRS="$(PKG_BUILD_DIR)"	\
		EXTRA_CFLAGS="$(EXTRA_CFLAGS)"	\
		modules
endef

define KernelPackage/app-monitor
  SECTION:=XXXX
  CATEGORY:=XXXX platform apps
  MAINTAINER:=XXXX
  DEPENDS:=
  TITLE:=app-monitor
  FILES:=$(PKG_BUILD_DIR)/app_monitor.ko
  AUTOLOAD:=$(call AutoLoad,99,app_monitor)
endef

define KernelPackage/app-monitor/description
	This is a kernel package which used by xxx
endef

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

define Build/Compile
	$(MAKE) -C $(LINUX_DIR) M=$(PKG_BUILD_DIR) $(strip $(MAKE_OPTS))
endef

define Build/InstallDev
	$(INSTALL_DIR) $(1)/usr/include
	$(CP) $(PKG_BUILD_DIR)/app_monitor.h $(1)/usr/include
endef

define KernelPackage/app-monitor/install
	$(INSTALL_DIR) $(1)/etc
endef

$(eval $(call KernelPackage,$(PKG_NAME)))

用户态模块+内核模块

即可以在同一个package中,同时包含两种。

有了上面两个例子,下面的例子更多是拼接,最核心在于后面的BuildPackageKernelPackage

#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#

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

PKG_NAME:=app-monitor
PKG_VERSION:=1.0

include $(INCLUDE_DIR)/package.mk

define KernelPackage/$(PKG_NAME)
  SECTION:=XXXX
  CATEGORY:=XXXX platform apps
  MAINTAINER:=XXXX
  DEPENDS:=
  TITLE:=app monitor kernel module for you
  FILES:=$(PKG_BUILD_DIR)/ipt/app-monitor.ko
  AUTOLOAD:=$(call AutoLoad,99,app-monitor)
endef

TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include
TARGET_LDFLAGS += -L$(STAGING_DIR)/usr/lib
TARGET_LDFLAGS += -L$(STAGING_DIR)/lib

PKG_DEPENDS:=+libc

APP_MONITOR_MAKE_OPTS:=

ifeq ($(CONFIG_XXXX), y)
EXTRA_CFLAGS += -I$(LINUX_DIR)/../bcmkernel/include
EXTRA_CFLAGS += -DCONFIG_XXXX=1
endif

TARGET_LDFLAGS += -L$(STAGING_DIR)/usr/lib 

APP_DPI_MAKE_OPTS+= \
        CROSS_COMPILE=$(KERNEL_CROSS) \
        ARCH=$(LINUX_KARCH) \
		KERNELPATH="$(LINUX_SRC_DIR)" \
        KBUILDPATH=$(LINUX_DIR) \
        EXTRA_CFLAGS="$(EXTRA_CFLAGS)"	\
        SUBDIRS=$(PKG_BUILD_DIR)

define Package/$(PKG_NAME)
  SECTION:=XXXX
  CATEGORY:=XXXX platform apps
  TITLE:=app-monitor application for XXXX
  MAINTAINER:=XXXX
  DEPENDS:=$(PKG_DEPENDS)
endef

define KernelPackage/$(PKG_NAME)/description
	This is a kernel module which do xxxxx thing
endef

define Package/$(PKG_NAME)/Description
	This is app-monitor module for XXXX
endef

define Package/$(PKG_NAME)/config
	config PACKAGE_MONITOR_VENDOR
		string "monitor vendor name(must be setted)"
		default name_of_provider

	config PACKAGE_MONITOR_VERSION
		string "monitor version(must be setted)"
		default X.Y.Z

	config PACKAGE_MONITOR_USE_IPT
		bool "monitor module use iptables to intercept packet"
		default n
endef

CONFIG_PACKAGE_MONITOR_USE_IPT ?= y
ifeq ($(CONFIG_PACKAGE_MONITOR_USE_IPT), y)
SRC_PATH:=ipt
PKG_DEPENDS+=+iptables
else #CONFIG_PACKAGE_MONITOR_USE_IPT

TARGET_LDFLAGS += -lpcap
PKG_DEPENDS+=+libnetfilter-queue +libpcap
SRC_PATH:=frame

endif #CONFIG_PACKAGE_MONITOR_USE_IPT

MONITOR_VENDOR ?= $(CONFIG_PACKAGE_MONITOR_VENDOR)
MONITOR_VERSION ?= $(CONFIG_PACKAGE_MONITOR_VERSION)
MONITOR_USE_IPT ?= $(CONFIG_PACKAGE_MONITOR_USE_IPT)

$(info $$MONITOR_VENDOR is [${MONITOR_VENDOR}])
$(info $$MONITOR_VERSION is [${MONITOR_VERSION}])
$(info $$MONITOR_USE_IPT is [${MONITOR_USE_IPT}])

INSTALL_BIN:=$(SRC_PATH)/app-monitor
INSTALL_LIB:=$(SRC_PATH)/libxt_monitor.so

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

define Build/Compile
	$(MAKE) -C $(PKG_BUILD_DIR)/$(SRC_PATH) \
    $(TARGET_CONFIGURE_OPTS) \
	TARGET_LDFLAGS="$(TARGET_LDFLAGS)" \
	TARGET_CFLAGS="$(TARGET_CFLAGS) $(TARGET_CPPFLAGS)" \
	MONITOR_VERSION="$(MONITOR_VERSION)" \
	CC="$(TARGET_CC)"
	$(MAKE) -C $(LINUX_DIR) M=$(PKG_BUILD_DIR)/$(SRC_PATH) MONITOR_VERSION=$(MONITOR_VERSION) $(strip $(APP_MONITOR_MAKE_OPTS))
endef

define Package/$(PKG_NAME)/install
	$(CP) -rf ./filesystem/* $(1)/

	$(INSTALL_DIR) $(1)/usr/lib/monitor/
	$(CP) $(PKG_BUILD_DIR)/sdk-$(MONITOR_VERSION)/lib/* $(1)/usr/lib/monitor/

	$(INSTALL_DIR) $(1)/usr/bin
	$(if $(INSTALL_BIN),$(CP) $(foreach bin,$(INSTALL_BIN),$(PKG_BUILD_DIR)/$(bin)) $(1)/usr/bin/)

	$(INSTALL_DIR) $(1)/usr/lib/iptables
	$(if $(INSTALL_LIB),$(CP) $(foreach lib,$(INSTALL_LIB),$(PKG_BUILD_DIR)/$(lib)) $(1)/usr/lib/iptables/)
endef

define Build/InstallDev

endef

define KernelPackage/$(PKG_NAME)/install
	$(INSTALL_DIR) $(1)/etc
endef

$(eval $(call KernelPackage,$(PKG_NAME)))

$(eval $(call BuildPackage,$(PKG_NAME)))

当然,具体到src目录下,用户态模块仍然用Makefile控制,而内核模块则Kbuild控制:

MODULE_NAME = app-monitor
$(MODULE_NAME)-objs := app-monitor-kmod.o component.o
obj-m += $(MODULE_NAME).o