diff --git a/articles/20240927-tinybpt-client-usage.md b/articles/20240927-tinybpt-client-usage.md new file mode 100644 index 0000000000000000000000000000000000000000..f60e85f60141f32ebccc03aea34610210c846cd0 --- /dev/null +++ b/articles/20240927-tinybpt-client-usage.md @@ -0,0 +1,150 @@ +> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [tounix spaces]
+> Author: 柴子轩
+> Date: 2024/09/27
+> Revisor: falcon
+> Project: [RISC-V Linux 内核剖析](https://gitee.com/tinylab/riscv-linux)
+> Sponsor: PLCT Lab, ISCAS + +# TinyBPT 和面向 buildroot 的二进制包管理服务(2):客户端说明 + +## 前言 + +TinyBPT (Tiny Buildroot Packaging Tool) 是一个 buildroot 的包管理工具,主要处理 buildroot 的包依赖关系,提供包的安装、卸载等功能。 + +本文档主要介绍 TinyBPT 客户端的使用。 + +## 安装方法 + +如果要在 `buildroot` 构建的子系统中直接安装,则需要在主机下载后通过构建本地 `HTTP` 服务的方式提供给子系统下载。(如果在构建系统时已经配置了 `HTTPS` 相关服务,则可以直接使用 `HTTPS` 服务下载。) + +默认下载为 RISC-V 64 位的版本,下载后解压到 `/` 目录下即可。 + +本地编译则需要先编译 `OpenSSL`,下载源码后执行如下命令: + +```shell +./Configure linux64-riscv64 no-zlib no-rc2 no-idea no-des no-bf no-cast no-md2 no-mdc2 no-dh no-err no-rc5 no-camellia no-seed no-tests -static --prefix=/usr/local/openssl/riscv64 --cross-compile-prefix=riscv64-linux-gnu- -flto + +make -j$(nproc) +make install_sw +``` + +使用 `no-*` 的配置选项目的是禁用多个加密算法和功能,以减少库的体积和依赖,并使用 `-flto` 启用链接时优化(Link Time Optimization),以提高生成代码的性能。 + +如果这些流程均在主机(非 `riscv` 机器)中完成,则需要将编译好的二进制文件,依赖文件和 `CA` 证书移动到嵌入式设备(`riscv` 机器)中。 + +如果是以调试为目的,可以使用 `ARCH=x86_64` 选项进行编译,或者使用 `CMake`。编译完成后,只需要将依赖文件移动到相应位置,或者在环境变量中设置 `TINYBPT_DB_PATH`。 + +### 直接安装 + +```shell +wget https://mirrors.lzu.edu.cn/buildroot-pkgs/riscv64/tinybpt/tinybpt-v0.1-rc1.tar.gz +mkdir -p /etc/tinybpt && mkdir -p /etc/ssl/certs +tar -xvf tinybpt-v0.1-rc1.tar.gz -C / +``` + +### 本地 Makefile 编译安装 + +移动到 `tinybpt` 目录下,执行如下命令: + +```shell +make ARCH=riscv64 -j$(nproc) +``` + +```shell +git clone https://gitee.com/tinylab/tinybpt.git +cd tinybpt +wget https://curl.se/ca/cacert.pem +make +make install +``` + +### 本地 CMake 编译安装 + +同上,先编译 `OpenSSL`,然后执行如下命令: + +```shell +git clone https://gitee.com/tinylab/tinybpt.git tinybpt +cmake -S tinybpt + -B build \ + -G Ninja +ninja -C build +ninja -C tinybpt/build install +``` + +### 使用环境变量指定依赖和下载路径(可选) + +默认情况下,TinyBPT 会将依赖和下载的文件存储在 `/etc/tinybpt` 和 `/var/cache/tinybpt` 目录下,如果需要指定其他路径,可以使用环境变量 `TINYBPT_DB_PATH` 和 `TINYBPT_DOWNLOAD_PATH`。 + +```shell +export TINYBPT_DB_PATH=/tinybpt_db.json +export TINYBPT_DOWNLOAD_PATH= +``` + +## 使用方法 + +```shell +# tinybpt +Tiny buildroot packaging tool + +Usage: tinybpt [options] + +Commands: + install Install package + uninstall [-f] Uninstall package (use -f to force uninstall) + list -all/-installed List all/installed packages + find Find package + +Options: + -h, -help + Show help information + -V, -version + Show version information + -set-mirror Set mirror URL + -get-mirror Show mirror URL +``` + +## 基本操作 + +使用 `tinybpt install/uninstall/list/find ` 进行包的安装、卸载、查找、列出操作。 + +```shell +# 安装包 +tinybpt install + +# 卸载包 +tinybpt uninstall + +# 列出所有包 +tinybpt list -all + +# 列出已安装的包 +tinybpt list -installed + +# 查找包 +tinybpt find + +# 设置镜像 URL +tinybpt -set-mirror + +# 获取镜像 URL +tinybpt -get-mirror + +# 显示帮助信息 +tinybpt -h + +# 显示版本信息 +tinybpt -V +``` + +## 其他说明 + +- 本工具仅支持 riscv64 buildroot 用户使用,其他架构的支持也将陆续开展,敬请期待! +- 本工具使用 CA 证书为 CA certificates extracted from Mozilla。 +- 本项目使用了基于 MIT 协议的第三方库 [nlohmann/json][001] 和 [cpp-httplib][002]。 + +## 参考资料 + +- [TinyBPT](https://gitee.com/tinylab/tinybpt) + +[001]: https://github.com/nlohmann/json +[002]: https://github.com/yhirose/cpp-httplib diff --git a/articles/20240927-tinybpt-design.md b/articles/20240927-tinybpt-design.md new file mode 100644 index 0000000000000000000000000000000000000000..2ab2caf8252d24e2ee82e2aae9b8b6f908bbbd14 --- /dev/null +++ b/articles/20240927-tinybpt-design.md @@ -0,0 +1,243 @@ +> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [tounix spaces header urls]
+> Author: 柴子轩
+> Date: 2024/09/27
+> Revisor: falcon
+> Project: [RISC-V Linux 内核剖析](https://gitee.com/tinylab/riscv-linux)
+> Sponsor: PLCT Lab, ISCAS + +# TinyBPT 和面向 buildroot 的二进制包管理服务(1):设计简介与框架 + +## 前言 + +在 buildroot 的使用过程中,我们经常会遇到一些问题,比如因为网络链接导致的编译失败,编译时间过长,或者想要使用某些特定软件时需要重新编译整个系统等。 + +本项目旨在解决这些问题,为 buildroot 搭建国内镜像站并新建一套面向 buildroot 的二进制包管理服务。并提供一个简单的、易于使用的 buildroot 包管理工具,[TinyBPT][001] 因此诞生了。 + +## 软件源与包管理 + +软件源镜像方法是确认上游源,同步到本地然后设置下载链接配置,还需要给同步程序设置选项使其忽略错误,防止因为某个软件包的链接失效导致整个同步过程失败,也可增加镜像站稳定性。同时,要补充 buildroot 源代码镜像的文档。 + +在搭建镜像站的过程中,一般会确定镜像站的上游源,使用 rsync 或者 wget 等工具将上游源的数据同步到镜像站上,然后通过 HTTP 或者 FTP 等协议对外提供服务。添加 buildroot 的镜像源,需要将 buildroot 的软件包源同步到镜像站上,然后通过设置 buildroot 的配置文件,将软件包的下载地址指向镜像站的地址。 + +为了提供一个稳定并可以持续更新的 buildroot 国内镜像源,在[兰州大学开源镜像][005]站上,我使用 [tsumugu][003] 工具同步 buildroot 的官方镜像源,将同步后的数据上传到镜像站上,并对外提供服务。 + +在此基础上,我尝试设计了 buildroot 包管理工具 TinyBPT,全称为 Tiny Buildroot Packaging Tool,其设计初衷是一个 buildroot 的二进制包管理工具,主要处理 buildroot 的包依赖关系,提供包的安装、卸载等功能。 + +## 依赖和协议 + +我在调研了一些现有的包管理器,例如 apt 、 yum 、 dnf 、 pacman 等后认为,它们都提供了类似的功 +能,但实现方式可能有所不同。例如, apt 使用 dpkg 来管理软件包,而 yum 使用 rpm ,等等。 + +在 apt 实现中,软件包的信息存储在 `/var/lib/dpkg/status` 文件中,这个文件包含了软件包的名称、版本、描述、依赖关系等信息。`apt-get update` 命令会从软件源获取最新的软件包信息,并更新 `/var/lib/dpkg/status` 文件。 + +因此在整个项目中,最核心的部分在于编译后二进制包的依赖问题。首先,buildroot 软件包并没有规范的依赖文件,大多数配置被写在 .mk 以及 .in,甚至 .in.host 文件中。这就导致了我需要自己去解析这些文件,提取出依赖关系。在通过对配置文件的简单分析后,我认为大部分都可以通过正则表达式来提取依赖关系。 + +在大多数 package 目录下的软件包配置文件中,.mk 文件格式大多不同,解析困难。但在大多数 .hash 文件中却有非常规范的 sha256、包名(含版本号)信息,例如: + +```shell +# Locally calculated after checking pgp signature +sha256 97203a72cae99ab89a067fe2210c1cbf052bc492b479eca7d226d9830883b0bd acl-2.3.2.tar.xz + +# Locally calculated +sha256 a45a845012742796534f7e91fe623262ccfb99460a2bd04015bd28d66fba95b8 doc/COPYING +sha256 01b1f9f2c8ee648a7a596a1abe8aa4ed7899b1c9e5551bda06da6e422b04aa55 doc/COPYING.LGPL +``` + +因此可以直接使用切片函数来获得信息: + +```python +with open(hash_file_path, "r", encoding="utf-8") as hash_file: + lines = hash_file.readlines() + if len(lines) > 1: + line = lines[1].strip() + pos = line.rfind(" ") + if pos != -1 and pos + 1 < len(line): + return line[pos + 1:] +``` + +同样的,大多数 .in 文件也包含着软件包的依赖信息,例如: + +```shell +config BR2_PACKAGE_BASH + bool "bash" + # uses fork() + depends on BR2_USE_MMU + depends on BR2_PACKAGE_BUSYBOX_SHOW_OTHERS + select BR2_PACKAGE_NCURSES + select BR2_PACKAGE_READLINE +``` + +因此,可以通过正则表达式来提取依赖信息: + +```python +dep_regex = re.compile(r"BR2_PACKAGE_\w+") +``` + +处理提取出的依赖数据等过程则用到了不同的脚本,最终将依赖数据存储在一个 JSON 文件中,以便后续的使用。因为有许多的配置文件并非按照上述格式,所以部分数据可能会有遗漏。 + +协议问题的解决则尤为烦人,因为默认配置编译出的 buildroot 系统中自带 busybox,其中的 wget 仅支持 http 协议,而大部分的软件包都是通过 https 协议下载的。因此,我需要使 TinyBPT 支持 https 协议的下载,以保证兼容性。我使用了基于 MIT 协议的第三方库 [cpp-httplib][004] 支持 HTTPS 传输,并配置 CA certificates extracted from Mozilla 作为 CA 证书。 + +```cpp +httplib::SSLClient cli(mirror_url.c_str()); +cli.set_ca_cert_path("/etc/ssl/certs/cacert.pem"); +``` + +我也使用了 [nlohmann/json][002] 库来处理 JSON 文件。 + +## TinyBPT 基本框架 + +TinyBPT 的结构如下: + +``` + +-------------------+ +-------------------+ + | | | | + | main.cpp | | utils.cpp | + | | | | + | - Handle CLI args| | - String handling| + | - Call pkg funcs | | - Time retrieval | + | | | - Pkg info lookup| + +---------+---------+ +---------+---------+ + | | + cacert.pem | | + | v v ++---------+---------+ | +---------+---------+ +---------+---------+ +| server | | | | | | +| | v | tinybpt.cpp |<------| json_utils.cpp | +| - Metadata Service|------>| | | | +| - Download Service| | - Install pkg | | - Handle JSON | +| - Package Storage | | - Uninstall pkg | | - List pkgs | +| - Compile Package | | - Download pkg | | - Find pkgs | +| | | - Manage deps | | - Update pkg info| +| | | | | - Read config | ++---------+---------+ +---------+---------+ +---------+---------+ + | | + v v + +---------+---------+ +---------+---------+ + | | | | + | Config struct | | Package struct | <--- tinybpt_db.json + | | | | + | - Mirror URL | | - Name | + | - Version info | | - Version | + | - config.json | | - Info | + | | | - Download time | + | | | - Dependencies | + +-------------------+ +-------------------+ +``` + +源码结构说明如下: +- src/ + - main.cpp: 处理命令行参数,调用包管理功能。 + - utils.cpp: 提供字符串处理、时间获取和包信息查找等功能。 + - tinybpt.cpp: 实现包的安装、卸载、下载和依赖管理功能。 + - json_utils.cpp: 处理 JSON 格式的包元数据,读取配置文件。 +- tinybpt_db.json: 存储配置信息,如镜像 URL 和版本信息。 +- cacert.pem: CA 证书,用于安全连接。 + +main.cpp 中的主函数负责处理命令行参数,调用包管理功能,其分析命令行输入的相关参数,然后调用 tinybpt.cpp 中的函数来执行相应的操作。 + +```cpp +int main(int argc, char *argv[]) { + if (argc < 2) { + print_help(); + return 1; + } + ··· +``` + +tinybpt.cpp 中包含了实现 TinyBPT 主要功能的函数。 + +例如函数 download_and_install_package,用于下载并安装指定的软件包。通过 find_version_by_name 查找软件包版本,构建下载地址并指定下载路径。调用 download_package 下载软件包,如果下载失败,输出错误信息并返回。读取软件包信息 read_package_info,遍历 packages 列表,找到匹配的软件包并更新本地信息。 + +```cpp +void download_and_install_package(const std::string &name, const std::string &url) { + std::string version = find_version_by_name(name, db_file); + std::string package_url = url + version + ".tar.gz"; + std::string output_path = download_path + "/" + name + "/"; + bool download_success = download_package(package_url, output_path, name); + if (!download_success) { + std::cerr << "Download and installation failed for package: " << name << std::endl; + return; + } + read_package_info(db_file, "packages"); + for (const auto &pkg : packages) { + if (pkg.name == name) { + update_local_package_info(db_file, pkg); + break; + } + } +} +``` + +因为处理 JSON 文件的操作较为繁琐,所以我将其封装在 json_utils.cpp 中,以便于调用。 + +例如函数 find_package 通过读取数据库文件中的软件包信息,查找并输出指定名称的软件包的详细信息(包括版本、信息和依赖项),如果未找到则输出提示信息。 + +```cpp +void find_package(const std::string &name, const std::string &key) { + read_package_info(db_file, key); + for (const auto &pkg : packages) { + if (pkg.name != name) + continue; + std::cout << "Found package: " << pkg.name << " (" << pkg.version << ")" << std::endl; + std::cout << "Info: " << pkg.info << std::endl; + std::cout << "Dependencies: " << pkg.dependencies << std::endl; + return; + } + std::cout << "Package not found: " << name << std::endl; +} +``` + +utils.cpp 则提供了一些功能相关的辅助函数。 + +例如函数 get_current_time 用于获取当前时间,返回一个格式化的时间字符串。 + +```cpp +std::string get_current_time() { + std::time_t now = std::time(nullptr); + char buf[80]; + std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", std::localtime(&now)); + return std::string(buf); +} +``` + +## 二进制包编译与服务端配置 + +使用 buildroot 的软件包进行交叉编译成 RISC-V 架构的二进制包,则需要借助 buildroot 编译过程中的中间文件,其保存在 `output/build/` 目录下。在编译过程中,buildroot 会将软件包的源码下载到 `output/build/` 目录下,并在此目录下进行编译。编译完成后,buildroot 会将编译好的二进制包安装到 `output/target/` 目录下。 + +基于此,我使用脚本将 `output/build/` 目录下编译成功的二进制包 `make install` 到指定目录下,然后将其打包成 tar.gz 文件,并在与配置文件进行对比处理后,上传到服务器上。 + +服务器端的配置如下: + +```shell +buildroot/ -- 源码镜像,直接镜像 buildroot 官方所有包的源码库 + +buildroot-pkgs/ -- 二进制包发布目录 + riscv64/ -- 处理器架构,独立的话方便第三方镜像 + main/2024.02.6/ -- main 用于存放所有 buildroot lts 版本的二进制包(动态编译) + tools/v6.10/ -- tools 用于存放 Linux lts 内核版本下的 tools 二进制包(以静态编译) + rootfs/ -- rootfs 用于存放 rootfs 包 + tinybpt/ + tinybpt-v0.1.0.tar.gz -- tinybpt 二进制包 + aarch64/ + main/2024.02.6/ + tools/v6.10/ + x86_64/ + main/2024.02.6/ + tools/v6.10/ +``` + +## 总结 + +本文介绍了 TinyBPT 以及面向 buildroot 的二进制包管理服务的设计简介与框架。TinyBPT 的设计初衷是一个 buildroot 的二进制包管理工具,主要处理 buildroot 的包依赖关系,提供包的安装、卸载等功能,主要包括了主程序、包管理、JSON 文件处理和辅助函数等模块。TinyBPT 的设计思路是通过解析依赖文件,提取出软件包的依赖关系,然后通过 HTTPS 协议下载软件包,最后安装软件包。 + +其他文章将继续介绍客户端和服务端的使用方法。 + +## 参考资料 + +- [TinyBPT][001] + +[001]: https://gitee.com/tinylab/tinybpt +[002]: https://github.com/nlohmann/json +[003]: https://github.com/taoky/tsumugu +[004]: https://github.com/yhirose/cpp-httplib +[005]: https://mirrors.lzu.edu.cn/ diff --git a/articles/20240927-tinybpt-server-usage.md b/articles/20240927-tinybpt-server-usage.md new file mode 100644 index 0000000000000000000000000000000000000000..60de88fb3e6345658ddbf4fe921f654141541ed3 --- /dev/null +++ b/articles/20240927-tinybpt-server-usage.md @@ -0,0 +1,100 @@ +> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.2-rc2 - [tounix spaces header]
+> Author: 柴子轩
+> Date: 2024/09/27
+> Revisor: falcon
+> Project: [RISC-V Linux 内核剖析](https://gitee.com/tinylab/riscv-linux)
+> Sponsor: PLCT Lab, ISCAS + +# TinyBPT 和面向 buildroot 的二进制包管理服务(3):服务端说明 + +## 前言 + +TinyBPT (Tiny Buildroot Packaging Tool) 是一个 buildroot 的包管理工具,主要处理 buildroot 的包依赖关系,提供包的安装、卸载等功能。 + +本文档主要介绍为了向 TinyBPT 提供服务,服务端的配置和使用。 + +## 在服务器端配置 buildroot 源码 + +### 使用工具 tsumugu 来更新源 + +```shell +wget https://github.com/taoky/tsumugu +``` + +配置运行脚本: + +```shell +RUST_LOG=Error /usr/local/bin/tsumugu sync --parser lighttpd http://sources.buildroot.net /mnt/tank2/buildroot +``` + +在网页设置中添加定时任务,每天更新一次,并将其路径展示在网页上,以 nginx 为例: + +```shell +server { +··· + + location ~* ^/(bmclapi|ubuntu|centos|debian-security|debian|archlinux|archlinuxcn|debian-nonfree|gentoo|manjaro|opensuse|ubuntukylin|wepe|cygwin|debian-cd|debian-multimedia|deepin-cd|openeuler|rpmfusion|ubuntukylin-cdimage|almalinux|buildroot|buildroot-pkgs|epel|rocky|radxa-apt|debian-ports) { + include /etc/nginx/config.d/backend.conf; + include /etc/nginx/config.d/cache.conf; + } +··· +``` + +## 二进制包 + +### 二进制包源 + +目前,二进制包在 `https://mirrors.lzu.edu.cn/buildroot-pkgs` 已经开始提供。 + +### 目录结构 + +```shell +buildroot/ -- 源码镜像,直接镜像 buildroot 官方所有包的源码库 + +buildroot-pkgs/ -- 二进制包发布目录 + riscv64/ -- 处理器架构,独立的话方便第三方镜像 + main/2024.02.6/ -- main 用于存放所有 buildroot lts 版本的二进制包(动态编译) + tools/v6.10/ -- tools 用于存放 Linux lts 内核版本下的 tools 二进制包(以静态编译) + rootfs// -- rootfs 用于存放 rootfs 包,以及相应的编译配置文件 + - rootfs-xxx.tar.gz + - rootfs-xxx.config + tinybpt/ + tinybpt-v0.1.0.tar.gz -- tinybpt 二进制包 + aarch64/ + main/2024.02.6/ + tools/v6.10/ + x86_64/ + main/2024.02.6/ + tools/v6.10/ +``` + +### 编译选项 + +如果要自行编译,编译配置在 TinyBPT 仓库的 `/web/settings/.config` 中(后续计划连同 rootfs 一起发布),使用编译配置替换原有配置,或使用 `make menuconfig` 自行勾选需要编译的包。 + +```shell +cd buildroot +make -j$(nproc) +``` + +### 二进制包的发布 + +完成后,进入 `output/build` 目录,运行 `web/script/install.sh` 脚本,将编译好的二进制包打包到 `/mnt/tinybpt` 目录下。 + +将打包目录下的所有文件名列出到 `deploy-pkgs-version.txt` 文件中,确保已有依赖文件 `packages.json` 也在运行目录下,运行 `web/script/compare.py` 脚本和 `web/script/del.py` 脚本,对比和删除不必要的包,更新依赖文件。 + +注意:二进制包的编译和发布方式会导致某些包无法编译,原因在于目录结构不同等。 + +### 提醒事项 + +为了解决编译中的问题,我们需要在编译前进行一些配置,例如目前已发现的: + +1. Buildroot 无法编译 host-heimdal ,问题是 heimdal 的配置脚本使用了已被删除的变量,需要手动修改,在 `buildroot-2024.02.6/package/heimdal/heimdal.mk` 文件中,将 `ac_cv_sys_large_files=1 ac_cv_sys_file_offset_bits=64` 添加到 `HOST_HEIMDAL_CONF_ENV` 变量中。 + +软件源码包大小约为 468 GB。 + +编译后的 RISC-V 二进制包大小约为 12 GB。 + +## 参考资料 + +- [TinyBPT](https://gitee.com/tinylab/tinybpt)