发布约定
同一份源码分别在目标 ABI 的容器中构建。宿主机只负责调度,不能代替目标系统。
| 目标 | 构建系统 | 最大 GLIBC | 服务器目录 |
|---|---|---|---|
| RHEL7 / CentOS 7 | CentOS 7.9 | 2.17 | compiled_version/<tool>/RHEL7 |
| RHEL8 | RHEL/Rocky/UBI 8 | 2.28 | compiled_version/<tool>/RHEL8 |
禁止:直接在服务器宿主机编译 RHEL8 客户程序。宿主机 GLIBC 是 2.32,会生成不兼容的二进制。
/root/ucs_code/source_code/<domain>/<tool>/<language> # 源程序 /root/ucs_code/compiled_version/<tool>/RHEL7 # 客户程序 /root/ucs_code/compiled_version/<tool>/RHEL8 /root/ucs_build_jobs/<tool>/<timestamp> # 临时构建、日志
服务器构建镜像
Rust readyRHEL7 / RHEL8 · Rust 1.97
Python readyRHEL7 Python 3.6 · RHEL8 Python 3.9
Perl readyRHEL7 Perl 5.16 · RHEL8 Perl 5.26
| 语言 | RHEL7 | RHEL8 |
|---|---|---|
| Rust | ucs/rhel7-rust-gui-build:20260714 | ucs/rhel8-rust-gui-build:20260714 |
| Python | ucs/centos7-build:latest | ucs/rhel8-python-build:20260726 |
| Perl | ucs/centos7-build:latest | ucs/rhel8-build:latest |
新建的 RHEL8 Python 镜像已完成 PyInstaller one-file 实测:GLIBC 2.14,能够在 RHEL8 runtime 镜像运行。
建立隔离构建任务
export TOOL=ucs_example
export LANGUAGE=rust
export SOURCE=/root/ucs_code/source_code/<domain>/<tool>/<language>
export STAMP="$(date +%Y%m%d_%H%M%S)"
export JOB="/root/ucs_build_jobs/${TOOL}/${STAMP}"
mkdir -p "$JOB/src" "$JOB/out/RHEL7" "$JOB/out/RHEL8" "$JOB/logs"
rsync -a --delete --exclude target --exclude build --exclude dist \
--exclude __pycache__ --exclude '*.log' --exclude '.ucs_license.conf' \
"$SOURCE/" "$JOB/src/"
find "$JOB/src" -type f -print0 | sort -z | xargs -0 sha256sum \
> "$JOB/SOURCE_SHA256SUMS"
所有生成日志必须位于 $JOB/logs;不能写到维护源码或客户程序目录。
Rust
cd "$JOB/src" cargo fmt --all -- --check cargo test --locked cargo clippy --all-targets --all-features -- -D warnings
RHEL7
docker run --rm -v "$JOB:/work" -w /work/src \
ucs/rhel7-rust-gui-build:20260714 bash -lc '
export CARGO_TARGET_DIR=/work/target/RHEL7
cargo build --release --locked --bin '"$TOOL"'
install -m 0755 "$CARGO_TARGET_DIR"/release/'"$TOOL"' \
/work/out/RHEL7/'"$TOOL"'
'
RHEL8
docker run --rm -v "$JOB:/work" -w /work/src \
ucs/rhel8-rust-gui-build:20260714 bash -lc '
export CARGO_TARGET_DIR=/work/target/RHEL8
cargo build --release --locked --bin '"$TOOL"'
install -m 0755 "$CARGO_TARGET_DIR"/release/'"$TOOL"' \
/work/out/RHEL8/'"$TOOL"'
'
两个 target 目录必须分开。共享 Rust license crate 必须编译进程序,并在受保护功能前调用 ucs_check_license()。
Python / PyInstaller
export ENTRY=ucs_example.py cd "$JOB/src" python3 -m compileall -q . python3 -m unittest discover -s tests -p 'test_*.py'
RHEL7
docker run --rm -v "$JOB:/work" -w /work/src \
ucs/centos7-build:latest bash -lc '
python3 -m PyInstaller --noconfirm --clean --onefile \
--name '"$TOOL"' --distpath /work/out/RHEL7 \
--workpath /work/pyinstaller/RHEL7/work \
--specpath /work/pyinstaller/RHEL7/spec '"$ENTRY"'
'
RHEL8
docker run --rm -v "$JOB:/work" -w /work/src \
ucs/rhel8-python-build:20260726 bash -lc '
python3.9 -m PyInstaller --noconfirm --clean --onefile \
--name '"$TOOL"' --distpath /work/out/RHEL8 \
--workpath /work/pyinstaller/RHEL8/work \
--specpath /work/pyinstaller/RHEL8/spec '"$ENTRY"'
'
只加入真实依赖。不得因为方便把 NumPy、pandas、Qt 或完整 site-packages 一起打包。PyInstaller 是部署格式,不等同于源码加密。
Perl / PAR Packager
export ENTRY=ucs_example.pl cd "$JOB/src" perl -c "$ENTRY" prove -lr t
RHEL7
docker run --rm -v "$JOB:/work" -w /work/src \
ucs/centos7-build:latest bash -lc '
pp -o /work/out/RHEL7/'"$TOOL"' -I /work/src/lib \
-M JSON::PP -M Excel::Writer::XLSX '"$ENTRY"'
chmod 0755 /work/out/RHEL7/'"$TOOL"'
'
RHEL8
docker run --rm -v "$JOB:/work" -w /work/src \
ucs/rhel8-build:latest bash -lc '
pp -o /work/out/RHEL8/'"$TOOL"' -I /work/src/lib \
-M JSON::PP -M Excel::Writer::XLSX '"$ENTRY"'
chmod 0755 /work/out/RHEL8/'"$TOOL"'
'
动态 require 或计算出来的模块名必须显式通过 -M 加入;共享 Perl license checker 必须包含在 PAR 文件中。
强制验证门禁
- 执行单元测试、代表性输入和 golden-output 回归。
- 用
file、readelf、objdump检查 x86_64 和最高 GLIBC。 - 分别在
ucs/rhel7-runtime和ucs/rhel8-runtime中执行--help与功能 smoke test。 - 验证有效、缺失、损坏三种 license 情况;release 中不得存在 license。
- 确认 RHEL7/RHEL8 输出在去除时间戳后功能一致。
- 扫描源码、私钥、SSH key、绝对开发路径和构建缓存。
objdump -T "$JOB/out/RHEL7/$TOOL" | sed -n 's/.*GLIBC_\([0-9.]*\).*/\1/p' | sort -Vu | tail -1 docker run --rm -v "$JOB/out/RHEL7:/release:ro" \ ucs/rhel7-runtime:20260713 /release/"$TOOL" --help docker run --rm -v "$JOB/out/RHEL8:/release:ro" \ ucs/rhel8-runtime:20260713 /release/"$TOOL" --help
归档与发布
cd "$JOB/out" sha256sum RHEL7/"$TOOL" RHEL8/"$TOOL" > SHA256SUMS cp "$JOB/BUILD_MANIFEST.txt" . cp /path/to/latest/usage.html usage.html
先复制到 compiled_version/<tool>.new_<timestamp>,验证部署版本后再原子替换;旧版只在新版本验证成功后清除。
- 源码 revision 和 hash 已记录
- 两个目标容器构建
- GLIBC 门禁通过
- 三类 license 测试通过
- 无源码、license、key、cache
- 无意外绝对路径
- runtime smoke test 通过
- SHA256SUMS 已生成
- 服务器只保留最新版
- 公开 Usage 无需登录