oerv: 记录第一次修复的promu包

记录一下第一次修包过程及后续提pr的规范

本次修复的包是promu

首先是查看日志:

https://build.tarsier-infra.isrc.ac.cn/package/show/openEuler:Master:Epol/promu

[  521s] GO111MODULE= /home/abuild/go/bin/promu build --prefix /home/abuild/rpmbuild/BUILD/promu-0.17.0
[  521s]  >   promu-0.17.0
[  521s] -buildmode=pie requires external (cgo) linking, but cgo is not enabled
[  521s] !! command failed: build -o /home/abuild/rpmbuild/BUILD/promu-0.17.0/promu-0.17.0 -ldflags -w -s -extldflags '-Wl,-z,relro -Wl,-z,now -pie' -X github.com/prometheus/common/version.Version=0.17.0 -w -s -extldflags '-Wl,-z,relro -Wl,-z,now -pie' -X github.com/prometheus/common/version.Revision=non-git -w -s -extldflags '-Wl,-z,relro -Wl,-z,now -pie' -X github.com/prometheus/common/version.Branch=non-git -w -s -extldflags '-Wl,-z,relro -Wl,-z,now -pie' -X github.com/prometheus/common/version.BuildUser=abuild@OERV-OBS-16 -w -s -extldflags '-Wl,-z,relro -Wl,-z,now -pie' -X github.com/prometheus/common/version.BuildDate=20250603-23:54:06  -extldflags '-static' -tags netgo,static_build github.com/prometheus/promu: exit status 1
[  521s] make: *** [Makefile:21: build] Error 1
[  521s] error: Bad exit status from /var/tmp/rpm-tmp.RiUY84 (%build)
首先发现可能的问题就是构建的时候没有开启cgo,也就是设置CGO_ENABLED=1。然后所做的尝试就是添加设置。因为spec里面可以直接设置环境变量。
%build
export GOFLAGS="-mod=vendor -buildmode=pie"
make build

#改为
%build
export GOFLAGS="-mod=vendor -buildmode=pie"
export CGO_ENABLED=1
make build
结果而言,就是看日志可以发现设置了环境变量,但是错误还是一样的。

然后就是去源码仓看了一下变更日志。没有发现什么可疑的地方,也就是最近有升级promu的版本从0.15.0到0.17.0。
openEuler-24.03-LTS-SP2
openEuler-24.03-LTS-SP1
#这两个使用0.15版本的包都能正常构建

然后,把 openEuler:Master:Epol/promu 和 openEuler:24.03:SP1:Epol/promu 都拉取到本地构建,结果和官网没有区别,成功还是成功,失败还是失败。

osc build standard_riscv64 riscv64

然后,希望本地构建进行调试,就直接在qemu-system里面下载代码,解压,手动应用补丁进行构建,结果,两个版本都是一样的报错

#0.15.0
root@special:~/promu/promu-0.15.0# make build
fatal: not a git repository (or any of the parent directories): .git
>> installing promu
GO111MODULE= GOOS= GOARCH= go install github.com/prometheus/promu
>> rebuilding binaries using promu
GO111MODULE= /root/go/bin/promu build --prefix /root/promu/promu-0.15.0
 >   promu-0.15.0
# github.com/prometheus/promu
loadinternal: cannot find runtime/cgo

#0.17.0
root@special:~/promu/promu-0.17.0# export GOFLAGS="-mod=vendor -buildmode=pie"
root@special:~/promu/promu-0.17.0# make build
fatal: not a git repository (or any of the parent directories): .git
>> installing promu
GO111MODULE= GOOS= GOARCH= go install github.com/prometheus/promu
>> rebuilding binaries using promu
GO111MODULE= /root/go/bin/promu build --prefix /root/promu/promu-0.17.0
 >   promu-0.17.0
# github.com/prometheus/promu
loadinternal: cannot find runtime/cgo
虽然生成了二进制,但是这里这个报错我以为是什么异常呢,最后装了一大堆包也没解决。就换了一种方式想调试代码:
osc build --vm-type=chroot standard_riscv64 riscv64 --shell

这里也遇见了一些坑,有一些经验:

  1. osc build standard_riscv64 riscv64,如果成功的话,环境里面rpmbuild下的BUILD目录没有解压后的包,构建失败的话,进入shell就能看见。这只是一种现象,看见了,也不要担心哪里有问题

  2. 如果之前使用osc build其他的包,也就是/var/tmp/build-root/里面已经有了环境,最好是使用 osc build --clean standard_riscv64 riscv64进行构建。否则,你可能会发现使用shell进入环境后,里面的包不是你需要构建的包,而是之前的;你也可能遇见环境不对的问题,比如什么库缺少之类的或者chroot的系统版本不对之类的。

  3. /var/tmp/build-root/ 下可以看见构建环境,就是一个根文件系统,可以chroot进去,但是和osc --shell进去有区别。这个系统虽然只能构建,缺少工具,但是你可以主机修改,shell里面能看见变化。

    最后,对比0.15.0和0.17.0的官网构建日志才发现:二者使用的go版本不同,然后0.15.0版本的日志,往上翻日志,也会发现我手动构建出现的错误。所以,可以认为构建出现

loadinternal: cannot find runtime/cgo

就算构建成功。

