0%

[OpenWrt]目录结构、创建维护feeds、创建package及其编译安装

总结OpenWRT目录结构,然后创建feeds,并创建package。

编译package,并安装到target进行测试。

1 OpenWRT目录结构

OpenWRT的目录结构解释如下,高亮部分是编译后创建的:

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
├── bin--编译完成后ipk和image文件存放在此。
│ ├── packages--存放base/luci/packages/routing/telephony等编译出来的ipk包。
│ └── targets--目标镜像文件。
├── BSDmakefile
├── build_dir--下载的软件包解压到此,然后进行编译。
│ ├── hostpkg--编译在host环境中使用的工具。
│ ├── target-aarch64_cortex-a53_musl--编译在target环境中使用的工具。
│ └── toolchain-aarch64_cortex-a53_gcc-11.2.0_musl--交叉工具链的编译。
├── config--menuconfig配置文件。
│ ├── check-uname.sh
│ ├── Config-build.in
│ ├── Config-devel.in
│ ├── Config-images.in
│ └── Config-kernel.in
├── Config.in--配置文件的总入口。
├── COPYING
├── dl--下载的软件包存放在此目录。
│ ├── attr-2.5.1.tar.gz
...
│ └── zstd-1.5.5.tar.gz
├── feeds--根据feeds.conf.default生成的OpenWRT的package来源地。
│ ├── luci
│ ├── luci.index -> luci.tmp/.packageinfo
│ ├── luci.targetindex -> luci.tmp/.targetinfo
│ ├── luci.tmp
│ ├── packages
│ ├── packages.index -> packages.tmp/.packageinfo
│ ├── packages.targetindex -> packages.tmp/.targetinfo
│ ├── packages.tmp
│ ├── routing
│ ├── routing.index -> routing.tmp/.packageinfo
│ ├── routing.targetindex -> routing.tmp/.targetinfo
│ ├── routing.tmp
│ ├── telephony
│ ├── telephony.index -> telephony.tmp/.packageinfo
│ ├── telephony.targetindex -> telephony.tmp/.targetinfo
│ └── telephony.tmp
├── feeds.conf.default
├── include--存放mk文件。
│ ├── autotools.mk
...
│ └── version.mk
├── key-build
├── key-build.pub
├── key-build.ucert
├── key-build.ucert.revoke
├── LICENSES
│ ├── BSD-2-Clause
│ ├── BSD-3-Clause
│ ├── GPL-1.0
│ ├── GPL-2.0
│ ├── ISC
│ ├── Linux-syscall-note
│ └── MIT
├── Makefile--make默认的配置文件。
├── package--不同类别package的makefile文件和menuconfig配置文件。
│ ├── base-files
│ ├── boot
│ ├── devel
│ ├── feeds
│ ├── firmware
│ ├── kernel
│ ├── libs
│ ├── Makefile
│ ├── network
│ ├── system
│ └── utils
├── README.md
├── rules.mk
├── scripts--编译过程中使用的脚本文件。
│ ├── arm-magic.sh
...
│ └── xxdi.pl
├── staging_dir--生成最终文件系统之前的临时安装目录。
│ ├── host
│ ├── hostpkg
│ ├── packages
│ ├── target-aarch64_cortex-a53_musl
│ └── toolchain-aarch64_cortex-a53_gcc-11.2.0_musl
├── target--imagebuilder、linux、sdk、toolchain的makefile和配置文件。
│ ├── Config.in
│ ├── imagebuilder
│ ├── linux
│ ├── llvm-bpf
│ ├── Makefile
│ ├── sdk
│ └── toolchain
├── tmp
│ ├── a.out
│ ├── info
│ ├── opkg_install_list
│ └── test.fs
├── toolchain--编译gcc/binutils/gdb/glibc/mold/must/nasm等工具的makefile文件和配置文件。
│ ├── binutils
│ ├── build_version
│ ├── Config.in
│ ├── fortify-headers
│ ├── gcc
│ ├── gdb
│ ├── glibc
│ ├── info.mk
│ ├── kernel-headers
│ ├── Makefile
│ ├── musl
│ ├── nasm
│ └── wrapper
└── tools--编译过程中所使用到的工具。
├── autoconf
...
└── zstd

2 OpenWRT feeds管理

feeds是一系列package的存放点。scripts/feeds脚本用于管理feeds。feeds.conf.default用于配置feeds。更多参考:参考:[OpenWrt Wiki] OpenWrt Feeds

2.1 feeds管理

./scripts/feeds用于管理OpenWRT的feeds:

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
32
33
Usage: ./scripts/feeds <command> [options]

