在源码目录下创建“files”目录,这个目录可以看成是根目录的映射,只要将要打包到固件的文件按照根目录的目录结构存放文件即可。
例如:
1.修改network配置文件源码固件
Ubuntu中openwrt-hiwooya-stable/files/etc/config/network <-----对应-----> 嵌入式系统中/etc/config/network
2.添加可执行文件setwifi
Ubuntu中openwrt-hiwooya-stable/files/usr/sbin/setwifi <-----对应-----> 嵌入式系统/usr/sbin/setwifi
OpenWrt是一个比较完善的嵌入式Linux开发平台,在无线路由器应用上已有4000多个软件包。用户可以按照OpenWrt的约定增加开源软件或自行开发的软件。加入软件包需要在package目录下创建一个目录,以包含该软件包的各种信息和与OpenWrt建立联系的文件。然后创建一个Makefile与OpenWrt建立联系,Makefile需要遵循OpenWrt的约定。另外可以创建一个patchs目录保存patch文件,对下载的源代码进行适量修改。
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一般在软件包的基本信息完成后再引入。
软件包的信息均以PKG_开头,其意思和作用如下:
应用程序和内核驱动模块的定义不一样。应用程序软件包使用Package,内核驱动模块使用KernelPackage。
应用程序的编译包以Package/开头。然后接着软件名,在Package定义中的软件名可以与软件包名不一样,而且可以多个定义。下面使用$(PKG_NAME)只是做一个标志,并非真正使用$(PKG_NAME),如Package/$(PKG_NAME)。
在用户空间的应用程序软件包中没有内核驱动模块的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。
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
按OpenWrt的习惯,一般把自己设计的程序全部在src目录下。
define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
$(TARGET_CONFIGURE_OPTS) CFLAGS="$(TARGET_CFLAGS) -I $(LINUX_DIR)/include"
endef
define Package/$(PKG_NAME)/install
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_DIR) $(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混在一起,以提高可读性。使用清晰的文件扩展名,更方便安装识别文件。
Linux分为内核空间和用户空间。开发者开发的内核部分可以直接加入Linux的Kernel程序,也可以生成内核模块以便需要时装入内核。OpenWrt一般希望开发者生成内核模块,在Linux启动后自动装载或手工使用insmod命令装载。内核模块使用KernelPackage开头,其他与一般应用软件包基本相同。
在内核驱动模块定义中增加了:
完成前面定义后,必须使用eval函数实现各种定义。其格式为:
对于一般应用软件包
$(eval $(call Package, $(PKG_NAME)))
或对于内核驱动模块
$(eval $(call KernelPackage, $(PKG_NAME)))
如果一个软件包有多个程序,例如:一个应用程序有自己的内核驱动模块,上面使用PKG_NAME需要灵活变通。eval函数可以设计多个。也可以当成多个软件包处理。
在openwrt-hiwooya-stable-master/package/cpp(你的程序文件夹名)/src下创建一个Makefile,用于编译该应用程序。
# build helloworld executable when user executes "make"
LDFLAGS += -L$(TOPDIR)/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/usr/lib/mysql
LDFLAGS += -L$(TOPDIR)/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/usr/lib/libevent
LDFLAGS += -L$(TOPDIR)/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/lib/ -lstdc++ -Wno-explicit
LDFLAGS += -L$(TOPDIR)/build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/libjsoncpp/
LIBS += -lmysqlclient -lpthread -lrt -lcurl -ljsoncpp -levent
CXXFLAGS += -I$(TOPDIR)/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/usr/include/mysql
CXXFLAGS += -I$(TOPDIR)/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/usr/include/libevent
CXXFLAGS += -I$(TOPDIR)/staging_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/usr/include
#CXXFLAGS += -I$(TOPDIR)/build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/json-c-0.12
CXXFLAGS += -I$(TOPDIR)/build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/libjsoncpp/include/
CXXFLAGS += -std=c++11
OBJ=cpp.o common.o Serial.o protocol.o CHttpClient.o \
CSocket.o CUDPSocket.o DALReceive.o SocketSend.o DALSend.o Central.o CMsg.o \
DALBase.o CustomMessage.o HCIModule.o HCIMatch.o \
SQLBase.o HCIServiceObject.o SQLServiceObject.o HCIEvent.o SQLEvent.o \
HCIGateway.o SQLGateway.o Gateway.o \
HCIIfttt.o SQLIfttt.o HCIAction.o SQLAction.o HCIDebug.o ServiceObject.o CustomCfg.o \
Load.o Event.o HandleThread.o HCIIftttLog.o SQLIftttLog.o Action.o \
Ifttt.o IftttLog.o Timer.o JsonVector.o HttpServer.o WebServer.o TimerThread.o Buffer.o
cpp: $(OBJ)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(LIBS) $(OBJ) -o $@
%.o: %.cpp
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(LIBS) -c $< -w
# remove object files and executable when user executes "make clean"
clean:
rm *.o cpp
在openwrt-hiwooya-stable-master/package/cpp(你的程序文件夹名)下创建一个Makefile,用于将该应用程序编译进OpenWrt系统。
##############################################
# OpenWrt Makefile for cpp program
#
#
# Most of the variables used here are defined in
# the include directives below. We just need to
# specify a basic description of the package,
# where to build our program, where to find
# the source files, and where to install the
# compiled program on the router.
#
# Be very careful of spacing in this file.
# Indents should be tabs, not spaces, and
# there should be no trailing whitespace in
# lines that are not commented.
#
##############################################
include $(TOPDIR)/rules.mk // 必须引入$(TOPDIR)/rules.mk文件
# Name and release number of this package
PKG_NAME:=cpp // 软件包名称
PKG_RELEASE:=1 // Makefile的版本号
# This specifies the directory where we're going to build the program.
# The root build directory, $(BUILD_DIR), is by default the build_mipsel
# directory in your OpenWrt SDK directory
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) // 软件包编译目录
include $(INCLUDE_DIR)/package.mk // 引入$(INCLUDE_DIR)/package.mk文件
# Specify package information for this program.
# The variables defined here should be self explanatory.
# If you are running Kamikaze, delete the DESCRIPTION
# variable below and uncomment the Kamikaze define
# directive for the description below
define Package/cpp
SECTION:=utils // 包的类型
CATEGORY:=Utilities // 包的分类,在make menuconfig的菜单下将可以找到。
// 与其他软件的依赖
DEPENDS:=+libmysqlclient +libpthread +libreadline +libstdcpp +librt +libcurl +libjsoncpp +libevent2
TITLE:=alm-tn01 // 软件包的简短描述
endef
# Uncomment portion below for Kamikaze and delete DESCRIPTION variable above
define Package/cpp/description // 软件包的详细描述
If you can't figure out what this program does, you're probably
brain-dead and need immediate medical attention.
endef
# Specify what needs to be done to prepare for building the package.
# In our case, we need to copy the source files to the build directory.
# This is NOT the default. The default uses the PKG_SOURCE_URL and the
# PKG_SOURCE which is not defined here to download the source from the web.
# In order to just build a simple program that we have just written, it is
# much easier to do it this way.
define Build/Prepare // 自行开发软件包的编译准备方法
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/ * $(PKG_BUILD_DIR)/
endef
# We do not need to define Build/Configure or Build/Compile directives
# The defaults are appropriate for compiling a simple program such as this one
# Specify where and how to install the program. Since we only have one file,
# the cpp executable, install it by copying it to the /bin directory on
# the router. The $(1) variable represents the root directory on the router running
# OpenWrt. The $(INSTALL_DIR) variable contains a command to prepare the install
# directory if it does not already exist. Likewise $(INSTALL_BIN) contains the
# command to copy the binary file from its current location (in our case the build
# directory) to the install directory.
define Package/cpp/install // 软件包的安装方法
$(INSTALL_DIR) $(1)/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/cpp $(1)/bin/
$(INSTALL_DIR) $(1)/etc/init.d // 自动运行的脚本文件安装和配置文件安装方法
$(INSTALL_BIN) ./files/cpp.init $(1)/etc/init.d/cpp
$(INSTALL_DIR) $(1)/etc/app
endef
# This line executes the necessary commands to compile our program.
# The above define directives specify all the information needed, but this
# line calls BuildPackage which in turn actually uses this information to
# build a package.
$(eval $(call BuildPackage,cpp)) // 使用定义