Step4-srpm源码包产出
本章节深入讲解 Bigtop 下 srpm 源码包的自动产出机制,通过 Gradle 脚本细节、产出目录结构、自动补丁插入、实操日志、目录截图以及流程图,全流程拆解源码包生成每一步,便于二次开发和团队自研环境快速落地。
# 1. srpm 的作用与定位
提示
什么是 srpm? srpm(Source RPM)即源码级 RPM 包,主要用于源码级分发、再编译和补丁集成。Bigtop 中 srpm 通常是自动化打包链路的“溯源依据”,便于内网分发、二次开发和定制补丁。
# 2. 关键流程与脚本注释
这一部分基于你实际用到的 Gradle 任务进行注释和拆解。
// srpm 任务依赖于变量初始化和tar包产出
task "$target-srpm"(dependsOn: ["${target}_vardefines", "${target}-tar"],
description: "Building SRPM for $target artifacts",
group: PACKAGES_GROUP) doLast {
// 如果目标srpm文件已存在,直接退出(避免重复构建)
if (new File(config.bigtop.components[target].targetsrpm)?.exists()) {
println "\tNothing to do. Exiting..."
return
}
// ===== 1. 变量初始化 =====
// 读取版本、包名、输出路径等动态参数
def final BIGTOP_BASE_VERSION = "${config.bigtop.base_version}"
def final PKG_NAME_SUFFIX = config.bigtop.components[target].rpm_pkg_suffix
def RPM_PKG_NAME_SUFFIX = PKG_NAME_SUFFIX
def GRADLE_PKG_NAME_SUFFIX = PKG_NAME_SUFFIX
if (!project.hasProperty("pkgSuffix") || !PKG_NAME_SUFFIX) {
RPM_PKG_NAME_SUFFIX = "%{nil}"
GRADLE_PKG_NAME_SUFFIX = ""
}
def final BIGTOP_BUILD_STAMP = System.getenv('BIGTOP_BUILD_STAMP') ?:
config.bigtop.components[target].version.release
def final NAME = config.bigtop.components[target].name
def final PKG_NAME = config.bigtop.components[target].pkg
def final PKG_NAME_FOR_PKG = NAME.replaceAll("-", "_")
def final PKG_BUILD_DIR = config.bigtop.components[target].builddir
def final SEED_TAR = config.bigtop.components[target].seedtar
def final PKG_VERSION = config.bigtop.components[target].version.pkg
def final BASE_VERSION = config.bigtop.components[target].version.base
def final PKG_OUTPUT_DIR = config.bigtop.components[target].outputdir
// ===== 2. 清理 rpm 构建目录,保证每次干净环境 =====
safeDelete("$PKG_BUILD_DIR/rpm")
['INSTALL', 'SOURCES', 'BUILD', 'SRPMS', 'RPMS'].each { rpmdir ->
mkdir("$PKG_BUILD_DIR/rpm/$rpmdir")
}
// ===== 3. 复制 SPEC、源码、补丁、脚本等资源到 rpm workspace =====
copy {
from fileTree("${BASE_DIR}/bigtop-packages/src/rpm/$NAME") {
include '**/*'
}
into "$PKG_BUILD_DIR/rpm"
}
copy { from SEED_TAR; into "$PKG_BUILD_DIR/rpm/SOURCES" }
copy { from "${BASE_DIR}/bigtop-packages/src/templates/init.d.tmpl"; into "$PKG_BUILD_DIR/rpm/SOURCES" }
copy { from "${BASE_DIR}/bigtop-packages/src/extensions"; into "$PKG_BUILD_DIR/rpm/SOURCES"; include "*" }
copy { from "${BASE_DIR}/bigtop-packages/src/scripts"; into "$PKG_BUILD_DIR/rpm/SOURCES"; include "*" }
// 复制通用和版本相关补丁
def baseCommonDir = "$BASE_DIR/bigtop-packages/src/common/$NAME"
def versionCommonDir = "$baseCommonDir/${BASE_VERSION}"
println "Copying common RPM SOURCES from: $baseCommonDir (excluding $BASE_VERSION) to $PKG_BUILD_DIR/rpm/SOURCES"
copy {
from fileTree(baseCommonDir) {
include '**/*'
exclude "${BASE_VERSION}/**"
}
into "$PKG_BUILD_DIR/rpm/SOURCES"
}
if (new File(versionCommonDir).exists()) {
println "Copying version-specific RPM SOURCES from: $versionCommonDir to $PKG_BUILD_DIR/rpm/SOURCES"
copy {
from fileTree(versionCommonDir) {
include '**/*'
}
into "$PKG_BUILD_DIR/rpm/SOURCES"
}
} else {
println "No version-specific directory found at: $versionCommonDir"
}
// ===== 4. 生成 bigtop.bom 版本清单文件 =====
def bomWriter = new File("$PKG_BUILD_DIR/rpm/SOURCES/bigtop.bom").newWriter()
bomVersions.each { bomWriter << "$it\n" }
bomWriter.close()
// ===== 5. 处理 spec 文件,动态插入补丁声明和应用命令 =====
def specFileName = "${PKG_BUILD_DIR}/rpm/SPECS/${NAME}.spec"
def specTmpFileName = "${PKG_BUILD_DIR}/rpm/SPECS/tmp_${NAME}.spec"
def specFile = new File(specFileName)
def specWriter = new File(specTmpFileName).newWriter()
def patches = new File("${PKG_BUILD_DIR}/rpm/SOURCES").list({ d, f -> f ==~ /patch.*diff/ }).sort()
specFile.eachLine { line ->
if (line.startsWith("#BIGTOP_PATCH_FILES")) {
def patchNum = 0
patches.each { p -> specWriter << "Patch$patchNum: $p\n"; patchNum++ }
} else if (line.startsWith("#BIGTOP_PATCH_COMMANDS")) {
def patchNum = 0
patches.each { p -> specWriter << "%patch$patchNum -p1\n"; patchNum++ }
} else {
specWriter << "$line\n"
}
}
specWriter.close()
specFile.delete()
new File(specTmpFileName).renameTo(specFileName)
// ===== 6. 调用 rpmbuild 产出 srpm 包 =====
def command = [
'--define', "_topdir $PKG_BUILD_DIR/rpm/",
'--define', "${PKG_NAME_FOR_PKG}_base_version $BASE_VERSION",
'--define', "${PKG_NAME_FOR_PKG}_version ${PKG_VERSION}",
'--define', "${PKG_NAME_FOR_PKG}_release ${BIGTOP_BUILD_STAMP}%{?dist}",
'-bs', '--nodeps', "--buildroot=${PKG_BUILD_DIR}/rpm/INSTALL",
specFileName,
'--define', "pkg_name_suffix ${RPM_PKG_NAME_SUFFIX}",
]
exec {
workingDir BASE_DIR
executable 'rpmbuild'
args command
}
// ===== 7. 归档产物到 output 目录 =====
mkdir(PKG_OUTPUT_DIR)
def RELEASE_DIST = "rpmbuild --eval '%{?dist}' 2>/dev/null".execute().text.trim().replaceAll("'", '')
copy {
from "$PKG_BUILD_DIR/rpm/SRPMS/${PKG_NAME}${GRADLE_PKG_NAME_SUFFIX}-${PKG_VERSION}-${BIGTOP_BUILD_STAMP}${RELEASE_DIST}.src.rpm"
into PKG_OUTPUT_DIR
}
touchTargetFile(config.bigtop.components[target].targetsrpm)
}
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# 3. srpm产出目录结构一览
核心目录说明:
目录或文件 | 用途说明 |
---|---|
rpm/SOURCES/ | 源码包、补丁、脚本等资源 |
rpm/SPECS/ | spec 打包规范 |
rpm/SRPMS/ | srpm 输出目录 |
rpm/INSTALL | 构建根目录(buildroot) |
output/ | 归档产物目录 |
# 4. 实际构建日志分析
通过日志可以直观观察整个流程的执行顺序和细节,便于排查问题:
07:45:49.261 > Task :redis-srpm
07:45:49.262 Copying common RPM SOURCES...
07:45:49.277 No version-specific directory found...
07:45:49.278 Starting process 'command 'rpmbuild''
07:45:49.375 Wrote: /opt/modules/bigtop/build/redis/rpm/SRPMS/redis_3_2_0-7.4.0-1.el8.src.rpm
07:45:49.399 Creating /opt/modules/bigtop/build/redis/.srpm
1
2
3
4
5
6
2
3
4
5
6
重点日志解读:
Copying common RPM SOURCES...
说明已同步通用资源No version-specific directory found...
若缺版本专属补丁,正常提示Starting process 'command 'rpmbuild''
触发源码包打包命令Wrote: ...src.rpm
表示源码包产出成功
完整的日志
07:45:49.261 [LIFECYCLE] [class org.gradle.internal.buildevents.TaskExecutionLogger] > Task :redis-srpm
07:45:49.261 [DEBUG] [org.gradle.internal.operations.DefaultBuildOperationExecutor] Build operation 'Task :redis-srpm' started
07:45:49.261 [DEBUG] [org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter] Putting task artifact state for task ':redis-srpm' into context took 0.0 secs
.
07:45:49.261 [INFO] [org.gradle.internal.execution.steps.ResolveCachingStateStep] Caching disabled for task ':redis-srpm' because:
Build cache is disabled
07:45:49.261 [DEBUG] [org.gradle.internal.execution.steps.SkipUpToDateStep] Determining if task ':redis-srpm' is up-to-date
07:45:49.261 [INFO] [org.gradle.internal.execution.steps.SkipUpToDateStep] Task ':redis-srpm' is not up-to-date because:
Task has not declared any outputs despite executing actions.
07:45:49.261 [DEBUG] [org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter] Executing actions for task ':redis-srpm'.
07:45:49.261 [DEBUG] [org.gradle.internal.operations.DefaultBuildOperationExecutor] Build operation 'Execute doLast {} action for :redis-srpm' started
07:45:49.262 [INFO] [org.gradle.process.internal.DefaultExecHandle] Starting process 'command 'rm''. Working directory: /opt/modules/bigtop Command: rm -rf /opt/modules/bigt
op/build/redis/rpm
07:45:49.262 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Environment for process 'command 'rm'': {PATH=/root/.nvm/versions/node/v12.13.0/bin:/opt/enhance_env/min
iconda3/bin:/opt/enhance_env/miniconda3/condabin:/usr/local/R-4.4.2/bin:/opt/modules/apache-maven-3.8.4/bin:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/b
in:/sbin:/bin:/opt/modules/gradle-5.6.4/bin:/opt/modules/apache-ant-1.10.12/bin:/opt/modules/apache-ivy-2.5.0/bin:/opt/modules/jdk1.8.0_202/bin, HISTCONTROL=ignoredups, COND
A_DEFAULT_ENV=base, CONDA_EXE=/opt/enhance_env/miniconda3/bin/conda, HISTSIZE=1000, JAVA_HOME=/opt/modules/jdk1.8.0_202, IMPALA_HOME=/opt/modules/bigtop/build/impala/rpm/BUI
LD/impala-4.4.1, BASH_FUNC_which%%=() { ( alias;
eval ${which_declare} ) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot $@
}, CONDA_PYTHON_EXE=/opt/enhance_env/miniconda3/bin/python, TERM=xterm, LANG=C.UTF-8, GRADLE_HOME=/opt/modules/gradle-5.6.4, CONDA_PREFIX=/opt/enhance_env/miniconda3, ANT_HO
ME=/opt/modules/apache-ant-1.10.12, MAVEN_HOME=/opt/modules/apache-maven-3.8.4, MAIL=/var/spool/mail/root, NVM_INC=/root/.nvm/versions/node/v12.13.0/include/node, _CE_M=, wh
ich_declare=declare -f, LOGNAME=root, NVM_NODEJS_ORG_MIRROR=https://npmmirror.com/mirrors/node, PWD=/opt/modules/bigtop, CONDA_SHLVL=1, NVM_CD_FLAGS=, NVM_DIR=/root/.nvm, LE
SSOPEN=||/usr/bin/lesspipe.sh %s, R_HOME=/usr/local/R-4.4.2, OLDPWD=/opt/modules/gradle-5.6.4, USER=root, _CE_CONDA=, HOSTNAME=rocky8, DEBUGINFOD_URLS=https://debuginfod.cen
tos.org/ , CONDA_PROMPT_MODIFIER=(base) , IVY_HOME=/opt/modules/apache-ivy-2.5.0, NVM_BIN=/root/.nvm/versions/node/v12.13.0/bin, HOME=/root, SHLVL=1}
07:45:49.262 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Changing state to: STARTING
07:45:49.262 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Waiting until process started: command 'rm'.
07:45:49.267 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Changing state to: STARTED
07:45:49.267 [DEBUG] [org.gradle.process.internal.ExecHandleRunner] waiting until streams are handled...
07:45:49.267 [INFO] [org.gradle.process.internal.DefaultExecHandle] Successfully started process 'command 'rm''
07:45:49.268 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Changing state to: SUCCEEDED
07:45:49.268 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Process 'command 'rm'' finished with exit value 0 (state: SUCCEEDED)
07:45:49.276 [QUIET] [system.out] Copying common RPM SOURCES from: /opt/modules/bigtop/bigtop-packages/src/common/redis (excluding 7.4.0) to /opt/modules/bigtop/build/redis/
rpm/SOURCES
07:45:49.277 [QUIET] [system.out] No version-specific directory found at: /opt/modules/bigtop/bigtop-packages/src/common/redis/7.4.0
07:45:49.278 [INFO] [org.gradle.process.internal.DefaultExecHandle] Starting process 'command 'rpmbuild''. Working directory: /opt/modules/bigtop Command: rpmbuild --define
_topdir /opt/modules/bigtop/build/redis/rpm/ --define redis_base_version 7.4.0 --define redis_version 7.4.0 --define redis_release 1%{?dist} -bs --nodeps --buildroot=/opt/mo
dules/bigtop/build/redis/rpm/INSTALL /opt/modules/bigtop/build/redis/rpm/SPECS/redis.spec --define pkg_name_suffix _3_2_0
07:45:49.279 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Environment for process 'command 'rpmbuild'': {PATH=/root/.nvm/versions/node/v12.13.0/bin:/opt/enhance_e
nv/miniconda3/bin:/opt/enhance_env/miniconda3/condabin:/usr/local/R-4.4.2/bin:/opt/modules/apache-maven-3.8.4/bin:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:
/usr/bin:/sbin:/bin:/opt/modules/gradle-5.6.4/bin:/opt/modules/apache-ant-1.10.12/bin:/opt/modules/apache-ivy-2.5.0/bin:/opt/modules/jdk1.8.0_202/bin, HISTCONTROL=ignoredups
, CONDA_DEFAULT_ENV=base, CONDA_EXE=/opt/enhance_env/miniconda3/bin/conda, HISTSIZE=1000, JAVA_HOME=/opt/modules/jdk1.8.0_202, IMPALA_HOME=/opt/modules/bigtop/build/impala/r
pm/BUILD/impala-4.4.1, BASH_FUNC_which%%=() { ( alias;
eval ${which_declare} ) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot $@
}, CONDA_PYTHON_EXE=/opt/enhance_env/miniconda3/bin/python, TERM=xterm, LANG=C.UTF-8, GRADLE_HOME=/opt/modules/gradle-5.6.4, CONDA_PREFIX=/opt/enhance_env/miniconda3, ANT_HO
ME=/opt/modules/apache-ant-1.10.12, MAVEN_HOME=/opt/modules/apache-maven-3.8.4, MAIL=/var/spool/mail/root, NVM_INC=/root/.nvm/versions/node/v12.13.0/include/node, _CE_M=, wh
ich_declare=declare -f, LOGNAME=root, NVM_NODEJS_ORG_MIRROR=https://npmmirror.com/mirrors/node, PWD=/opt/modules/bigtop, CONDA_SHLVL=1, NVM_CD_FLAGS=, NVM_DIR=/root/.nvm, LE
SSOPEN=||/usr/bin/lesspipe.sh %s, R_HOME=/usr/local/R-4.4.2, OLDPWD=/opt/modules/gradle-5.6.4, USER=root, _CE_CONDA=, HOSTNAME=rocky8, DEBUGINFOD_URLS=https://debuginfod.cen
tos.org/ , CONDA_PROMPT_MODIFIER=(base) , IVY_HOME=/opt/modules/apache-ivy-2.5.0, NVM_BIN=/root/.nvm/versions/node/v12.13.0/bin, HOME=/root, SHLVL=1}
07:45:49.279 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Changing state to: STARTING
07:45:49.279 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Waiting until process started: command 'rpmbuild'.
07:45:49.283 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Changing state to: STARTED
07:45:49.283 [INFO] [org.gradle.process.internal.DefaultExecHandle] Successfully started process 'command 'rpmbuild''
07:45:49.283 [DEBUG] [org.gradle.process.internal.ExecHandleRunner] waiting until streams are handled...
07:45:49.375 [QUIET] [system.out] Wrote: /opt/modules/bigtop/build/redis/rpm/SRPMS/redis_3_2_0-7.4.0-1.el8.src.rpm
07:45:49.379 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Changing state to: SUCCEEDED
07:45:49.379 [DEBUG] [org.gradle.process.internal.DefaultExecHandle] Process 'command 'rpmbuild'' finished with exit value 0 (state: SUCCEEDED)
07:45:49.399 [INFO] [org.gradle.api.internal.project.ant.AntLoggingAdapter] [ant:touch] Creating /opt/modules/bigtop/build/redis/.srpm
07:45:49.400 [DEBUG] [org.gradle.internal.operations.DefaultBuildOperationExecutor] Completing Build operation 'Execute doLast {} action for :redis-srpm'
07:45:49.400 [DEBUG] [org.gradle.internal.operations.DefaultBuildOperationExecutor] Build operation 'Execute doLast {} action for :redis-srpm' completed
07:45:49.400 [DEBUG] [org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter] Removed task artifact state for {} from context.
07:45:49.400 [DEBUG] [org.gradle.internal.operations.DefaultBuildOperationExecutor] Completing Build operation 'Task :redis-srpm'
07:45:49.400 [DEBUG] [org.gradle.internal.operations.DefaultBuildOperationExecutor] Build operation 'Task :redis-srpm' completed
07:45:49.400 [INFO] [org.gradle.execution.plan.DefaultPlanExecutor] :redis-srpm (Thread[Execution worker for ':',5,main]) completed. Took 0.138 secs.
07:45:49.400 [DEBUG] [org.gradle.internal.resources.AbstractTrackedResourceLock] Execution worker for ':': released lock on :
07:45:49.400 [DEBUG] [org.gradle.internal.work.DefaultWorkerLeaseService] Worker lease root.1.6 completed (1 worker(s) in use)
07:45:49.400 [DEBUG] [org.gradle.internal.resources.AbstractTrackedResourceLock] Execution worker for ':': released lock on root.1.6
07:45:49.400 [DEBUG] [org.gradle.internal.resources.AbstractTrackedResourceLock] Execution worker for ':' Thread 2: acquired lock on :
07:45:49.400 [DEBUG] [org.gradle.internal.work.DefaultWorkerLeaseService] Worker lease root.1.7 started (1 worker(s) in use).
07:45:49.400 [DEBUG] [org.gradle.internal.resources.AbstractTrackedResourceLock] Execution worker for ':' Thread 2: acquired lock on root.1.7
07:45:49.400 [INFO] [org.gradle.execution.plan.DefaultPlanExecutor] :redis-rpm (Thread[Execution worker for ':' Thread 2,5,main]) started.
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
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
- 01
- bigtop-select 打包缺 compat 报错修复 deb07-16
- 02
- bigtop-select 打包缺 control 文件报错修复 deb07-16
- 03
- 首次编译-环境初始化 必装07-16