文档章节

OpenWRT开发之——创建软件包(有更新)

临峰不畏
 临峰不畏
发布于 2015/05/04 23:03
字数 1910
阅读 17188
收藏 47

试验步骤

为了达到自己编写一个程序打包成ipk,并能在OpenWRT上运行的目的。我在网上找了些学习的资料。

本人参考的是:如何在OpenWRT上做开发

感谢该网友的耐心解答。虽然有现成的步骤,博主还是喜欢亲自实践一下,写下自己的实践过程。


第一步:生成SDK

make menuconfig 选上 “Build the OpenWRT SDK”

在 trunk目录下,执行:

$ make menuconfig

选择对应的"Target System"与"Target Profile",并选上"Build the OpenWrt SDK"。


然后 Save,退出。再make一次。

$ make V=99

make 完成之后,在 bin/ar71xx/ 目录下会生成SDK的压缩文件:

OpenWrt-SDK-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-i686.tar.bz2

第二步:安装SDK

将上面所生成的 OpenWrt-SDK-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-i686.tar.bz2 复制到其它路径下(指可以不在OpenWrt的源码路径下),再解压出来。

比如我将其放到 ~/Workspace/OpenWRT/ 路径下:

$ cp bin/ar71xx/OpenWrt-SDK-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-i686.tar.bz2 ~/Workspace/OpenWRT
$ cd ~/Workspace/OpenWRT
$ tar jxvf OpenWrt-SDK-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-i686.tar.bz2

在 ~/Workspace/OpenWRT/ 路径下就生成了 OpenWrt-SDK-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-i686 目录。

为了方便,我将这个长长的目录名简化为:OpenWrt-SDK。修改后,完整的路径是:~/Workspace/OpenWRT/OpenWrt-SDK

据说这个目录结构跟 OpenWrt的源码目录结构差不多。


第三步:创建helloworld项目

其实,这里可以是任意我们想要加入的程序,库等。这里就以helloword为例。

在任意路径下,创建helloword项目。比如这里还是在 ~/Workspace/OpeWRT 目录下。

$ cd ~/Workspace/OpenWRT
$ mkdir helloword
$ cd helloword
$ touch helloword.c Makefile

在 ~/Workspace/OpenWRT/ 目录下创建了 helloword 目录,并生成 helloword.c与Makefile文件。

如下为 helloworld.c的内容:

#include <stdio.h>

int main()
{
    printf("This is my hello word!\n");
    return 0;
}

Makefile的内容:

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

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

clean :
    rm *.o helloworld

首先,确保在程序没问题,在本地能正常编过。为了检验一下,可以就地 make 一下,看程序本身有没有问题。

这个程序都如些之简单了,本人自己了make了一下,OK,再run了一下,正常。


第四步:创建helloworld包

进入 OpenWrt/Packages/ 并在该目录下创建 helloworld 目录,并进入该目录。

$ cd ~/Workspace/OpenWrt/OpenWrt-SDK/package
$ mkdir helloworld
$ cd helloworld

将我们第三步写的程序复制到这个目录下来,更名为src。再新建一个 Makefile 文件。

$ cp -r ../../../helloworld src
$ touch Makefile

整个过程下来,package目录结构如下:

