Skip to content

lpkg 包管理器 ​

⚡ 此页面由 scripts/fetch-lpkg-docs.mjs 在构建时自动生成,从 GitHub 仓库的 lpkg/README.md 拉取。

lpkg

为 LankeOS 设计的轻量级、基于命令行的 C++20 包管理器。
原子 WAL 事务回滚 · needed_so ABI 校验 · 聚合索引 · 静态构建

Quick StartLicense

Build statusC++20License

DockerBashzstd

Claude Code

lpkg 是一个为 LankeOS 设计的轻量级、基于命令行的包管理器。它使用 C++20 编写,旨在为 LFS (Linux From Scratch) 环境提供原子化、可追溯的软件包管理方案。

功能特性 ​

  • 全生命周期管理:安装、卸载、升级、重装软件包。
  • needed_so 依赖校验 + 符号版本:安装前自动验证每个 ELF DT_NEEDED 声明的 SONAME 在仓库中有对应的提供者包,无提供者则拒绝安装,杜绝"空 provides 还能装"的漏洞。SONAME 可带 ELF 符号版本(libc.so.6@GLIBC_2.40 或 libc.so.6@{GLIBC_2.40,GLIBC_2.39}):带符号版本的需求只能被同样声明了它、且覆盖它的提供者满足(保守语义 —— 只写裸 SONAME 的包不算数),用于抓"新二进制要求新 glibc 符号版本"这类光看 SONAME 看不见的 ABI 断裂。
  • SIGINT 优雅退出:Ctrl+C 设置优雅退出标志,当前操作(含必要回滚)完整执行完毕后退出,防止事务中断导致系统不一致。不提供强制终止——确保回滚永不被打断。
  • rpm 版本语义:版本串就是 rpm 的 [epoch:]version[-release],判据只有一份(libsolv 的 EVR 比较)—— 支持多位修订号(6.16.1 > 6.6.1)、预发布(1.0~rc1 < 1.0)、发行修订号(1.0-1 > 1.0)与复合区间约束(>= 2.0.0 < 3.0.0)。
  • 聚合索引:采用 index.txt 聚合格式,一行即可记录包的所有版本及各自的哈希、依赖、provides、provides_soname、needed_so。
  • 包内嵌元数据:采用 metadata.json 嵌入包内,统一存储名称、版本、依赖、虚拟提供(provides)、导出的 SONAME(provides_soname)、需要的 SONAME(needed_so)、手册页等元数据。
  • 自动 SONAME 扫描:构建农场(farm/,Rust)在打包后扫描每个 ELF 的 DT_NEEDED SONAME(以及 .gnu.version_d / .gnu.version_r 符号版本)生成 needed_so 与 provides_soname。deps 不由农场扫描推导 —— 它声明在包配方里。
  • 内容即文件布局:包的 content/ 目录结构直接对应根目录文件布局。
  • 自动化运维:提供 lrepo-mgr.py 工具,支持一键推送到 S3 兼容存储或 SCP 远程服务器。新增 --path 参数支持本地文件系统仓库,便于离线测试。
  • 高兼容性静态构建:内置系统 CA 证书路径自动探测,确保静态编译版本在不同 Linux 发行版上都能正常联网。
  • 安全性:强制 SHA256 哈希校验、文件冲突检测、恶意路径过滤。
  • 系统钩子与触发器:支持包级 postinst/prerm 脚本及系统级触发器(如 ldconfig)。

使用方法 ​

lpkg 的大部分操作需要 root 权限。

通用语法:

bash
lpkg [选项] <命令> [参数]

常用命令 ​

  • install <包名>[:版本]: 安装包。缺省版本时自动安装最新版。
  • upgrade: 自动从索引中查找所有已安装包的更新。
  • remove <包名> [--force]: 移除包。使用 --force 可强制删除被依赖的包。
  • query [-p] <包名|文件名>: 查询文件归属或列出包内文件。
  • scan [目录]: 扫描系统中不属于任何包的"孤儿"文件。
  • pack -o <输出文件> -d <目录>: 构建 .lpkg 格式的软件包,从 <目录>/metadata.json 读取包元数据。
  • build [目录]: 自动编译并打包软件包。

