本文链接:如何在OpenWrt上开发
最近,因为一些原因,我需要把自己之前开发的程序移植到OpenWrt上面。要做到这件事,至少需要一台装有OpenWrt的设备(可以用虚拟机)、一台Linux设备用于编译(WSL我猜或许也可以)、Linux编程的知识、GNU编译工具的用法、和一定的英语水平(看文档或者查错之类的)。
下载开发工具
从官方文档里能找到下载开发工具的部分:https://openwrt.org/docs/guide-developer/using_the_sdk#downloads。
我使用了最新快照对应的工具,平台是ramips/mt7621,所以对应的下载位置在 https://downloads.openwrt.org/snapshots/targets/ramips/mt7621/。找到名为openwrt-sdk-ramips-mt7621_gcc-8.4.0_musl.Linux-x86_64.tar.xz的文件,下载之。
在Linux下解压,我用了Ubuntu 20.04,其他的系统应该也可以:
1 2 |
tar -xf openwrt-sdk-ramips-mt7621_gcc-8.4.0_musl.Linux-x86_64.tar.xz mv openwrt-sdk-ramips-mt7621_gcc-8.4.0_musl.Linux-x86_64.tar openwrt |
这样,开发工具就在openwrt目录下准备好了,下面提到的openwrt
目录都是指这个目录。
创建本地Feed
OpenWrt提供了包管理工具opkg,其开发工具编译生成的最小单元也是包,而不是单个的可执行文件,虽然也可以把生成的可执行文件解出来放到OpenWrt上运行。包中除了可执行文件外还定义了安装方式,在使用时就可以一键安装和更新。
虽然可以直接在openwrt/package
目录下面直接建包,但更推荐的方式是创建Feed来存放包,你可以把Feed整个放到代码版本库比如Git上面,当OpenWrt开发工具更新时,不需要把自己的包的代码移来移去。
Feed其实就是一个目录,里面包含了包的定义。我在openwrt
目录外的地方建了个目录来作为Feed,然后将它配置到OpenWrt中。
1 2 3 |
mkdir myfeed cd /path/to/openwrt cp feeds.conf.default feeds.conf |
在feeds.conf
里加入以下内容:
1 |
src-link myfeed /path/to/myfeed |
这样OpenWrt就知道多了一个名叫myfeed
的Feed,对应的路径是/path/to/myfeed
。
创建包
在myfeed
目录中创建目录:
1 |
mkdir mypackage |
OpenWrt开发工具在找包的时候会遍历目录,所以把包放在Feed更深处也是可以的:
1 |
mkdir -p mycategory/mysubcategory/mypackage |
在mypackage
中创建名为Makefile
的文件,写入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# 固定写法,TOPDIR是指openwrt目录 include $(TOPDIR)/rules.mk # 包名、版本和版本后缀 PKG_NAME:=mypackage PKG_VERSION:=1.0 PKG_RELEASE:=1 # 作者 PKG_MAINTAINER:=Chaofan <herbix@163.com> PKG_LICENSE:=Private # 固定写法,INCLUDE_DIR指openwrt/include目录 include $(INCLUDE_DIR)/package.mk # 定义基本信息,DEPENDS这行如果没有依赖可以不写 define Package/mypackage SECTION:=utils CATEGORY:=Utilities TITLE:=My first package DEPENDS:=+another_package endef # 描述 define Package/mypackage/description My first package endef # 固定写法 $(eval $(call BuildPackage,mypackage)) |
虽然包里什么都没有,但是它已经是个合法的包了。
从Feed中导入包
回到openwrt
目录,用以下命令导入包:
1 2 |
./scripts/feeds update myfeed ./scripts/feeds install mypackage |
这时,运行以下命令就应该能在Utilities
分类下看到mypackage
这个包了。
1 |
make menuconfig |
还可以试着去编译它,虽然不会有输出,因为它是空的。
1 |
make package/mypackage/compile |
加入可执行程序
在mypackage
目录下创建目录src
,用来放源代码。在src
下创建main.c
和Makefile
文件,分别写入:
1 2 3 4 5 6 7 8 |
#include <stdio.h> int main(int argc, char** argv) { puts("Hello, OpenWrt!"); return 0; } |
1 2 |
all: main.c $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Wall -o mypackage $^ $(LDLIBS) |
然后修改mypackage
目录中的Makefile
,在call BuildPackage
这一行前面加入以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 在编译前执行,默认编译会找PKG_BUILD_DIR目录下的Makefile并执行它 define Build/Prepare mkdir -p $(PKG_BUILD_DIR) $(CP) ./src/* $(PKG_BUILD_DIR)/ endef # 安装命令,注意这些命令只是一些定义而不是在安装时实际执行的 # $(1)在这里相当于OpenWrt系统的根目录 # 所以这里是说安装时将mypackage这个可执行文件放到/usr/bin目录下 define Package/mypackage/install $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/mypackage $(1)/usr/bin/ endef |
然后回到openwrt
目录下运行:
1 |
make package/mypackage/compile |
如果没出错,就能在openwrt/bin/packages/<平台>/myfeed/
目录下找到.ipk
后缀的文件,可以在OpenWrt界面上上传安装或者用opkg
命令安装这个包。安装后在/usr/bin
目录下能找到mypackage
文件,执行它会出现:
1 |
Hello, OpenWrt! |
总结
用以上的方法可以将自己的代码编译到目标平台,并且打成包,方便OpenWrt管理。但实际上我们需要的功能可能不止于此,还需要有配置文件、开机自启动、管理界面等待。限于篇幅,我会在后文中介绍。