# Go language - https://golang.org/
[buildout]
extends =
  ../findutils/buildout.cfg
  ../gcc/buildout.cfg
  ../git/buildout.cfg
  ../pkgconfig/buildout.cfg
  ../swig/buildout.cfg
  ../patch/buildout.cfg
  ./buildout.hash.cfg

parts = gowork go

# ---- Go builds itself ----

[golang-common]
recipe = slapos.recipe.cmmi
shared = true
configure-command = :
location = @@LOCATION@@
make-binary =
make-targets =
  cd src &&
  unset GOBIN &&
# build and test Go and its standard library
  ./all.bash &&
# clean intermediate cache before installing
# contrary to build cache in gowork, build cache, that Go uses during its own build, is not reused anywhere:
# https://github.com/golang/go/blob/go1.18.2-0-g8ed0e51b5e/src/cmd/dist/build.go#L239-L242
  GOCACHE=`pwd`/../pkg/obj/go-build ../bin/go clean -cache &&
# also clean the global cache, which is used during the tests.
  ../bin/go clean -cache &&
  cp -alf .. ${:location}
# some testdata files have an issue with slapos.extension.strip.
post-install = ${findutils:location}/bin/find ${:location}/src -type d -name testdata -exec rm -rf {} \; || true
environment =
  PATH=${swig:location}/bin:${patch:location}/bin:%(PATH)s
  GOROOT_FINAL=${:location}
  ${:environment-extra}
patch-options = -p1

[golang-common-pre-1.21]
<= golang-common

# TestChown currently fails in a user-namespace
# https://github.com/golang/go/issues/42525
# the patches apply to 1.21 > go >= 1.12
# (in go 1.21 we can't apply it, due to code changes,
#  in go > 1.21 it's hopefully fixed with
#  https://github.com/golang/go/commit/9f03e8367d85d75675b2f2e90873e3293799d8aa)
patches +=
  ${:_profile_base_location_}/skip-chown-tests.patch#d4e3c8ef83788fb2a5d80dd75034786f

[golang-common-pre-1.19]
<= golang-common-pre-1.21

# TestSCMCredentials fails in a user-namespace if golang version < 1.19
# https://github.com/golang/go/issues/42525
patches +=
  ${:_profile_base_location_}/fix-TestSCMCredentials.patch#1d8dbc97cd579e03fafd8627d48f1c59

[golang14]
<= golang-common-pre-1.19
# https://golang.org/doc/install/source#bootstrapFromSource
url = https://dl.google.com/go/go1.4-bootstrap-20171003.tar.gz
md5sum = dbf727a4b0e365bf88d97cbfde590016
environment-extra =
# build Go without testing it
# NOTE go1.4 does not have build cache
setarch =
make-targets= cd src && unset GOBIN && ${:setarch} ./make.bash && cp -alf .. ${:location}

# go1.4 is used for bootstrap and does not support CGO
environment-extra =
  CGO_ENABLED=0

# skip-chown-tests.patch does not apply to go1.4, but we don't run go1.4 tests.
patches =

# go1.4 does not have support for arm64 - build it in arm32 mode
[golang14:platform.machine() == 'aarch64']
setarch = setarch arm

[golang1.13]
<= golang-common-pre-1.19
url = https://go.dev/dl/go1.13.15.src.tar.gz
md5sum = 4f4af14d88352a62761a9dcedf863ac0

# go1.13 needs go1.4 to bootstrap
environment-extra =
  GOROOT_BOOTSTRAP=${golang14:location}

patches +=
  https://lab.nexedi.com/kirr/go/commit/a724597faa7506c74f56208bed5432abc0935264.patch#2465a69e70bef37f34a5b2b7c93ebbb7
  https://lab.nexedi.com/kirr/go/commit/d5cb71524482154b23c9e582ff0be0fc6d2856b2.patch#cc8c7524d12ebd2fc9334063901a9054
  https://lab.nexedi.com/kirr/go/commit/6dfc2256e2cd1ad46f3a5e9da85af6a70be7fba3.patch#fa9de83838b198490abec0a6a924ad8d
  https://lab.nexedi.com/kirr/go/commit/28fbdd01d6c89db1e81e12bd05910fdec4c3b9b3.patch#c75e2eb7aaaeffdd3c507ec1beacd3ca

[golang1.15]
<= golang-common-pre-1.19
url = https://go.dev/dl/go1.15.15.src.tar.gz
md5sum = 05fedd8289291eb2d91cd0c092b41aaa

# go1.1 needs go1.4 to bootstrap
environment-extra =
  GOROOT_BOOTSTRAP=${golang14:location}

[golang1.16]
<= golang-common-pre-1.19
url = https://golang.org/dl/go1.16.15.src.tar.gz
md5sum = fda3664a020a79fabe2d0d5d9d10861f

# go1.16 needs go1.4 to bootstrap
environment-extra =
  GOROOT_BOOTSTRAP=${golang14:location}

[golang1.17]
<= golang-common-pre-1.19
url = https://golang.org/dl/go1.17.13.src.tar.gz
md5sum = 4476707f05cf6915ec1173038dc357a9

# go1.17 needs go1.4 to bootstrap
environment-extra =
  GOROOT_BOOTSTRAP=${golang14:location}

[golang1.18]
<= golang-common-pre-1.19
url = https://golang.org/dl/go1.18.10.src.tar.gz
md5sum = 002b4daec72ab396dc023a5ec445a68a

# go1.18 needs go1.4 or go1.17 to bootstrap.
# We use go1.4 to reduce the amount of components which
# need to be installed. See following note for rationale:
# https://lab.nexedi.com/nexedi/slapos/merge_requests/1305#note_174936
environment-extra =
  GOROOT_BOOTSTRAP=${golang14:location}

