首页 > 其他分享 >在OpenWrt中添加package

在OpenWrt中添加package

时间:2024-08-02 17:19:06浏览次数:14  
标签:package make helloworld source 添加 buildbot home OpenWrt

Add new package to Openwrt

主要记录笔者学习官方教程"Hello, world!" package for OpenWrt的经历,并对在OpenWrt下加包的流程进行梳理。

  在开始之前我们先约定开发环境:

  • 开发的主目录为/home/buildbot
  • 使用的OpenWrt版本为v23.05.3
  • WSL2+Ubuntu20.04
  • gcc的版本是9.4.0

1. Preparing your OpenWrt build system for use

公司的网络可以直接连到OpenWrt官网并提供可观的下载速度,因此我们可以直接使用以下命令下载源码:

git clone https://git.openwrt.org/openwrt/openwrt.git source

这会把代码下载到source文件夹下,即/home/buildbot/source。此外在GitHub上也有OpenWrt的镜像。
进入source目录,切换到我们需要的分支上:

cd /home/buildbot/source
git checkout v23.05.3
make distclean

此时推荐更新我们的feeds包(在OpenWrtfeed是一组共享相同位置的包的集合。更近一步的信息参考OpenWrt Feeds),更新的命令如下:

./scripts/feeds update -a
./scripts/feeds install -a

可用的feed列表在feeds.conffeeds.conf.default下进行配置,默认的情况下feeds.conf.defaultopenwrt目录下,也就是本文中的source。我们可以看一下的它的内容:

src-git packages https://git.openwrt.org/feed/packages.git^063b2393cbc3e5aab9d2b40b2911cab1c3967c59
src-git luci https://git.openwrt.org/project/luci.git^b07cf9dcfc37e021e5619a41c847e63afbd5d34a
src-git routing https://git.openwrt.org/feed/routing.git^648753932d5a7deff7f2bdb33c000018a709ad84
src-git telephony https://git.openwrt.org/feed/telephony.git^86af194d03592121f5321474ec9918dd109d3057

由于某些原因对这些网址的访问将会变得艰难(是的,就是那个原因),因此在自己电脑上运行的时候可以考虑把网址修改一下,比如去gitee看看有没有好心人搬运,或者干脆自己动手。但好在公司的网络依然给力。feeds.conf可以由我们自己创建,我们自己写的包就可以放在这里。

接下来配置我们的交叉编译链:

make menuconfig

在菜单里我们可以选择Target System(目标架构),Subtarget(更细化的架构)和Target Profile(一些配置)。教程作者选用了Lantiq、XRX200、P2812HNU-F1,但是笔者什么也没有。选择结束之后保存你的配置并且退出,此时他会让你给配置文件命名。这里的建议是直接采用默认的.config,不然还要连带着修改很多别的地方。

以上结束之后开始编译我们的工具链:

make toolchain/install

按照教程作者的说法这个时候你可以去喝杯咖啡,但实际操作中耗时远比想象中更长。主要的时间浪费在下载Linux5.15的内核,在这一点上公司的网络也没有太大帮助。建议上午开始做这件事情,不然就等着拿餐补吧。

工具链会被放在staging_dir/host/staging_dir/toolchain/下面,所有一个建议是把他们添加到环境变量里:

export PATH=/home/buildbot/source/staging_dir/host/bin:$PATH

以上。

2. Creating a simple "Hello,world!" application

  出于SoC(Separation of Concerns)的目的我们单开一个文件夹写代码:

cd /home/buildbot
mkdir helloworld
cd helloworld
touch helloworld.c

文档的代码如下,当然你可以不按照它的写:

#include <stdio.h>
 
int main(void)
{
    printf("\nHello, world!\n\n");
    return 0;
}

接下来就是运行一下你的代码看看有没有问题,注意到这里还是使用本地的编译工具。此外编译选项建议加上-Wall-Werror(多加点小心总归是好事),对了,结束之后记得把这些生成文件删除掉,包代码里面不需要这些东西。

3. Creatint a package from your application

  接下里为我们的包创建feed

cd /home/buildbot
mkdir -p mypackages/examples/helloworld