Commands:
list [options]: List feeds, their content and revisions (if installed)
Options:
-n : List of feed names.
-s : List of feed names and their URL.
-r <feedname>: List packages of specified feed.
-d <delimiter>: Use specified delimiter to distinguish rows (default: spaces)
-f : List feeds in feeds.conf compatible format (when using -s).

install [options] <package>: Install a package
Options:
-a : Install all packages from all feeds or from the specified feed using the -p option.
-p <feedname>: Prefer this feed when installing packages.
-d <y|m|n>: Set default for newly installed packages.
-f : Install will be forced even if the package exists in core OpenWrt (override)

search [options] <substring>: Search for a package
Options:
-r <feedname>: Only search in this feed

uninstall -a|<package>: Uninstall a package
Options:
-a : Uninstalls all packages.

update -a|<feedname(s)>: Update packages and lists of feeds in feeds.conf .
Options:
-a : Update all feeds listed within feeds.conf. Otherwise the specified feeds will be updated.
-i : Recreate the index only. No feed update from repository is performed.
-f : Force updating feeds even if there are changed, uncommitted files.

clean: Remove downloaded/generated files.
  • update:根据feeds.conf获取package,并拷贝到feeds目录下。
  • list:显示feeds,或其package列表详细信息。
  • install:将update命令从feeds获取packages链接到package/feeds/中。
  • uninstall:移除某个package。
  • search:查找特定package信息。

2.2 新增feeds

修改feeds.conf.default文件,新增feeds配置:

Method Function
src-bzr Data is downloaded from the source path/URL using bzr
src-cpy Data is copied from the source path. The path can be specified as either relative to OpenWrt repository root or absolute.
src-darcs Data is downloaded from the source path/URL using darcs
src-git Data is downloaded from the source path/URL using git as a shallow (depth of 1) clone
src-git-full Data is downloaded from the source path/URL using git as a full clone
src-gitsvn Bidirectional operation between a Subversion repository and git
src-hg Data is downloaded from the source path/URL using hg
src-link A symlink to the source path is created. The path must be absolute.
src-svn Data is downloaded from the source path/URL using svn

以git为例:

1
2
src-git local_feed_name https://example.com/repo_name/something.git;branch_name
src-git local_feed_name https://example.com/repo_name/something.git^commit_hash

3 OpenWRT编译流程

3.1 整体编译

在对OpenWRT的feeds进行配置后,可以进行配置和编译。

配置toolchain、kernel、packages:

1
make menuconfig

make即可开始编译:

  • 下载选中的package源码。
  • 编译交叉编译工具链和host应用。
  • 交叉编译kernel和选中的packages。

make V=x指定输出的不同编译log等级:

1
2
3
4
5
6
7
8
V=99 and V=1 are now deprecated in favor of a new verbosity class system,
though the old flags are still supported.
You can set the V variable on the command line (or OPENWRT_VERBOSE in the
environment) to one or more of the following characters:

- s: stdout+stderr (equal to the old V=99)
- c: commands (for build systems that suppress commands by default, e.g. kbuild, cmake)
- w: warnings/errors only (equal to the old V=1)

其他常见编译操作:

  • 运行make menuconfig选定目标映像;
  • 运行make defconfig为构建环境和设备设定默认配置;
  • 运行make kernel_menuconfig(可选);
  • 运行make menuconfig配置软件包;
  • 运行make download(在最终构建前下载所有依赖, 并激活多线程编译);
  • 运行scripts/diffconfig.sh >mydiffconfig(将所有修改保存到mydiffconfig文件);

3.2 package编译

单独编译某一个模块:

1
2
3
4
5
make package/example/download - download the soures of example
make package/example/prepare - extract the sources, apply patches and download if necessary
make package/example/compile - compile example, prepare and download if necessary
make package/example/clean - clean the sourcecode
make package/index - build a repository index to make the output directory usable as local opkg source

对一个package执行多个编译选项,注意clean和compile之间不能有空格:

1
make package/example/{clean,compile} V=99

编译中间过程位于build_dir中,按照不同的package分列,里面包含源代码、编译脚本、编译中间文件以及输出可执行或者库文件等:

1
2
3
4
5
6
build_dir/target-aarch64_cortex-a53_musl/
├── busybox-default...
├── root-armvirt--即将要打包的rootfs文件集合。
├── root.orig-armvirt
...
└── zlib-1.2.11

staging_dir是一个临时集合,后面可能还会有strip等操作:

1
2
3
4
5
6
7
staging_dir/target-aarch64_cortex-a53_musl/
├── host
├── packages
├── pkginfo
├── root-armvirt
├── stamp
└── usr