回到之前的官网的构建错误:
[  521s] -buildmode=pie requires external (cgo) linking, but cgo is not enabled
[  521s] !! command failed: build -o /home/abuild/rpmbuild/BUILD/promu-0.17.0/promu-0.17.0 -ldflags -w -s -extldflags '-Wl,-z,relro -Wl,-z,now -pie' -X 
这一串东西是出现在补丁里面的,所以我vscode打开解压的未修改的源代码没有搜索到,但是能搜索到command failed。定位了cmd/build.go,看了一下这里面的代码。

发现它会代码设置CGO是否启用,所以之前传入环境变量不好使。改了代码,加了输出,就发现外部设置cgo没用,程序没有检测到。

首要的流程就是跑通构建过程,所以,改代码,设置开启程序中的cgo,就构建成功了。
#0.17.0 没有遇见 loadinternal: cannot find runtime/cgo的错误,遇见了下面的警告
#因为本机运行忘了记录,就找的官网构建日志
[  604s] /usr/bin/ld: /tmp/go-link-2581461321/000002.o: in function `mygetgrouplist':
[  604s] /_/GOROOT/src/os/user/getgrouplist_unix.go:15:(.text+0x11a): warning: Using 'getgrouplist' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking

#好在,它是一个警告,测试了构建的rpm包,可以正常运行
剩下的工作,就是正式化了。

看了下代码,可以修改Makefile来传入cgo,也就是程序运行参数传入。这里,比较方便的做法是

1.复制一个Makefile进行修改,然后diff生成补丁。

2.再把补丁复制到fork 然后clone到本地的源码包目录下,最后上传到gitee。

3.然后在自己branch的包下修改_service文件,指向你fork的包的地址和修改的分支进行构建。

具体见命令:

#这些命令还是在osc build --shell那个路径进行,不过主机上操作就行了,不构建
cp Makefile fix
vim fix
diff -u Makefile fix > set_cgo.patch
#把补丁复制到解压出来的promu源代码那里应用
patch -p1  < set_cgo.patch
#应用补丁,发现修改生效。
#还需要注意的是:diff这里生成的patch,格式需要做一些调整,因为是两个名称不同的文件
#也就是patch文件里面文件名前面需要添加a/ b/这样的
#或许对Makefile单独放到一个git仓库进行diff就可以免手动调整了

做好这几步,就可以构建成功了,但是提交PR还不够。

我直接提交了PR,然后就遇见了以下问题:

https://openeulerjenkins.osinfra.cn/job/multiarch/job/src-openeuler/job/trigger/job/promu//34/console

2025-06-08 20:49:25,738 [  ERROR] : Every pr commit requires a changelog!
2025-06-08 20:49:25,739 [  ERROR] : check version_pr_changelog fail 
#spec文件修改了打补丁,但是忘记了changelog

https://openeulerjenkins.osinfra.cn/job/multiarch/job/src-openeuler/job/trigger/job/promu//35/console
2025-06-08 21:29:26,960 [  ERROR] : release error in changelog: 3 is different from 2
2025-06-08 21:29:26,961 [  ERROR] : check changelog fail 
2025-06-08 21:29:26,971 [   INFO] : gr.spec_file:promu.spec
2025-06-08 21:29:26,983 [  ERROR] : current version: 0.17.0-r2, last version: 0.17.0-r2
2025-06-08 21:29:26,983 [  ERROR] : check version_pr_changelog fail 
#每次changelog,realease号需要+1

https://openeulerjenkins.osinfra.cn/job/multiarch/job/src-openeuler/job/trigger/job/promu//36/console

025-06-08 21:30:24,315 [  ERROR] : bogus date in changelog: Sun Jun 8 2015 yyjeqhc <jialin.oerv@isrc.iscas.ac.cn> - 0.17.0-3
- Set cgo parameter explicitly for promu

2025-06-08 21:30:24,315 [  ERROR] : check changelog fail 
#注意typo error,这个检查挺严格的,日期错误也会检查到

image

以上,spec规范没有问题,构建、安装、证书没有问题,就算构建成功了。但是还有其他错误:

image

向老师请教以后,才注意到需要考虑其它的架构,它们是否需要应用补丁。

https://eulermaker.compass-ci.openeuler.openatom.cn/
#可以在这个网站上构建非riscv64架构的包,使用和https://build.tarsier-infra.isrc.ac.cn/类似。

image

不过,这个环境里面go的版本也是1.21,所以在主机(go 1.24)里面下载代码,手动构建了一下,没有出现问题,就暂且认为它们不需要应用补丁。于是在spec文件里面修改

#打补丁
%prep
%setup -q -T -n %{name}-%{version} -b 0
tar -xzvf %{SOURCE1}
%patch 0 -p1
%patch 1 -p1
%ifarch riscv64
%patch 2 -p1
%endif
#设置为只对riscv64打补丁
最后,两个网站都拉取同样的代码,都构建成功,把修改应用到set_cgo,强制推送代码,CI结果和之前一致,可以认为没有问题。

总结:

细致的分析日志很重要,这里就需要早点注意到go版本的区别,还有OBS构建和手动构建的区别(**OBS忽略了 runtime/cgo的错误,主机遇见错误就结束构建了**);**环境的清理**也很重要,没有及时清理环境,和不存在的问题battle了一段时间;合适的利用AI也很重要,它们的知识未必是对的,甚至会自相矛盾。最后也是发现go的版本不同,认为这个可能会对buildmode=pie产生了影响,gemini联网搜索才找到类似的问题。

参考:

https://github.com/golang/go/issues/64875
https://go-review.googlesource.com/c/website/+/569296
posted @ 2025-07-01 22:44  念秋  阅读(49)  评论(0)    收藏  举报