openSUSE:打包 Go

跳转到:导航搜索
Packaging Go 是一个循序渐进的介绍,说明如何使用 openSUSE 构建服务 为 openSUSE 构建 Golang 软件包。

关于 golang

Go(或 golang,更利于搜索引擎)是一种表达力强、并发、垃圾回收的系统编程语言,具有类型安全和内存安全。它具有指针但没有指针算术。Go 具有快速构建、简洁的语法、垃圾回收、适用于任何类型的的方法以及运行时反射。它感觉像一种动态语言,但具有静态语言的速度和安全性。

命名方案

请注意,golang 包遵循严格的命名约定,但为了方便起见,也存在例外情况。

Golang 包的名称以“golang-” 前缀开头,后跟从 $IMPORTPATH 修改后的字符串,这是您 `go get` 时看到的“url”(实际上它是一个路径)。从技术上讲,$IMPORTPATH 看起来像是 C 中的“include <xxx.h>”、Ruby 中的“require 'xx” 或 Python 中的“from package import function”,但格式为“import golang.org/google/api”。在这种情况下,“golang.org/google/api” 是 $IMPORTPATH。

可以将其分为三个部分:vendor => golang.org,author => google,pkg => api。以下是如何将它修改为 golang 包名称中的以下字符串

vendor:通常我们使用供应商的常用名称,例如“github.com” 将为“github”,而“code.google.com/p/” 将为“googlecode”。当供应商没有常用名称时,例如“gopkg.in”,我们只需跳过供应商 url 中的“点”,即“gopkgin”。

author:通常这部分足够唯一,其中大多数是人名,所以我们保持原样。在某些情况下也可以跳过。例如:“code.google.com/p/xxx”,importpath 中根本没有作者(不是“p”)。但在其他情况下,必须明确保留,例如“golang.org/x/net”,这里的“x”意味着它是一些“标准库”,因此必须保留。而“github.com/nsf/gocode”中的“nsf” 绝对不能跳过。

pkg:通常我们保持原样。但如果上游包名称中的某个地方有字符串“go”

  • go-XX:跳过“go”,我们不想看到类似“golang-github-xxx-go-xxx”的包名称, “golang-” 前缀已经标识了它
  • XX.go:这是 Go1 时代的历史。只需跳过“go”
  • goXX:保留“go”,因为它“在”包名称中,而不是前缀或后缀。

版本控制方案

大多数 golang 包尚未遵循严格的版本控制方案。您应该使用检索上游的时间(例如通过 git/mercurial/etc. 检出)加上 VCS,例如 0.0.0+gitYYYYMMDD,例如 0.0.0+git20150726,或者您可以让我们的构建服务通过 _service 文件为您完成此操作。如果上游维护者决定开始使用版本控制方案,这将确保将来的包升级更加容易。

开发仓库和流程

openSUSE 构建服务中的 devel:languages:go 仓库开发 Golang 包。

如果您想将包提交到此仓库,请

  • 分支它(简单方法:访问此仓库并单击现有包内的“分支”按钮)
  • 将您的包从您的主仓库复制到分支仓库
  • build
  • submit

这将确保您的包将为该仓库构建。

打包前需要了解的事项

并非所有包都会被接受

并非所有包都能进入 devel:languages:go 项目。将被接受的包包括二进制包(例如 clair 或 packer)及其直接和间接依赖项。其他所有包很可能不会被添加。我们建议使用 `go get` 获取这些包。

Golang 确实有依赖项

Golang 提供了一种称为“go get”的方法,这通常由上游使用。它将获取包的源代码以及所有依赖项的源代码,构建它们/tmp,并将编译后的代码安装到~/go/pkg/linux_${go_arch}/。(下载、`go build` 和 `go install`.)