bin中存放最终镜像和安装包:

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
bin/targets/
└── armvirt
└── 64
├── config.buildinfo
├── feeds.buildinfo
├── openwrt-armvirt-64-default.manifest
├── openwrt-armvirt-64-default-rootfs.tar.gz
├── openwrt-armvirt-64-Image
├── openwrt-armvirt-64-Image-initramfs
├── openwrt-armvirt-64-rootfs.cpio.gz
├── openwrt-armvirt-64-rootfs-ext4.img.gz
├── openwrt-armvirt-64-rootfs-squashfs.img.gz
├── packages
│ ├── base-files_1505-r20341-591b7e93d3_aarch64_cortex-a53.ipk
│ ├── dropbear_2022.82-4_aarch64_cortex-a53.ipk
│ ├── fstools_2022-06-02-93369be0-2_aarch64_cortex-a53.ipk
│ ├── fwtool_2019-11-12-8f7fe925-1_aarch64_cortex-a53.ipk
│ ├── index.json
│ ├── kernel_5.10.221-1-95f66e1daaaff0091d354d5d867e8a64_aarch64_cortex-a53.ipk
...
│ ├── mtd_26_aarch64_cortex-a53.ipk
│ ├── Packages
│ ├── Packages.gz
│ ├── Packages.manifest
│ └── Packages.sig
├── sha256sums
└── version.buildinfo

4 OpenWRT新增package和feeds

参考:《[OpenWrt Wiki] Creating a simple “Hello, world!” application》、《[OpenWrt Wiki] Creating a package from your application》、《[OpenWrt Wiki] Including your package feed into OpenWrt build system》、《[OpenWrt Wiki] Building, deploying and testing your application》。

4.1 创建package内容

编写测试程序hello world.c:

1
2
3
4
5
6
7
#include <stdio.h>

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

编写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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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/al/openwrt/openwrt/mypackages/examples/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)
$(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 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))

4.2 创建feeds并安装

为helloworld package创建feeds目录,并将hello world.c和Makefile放入其中:

1
2
3
4
5
mypackages/
└── examples
└── helloworld
├── helloworld.c
└── Makefile

修改feeds.conf.default文件:

1
2
3
4
5
src-git-full packages https://git.openwrt.org/feed/packages.git;openwrt-22.03
src-git-full luci https://git.openwrt.org/project/luci.git;openwrt-22.03
src-git-full routing https://git.openwrt.org/feed/routing.git;openwrt-22.03
src-git-full telephony https://git.openwrt.org/feed/telephony.git;openwrt-22.03
src-link mypackages /home/al/openwrt/openwrt/mypackages

单独更新mypackages feed:

1
./scripts/feeds update mypackage

在feeds下创建mypackages feed相关信息:

1
2
3
4
5
6
7
feeds
├── mypackages -> /home/al/openwrt/openwrt/mypackages
├── mypackages.index -> mypackages.tmp/.packageinfo
├── mypackages.targetindex -> mypackages.tmp/.targetinfo
├── mypackages.tmp
│ ├── info
│ └── location

将mypackages feed的package安装到OpenWRT系统中:

1
./scripts/feeds install -a -p mypackages

安装结果如下:

1
2
package/feeds/mypackages/
└── helloworld -> ../../../feeds/mypackages/examples/helloworld

4.3 配置并编译package

make menuconfig选择helloworld,并保存配置:

img

编译helloworld:

1
make package/feeds/mypackages/helloworld/compile

在./build_dir/target-aarch64_cortex-a53_musl/helloworld-1.0目录存放编译过程文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
./build_dir/target-aarch64_cortex-a53_musl/helloworld-1.0
├── helloworld
├── helloworld.c
├── helloworld.o
├── ipkg-aarch64_cortex-a53
│ └── helloworld
│ ├── CONTROL
│ │ ├── control
│ │ ├── postinst
│ │ └── prerm
│ └── usr
│ └── bin
│ └── helloworld
└── Makefile

生成ipkg安装包位于./bin/packages/aarch64_cortex-a53/mypackages/:

1
2
./bin/packages/aarch64_cortex-a53/mypackages/
└── helloworld_1.0-1_aarch64_cortex-a53.ipk

根据Makefile配置helloworld也被安装到staging_dir下:
./staging_dir/target-aarch64_cortex-a53_musl/root-armvirt/usr/bin/helloworld。

此时如果执行make,则helloworld可执行文件已经位于镜像中,烧录启动即可使用。

4.4 安装卸载package

通过scp将ipk传到target:

1
scp bin/packages/aarch64_cortex-a53/mypackages/helloworld_1.0-1_aarch64_cortex-a53.ipk root@192.168.2.2:/

安装ipk:

1
opkg install helloworld_1.0-1_aarch64_cortex-a53.ipk

执行helloworld:

1
Hello, world!

卸载helloworld:

1
opkg remove helloworld

opkg显示已安装列表:

1
opkg list

转载:https://www.cnblogs.com/arnoldlu/p/18306851