package
|-- helloworld
|   |-- Makefile
|   `-- src
|       |-- helloworld.c
|       `-- Makefile
`-- Makefile

package/Makefile 不要去修改它。

我们要编写的是 package/helloworld/Makefile 这个文件。

在这个文件中,我们要描述 helloworld 包的信息,比如:如何配置、如何编译、如何打包、安装等等信息。
这个文件与一般的 Makefile 格式还不一样,详见OpenWrt上的说明文档:OpenWrt官网Packages说明

这里我就依照例子编写 helloworld/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 -- prints a snarky message
endef

define Package/helloworld/description
    It's my first package demo.
endef

define Package/helloworld/Prepare
    echo "Here is Package/Prepare"
    mkdir -p $(PKG_BUILD_DIR)
    $(CP) ./src/* $(PKG_BUILD_DIR)/
endef

define Package/helloworld/install
    echo "Here is Package/install"
    $(INCLUDE_DIR) $(1)/bin
    $(INCLUDE_BIN) $(PKG_BUILD_DIR)/helloworld$(1)/bin/
endef

$(eval $(call BuildPackage, helloworld))

然后回到 OpenWrt-SDK 目录下,执行:make V=s,结果有以下错误提示:

$ make V=s
ERROR: please fix package/helloworld/Makefile - see logs/package/helloworld/dump.txt for details

说是我写的这个Makefile有错,请查看 dump.txt 文件。无奈只好去看看到底错在哪里啰。

打开 OpenWrt-SDK/logs/package/helloworld/dump.txt 文件:

Package:  helloworld
Version: 1
Depends: +libc +SSP_SUPPORT:libssp +USE_GLIBC:librt +USE_GLIBC:libpthread 
Conflicts: 
Menu-Depends: 
Provides: 
Section: opt
Category: Extra packages
Title: 
Maintainer: 
Source: 
Type: ipkg
Description: 

@@

Makefile:32: *** invalid syntax in conditional.  Stop.

前面那么多行信息没什么用,最重要的是最后一行,好像是说32行条件语法错误。赶紧打开 package/helloworld/Makefile,定位到32行看看。结果是:

$(eval $(call BuildPackage, helloworld))

这个,我何错之有呢?

最后反复排查,原来是 "BuildPackage," 逗号后面与 "helloworld" 之间多了个空格。不会吧!多个空格少个空格都会导致语法错误?!

好了,改正过来了。

$(eval $(call BuildPackage,helloworld))  #去掉空格

现在 make V=s 不再是刚才那个错了。

make[3]: Entering directory `/home/hevake_lcj/Workspace/OpenWRT/my-packages/OpenWrt-SDK/package/helloworld'
CFLAGS="-Os -pipe -mno-branch-likely -mips32r2 <此处省略好长串...>" 
CXXFLAGS="-Os -pipe -mno-branch-likely -mips32r2 <此处省略好长串...>" 
LDFLAGS="<此处省略好长串...>" 
make -j1 -C /home/hevake_lcj/Workspace/OpenWRT/my-packages/OpenWrt-SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/helloworld/. 
AR="mips-openwrt-linux-uclibc-gcc-ar" 
AS="mips-openwrt-linux-uclibc-gcc -c -Os -pipe -mno-branch-likely -mips32r2 -mtune=34kc -fno-caller-saves -fhonour-copts -Wno-error=unused-but-set-variable -msoft-float" 
LD=mips-openwrt-linux-uclibc-ld 
NM="mips-openwrt-linux-uclibc-gcc-nm" 
CC="mips-openwrt-linux-uclibc-gcc" 
GCC="mips-openwrt-linux-uclibc-gcc" 
CXX="mips-openwrt-linux-uclibc-g++" 
RANLIB="mips-openwrt-linux-uclibc-gcc-ranlib" 
STRIP=mips-openwrt-linux-uclibc-strip 
OBJCOPY=mips-openwrt-linux-uclibc-objcopy 
OBJDUMP=mips-openwrt-linux-uclibc-objdump 
SIZE=mips-openwrt-linux-uclibc-size 
CROSS="mips-openwrt-linux-uclibc-" 
ARCH="mips" ;
make[4]: Entering directory `/home/hevake_lcj/Workspace/OpenWRT/my-packages/OpenWrt-SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/helloworld'
make[4]: *** No targets specified and no makefile found.  Stop.  # 错误:没有找 Makefile 文件!!
make[4]: Leaving directory `/home/hevake_lcj/Workspace/OpenWRT/my-packages/OpenWrt-SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/helloworld'
make[3]: *** [/home/hevake_lcj/Workspace/OpenWRT/my-packages/OpenWrt-SDK/build_dir/target-mips_34kc_uClibc-0.9.33.2/helloworld/.built] Error 2
make[3]: Leaving directory `/home/hevake_lcj/Workspace/OpenWRT/my-packages/OpenWrt-SDK/package/helloworld'
make[2]: *** [package/helloworld/compile] Error 2
make[2]: Leaving directory `/home/hevake_lcj/Workspace/OpenWRT/my-packages/OpenWrt-SDK'
make[1]: *** [/home/hevake_lcj/Workspace/OpenWRT/my-packages/OpenWrt-SDK/staging_dir/target-mips_34kc_uClibc-0.9.33.2/stamp/.package_compile] Error 2
make[1]: Leaving directory `/home/hevake_lcj/Workspace/OpenWRT/my-packages/OpenWrt-SDK'
make: *** [world] Error 2

为什么 build_dir/target-mips_34kc_uClibc-0.9.33.2/helloworld 目录下没有 Makefile 文件?

我们要好好排查一个 package/helloworld/Makefile 文件中的 Package/helloworld/Prepare 宏。

define Package/helloworld/Prepare
    echo "Here is Package/Prepare"
    mkdir -p $(PKG_BUILD_DIR)
    $(CP) ./src/* $(PKG_BUILD_DIR)/
endef

好像这个宏压根没有被执行到。

为什么呢?

<今天太晚了,明天再整>

<接着昨晚的问题>

最后与例子仔细比对,发现原来我将 "Build/Prepare" 写成了 "Package/helloworld/Prepare"

最终完整的 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 -- prints a snarky message
endef

define Package/helloworld/description
    It's my first package demo.
endef

define Build/Prepare   #已修正
    echo "Here is Package/Prepare"
    mkdir -p $(PKG_BUILD_DIR)
    $(CP) ./src/* $(PKG_BUILD_DIR)/
endef

define Package/helloworld/install
    echo "Here is Package/install"
    $(INSTALL_DIR) $(1)/bin
    $(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/bin/
endef

$(eval $(call BuildPackage,helloworld))   #已去除逗号后面的空格

这次 make -j1 V=s 成功了。生成了 helloworld_1_ar71xx.ipk 。find 一下,看在哪里。

$ find -name helloworld*.ipk
./bin/ar71xx/packages/base/helloworld_1_ar71xx.ipk


第五步:试验helloworld

将刚生成的 helloworld_1_ar71xx.ipk 文件用 scp 传到目标路由上。本人的路由IP为:192.168.1.2

$ scp bin/ar71xx/packages/base/helloworld_1_ar71xx.ipk root@192.168.1.2:
root@192.168.1.2's password: 
helloworld_1_ar71xx.ipk                 100% 1993     2.0KB/s   00:00

SSH登陆路由器,并安装 helloworld_1_ar71xx.ipk包。

$ ssh root@192.168.1.2
root@192.168.1.2's password: 

BusyBox v1.23.2 (2015-05-03 12:46:04 CST) built-in shell (ash)
  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 -----------------------------------------------------
 CHAOS CALMER (Bleeding Edge, r45594)
 -----------------------------------------------------
  * 1 1/2 oz Gin            Shake with a glassful
  * 1/4 oz Triple Sec       of broken ice and pour
  * 3/4 oz Lime Juice       unstrained into a goblet.
  * 1 1/2 oz Orange Juice
  * 1 tsp. Grenadine Syrup
 -----------------------------------------------------
root@OpenWrt:~# ls
helloworld_1_ar71xx.ipk
root@OpenWrt:~# opkg install helloworld_1_ar71xx.ipk 
Installing helloworld (1) to root...
Configuring helloworld.
root@OpenWrt:~#

安装完成后,执行一下试试看。

root@OpenWrt:~# helloworld 
This is my hello word!

用which命令查看 helloworld 安装的路径:

root@OpenWrt:~# which helloworld
/bin/helloworld

在 /bin/ 路径下。


总结

本人没有将网上的例子直接贴在自己的博文上,而是自己亲自尝试整个过程,并记录自己所遇到的问题,这样会更真实一些。

整个过程,就属“第四步:建helloworld包”遇到困难最多。这也是整个过程中最核心的工作。不过,我还是一一解决了。

我们在按照例程走完一次流程,不能只是走马观花,而更应该是去领悟其中的原理。

可以想像,真正的应用远比这个复杂。后面,我会另起一个博文专门研究 OpenWrt 的 package Makefile。尽请关注~


求关注

想与我一起研究技术,就请关注我吧!

© 著作权归作者所有

临峰不畏
粉丝 221
博文 187
码字总数 98583
作品 0
深圳
架构师
私信 提问
加载中

评论(2)

特斯拉999
特斯拉999
好厉害
Asiam
Asiam
谢谢博主!
移植OpenWrt到RT5350

slider >>> Too few posts! (required minimum are 3) (the featured image may be missing) Previous 移植OpenWrt到CuHead Pro WiFi Posted by: zou, baozhu , 三月 13, 2014 CuHead Pro是一......

Pillar_zuo
2014/03/13
23.3K
5
OpenWrt系列教程汇总 & OpenWrt简体中文Wiki

OpenWrt系列教程汇总 OpenWrt简体中文Wiki 快速导航

AlphaJay
2011/07/26
42.7K
1
为pcDuino安装OpenWrt

OpenWrt是一个高度模块化、高度自动化的嵌入式Linux系统,拥有强大的网络组件,常常被用于工控设备、电话、小型机器人、智能家居、路由器以及VOIP设备中。OpenWrt支持各种处理器架构,无论是...

酸酸苹果汁
2014/02/18
6.8K
1
极路由4刷OpenWrt(LEDE)

申请开发者模式 登录路由器后台 进入插件中间 选中路由器信息 申请开发者权限 安装开发者插件 刷 Bootloader 下载 的 Breed 通过SSH登录路由器 (必须安装开发者插件,端口 账号 密码 ) 通过...

dingdayu
02/24
1K
0
开源路由器项目 OpenWrt 发布 18.06 稳定分支的首个版本

OpenWrt 18.06.0 - First Stable Release - July 2018 OpenWrt 项目是一个针对嵌入式设备的 Linux 操作系统。它完全取代了厂商提供的各种无线路由器和非网络设备的固件。已被支持的设备,请参...

Just_4_Fun
2018/08/01
8.9K
12

没有更多内容

加载失败,请刷新页面

加载更多

自建redis笔记

自建redis笔记 最近在linux安装了一下redis,特做一些笔记! 本文先单节点启动redis,然后再进行持久化配置,在次基础上,再分享搭建主从模式的配置以及Sentinel 哨兵模式及集群的搭建 单节点...

北极之北
9分钟前
1
0
vue+element之多表单验证

方法一:利用promise var p1=new Promise(function(resolve, reject) { this.$refs[form1].validate((valid) => { if(valid){ ......

沉迷代码我爱学习
12分钟前
1
0
golang 1.13 errors 包 新函数介绍

引 这次 errors 包算重量级更新。很有更能把以前的一些设计模式给推到。下面聊下用法。 error 装包 以前返回一个错误,想要保存 error 链,还要定义结构体保存以前的 error 信息。感兴趣看下...

guonaihong
21分钟前
30
0
并发编程之线程池

一、线程池 1、什么是线程池 Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序 都可以使用线程池。在开发过程中,合理地使用线程池能够带来3个好处。 第一:降...

codeobj
23分钟前
2
0
知识点总结思维导图模板分享,良心安利,建议收藏

思维导图经常被用在学习中,对大脑思维进行发散,对知识进行记忆。使用思维导图可以让知识更加简单更有层次。下面是利用思维导图所绘制的几款知识点总结思维导图模板,大家可以进行进行参考使...

干货趣分享
26分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部