Compile OpenWrt Program using SDK

有两种方法可以编译在OpenWrt上运行的程序(软件),一种是利用toolchain编译可执行文件,进而在OpenWrt下直接运行,一种是利用SDK编译可以在OpenWrt上安装的ipk软件包,在OpenWrt上安装使用。由于SDK的灵活性更高、适用性更广,本文描述如何利用SDK编译简单的软件包。

准备工作:
TL-WR703N无线AP一个
装Ubuntu的计算机一台
如果Ubuntu上没有编译OpenWrt固件的环境,应该先搭建起编译环境,操作如下:
1、安装依赖
执行如下指令:
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install build-essential subversion git-core libncurses5-dev zlib1g-dev gawk flex quilt libssl-dev xsltproc libxml-parser-perl unzip
2、下载OpenWrt Buildsystem
git clone http://git.openwrt.org/12.09/openwrt.git
其中12.09是Attitude Adjustment版本,其他版本对应关系如下:
Backfire 10.03
Barrier Breaker 14.07
Chaos Calmer 15.05
所以可以将上面git指令中的12.09换为其他对应的版本,git完成之后要更新和安装feeds,指令如下
cd openwrt
./scripts/feeds update -a
./scripts/feeds install -a
3、编译OpenWrt固件
在openwrt目录下执行指令:
make menuconfig
在配置菜单中选择Target System和Target Profile,我用的是TL-WR703N,配置的是AR7240 CPU和AR9331芯片组,所以分别选择的是Atheros AR7xxx/AR9xxx;此外还要选择Build OpenWrt SDK,如果想用Toolchain的话可以选择Package the OpenWrt-based Toolchain。如果还想利用U盘对TL-WR703N进行扩容,需要选择Libraries->libubox, Kernel modules->Filesystems->kmod-fs-ext4(包含Kernel modules->Libraries->kmod-lib-crc16和Kernel modules->Cryptographic API Modules->kmod-crypto-hash),USB Support->kmod-usb-storage-extras(包含USB Support->kmod-usb-storage),选择完成之后退出菜单就可以进行编译了。
执行命令:
make V=99
make后面的参数是要求在编译过程中输出编译信息,整个编译过程会持续数个小时,因为要下载很多安装包,而且可以回出现编译中断,出现中断时查看在下载和安装哪个安装包时出的问题,如果是通过wget下载的,应该在出现中断后进入dl目录下查看是否下载了出问题的安装包,并删除它,接着再一次进行make。
4、用SDK编译软件包
make完成之后,进入bin目录下查看是否存在SDK的压缩包,可以将压缩包解压到主目录下,接下来主要在SDK目录下进行操作。在package目录下新建helloworld目录,并在helloworld目录下新建src目录,helloworld目录将包含src和用于指导编译和安装软件包的Makefile,src目录下包含的是源文件和用于编译的Makefile,应当注意到两个Makefile功能时不同的。接下来在src目录下新建helloworld.c,内容如下
#include <stdio.h>
int main() {
printf(“hello world\n”);
return 0;
}
接着在src目录下新建Makefile,内容如下:

build helloworld executable when user executes “make”

helloworld: helloworld.o
$(CC) $(LDFLAGS) helloworld.o -o helloworld
helloworld.o: helloworld.c
$(CC) $(CFLAGS) -c helloworld.c

remove object files and executable when user executes “make clean”

clean:
rm *.o helloworld
接着在helloworld目录下新建Makefile,内容如下:
##############################################

OpenWrt Makefile for helloworld 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

Name and release number of this package

PKG_NAME:=helloworld
PKG_RELEASE:=1

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

Specify package information for this program.

The variables defined here should be self explanatory.

define Package/helloworld
SECTION:=utils
CATEGORY:=Utilities
TITLE:=Helloworld — prints a snarky message
endef
define Package/helloworld/Description
A simple hello world program
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 helloworld 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/helloworld/install
$(INSTALL_DIR) $(1)/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/bin/
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,helloworld))
这个Makefile对于这个简单的编译来说是重中之重,每一项都值得细细推敲和理解,完成后目录和文件应该是下面的形式:
package/helloworld—-
|
Makefile
|
src—-
|
helloworld.c
|
Makefile
接下来编译软件包,回到SDK目录下,执行命令:
make package/helloworld/compile V=99
没有报错的话就顺利完成了编译,编译生成的ipk文件在bin目录下,将ipk文件用WinSCP传入TL-WR703N的/tmp目录下,并安装,指令如下:
opkg install package_name.ipk
安装完成后可以再任何目录下测试软件功能,即输入helloworld,回车就可以看到系统输出的hello world.
至此,安装和功能测试完成。