blob: 6882a61db80d00b60bc700beb92ae2d9314bd1e3 [file] [log] [blame]
# Copyright 2017 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Recipe for building Go toolchain."""
from PB.recipes.fuchsia.contrib.go_toolchain import InputProperties
DEPS = [
"fuchsia/buildbucket_util",
"fuchsia/cipd_util",
"fuchsia/git_checkout",
"fuchsia/go",
"fuchsia/macos_sdk",
"recipe_engine/cipd",
"recipe_engine/context",
"recipe_engine/file",
"recipe_engine/path",
"recipe_engine/platform",
"recipe_engine/properties",
"recipe_engine/step",
]
PROPERTIES = InputProperties
# Files and directories to clean up before and after a build, mirroring what go
# itself does for a release.
# See https://github.com/golang/build/blob/6c34d49dff4864185cb351d06518ce3a76efb6a2/cmd/release/release.go#L240:L248
PREBUILD_CLEAN_FILES = [
".gitattributes",
".gitignore",
".hgignore",
".hgtags",
"misc/dashboard",
"misc/makerelease",
]
PREBUILD_CLEAN_DIRS = [
".git",
".github",
]
# See https://github.com/golang/build/blob/6c34d49dff4864185cb351d06518ce3a76efb6a2/cmd/release/release.go#L464:L467
POSTBUILD_CLEAN_FILES = [
"VERSION.cache",
]
POSTBUILD_CLEAN_DIRS = [
"pkg/bootstrap",
"pkg/obj",
]
FUCHSIA_THIRD_PARTY_GO_REPO = "https://fuchsia.googlesource.com/third_party/go"
def RunSteps(api, props):
host_platform = api.cipd_util.platform_name
target_platform = props.platform or host_platform
go_dir, revision = api.git_checkout(
repo=FUCHSIA_THIRD_PARTY_GO_REPO, rebase_merges=True
)
with api.step.nest("ensure_packages"), api.context(infra_steps=True):
cipd_dir = api.path.start_dir / "cipd"
pkgs = api.cipd.EnsureFile()
pkgs.add_package(
"fuchsia/third_party/clang/${platform}",
"integration",
)
api.cipd.ensure(cipd_dir, pkgs)
# Create a symlink for `ar` on PATH. Despite Go accepting the environment
# variable `AR`, it appears some code paths hardcode `ar` and do PATH
# lookups and do not find `llvm-ar`.
tool_symlink_dir = api.path.mkdtemp()
if not api.platform.is_win:
with api.step.nest("create tool symlinks"):
for tool in ["ar"]:
api.file.symlink(
f"create {tool}".format(tool),
cipd_dir.joinpath("bin", f"llvm-{tool}".format(tool)),
tool_symlink_dir / tool,
)
cipd_os, cipd_cpu = target_platform.split("-")
goos = cipd_os.replace("mac", "darwin")
goarch = cipd_cpu.replace("armv6", "arm")
# Set CGO_ENABLED=0 as it is not necessary for builds of the Go toolchain
# post-1.20 and we do not have `gcc` installed for it to find. However,
# some tests appear to ignore CGO_ENABLED=0 and attempt to run compiles
# with a cgo toolchain, so feed it `CC` and `AR` to make those happy. Also
# see additional comments about `ar` above.
env = {
"AR": cipd_dir.joinpath("bin", "llvm-ar"),
"CC": cipd_dir.joinpath("bin", "clang"),
"CGO_ENABLED": 0,
"GOOS": goos,
"GOARCH": goarch,
"GOROOT_BOOTSTRAP": api.go.go_root,
}
with api.macos_sdk(), api.context(
cwd=go_dir / "src",
env=env,
env_prefixes={"PATH": [cipd_dir / "bin", tool_symlink_dir]},
):
with api.step.nest("pre-build file removal"):
for filename in PREBUILD_CLEAN_FILES:
api.file.remove(filename, go_dir / filename)
for dirname in PREBUILD_CLEAN_DIRS:
api.file.rmtree(dirname, go_dir / dirname)
api.step("build", [go_dir.joinpath("src", "make.bash")])
if host_platform == target_platform:
with api.context(env_prefixes={"PATH": [go_dir / "bin"]}):
api.step(
"test",
[
go_dir.joinpath("src", "run.bash"),
],
)
# Remove after testing, as some tests may rely on the contents.
with api.step.nest("post-build file removal"):
for filename in POSTBUILD_CLEAN_FILES:
api.file.remove(filename, go_dir / filename)
for dirname in POSTBUILD_CLEAN_DIRS:
api.file.rmtree(dirname, go_dir / dirname)
# The builders cross-compile for arm64, which results in the bin/go binary
# being x86 with the actual arm binary at bin/linux_arm64/go.
# Modify the output to ensure that bin/go is the appropriate binary.
if cipd_os == "linux" and cipd_cpu == "arm64":
with api.step.nest("post-build linux-arm64 modifications"):
api.file.move(
"move bin/linux-arm64/go to bin/go",
go_dir / "bin/linux_arm64/go",
go_dir / "bin/go",
)
api.file.rmtree("remove bin/linux_arm64/", go_dir / "bin/linux_arm64")
if api.buildbucket_util.is_dev_or_try:
return
go_version = (
api.file.read_text(
"read go version", go_dir / "VERSION", test_data="go1.8\nblah"
).strip()
# The VERSION file may contain multiple lines, only the first line
# should be considered as the version.
.splitlines()[0]
)
assert go_version, "Cannot determine Go version"
api.cipd_util.upload_package(
"fuchsia/go/" + target_platform,
go_dir,
search_tag={"git_revision": revision},
repository=FUCHSIA_THIRD_PARTY_GO_REPO,
metadata=[("version", go_version)],
)
def GenTests(api):
properties = {
"checkout.project": "integration",
"checkout.manifest": "third_party/go",
"checkout.remote": "https://fuchsia.googlesource.com/third_party/go",
}
amd64 = {
"platform": "linux-amd64",
}
arm64 = {
"platform": "linux-arm64",
}
yield api.buildbucket_util.test("cq-amd64", tryjob=True) + api.properties(
**properties
) + api.properties(**amd64)
yield api.buildbucket_util.test("ci-amd64", tryjob=False) + api.properties(
**properties
) + api.properties(**amd64)
yield api.buildbucket_util.test("cq-arm64", tryjob=True) + api.properties(
**properties
) + api.properties(**arm64)