快速开始 ​

依赖 ​

以下库仅在主机上直接编译(动态/静态链接)时需要;推荐用 Docker 构建,主机无需安装任何依赖:

  • libcurl: 用于文件下载。
  • libarchive: 用于解压包文件。
  • libcrypto (OpenSSL): 用于计算哈希。

在 Arch Linux 上安装:

bash
sudo pacman -S curl libarchive openssl

编译与安装 ​

  1. Docker 构建 (推荐): 完整构建与测试只需要 Docker。所有依赖(含 libgit2、libsolv 等静态库)都会在 alpine:3.19 容器内自动安装,产出纯静态二进制:
    bash
    make docker          # 纯静态二进制: build/lpkg-docker
    sudo make docker-install
    make test            # 在同一容器内运行完整测试套件
  2. 动态编译 (主机): 需要主机上的 libcurl、libarchive、libelf、libgit2、libsolv、libopenssl:
    bash
    make && sudo make install

仓库管理 (运维指南) ​

项目在 main/scripts/lrepo-mgr.py 提供了自动化运维脚本。

1. 配置仓库连接 ​

支持 S3 兼容存储 或 SCP:

bash
## 配置 S3 兼容存储
./main/scripts/lrepo-mgr.py config --set \
    storage.type=s3 \
    storage.endpoint=https://your-s3-endpoint.example.com \
    storage.bucket=your-bucket-id \
    storage.access_key=AK... \
    storage.secret_key=SK...

2. 发布软件包 ​

该命令会自动更新聚合索引并上传:

