陆续用OpenWrt已经有5年多了, 一直以来都没有勇气用OpenWrt写原生的C程序.

OpenWrt本身是维护了一些菜谱(recipe), 表现形式是Makefile. 它里面定义了包名/描述/类别/上游等等信息.

make menuconfig的时候, 会先把package/目录里的所有包都扫描一遍, 生成总体的Makefile.

想单独编译这个包, make package/your_package/compile即可, 会生成到bin/ar71xx/packages/base/your_package_blahblah.ipk

一个最小的例子

最好在与目标固件在同一个编译树下面做以下事情, 否则可能会因为libc版本不一致导致程序无法运行.

目录结构:

openwrt/package/helloworld
├── Makefile
└── src
    ├── helloworld.c
    └── Makefile

外层的 Makefile

include $(TOPDIR)/rules.mk

PKG_NAME:=helloworld
PKG_RELEASE:=1

PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)

include $(INCLUDE_DIR)/package.mk


define Package/helloworld
	SECTION:=utils
	CATEGORY:=Utilities
	TITLE:=Helloworld
endef

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

define Package/helloworld/install
	$(INSTALL_DIR) $(1)/bin
	$(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/bin/
endef

$(eval $(call BuildPackage,helloworld))

src/helloworld.c

#include <stdio.h>

int main(void)
{ 
	printf("hello world!\n");
	return 0;
}

src/Makefile

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

clean:
	rm *.o helloworld

编译

make menuconfig 
# 把Utilities里的helloworld要么打M, 要么打*
make package/helloworld/compile
ls bin/ar71xx/packages/base/helloworld*.ipk

### 然后部署
scp bin/ar71xx/packages/base/helloworld*.ipk root@192.168.1.1:/tmp/
opkg install helloworld*.ipk

注意: package/helloworld/src/里的.o文件要被清理掉, 我之前有一次是在电脑上执行了package/helloworld/src/里的make, 结果报了一个libc相关的错误. 原因就是OpenWrt的make(mips)复用了里面的.o(x86_64).

用SDK来编译

用SDK编译的好处是不用把整个代码树clone下来, 省事, 优雅.

首先要选对SDK版本

注意一定要用对应的SDK版本, 否则libc的版本或者其它库的版本对不上, 尽管编译出ipk包, 扔上去会执行不了, 提示

# ./helloworld
 - ash: no file helloworld found

SDK页面上下载, 例如: https://downloads.openwrt.org/barrier_breaker/14.07/ar71xx/generic/OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2.tar.bz2

(或者用TUNA的镜像: 示例)

每个snapshot都会有对应的SDK可以下载, 同时, 也可以自己make menuconfig的时候生成一份SDK.
(想必大家被坑过: 用snapshot版本, 结果后面snapshot更新了, 新的包拿下来无法使用….)

要装 gawk

sudo apt-get install gawk

否则会报错:

awk: include/scan.awk: line 21: function asort never defined

feed update以及编译

以下摘自shadowsocks-openwrt:

tar xjf OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2.tar.bz2
cd OpenWrt-SDK-ar71xx-*

./scripts/feeds update packages
./scripts/feeds install libpcre

git clone https://github.com/shadowsocks/openwrt-shadowsocks.git package/shadowsocks-libev
make menuconfig
make package/shadowsocks-libev/compile V=99

See also