[golang1.20]
<= golang-common-pre-1.21
url = https://go.dev/dl/go1.20.14.src.tar.gz
md5sum = 71103194b2ca39cc9cb943df9aa6154c
# go1.20 requires go1.17.13 to bootstrap (see https://go.dev/doc/go1.20#bootstrap)
environment-extra =
  GOROOT_BOOTSTRAP=${golang1.17:location}

[golang1.21]
<= golang-common
url = https://go.dev/dl/go1.21.9.src.tar.gz
md5sum = 3cc8b75a5499b5d309f267e21c3432df
# go1.21 requires go1.17.13 to bootstrap (see https://go.dev/blog/rebuild)
environment-extra =
  GOROOT_BOOTSTRAP=${golang1.17:location}

patches +=
# TestChown fix, old fix doesn't work due to code change,
# for golang > 1.21 this patch is hopefully already included with
# https://github.com/golang/go/commit/9f03e8367d85d75675b2f2e90873e3293799d8aa
  ${:_profile_base_location_}/os-skip-Chown-tests-for-auxiliary-groups-that-fail-d.patch#81b7f75786d9024049c26d1663b79ba4
  ${:_profile_base_location_}/skip-unshare-mount-test.patch#325446d5135452e8685e95ab99c13a51

# ---- infrastructure to build Go workspaces / projects ----

# gowork is the top-level section that defines Go workspace.
#
# It specifies global settings that are used to build Go programs:
#
# - Go toolchain to use, e.g.
#
#   [gowork]
#   golang = ${golang1.15:location}
#
# - For Cgo support pkg-config is made pre-available by gowork, and users
#   should list paths where to search for pkg-config files, e.g. this way:
#
#   [gowork]
#   cpkgpath =
#       ${sqlite3:location}/lib/pkgconfig
#       ${zlib:location}/lib/pkgconfig
#
# - It is also possible to specify Go build flags used for compilation e.g. this way:
#
#   [gowork]
#   buildflags = -race
#
# - If some environment variables are needed during the build, they can be
#   added with environment option, e.g. this way:
#
#   [gowork]
#   environment =
#     CGO_ENABLED = 1
#     FOO = bar
#
# Users can also add `install` field to [gowork] to request Go programs to be
# automatically installed, for example:
#
#   [gowork]
#   install =
#       lab.nexedi.com/kirr/neo/go/...@v0.0.0-20210103165133-f3effa6c535f
#       golang.org/x/tools/gopls@v0.4.3
#       ${helloweb:location}/go:./...
#
#
# ${go:exe} is standalone executable that runs go in activated gowork environment.
[go]
recipe  = slapos.recipe.template
exe     = ${buildout:bin-directory}/go
output= ${:exe}
inline =
  #!/bin/sh -e
  . ${gowork:env.sh}
  exec go "$@"

[gowork]
directory = ${gowork.dir:directory}
src	= ${gowork.dir:src}
bin	= ${gowork.dir:bin}
depends = ${gowork.goinstall:recipe}

# go version used for the workspace (possible to override in applications)
golang  = ${golang1.21:location}

# no special build flags by default
buildflags =

# empty pkg-config path by default
cpkgpath =

# by default don't `go install` anything
install =

# empty key=value environment by default
environment =

# everything is done by dependent parts
recipe  = plone.recipe.command
command = :

# env.sh for compiling and running go programs
env.sh  = ${gowork-env.sh:output}

[gowork-env.sh]
recipe	= slapos.recipe.template
url     = ${:_profile_base_location_}/${:filename}
output	= ${gowork.dir:directory}/env.sh
depends = ${gowork.dir:recipe}

[gowork.dir]
directory = ${buildout:directory}/go.work
src	= ${:directory}/src
bin	= ${:directory}/bin
# NOTE do not use slapos.cookbook:mkdirectory here - if anything in software (not instance)
# uses slapos.cookbook:* in recipe - slapos.cookbook will get compiled against system
# libxml/libxslt or fail to bootstrap at all if those are not present.
recipe  = plone.recipe.command
command = mkdir -p ${:directory}
update-command = ${:command}
stop-on-error = true

# install go programs
# clients can put program list to install to gowork:install
[gowork.goinstall]
recipe  = plone.recipe.command
command = bash -c ". ${gowork:env.sh}
	set -e
	for x in $(echo -n '${gowork:install}' |tr '\n' ' '); do
		case "\$x" in

		# external module, e.g. golang.org/x/tools/gopls@v0.4.3
		*@*)
			echo GOMOD \$x
			GO111MODULE=on go install ${gowork:buildflags} -v \$x
			;;

		# locally-cloned module source, e.g. <module-src-location>:./...
		*:*)
			echo GOMODSRC \$x
			dir=\"\$${x%%:*}\"
			arg=\"\$${x#*:}\"
			(cd \$dir && GO111MODULE=on go install ${gowork:buildflags} -v \$arg)
			;;

		# non-module
		*)
			echo GOPKG \$x
			GO111MODULE=off go install ${gowork:buildflags} -v \$x
			;;
		esac
	done
	"
update-command = ${:command}
stop-on-error = true


[git-repository]
recipe  = slapos.recipe.build:gitclone
git-executable = ${git:location}/bin/git

# a go package should:
# 1) <= go-git-package
# 2) provide go.importpath
# 3) provide repository (which is not the same as importpath in general case)
#
# the list of go packages for a go workspace state can be automatically
# generated with the help of gowork-snapshot tool.
[go-git-package]
<= git-repository
location = ${gowork.dir:src}/${:go.importpath}