bash
./main/scripts/lrepo-mgr.py push ./pkgs/*.lpkg

3. 本地仓库(离线测试) ​

bash
## 初始化本地 repo 并推送包
./main/scripts/lrepo-mgr.py --path /tmp/repo push ./pkgs/*.lpkg

## 查看生成的索引
cat /tmp/repo/x86_64/index.txt

4. 清理历史版本 ​

从存储端删除所有不在 index.txt 记录中的旧版本文件:

bash
./main/scripts/lrepo-mgr.py cleanup

包格式规范 ​

每个 .lpkg 文件是一个 tar.zst 压缩包,包含以下内容:

text
metadata.json         # 包元数据(名称、版本、依赖、提供、手册页等)
content/              # 文件内容(直接对应根目录结构)
hooks/                # 钩子脚本(可选)

metadata.json 示例 ​

json
{
  "name": "curl",
  "version": "8.11.1",
  "deps": ["glibc", "openssl", "zlib", "zstd", "bash"],
  "provides": [],
  "provides_soname": ["libcurl.so.4"],
  "needed_so": ["libc.so.6", "libssl.so.3", "libcrypto.so.3", "libz.so.1", "libzstd.so.1"],
  "man": "curl(1) - transfer a URL\n..."
}
字段说明
name包名
version版本号
deps依赖包名列表(声明在配方里;农场不从 needed_so 推导)
provides本包提供的虚拟能力列表(如 java-runtime;与 .so 无关)
provides_soname本包导出的 SONAME 列表(由构建农场扫描产物 ELF 生成;可带符号版本,见下)
needed_so本包 ELF 文件声明的 DT_NEEDED SONAME 列表(运行时依赖的原始真相;可带符号版本)
man内联手册页内容(可选)

content/ 目录下的文件布局直接对应目标根目录(/)。

构建标志配置(build.conf) ​

lpkg build 默认使用 Arch Linux 编译/链接标志,ISA 基线 x86-64-v3(绝不用 -march=native,避免把构建宿主超出 v3 的 CPU 特性烙进发行版包;v3 = AVX2/FMA 等, 覆盖 2013 年后绝大多数主流 x86-64 机器)。默认值见 main/src/base/build_defaults.hpp(fallback),系统级配置见 /etc/lpkg/build.conf(makepkg.conf 风格,由 make install 从 main/conf/build.conf 安装):

text
CFLAGS="-march=x86-64-v3 -mtune=generic -O2 -pipe -fno-plt -fexceptions ..."
CXXFLAGS="$CFLAGS -Wp,-D_GLIBCXX_ASSERTIONS"   # 写法上为完整展开
LDFLAGS="-Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now ..."
LTOFLAGS="-flto=auto"
MAKEFLAGS="-j$(nproc)"                          # $(nproc) 自动展开为逻辑核心数

build 的每个阶段(lankebuild_prepare/build/package)执行前会把上述标志 export 到构建环境,configure/make/cmake 自动继承;LankeBUILD 脚本也可引用 模板变量 {CFLAGS}、{CXXFLAGS}、{LDFLAGS}、{MAKEFLAGS}。

逐包覆盖(优先级最高):LankeBUILD.json 增加可选字段,留空 = 用配置默认:

json
{
  "name": "foo",
  "version": "1.0",
  "cflags": "-O2 -march=x86-64-v3",
  "ldflags": "-Wl,--as-needed",
  "makeflags": "-j2",
  "lto": true
}

"lto": true 会把 LTOFLAGS(默认 -flto=auto)追加到编译与链接标志。

仓库规范 ​

目录结构 ​

text
/x86_64
  ├── index.txt           # 核心索引:包名|版本:哈希:依赖:provides:provides_soname:needed_so;...|
  └── bash/
      ├── 5.3.lpkg        # 实际的 tar.zst 压缩包
      └── 5.4.lpkg

索引行示例 ​

text
## 版本块恰好 6 个冒号字段:版本:哈希:依赖:provides:provides_soname:needed_so
curl|8.11.1:hash:glibc,openssl,zlib,zstd,bash::libcurl.so.4:libc.so.6,libssl.so.3,libz.so.1,libzstd.so.1|

SONAME 规格(symbol version) ​

text
libc.so.6                        # 裸 SONAME(不声明符号版本)
libc.so.6@GLIBC_2.40             # 单个符号版本
libc.so.6@{GLIBC_2.40,GLIBC_2.39} # 多个(符号名字符集 [A-Za-z0-9_.+-];**规格里不许有空白**)
  • 匹配(保守):带符号版本的需求只能被"也声明了符号版本、且覆盖它"的提供者满足; 只声明裸 libc.so.6 的提供者不算(否则这个特性形同虚设)。裸需求照旧 —— 任何声明了该 SONAME 的提供者都算,声明得更细不会把裸需求打破。
  • 存储:metadata.json 与 index.txt 里原样保留 {} 写法(不展开);只有灌 libsolv 时才展开成池里的能力。索引字段里的列表分隔符仍是逗号 —— 切分是花括号感知的 (花括号内的逗号不是分隔符)。
  • 谁产出:构建农场自动产出(扫 ELF 的 .gnu.version_d / .gnu.version_r)—— 这两个字段由 farm 生成(手写的会被扫描值覆盖)。farm 按裸 SONAME 建索引/查表,但 漂移判定是版本级的(verify 比 (裸名, 去重排序的版本集):少一个版本节点 → AbiBreak, 多出来 / needed_so 规格变化 → Repack)。

    ⚠️ 订正 2026-10-05:原文写"farm 同时按裸 SONAME 做基线归一,不会把已有的规格当漂移 抹掉"—— 已不成立(提供者侧现在就是按版本级判漂移的,漂移时会用扫描值写回配方)。

源码架构 ​

  • Repository: 解析聚合索引,实现版本智能排序。
  • InstallationTask: 原子事务模型,支持失败自动回滚。
  • Downloader: 封装了 libcurl 并集成了多路径证书探测逻辑。
  • Cache: 本地状态数据库,存储于 /var/lib/lpkg/。
  • metadata.json: 包内嵌元数据(名称、版本、依赖、提供、手册页)。

贡献 ​

欢迎提交 PR 或报告 Bug。对于新的功能建议,请优先考虑保持二进制文件的轻量化。

许可证 ​

基于 GPL3 许可证开源。

源码按 GPL-3.0 开源 · 文档内容(Markdown)采用 CC BY-SA 4.0