# RPMSpecSample **Repository Path**: reganhe_xx/RPMSpecSample ## Basic Information - **Project Name**: RPMSpecSample - **Description**: rpm 打包常见问题及解决方案 - **Primary Language**: Lua - **License**: BSD-3-Clause - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 2 - **Created**: 2022-02-09 - **Last Updated**: 2026-06-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: rpm, Packaging, PackageGuide, rpmSPEC ## README # RPMSpecSample RPM Spec 文件示例仓库,提供软件打包过程中常见问题的解决方案与 Spec 规范编写参考。 > 本仓库旨在帮助 RPM 打包开发者快速定位和解决 Spec 文件编写中的典型问题,涵盖 Rust、Go、Java、Python、Node.js 等多语言场景,并提供 Maven 构建代理配置、许可证管理、systemd 服务集成等配套参考。 --- ## 目录 - [仓库定位](#仓库定位) - [目录结构](#目录结构) - [核心专题索引](#核心专题索引) - [Maven Settings 配置说明](#maven-settings-配置说明) - [许可证文件说明](#许可证文件说明) - [Systemd 服务文件说明](#systemd-服务文件说明) - [使用指引](#使用指引) - [按场景快速定位](#按场景快速定位) - [引用与贡献](#引用与贡献) - [许可证](#许可证) --- ## 仓库定位 本仓库提供 **RPM Spec 文件示例** 与 **打包问题解决方案参考**,主要面向以下人群: - Linux 发行版(如 openEuler、CentOS、Fedora)的 RPM 打包维护者 - 需要将自研或第三方软件打包为 RPM 的开发/运维工程师 - 希望了解 RPM Spec 编写规范和最佳实践的初学者 仓库中的 `SuperSample.spec` 并非一个真实可构建的软件包,而是一个 **"问题场景大全"** 式的示例 Spec 文件,集中展示了数十种常见打包问题及其标准解法。配套目录提供了 Maven 构建代理配置、许可证模板、systemd 服务模板等辅助参考。 --- ## 目录结构 ``` RPMSpecSample/ ├── SuperSample.spec # RPM Spec 综合示例(核心文件,涵盖全部问题场景) ├── LICENSE # 仓库许可证(BSD 3-Clause) ├── docs/ │ └── README.md # 本文档 —— 仓库介绍与使用指南 ├── config/ │ ├── maven_settings.xml # Maven settings 全功能参考模板 │ ├── build_maven_settings.xml # RPM 构建场景下的 Maven 代理配置(双 Profile) │ └── aliyun_maven_settings.xml # ARM 架构 aarch64 专用 Maven 仓库配置 ├── licenses/ │ ├── Apache-License # Apache License 2.0 占位文件 │ └── GPL-License # GPL v2(或更高版本)占位文件 └── service/ ├── java_process_sample.service # Java 进程 systemd 服务示例 └── python-with-port.service # Python 端口监听 systemd 服务示例 ``` | 路径 | 类型 | 说明 | |------|------|------| | `SuperSample.spec` | 核心文件 | 综合示例 Spec,覆盖 30+ 主题的场景式教程 | | `docs/README.md` | 文档 | 本仓库介绍文档 | | `config/maven_settings.xml` | 配置参考 | Maven settings 全功能模板(含代理、镜像、profile) | | `config/build_maven_settings.xml` | 构建配置 | RPM 编译专用,aarch64/通用场景双 Profile | | `config/aliyun_maven_settings.xml` | 构建配置 | ARM 架构专用 Maven 代理配置 | | `licenses/Apache-License` | 许可证 | Apache 2.0 许可证占位文件,用于 %license 声明 | | `licenses/GPL-License` | 许可证 | GPL v2+ 许可证占位文件,用于 %license 声明 | | `service/java_process_sample.service` | 服务模板 | Java 进程(JanusGraph)systemd 服务单元 | | `service/python-with-port.service` | 服务模板 | Python 端口监听(Heron Tracker)systemd 服务单元 | --- ## 核心专题索引 `SuperSample.spec` 按照 RPM Spec 编写流程组织,将典型问题场景分散到 Spec 的不同章节中。下表按专题列出索引,便于快速定位。 | # | 专题 | 章节/位置 | 说明 | |---|------|-----------|------| | 1 | **Rust Cargo 编译宏优化** | 全局变量区域(`%global __cargo`) | 扩展 `__cargo` 宏添加 `-vv` 详细日志;设置 `__cargo_skip_build = 0` 确保 cargo_build 宏被调用 | | 2 | **Debug 包生成抑制** | 全局变量区域(`%global debug_package`) | Rust/Go/Java 等无法正常生成 debuginfo 时,全局禁用 debug 子包的生成 | | 3 | **Python 脚本编译控制** | 全局变量区域(`__os_install_post`) | 在 install 阶段后禁用 `brp-python-bytecompile`,避免不适合编译的 Python 脚本报错 | | 4 | **GitHub 项目版本号 / Commit 拼接** | 全局变量区域(`%global commit`) | 对无正式 Release 号的项目,使用 commit 号 + 日期拼接 Release 后缀(alphatag) | | 5 | **条件编译(bcond_with / bcond_without)** | 全局变量区域 | `%bcond_with cond1` 与 `%bcond_without cond2` 控制 rpmbuild 命令行可选参数 | | 6 | **宏函数定义** | 全局函数区域(`%define setup_mod()`) | 多个子包重复相同逻辑时,使用 `%define funcname()` 定义可复用宏函数 | | 7 | **JAR 包 OSGi Provides/Requires 过滤** | 全局变量区域 | `%undefine __osgi_provides` + `__osgi_requires` 避免 Java 包与公共能力提供者冲突 | | 8 | **Maven 依赖缺失处理** | 全局变量区域 | `%undefine __maven_requires` 在无法满足所有编译依赖时禁用自动依赖扫描 | | 9 | **ldconfig 调用规范** | 宏定义区域 | 安装/卸载后调用 ldconfig 时,必须使用 `ldconfig` 而非 `/sbin/ldconfig` | | 10 | **Provides / Requires 过滤** | 全局变量区域 | 使用 `__provides_exclude_from`、`__requires_exclude` 和 `__filter_GLIBC_PRIVATE` 精确控制包依赖/提供符号 | | 11 | **多线程编译** | 全局变量区域后注释 | 通过 `export RPM_BUILD_NCPUS=$(nproc)` 利用全部 CPU 线程加速编译 | | 12 | **架构条件依赖** | 基本信息区域(`%ifarch`) | 使用 `%ifarch aarch64` / `%ifarch x86_64` 区分不同 CPU 架构的 BuildRequires/Requires | | 13 | **冲突、废弃与弱依赖** | 基本信息区域 | 使用 `Conflicts`、`Obsoletes`、`Recommends`、`Supplements`、`Enhances`、`Suggests` 精细管理包间关系 | | 14 | **布尔依赖(Boolean Dependencies)** | 基本信息区域 | RPM ≥ 4.13 支持的 `and`、`or`、`if`、`else`、`not` 逻辑表达式依赖声明 | | 15 | **多子包声明** | 子包声明区域 | python3 子包、devel 子包、static 子包、doc 子包、javadoc 子包的定义规范 | | 16 | **%prep 准备阶段** | %prep 区域 | `%setup` 与 `%autosetup` 的选择;`%autopatch` 多参数用法(`-M`/`-N` 编号范围、`-p0` 路径剥离) | | 17 | **GitHub / Go / npm / pip 代理配置** | %prep 区域 | 设置国内镜像站加速依赖下载(hub.fastgit.org、goproxy.cn、huaweicloud npm/pip) | | 18 | **C/C++ 安全编译宏** | %build 区域 | `%set_build_flags`、`%build_cflags` 系列宏;调试时将优化级别从 -O2 降为 -O0 | | 19 | **Java Maven 编译与 POM 修改** | %build 区域 | 使用 `%pom_*` 系列宏(add_dep、remove_dep、disable_module、xpath_inject 等)调整 pom.xml | | 20 | **Bazel 编译配置** | %build 区域 | 指定内存、CPU 资源、仓库缓存路径的 Bazel 编译参数 | | 21 | **Rust Cargo 国内镜像代理** | %build 区域 | 创建 `.cargo/config` 文件将 crates-io 替换为 USTC 镜像 | | 22 | **Install 最佳实践** | %install 区域 | 推荐 `install` 而非 `mkdir` 创建目录;`install -D` 自动创建前导路径;权限精确控制 | | 23 | **JAR 包 ARM 适配** | %install 区域 | 使用 `jar uf` 命令向已有 JAR 包注入 aarch64 架构动态库 | | 24 | **Shebang 修正** | %install 区域 | 批量修正 `/bin/env bash` → `/usr/bin/bash` 等不合规的解释器声明 | | 25 | **RPATH 删除** | %install 区域 | 使用 `chrpath --delete` 从编译出的 ELF 二进制文件中删除冗余 RPATH | | 26 | **事务脚本** | %pre / %preun / %post / %postun 区域 | 安装/升级/卸载 4 种操作的参数含义及 systemd 宏调用规范 | | 27 | **子包事务** | 子包事务区域 | 为 python3 子包、devel 子包分别指定自定义 post/postun 脚本 | | 28 | **%files 文件列表** | %files 区域 | `%license`、`%doc`、`%config(noreplace)`、`%exclude`、`%defattr`、`%attr` 的用法示例 | | 29 | **%changelog 格式** | 文件末尾 | ChangeLog 的标准时间格式与条目写法 | --- ## Maven Settings 配置说明 `config/` 目录下提供了三个 Maven 配置文件,适用于不同的 Maven 构建场景: ### 1. `maven_settings.xml` — 全功能参考模板 **用途:** Maven settings 配置的综合示例,展示所有常用配置项的结构与默认值。 **包含的配置项:** | 配置块 | 说明 | |--------|------| | `localRepository` | 本地仓库路径 | | `interactiveMode` | 是否交互式(true/false) | | `offline` | 离线模式开关 | | `pluginGroups` | 插件组织 ID 默认搜索列表 | | `proxies` | HTTP 代理配置(含无代理主机列表) | | `servers` | 远程仓库鉴权信息(用户名/密码/私钥) | | `mirrors` | 镜像仓库配置(mirrorOf 与 central 的关系) | | `profiles` | 基于 JDK 版本自动激活的 profile 示例 | | `activeProfiles` | 默认激活 profile 列表 | **推荐场景:** 学习 Maven settings 文件整体结构,或作为**自定义 settings.xml 的起点模版**。 ### 2. `build_maven_settings.xml` — RPM 构建代理配置(双 Profile) **用途:** 专为 RPM 打包编译设计,提供两个 Profile 按架构切换 Maven 仓库。 **Profile 说明:** | Profile | 激活方式 | 适用架构 | 仓库来源 | |---------|----------|----------|----------| | `common_profile` | `activeByDefault`(默认激活) | x86_64 等通用架构 | 华为云、阿里云公共仓库 | | `aarch64_profile` | 需要在 mvn 命令行显式指定 `-P aarch64_profile`(或在 spec 中通过 `%ifarch` 判断添加) | aarch64 | 鲲鹏 Maven 代理 + 阿里云公共仓库 | **推荐场景:** RPM 构建时作为 `%mvn_build -b -f` 的 `-s` 参数传入,实现按架构自动选择 Maven 仓库源。 ### 3. `aliyun_maven_settings.xml` — aarch64 专用仓库配置 **用途:** 纯 ARM 架构的 Maven 代理配置,Profile 结构最简单。 **Profile 说明:** | Profile | 激活方式 | 仓库来源 | |---------|----------|----------| | `common_profile` | `activeByDefault`(默认激活) | 阿里云 Central + Releases + Snapshots 等全部镜像 | | `aarch64_profile` | 显式激活(`activeByDefault=false`) | 华为云鲲鹏 Maven 代理 | **推荐场景:** 在 ARM 服务器(如华为鲲鹏)上进行本地 Maven 构建时的 settings.xml。如需增加鲲鹏专用仓库,激活 `aarch64_profile` 即可。 --- ## 许可证文件说明 `licenses/` 目录下包含两个许可证占位文本文件,用于在 `%files` 的 `%license` 指令中声明: | 文件 | 许可证类型 | 说明 | |------|-----------|------| | `licenses/Apache-License` | Apache License 2.0 | Apache 2.0 许可证占位文本,**构建前需替换为完整的许可证原文** | | `licenses/GPL-License` | GNU GPL v2(或更高版本) | GPL 许可证占位文本,**构建前需替换为完整的许可证原文** | 这些文件在 `SuperSample.spec` 的 `%files` 段中被引用: ``` %license LICENSE licenses/Apache-License licenses/GPL-License ``` > **注意:** 这两个文件为占位文件,内容仅说明许可证来源。在实际构建 RPM 之前,必须根据软件的实际版权情况,用完整的许可证原文(可从 [SPDX License List](https://spdx.org/licenses) 或 [github.com/spdx/license-list-data](https://github.com/spdx/license-list-data/tree/main/text) 下载)替换这些文件,否则 `rpmbuild -bb` 会因许可证文件缺失或无效而失败。 --- ## Systemd 服务文件说明 `service/` 目录下提供两个 systemd service 单元文件示例,用于集成服务管理: ### 1. `java_process_sample.service` — Java 守护进程(Forking 模式) | 配置项 | 值 | 说明 | |--------|-----|------| | Service Type | `forking` | 主进程 fork 出子进程后退出,适用于传统 Java 服务 | | 用户/组 | `janusgraph:janusgraph` | 以专用系统用户运行 | | PID 文件 | `/run/janusgraph/janusgraph.pid` | Forking 模式必须指定 PID 文件 | | ExecStart | `/bin/bash -c '.../gremlin-server.sh start'` | 使用 shell 包裹启动命令 | | ExecStop | `/bin/bash -c '.../gremlin-server.sh stop'` | 独立的停止命令 | | SuccessExitStatus | `0 143` | 正常退出码 0 + SIGTERM 默认返回码 143 | **推荐场景:** 使用启动/停止脚本(非内置 daemonize)的传统 Java 服务(如 JanusGraph、Tomcat)。 ### 2. `python-with-port.service` — Python 端口监听服务(Simple 模式) | 配置项 | 值 | 说明 | |--------|-----|------| | Service Type | `simple` | 主进程直接在前台运行,适用于 Web/API 服务 | | Environment | `PORT=8888` | 通过环境变量传递端口号 | | ExecStartPre | `lsof -i:${PORT}` 端口占用检查 | 启动前检查端口是否被占用,已占用则直接失败 | | ExecStart | `/usr/lib/heron/bin/heron-tracker --port ${PORT}` | 主进程命令 | | ExecReload | `/bin/kill -HUP $MAINPID` | 平滑重载配置 | | KillMode | `mixed` | 主进程 + 所有子进程一起终止 | | PrivateTmp | `true` | 使用私有 /tmp 空间,提升安全性 | | Restart | `on-failure` | 非正常退出时自动重启 | **推荐场景:** 监听端口的 Python Web 服务或 API 服务(如 Heron Tracker、Flask/Gunicorn 应用)。 --- ## 使用指引 ### 如何阅读本仓库 `SuperSample.spec` 以**"场景驱动"**的方式组织内容,每个专题单独成段,并附有详细注释说明问题背景、原因和标准解法。建议按以下步骤使用: 1. **先浏览目录结构** —— 确认仓库包含 Spec 文件、Maven 配置、许可证模板、systemd 服务模板四大内容块 2. **再查阅核心专题索引表** —— 根据你遇到的实际问题在上表中找到对应编号和章节位置 3. **直接跳转至对应的 Spec 片段** —— 阅读注释和代码示例,理解问题的成因与推荐的解决方式 4. **根据自身需求截取或改造代码** —— 将适合你项目的 `%global` 定义、`BuildRequires` 声明、`%build` 或 `%install` 段中的代码块复制到你的 Spec 文件中,并根据实际情况调整参数 ### 典型工作流 ``` 遇到打包问题 │ ├─→ 查阅「按场景快速定位」找到相关场景 │ │ │ └─→ 根据专题索引跳转到 SuperSample.spec 对应章节 │ │ │ └─→ 阅读注释 + 代码示例 │ │ │ └─→ 截取片段 → 适配到你的 Spec 文件 │ │ │ └─→ 执行 rpmbuild 验证 ``` --- ## 按场景快速定位 | 使用场景 | 相关专题(索引编号) | 涉及文件 | |----------|---------------------|----------| | 打包 Rust 项目,cargo 编译日志不够详细 | #1 Rust Cargo 宏 | `SuperSample.spec` | | Rust/Go/Java 包生成空 debuginfo 或 debuginfo 错误 | #2 Debug 包抑制 | `SuperSample.spec` | | Python 打包时 brp-python-bytecompile 报错 | #3 Python 编译控制 | `SuperSample.spec` | | 从 GitHub 拉取无 Release 号的源码打包 | #4 Commit 版本拼接 | `SuperSample.spec` | | 按条件开关编译选项或跳过测试 | #5 条件编译(bcond) | `SuperSample.spec` | | 多个子包重复相同逻辑,想复用代码 | #6 宏函数 | `SuperSample.spec` | | Java 包打包后与公共能力提供者冲突 | #7 OSGi Provides 过滤 | `SuperSample.spec` | | Java Maven 编译缺少部分依赖 | #8 Maven 依赖缺失 | `SuperSample.spec` | | 共享库安装/卸载后 ldconfig 调用失败 | #9 ldconfig 规范 | `SuperSample.spec` | | 包自动扫描出多余的 Provides/Requires | #10 过滤规则 | `SuperSample.spec` | | 单核编译太慢,想加速 | #11 多线程编译 | `SuperSample.spec` + 手动设置 | | 需要为 x86_64 和 aarch64 定义不同依赖 | #12 架构条件 | `SuperSample.spec` | | 包与旧版本冲突或需要废弃旧包 | #13 冲突与废弃 | `SuperSample.spec` | | 使用 RPM ≥ 4.13 的布尔依赖表达式 | #14 布尔依赖 | `SuperSample.spec` | | 打包 Python 模块、静态库、开发头文件、文档 | #15 多子包 | `SuperSample.spec` | | 补丁文件应用失败 | #16 `%prep` + `%patch` | `SuperSample.spec` | | GitHub/Go/npm/pip 依赖下载慢 | #17 国内代理 | `SuperSample.spec`(%prep 段) | | C/C++ 安全编译选项未开启,或调试时变量被优化 | #18 安全编译宏 | `SuperSample.spec`(%build 段) | | 修改 pom.xml 中的依赖、模块、插件 | #19 Maven POM 宏 | `SuperSample.spec`(%build 段) | | 使用 Bazel 编译 | #20 Bazel 参数 | `SuperSample.spec`(%build 段) | | Rust 编译时 crates-io 下载失败 | #21 Cargo 镜像 | `SuperSample.spec`(%build 段) | | 需要精确控制安装路径和权限 | #22 Install 最佳实践 | `SuperSample.spec`(%install 段) | | Java JAR 包需要在 aarch64 上注入动态库 | #23 JAR ARM 适配 | `SuperSample.spec`(%install 段) | | RPM 包中脚本的 shebang 不符合规范 | #24 Shebang 修正 | `SuperSample.spec`(%install 段) | | 二进制文件中包含冗余 RPATH | #25 RPATH 删除 | `SuperSample.spec`(%install 段) | | 软件需要使用 systemd 管理服务 | #26 事务脚本 + #27 systemd 宏 | `SuperSample.spec` + `service/*` | | 需要配置 Maven 构建代理 | — | `config/build_maven_settings.xml` | | 需要完整的 Maven settings 模版 | — | `config/maven_settings.xml` | | ARM 服务器 Maven 构建 | — | `config/aliyun_maven_settings.xml` | | 给服务写 systemd Unit 文件 | — | `service/java_process_sample.service` | | 给 Web 服务写 systemd Unit 文件 | — | `service/python-with-port.service` | --- ## 引用与贡献 - **License 合规查询:** [openEuler 貂蝉平台](https://compliance.openeuler.org) - **SPDX 许可证标识符参考:** - **Fedora 打包指南:** 欢迎通过 Issue 或 Pull Request 提交新的问题场景或改进建议。请在提交前确保新增内容聚焦于 RPM Spec 编写中的典型问题场景,并附带清晰的注释说明。 --- ## 许可证 本仓库以 BSD 3-Clause 许可证发布,参见仓库根目录的 [LICENSE](../LICENSE) 文件。 --- *文档维护者:Regan He · 最后更新:2026-06-09*