` 的组合)。就像其他新的脚本语言一样,例如 Nodejs,它会使新的打包者感到困惑。有些人可能会认为此包除了“go”主包之外没有其他依赖项,遇到此问题,并发现它有 30 多个依赖项需要先打包。请先检查您的 ~/go 目录,然后再断言此包没有其他依赖项并陷入混乱。

Golang 将在何处查找依赖项?

Golang 将从以下位置查找依赖项$GOROOT(go 本身安装的位置)和$GOPATH(go 包安装的位置)。您可以运行

go env

来找到您的。基本上,在构建基础设施内部,它将是

/usr/lib(64)/go/pkg/linux_%{go_arch}/ ($GOROOT)
/usr/lib(64)/go/contrib/pkg/linux_%{go_arch}/ ($GOPATH)
/home/abuild/rpmbuild/BUILD/go/pkg/linux_%{go_arch}/ ($GOPATH)

在普通环境中,它将是

/usr/lib(64)/go/pkg/linux_%{go_arch}/ ($GOROOT)
/usr/lib(64)/go/contrib/pkg/linux_%{go_arch}/ ($GOPATH)
~/go/pkg/linux_%{go_arch}/ ($GOPATH)

但是,在构建日志中,它将不同,因为 go 的编译器(例如 6g 6l...)将

1st:尝试在上述路径中找到编译后的依赖项

2nd:尝试在以下路径中找到依赖项的源代码,编译它们,并将它们安装到$GOPATH正在运行 go 的用户的目录中,然后将它们用作依赖项。

在构建基础设施内部

/usr/lib64/go/src/pkg/$IMPORTPATH ($GOROOT)
/home/abuild/rpmbuild/BUILD/go/src/$IMPORTPATH ($GOPATH)
/usr/lib64/go/contrib/src/$IMPORTPATH ($GOPATH)

在普通环境中

/usr/lib64/go/src/pkg/$IMPORTPATH ($GOROOT)
~/go/src/$IMPORTPATH ($GOPATH)
/usr/lib64/go/contrib/src/$IMPORTPATH ($GOPATH)

3rd(仅在 `go get` 模式下可用):将源代码下载到$GOPATH正在运行 go 的用户的目录中,并重复第 2 步。

因此,如果 OBS 向您显示错误,通常发生在第 2 步,因为您不小心使用了 `go get` 方法来替换默认的%gobuild宏,这将显示诸如“找不到 git”或“网络不可达”之类的错误。

Go 布局

Go 的标准目录布局如下所示

  go
    .. pkg
       .. linux_%{go_arch}
          .. $IMPORTPATHs for packages (compiled codes reside here)
    .. src
       .. pkg
          .. $IMPORTPATHs for packages (source codes reside here)
    .. contrib
       .. pkg (same as above)
       .. src (same as above)

contrib 目录用于第三方实现(通常是我们的包)。但在~/go中,Go 将编译后的代码放在pkg并将源代码放入src直接(没有contrib目录)。

示例模板

您可以使用以下 spec 文件模板。请确保将 $VARIABLES 替换为适当的值。

基于 Go 模块

现在大多数基于 golang 的应用程序可能会使用 Go 模块来管理它们的依赖项。这意味着我们可以使用它来将所有依赖项收集到所谓的 vendor tarballs 中。为了帮助简化此步骤,openSUSE 项目创建了 obs-service-go_modules。使用包中的 _service 文件,我们可以为我们设置它

<services>
 <service name="go_modules" mode="manual">
   <param name="compression">zst</param>
 </service>
</services>

现在运行 osc service runall 应该为我们创建 vendor.tar.zst。有关受支持的所有参数,请查看 go_modules 文档

#
# spec file for <package name>
#
# Copyright (c) 2023 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.

# Please submit bugfixes or comments via https://bugs.opensuse.org/
#


Name:           name
Version:        0.0.1
Release:        0
Summary:        <summary>
License:        License-2-Clause
Group:          Productivity/Networking/Instant Messenger
URL:            <package homepage url>
Source:         https://upstream/path/to/%{name}-%{version}.tar.gz
Source1:        vendor.tar.zst
BuildRequires:  golang-packaging
BuildRequires:  zstd

%description
Description.

%prep
%autosetup -p1 -a1

%build
go build \
   -mod=vendor \
   -buildmode=pie

%install
install -D -m0755 %{name} %{buildroot}%{_bindir}/%{name}
install -D -m0644 man/%{name}.1 %{buildroot}%{_mandir}/man1/%{name}.1

%files
%license LICENSE
%doc README.md
%{_bindir}/%{name}
%{_mandir}/man1/%{name}.1%{?ext_man}

%changelog

旧式 golang 应用程序

对于不支持的 golang 软件,您可以使用 golang 宏来简化构建。下面是一个示例 spec 文件。

#
# Copyright (c) 2021 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
 
# Please submit bugfixes or comments via https://bugs.opensuse.org/
# 
%global provider_prefix github.com/example/repo
%global import_path     %{provider_prefix} 

Name:           golang-$STRING
Version:        0.0.0+git20140916
Release:        0
License:        $LICENSE
Summary:        $SUMMARY
Url:            $HOMEPAGE
Group:          Development/Languages/Other
Source:         $EXACT_UPSTREAM_NAME-%{version}.tar.xz
BuildRequires:  golang-packaging
BuildRequires:  xxx-devel
BuildRequires:  xz
Requires:       xxx-devel

%{go_provides}

%description
$DESCRIPTION
 
%prep
%autosetup -p1 -n $EXACT_UPSTREAM_NAME-%{version}

%build
%goprep %{import_path}
%gobuild .

%install
%goinstall
%gosrc

%gofilelist

%check
%gotest %{import_path}

%files -f file.lst
%license LICENSE
%doc README

%changelog

复杂的解释

您可以在文件 /usr/lib/rpm/macros.d/macros.go 中查找提供的宏。

下面解释了一些常见的宏(但并非所有宏,因为某些宏,例如%go_exclusivearch仅供内部使用,并且已经包含在其他宏中)。

注意:某些宏不能加引号

通常,您已经知道 %make 等同于 %{make},就像 shell 脚本一样。

此规则适用于 RPM 打包的几乎所有方面。但在 golang 打包中,您必须消除这种漫不经心的想法。

我知道,%goprep, %gofix, %gobuild, %goinstall, %gosrc, %gotest是不能加引号的宏,因为它们允许参数。因此,请在运行“spec-cleaner -i xxx.spec”后仔细检查,它将引用这些宏。

%go_ver

它将返回 golang 的版本,例如 1.4.2

%go_arch

它将返回 golang 的架构:i386amd64

%go_nostrip

您不应该使用它。它将禁用二进制文件的剥离。 很久以前,对 go 编译的二进制文件使用 strip 会导致错误,但似乎已修复。

%go_requires

在 golang-packaging v15.0.0 中已移除

需要你的包的主包。

Icon-warning.png
警告:如果你的包需要其他包来构建,请务必将它们手动添加到 Requires 以及 BuildRequires 中。Golang 是静态构建,常见的共享库检测机制 (/sbin/ldconfig) 将无法找到它的依赖项。也就是说,%go_requires本身通常是不够的。

%go_provides

它将为你的包添加 Provides %{name}-devel 和 %{name}-devel-static。

与 C/C++ 包不同,Golang 包没有头文件。它们是静态构建的,因此主包也是 devel 包

%go_recommends (已移除)

在 golang-packaging v15.0.0 中已移除

它将为你的包添加 Recommends %{name}-doc 子包。

与常见的 RPM 软件包不同,%{name}-doc 在 golang 中实际上是源包,而不是文档包。

%godoc_package (已移除>

在 golang-packaging v15.0.0 中已移除

类似于 %lang_package,它将在 specfile 中创建一个 %{name}-doc 子包。

%go_contribdir

go 二进制文件/静态库将被安装到此目录中

%{_libdir}/go/contrib/pkg/linux_%{go_arch}

%go_contribsrcdir

go 源代码将被安装到此目录中

%{_datadir}/go/contrib/src/pkg

%goprep

这个宏将为 golang 准备构建环境。

你必须向它提供一个参数 $IMPORTPATH。如果你看过一些 golang specfile,你会发现类似这样的内容

%goprep gopkg.in/qml.v1
%goprep github.com/howeyc/fsnotify

这些 gopkg.in/qml.v1github.com/howeyc/fsnotify 实际上是 不是 URL 而是 PATH,尽管 http://gopkg.in/qml.v1 可以访问(实际上它是这个库的主页)。

%goprep 将创建一个 %{_builddir}/go/src/gopkg.in/qml.v1 目录。

那么这个 $IMPORTPATH 的目的是什么,以及如何找到它?

它用于导入。例如,在 golang 代码中

import (
      qml gopkg.in/qml.v1
)

并且 golang 将在以下位置找到这样的库

%{go_contribsrcdir}
~/go/pkg/linux_amd64/
/home/abuild/rpmbuild/BUILD/go/pkg/linux_amd64/ (This only exists in OBS build environment, that is, ~/rpmbuild/BUILD/go/pkg/linux_amd64/ will not count unless you're building inside it)

你可以查看上游提供的示例,轻松地在源 tarball 中找到 $IMPORTPATH。

%gobuild

它实际上会构建并安装编译后的 golang 代码到 %{_builddir} 中。

默认情况下,它将构建 %{_builddir}/go/src/$IMPORTPATH 内部的所有内容。如果你想选择性地构建 $IMPORTPATH 内部的一些子目录,请安装 "go" 包并阅读 /usr/lib/rpm/macros.d/macros.go 以了解 $IMPORTPATH_MODIFIER 参数的用法。

%goinstall

它会将编译后的代码从 %{_builddir} 复制到 %{buildroot} 以进行 RPM 软件包创建。

%gosrc

它将扫描源代码目录并将所有 *.go、*.s 和 *.h 文件复制到 %{go_contribsrcdir}

%gofilelist

它将扫描 %{go_contribsrcdir} 中的文件和目录,并生成一个文件 (file.lst) 列出每个文件和目录。然后可以使用此文件进行 %files 宏,请参阅 此处

%godoc

在 golang-packaging v15.0.0 中为 无操作

它将扫描源代码目录并将所有 *.go 文件复制到 %{go_contribsrcdir} 以创建一个 %{name}-doc 包,就像 %find_lang 一样,但没有参数。

%gotest importpath

它将测试 importpath 目录内的所有 golang 代码。

Icon-warning.png
警告: 它将测试所有内容,包括示例。但一个常见的问题是,上游有时只会修复/更新功能代码而不是示例(Debhelper 有一个函数可以跳过测试示例,因此上游可能无法发现任何问题)。一些示例可能无法与较新的 golang 或库编译(它会在 OBS 上触发大量构建错误)。你可以选择禁用 %check 或修复示例(甚至 "rm -rf" 它们)。但请确保不要留下无法为我们的用户运行的代码。

BUILD 目录布局的变化

Icon-warning.png
警告: 用于 go 软件包的 RPM 宏将破坏 %{_builddir} 中的当前目录布局,因此,如果你在 %goprep 宏之后执行某些操作,除非你阅读 /usr/lib/rpm/macros.d/macros.go 定义或此帮助,否则你将不知道 BUILD 目录布局。始终记住这一点。

这种情况下有多种衍生情况

  • 如果你收到“文件或目录未找到”错误,并且想在 %install 等部分执行“ls -l”。
  • 如果你想选择性地将文件放入 %{name}-doc 包中,而不是放入上游提供的一切。这通常涉及文件添加/删除,进一步假设你知道你正在操作的文件夹的目录布局。

为什么?

Golang 是一种结构敏感的语言。它需要这样的布局来构建和放置构建结果。

%goprep 之后布局

运行 %goprep 后,将创建一个额外的 Go 特定的目录结构。然后,BUILD/%{name}-%{version} 中的所有文件将被复制到新的目录 BUILD/go/src/$IMPORTPATH

虽然 RPM 仍然会 cd 进入 BUILD/%{name}-%{version} 到达 %build%install 部分时,但这种新的目录结构对于包本身及其依赖项是必要的。它还将设置在 GOPATH 环境变量中,该变量反过来在运行 %gobuild 时使用。

%gobuild 之后布局

运行 %gobuild 后,你的包将被安装为

BUILD/go/pkg/linux_%{go_arch}/xxx/xxx/%{name}.a

BUILD/go/bin/%{name}

%goinstall 之后布局

运行 %goinstall 后,包将被安装到

BUILD/usr/bin/

静态库 (*.a 文件) 不会被安装,因此不会成为已发行的包的一部分。

%gosrc 之后布局

运行 %gosrc 后,你的包源代码将被安装到

BUILDROOT/%{_datadir}/go/contrib/src/pkg/xxx/xxx/%{name}/

它将复制 *.go 文件以及 *.s 和 *.h 文件。如果需要任何其他文件,则必须手动将这些文件复制到此路径。

%{go_contribdir} 中没有 %{name} 目录

从前面的章节我们知道 xxx/xxx/%{name} 不是 URL 而是 $IMPORTPATH。

因此,有些人可能会尝试 "pushd BUILDROOT/%{go_contribdir}/xxx/xxx/%{name}" 然后执行 "ls -l" 或 "find" 来查看哪里出错。

但是 BUILDROOT/%{go_contribdir}/ 中将不会有这样的目录。实际上只有 xxx/xxx 存在,%{name}.a 实际上是一个静态编译的文件。如果源代码有子目录,它们将被编译为 xxx/xxx/%{name}/<subdirectory-name>.a 或 xxx/xxx/%{name}/<subdirectory-name>/<some-other-name>.a。但无论如何

xxx/xxx/%{name}/*.go 将被编译为 xxx/xxx/%{name}.a

也就是说,即使你可以 "cd" 进入 %{name} 目录之后,你也不会看到任何相关内容。

注意:这仅适用于 BUILDROOT/%{go_contribdir},BUILDROOT/%{go_contribsrcdir} 仍然具有包含 *.go 文件的 %{name} 目录。

依赖项 (Requires)

Golang 包是“静态”构建,因此 shlib 解析工具 (/sbin/ldconfig) 不起作用。

快速参考

记住:你的 BuildRequires 也是你的 Requires

这听起来很奇怪,但从某种程度上说,Golang 就像 Python。你可以在二进制编译的代码 (*.pyc) 或源代码 (*.py) 中运行 Python 代码,也可以在二进制编译的代码 (*.a) 或源代码 (*.go) 中运行 Golang 代码。(但与 Python 不同,“go run” 无法运行编译后的代码。)

因此,你在构建环境中需要的,也将是你需要在运行时环境中的。

不要被 ".a" 后缀所迷惑。在 C 中,这意味着静态,你不需要安装共享库依赖项。但在 Golang 中,它不会吸收所有依赖项。它也不会吸收来自 GTK 等 C 依赖项代码。

艰难的学习

“纯” Golang 包

如果你跳过了必要的 Requires(通常是构建包所必需的,例如 lime 的 go-log4go),当用户运行包时,它将导致错误

test.go:2:8: cannot find package "code.google.com/p/log4go" in any of:
        /usr/lib64/go/src/pkg/code.google.com/p/log4go (from $GOROOT)
        /home/marguerite/go/src/code.google.com/p/log4go (from $GOPATH)
        /usr/lib64/go/contrib/src/code.google.com/p/log4go

可以通过提供 RequiresBuildRequires 来修复

Requires:      golang(code.google.com/p/log4go)
BuildRequires: golang(code.google.com/p/log4go)

但是,有些错误可能看起来更复杂

panic: runtime error: invalid memory address or nil pointer dereference [recovered]
        panic: ([]interface {}) (0x64c540,0xc208045cc0)
[signal 0xb code=0x1 addr=0x0 pc=0x4165ba]

...
[ follwing with a very looong "goroutine" ]
...

在这种情况下,在本地进行简单的测试可以帮助定位问题

  • 对于一个库:你可以从上游下载源代码并运行 go run xxx.go 来查看哪里失败。
  • 对于一个应用程序:只需卸载所有 Golang 包,除了 "go" 基本包,然后运行你的应用程序。这样你就可以捕获所有运行时依赖项。

Golang C/C++ 包装器包

Golang C/C++ 库的包装器,例如 go-gozmq 用于 zeromq,将使用 pkg-config 查找其运行时 C/C++ 依赖项,这意味着如果你没有安装 "pkg-config" 和 "zeromq-devel"(提供 /usr/lib64/pkgconfig/zeromq.pc),gozmq 将无法检测到 libzmq4 库,即使你已安装它。当运行示例时,它会抱怨

$ go run client.go 
# command-line-arguments
/usr/lib64/gcc/x86_64-suse-linux/4.8/../../../../x86_64-suse-linux/bin/ld: cannot find -lzmq
collect2: error: ld returned 1 exit status

对于这样的 Golang 包装器,因此可能需要安装一个 *-devel 包才能构建包。

常见的 Golang 错误

本节收集了一些常见的 Golang 错误,供那些对 Golang 了解不多的打包人员使用。

undefined reference to SOME_C_FUNCTION

Golang 可以调用用纯 C 编写的函数,使用名为 cgo 的工具。如果你看到

/*
#include <stdio.h>
*/
import "C"

在 .go 文件中,此文件调用了一些 C 函数。作为一名合格的打包人员,我们或多或少都有一些关于 CFLAGS 和 LDFLAGS 的想法,因此知道“undefined reference”错误意味着编译器找不到 C 中的相关头文件或 *FLAGS。但是我们如何在 Golang 中修复这些错误?这里是

  • 修复头文件很简单。
  • 以下是如何修复 CFLAGS 和 LDFLAGS
/*
#include <stdio.h>
#cgo pkgconfig: geoip
#cgo LDFLAGS: -lGeoIP
#cgo CFLAGS: -xxxxxx
/*

main redeclared in this block

Golang 是一种结构敏感的语言。如果一个文件夹包含多个文件,并且这些文件有多个“main”函数,则会触发此错误。但一些旧的 go 项目(例如,自 Golang 1.1 以来)仍然没有将示例文件放在像“examples”这样的单独文件夹中。我们知道示例是一些小的、独立的演示,依赖于这个项目,必须有一个单独的“main”函数。因此,修复很简单,只需在%prepspecfile 的 section 中执行 "mkdir -p" 创建一个 "examples" 文件夹,并将所有这些文件放入其中(参见 #Layout after %goprep 章节)。

对象是 [linux amd64 go1.3 X:precisestack],预期是 [linux amd64 go1.3.1 X:precisestack]

此错误意味着你的包是使用 go 1.3 构建的,但你当前的 Golang 环境是 go 1.3.1。通常,重新构建将解决问题。

stat "bitbucket.org/taruti/ssh.go" 没有这样的文件或目录

这是因为新版本的 Go 中不再允许使用 "*.go" 作为导入路径。

因此,在这种情况下,你需要更改

%goprep bitbucket.org/taruti/ssh.go

%goprep bitbucket.org/taruti/ssh-go

并在 .changes 文件中提及,以便使用我们存储库的开发人员知道更改。

但是通常这表明该项目太旧了,如果上游本身没有适应更改,你应该找到较新的实现。在上面的例子中,你应该使用 "code.google.com/p/go.crypto/ssh",它更新且官方。

Go 的打包技巧

"tags" 在 go get 中

有时上游例如 gozmq 告诉你 "go get -tags xxx $IMPORTPATH" 来获取特定版本,并且他们将所有标签的文件放在一个存储库中。更糟糕的是,较新的标签,例如 "zmq_4_x",需要来自较旧标签的文件,例如 "zmq_3_x" 和 "zmq_2_2" 来构建(也许这就是为什么上游没有将文件拆分为不同的 git 分支)。加上 "*_test.go" 文件,它们完全让我们困惑,关于哪些文件可以删除以进行特定版本的构建。

因此,我们不能简单地删除 "zmq_3_x" 文件进行 "zmq_4_x" 构建,并且考虑到 "*_test.go" 文件,使用 "%{?suse_version}" 删除文件将是一团糟(不合逻辑,随时可变)。总而言之,“go get -tags” 是完美、最简单且(可能是)唯一可能的解决方案。

在这种情况下,我们需要手动“构造”一个 "go get" 来替换 %gobuild。如 #Where will Golang find dependencies? 所示,“go get” 将尝试在 $GOPATH 中查找源,然后再实际下载在线内容(后者肯定会失败,因为 OBS 构建 VM 没有网络),这表明如果我们把源放在正确的位置 (%goprep) 并导出正确的环境变量,“go get” 是可用的 在 OBS 上。因此,我们可以更改 specfile 中的命令,如下所示

%build
%goprep github.com/alecthomas/gozmq
%gobuild
%install
%goinstall

%build
%goprep github.com/alecthomas/gozmq
# manual build
export IMPORTPATH="github.com/alecthomas/gozmq"
export BUILDFLAGS="-s -v -p 4 -x"
export GOPATH=%{_builddir}/go:%{_libdir}/go/contrib
%if 0%{?suse_version} >= 1230
%if 0%{?suse_version} > 1315
go get --tags zmq_4_x $BUILDFLAGS $IMPORTPATH
%else
go get --tags zmq_3_x $BUILDFLAGS $IMPORTPATH
%endif
%else
go get --tags zmq_2_1 $BUILDFLAGS $IMPORTPATH
%endif
%install
%goinstall

$GOTOOLDIR 不可重写

有时在构建 Go 官方软件包(例如 go.tools)时,一些二进制文件,例如 "godoc",会强制自己安装到 %{_libdir}/go/pkg/tool/linux_%{go_arch},即使你已经重新构建了 %gobuild 宏并将 GOTOOLDIR 导出到 %{_builddir}/go/pkg/tool/linux_%{go_arch}。

这是有意的,因为 Go 上游不希望像 godoc 这样的官方工具与 go 主包分开更新。但是,由于 go.tools 与 go 主包分开构建,因此此决定将在 OBS 上触发“open /usr/lib64/go/pkg/tool/linux_amd64: Permission Denied”错误。

我们修补了 go 主包并提供了一个名为 "GOROOT_TARGET" 的宏。如果你

export GOROOT_TARGET="%{buildroot}%{_libdir}/go"

在 %gobuild 之前,你可以获得此解决方法。

修复依赖项中的 CVE

推荐方法

使用 obs-service-go_modules,请参见此处:https://github.com/openSUSE/obs-service-go_modules/?tab=readme-ov-file#update-a-go-module-with-go-mod-edit--replace

替代方法

修复依赖项中的 CVE,当依赖项有新版本时

quilt setup *spec
cd newdirectory
quilt edit go.mod #change the version of the dep to the fixed version
quilt go.sum
go mod vendor
tar cvzf ../../vendor.tar.gz vendor/

团队成员

外部链接