OpenWrt构建系统中的每一个包都由一个包清单文件(package mnanifest file)描述,包清单文件描述了包的功能,源码位置,编译方式以及最终安装包中含有的文件,并可能包括一些配置脚本。所以接下来我们创建这个清单文件:

cd home/buildbot/mypackages/examples/helloworld
touch Makefile

一个可参考的Makefile如下:

include $(TOPDIR)/rules.mk

# Name, version and release number
# The name and version of your package are used to define 
# the variable to point to the build directory of your package : $(PKG_BUILD_DIR)
PKG_NAME:=helloworld
PKG_VERSION:=1.0
PKG_RELEASE:=1

# Source settings (i.e. where to find the source codes)
# This is a custom variable, used below
SOURCE_DIR:=/home/wjm/projects/buildbot/helloworld

include $(INCLUDE_DIR)/package.mk

# Package definition; instructs on how and where our package will appear in the overall
# configuration menu ('make menuconfig')
define Package/helloworld
	SECTION:=examples
	CATEGORY:=Examples
	TITLE:=Hello,World!
endef

# Package description; a more verbose description on what our package does
define Package/helloworld/description
	A simple "Hello, world!" -application.
endef

# Package preparation instructions; create the build directory and copy the source code.
# The last command is necessary to ensure our preparation instructions remain compatible
# with the patching system.
define Build/Prepare
	mkdir -p $(PKG_BUILD_DIR)
	cp $(SOURCE_DIR)/* $(PKG_BUILD_DIR) -r
	$(Build/Patch)
endef

# Package build instructions; invoke the target-specific compiler to first compile the source file,
# and then to link the file into the final executable
# define Build/Compile
# 	$(TARGET_CC) $(TARGET_CFLAGS) -o $(PKG_BUILD_DIR)/helloworld.o -c $(PKG_BUILD_DIR)/helloworld.c
# 	$(TARGET_CC) $(TARGET_LDFLAGS) -o $(PKG_BUILD_DIR)/$1 $(PKG_BUILD_DIR)/helloworld.o
# endef

# Package build instructions; invoke the GNU make tool to build our package
define Build/Compile
	$(MAKE) -C $(PKG_BUILD_DIR) \
	CC="$(TARGET_CC)" \
	CFLAGS="$(TARGET_CFLAGS)" \
	LDFLAGS="$(TARGET_LDFLAGS)"
endef

# Package install instructions; create a directory inside the package to hold our executable,
# and then copy the executable we built previously into the folder
define Package/helloworld/install
	$(INSTALL_DIR) $(1)/usr/bin
	$(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/usr/bin
endef

# This command is always the last, it uses the definitions and variables we give above in order to
# get the job done
$(eval $(call BuildPackage,helloworld))

注意到这里的cp指令其实比教程中多了一个-r,考虑到实际的包往往结构复杂,所以这里未雨绸缪一下(单押成功)。关于Build/Compile,教程提供的是注释掉的版本,在后面会解释为什么会做这样的修改。此外make对空格极不友好,比如CC="$(TARGET_CC)"中在赋值号左右加上空格就会报错,因为它会把这些理解成选项。

4. Inculding your package feed into OpenWrt build system

OpenWrtfeeds.conf来表示在固件配置阶段提供的feeds,那么为了把我们自己的feed包括进去,我们需要创建feeds.conf

cd /home/buildbot/source
touch feeds.conf

接下来我们修改feeds.conf来指定本地的package feed

src-link mypackages /home/buildbot/mypackages

既然加入了新的feed,那么当然要更新一下啦:

cd /home/buildbot/source
./scripts/feeds update mypackages
./scripts/feeds install -a -p mypackages

feeds系统会自动检测清单文件内的变化,并在需要时进行更新。

5. Building, deploying and testing your applicatin

  为了将我们的包集成进来,运行make menuconfig并选中我们的包。在离开菜单之后运行下述命令编译我们的包:

make package/helloworld/compile

如果一切顺利,那我们将在bin/package/<arch>/mypackages文件夹下看到helloworld_1.0-1_<arch>.ipk

之后是部署我们的包,因为笔者手头并没有合适的设备,所以我们略过这里...

6. Migrating to use GNU make in your application

  考虑到实际包的代码不会像我们的helloworld一样简单,所以把它的编译方式硬编码到清单文件中其实并不合适,所以我们会在源码中额外提供一个Makefile

cd /home/buildbot/helloworld
touch Makefile

一个可参考的Makefile如下:

# Global target; when 'make' si run without arguments, this is what it should do
all:helloworld

# These variables hold the name of the compilation tool, the compilation flags and the link flags
# We make use of these variables in the package manifest
CC = gcc
CFLAGS = -Wall
LDFLAGS = 

# This variable identifies all header files in the directory; we use it to create a dependency chain 
# between the object files and the source files
# This approach will re-build your application whenever any header file changes. In a more complex application,
# such behavior is often undesirable
DEPS = $(wildcard *.h)

# This variable holds all source files to consider for the build; we use a wildcard to pick all files 
SRC = $(wildcard *.c)

# This variable holds all object file names, constructed from the source file names using pattern substitution
OBJ = $(patsubst %.c, %.o, $(SRC))

# This rule builds individual object files, and depends on the corresponding C source files and the header files
%.o: %.c $(DEPS)
	$(CC) -c -o $@ $< $(CFLAGS)

# To build 'helloworld', we depend on the object files, and link them all into a single executable using the 
# compilation tool
# We use automatic variables to specify the final executable name 'helloworld', using '$@' and the '$^' will hold 
# the names of all the dependencies of this rule
helloworld: $(OBJ)
	$(CC) -o $@ $^ $(LDFLAGS)

# To clean build artifacts, we specify a 'clean; rule, and use PHONY to indicate that this rule never matches with 
# a potential file in the directory
.PHONY: clean
clean:
	rm -f helloworld *.o

接可以跑一下make看看有没有问题(再次提醒没有把握的不要乱加空格),一切安好的话可以更新一下清单文件,也就是我们第三部分提供的Makefile(如果你一开始用的就是更新过的Makefile,那就什么都不用做)。

接下来测试一下我们的包:

cd /home/buildbot/source
make package/helloworld/{clean,compile}

如果这一步遇到问题的话可能有两种情况:

  • 更新feeds
      cd /home/buildbot/source
      ./scripts/feeds update mypackages
      ./scripts/feeds install -a -p mypackages
    
  • 记得删除源码目录下的目标文件和可执行文件。

7. Patching your application: Adding new files

  考虑到程序的修改需求,OpenWrt支持patch,完成这项任务的工具是Quilt。关于Quilt可以参考这篇文档Working with patches,在开始后续操作之前最好先配置一下。

还记得第一部分中添加的环境变量吗?如果你做了这件事你会发现在bin下面存在一个quilt,但是在笔者的操作中会发现这个quilt的功能并不完善,所以笔者还是建议sudo一下(sudo,启动!)。

cd /home/buildbot/source/
make package/helloworld/{clean,prepare} QUILT=1
cd build_dir/target-.../helloworld-1.0/
quilt push -a

在这里quilt报错是很正常的事情,因为我们还没有patch。稳住。

quilt new 100-add_module_files.patch

patch的名字来源于OpenWrt的惯例:一个可能含有某些意义的数字+一段简短的描述。这个命令的输出将告诉你patch被创建并且处于patch stack的顶端。

接下来是我们patch的源码:

quilt add functions.c
quilt add functions.h

touch functions.c
quilt edit functions.c

touch functions.h
quilt functions.h

具体的内容如下:

//functions.c
int add(int a, int b)
{
    return a + b;
}
//functions.h
int add(int, int);

如果你参考了quilt文档的默认配置,那使用的编辑器应该是nano。写完代码之后用Ctrl+o保存,Enter确定文件名,Ctrl+x退出。

可以使用quilt diff 查看前后的差别,如果确认修改正确,使用quilt refresh接受。

OpenWrt中,patch在源码路径创建,然后迁移到所属的package中。为了迁移我们的patch,执行如下的命令:

cd /home/buildbot/source
make package/helloworld/update

为了确保我们的patch被正确应用了:

cd /home/buildbot/source
make package/helloworld/{clean,prepare}
ls -la build_dir/target-<arch>_<subarch>_<clib>_<clibversion>/

通过上述命令我们可以看到我们的patch被应用了,并且新的文件在构建目录中。

8. Patching your application: Editing existing files

  因为我们不是总需要创建新的文件,很多时候只是在之前的文件上修修补补,所以有了这么一节

标签:package,make,helloworld,source,添加,buildbot,home,OpenWrt
From: https://www.cnblogs.com/shaoxuan/p/18339188

相关文章

  • 将 cookie 数据添加到 requests.urlretrieve 中
    我正在尝试从受密码保护的网站下载.torrent文件。我已经成功地使用cookie访问该网站,如下所示:cookies={'uid':'232323','pass':'31321231jh12j3hj213hj213hk','__cfduid':'kj123kj21kj31k23jkl21j321j3kl213kl21j3'}......
  • Animate软件基础:在时间轴中添加或插入帧
    FlashASer:AdobeAnimate2021软件零基础入门教程https://zhuanlan.zhihu.com/p/633230084FlashASer:实用的各种AdobeAnimate软件教程https://zhuanlan.zhihu.com/p/675680471FlashASer:Animate教程及作品源文件https://zhuanlan.zhihu.com/p/677437436FlashASer:Animate2022零......
  • platformio 添加github的库
    platformio添加github的库在PlatformIO中添加GitHub上的库,你需要在项目的platformio.ini文件中使用库的GitHubURL。以下是添加库的步骤:打开你的PlatformIO项目的platformio.ini文件。在[env:default]部分或者特定的环境部分下,使用lib_deps指令添加GitHub上的库......
  • 直接添加GO词云到基因表达热图上
    我想这将是一个非常有用的功能。对于一个基因表达热图,如果对热图中的行进行了切分,那么这个新的anno_GO_keywords()函数会自动对每个rowcluster中的基因进行基因集合富集分析(Genesetenrichmentanalysis/over-representationanalysis),然后提取显著的GO条目,提取其关键词,通......
  • 前端项目package.json文件引用本地依赖
    在前端项目的package.json文件中引用本地依赖,可以使用以下几种方式:1.使用file:前缀如果本地依赖是一个已经存在的目录,可以在package.json中使用file:前缀来引用它。{"dependencies":{"your-local-package":"file:../path-to-your-local-package"}}2.......
  • mapbox 结合deckgl添加3DTiles等操作
    1.初始化import{MapboxOverlay}from"@deck.gl/mapbox";import{LineLayer,GeoJsonLayer}from"@deck.gl/layers"; import{TripsLayer,Tile3DLayer}from"@deck.gl/geo-layers"; import{Tiles3DLoader}from"@loade......
  • Maven手动添加jar项目导本地、通过pom.xml引入依赖、打包后依然生效
    1、到jar包目录、cmd以管理员身份运行、执行如下命令mvninstall:install-file-Dfile=sqljdbc4.jar-Dpackaging=jar-DgroupId=com.microsoft.sqlserver-DartifactId=sqljdbc4-Dversion=4.02、pom.xml进行引入`<dependency> <groupId>com.microsoft.sqlserver</groupI......
  • 为什么当我们返回主程序时,这个全局不会保持更新,除非我向程序添加一个新的入口点?
    m1是collect_finetuning.py中的全局变量:m1:list=[]当我通过以下方式运行collect_finetuning.py时:if__name__=="__main__":main()我们看到这种行为,其中collect_finetuning中的函数更新了m1,并且它丢失了main()中的更新值:|||我能够在第二张图片......
  • 如何将优先级任务添加到celery队列而不禁用获取
    我有一个celery工作线程,并发度设置为1,它从RabbitMQ获取任务。我想创建一个在单个并发设置中只有一个队列的系统,因此,所有任务都将添加到主队列中。关于任务-它只是一个循环,我们用更新状态。|||并行地我有两个服务。task.update_state()Celery-beat......
  • 如何使用“pyroute2”“添加”通过“get”接收的路由?
    不幸的是,pyroute2模块的文档相当具体,所以我找不到我遇到的一个特定问题的答案。我的目标是保存一个特定表(让我们将其命名为表A)中的所有路由,然后恢复它们。我可以(显然)接收路由转储并使用单个命令清除表:IPRoute().flush_routes(table=A)路线存储为字典......