blob: cd112c4d2ae69ee66ebd44883bc94f5ac301a972 [file] [log] [blame]
# Copyright 2016 The Bazel Go Rules Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Toolchain rules used by go.
"""
load("@bazel_skylib//lib:selects.bzl", "selects")
load("//go/private:common.bzl", "GO_TOOLCHAIN")
load("//go/private:platforms.bzl", "PLATFORMS")
load("//go/private:providers.bzl", "GoSDK")
load("//go/private/actions:archive.bzl", "emit_archive")
load("//go/private/actions:binary.bzl", "emit_binary")
load("//go/private/actions:link.bzl", "emit_link")
load("//go/private/actions:stdlib.bzl", "emit_stdlib")
def _go_toolchain_impl(ctx):
sdk = ctx.attr.sdk[GoSDK]
cross_compile = ctx.attr.goos != sdk.goos or ctx.attr.goarch != sdk.goarch
return [platform_common.ToolchainInfo(
# Public fields
name = ctx.label.name,
cross_compile = cross_compile,
default_goos = ctx.attr.goos,
default_goarch = ctx.attr.goarch,
actions = struct(
archive = emit_archive,
binary = emit_binary,
link = emit_link,
stdlib = emit_stdlib,
),
flags = struct(
compile = (),
link = ctx.attr.link_flags,
link_cgo = ctx.attr.cgo_link_flags,
),
sdk = sdk,
# Internal fields -- may be read by emit functions.
_builder = ctx.executable.builder,
)]
go_toolchain = rule(
_go_toolchain_impl,
attrs = {
# Minimum requirements to specify a toolchain
"builder": attr.label(
mandatory = True,
cfg = "exec",
executable = True,
doc = "Tool used to execute most Go actions",
),
"goos": attr.string(
mandatory = True,
doc = "Default target OS",
),
"goarch": attr.string(
mandatory = True,
doc = "Default target architecture",
),
"sdk": attr.label(
mandatory = True,
providers = [GoSDK],
cfg = "exec",
doc = "The SDK this toolchain is based on",
),
# Optional extras to a toolchain
"link_flags": attr.string_list(
doc = "Flags passed to the Go internal linker",
),
"cgo_link_flags": attr.string_list(
doc = "Flags passed to the external linker (if it is used)",
),
},
doc = "Defines a Go toolchain based on an SDK",
provides = [platform_common.ToolchainInfo],
)
def declare_go_toolchains(host_goos, sdk, builder):
"""Declares go_toolchain targets for each platform."""
for p in PLATFORMS:
if p.cgo:
# Don't declare separate toolchains for cgo_on / cgo_off.
# This is controlled by the cgo_context_data dependency of
# go_context_data, which is configured using constraint_values.
continue
link_flags = []
cgo_link_flags = []
if host_goos == "darwin":
cgo_link_flags.extend(["-shared", "-Wl,-all_load"])
if host_goos == "linux":
cgo_link_flags.append("-Wl,-whole-archive")
go_toolchain(
name = "go_" + p.name + "-impl",
goos = p.goos,
goarch = p.goarch,
sdk = sdk,
builder = builder,
link_flags = link_flags,
cgo_link_flags = cgo_link_flags,
tags = ["manual"],
visibility = ["//visibility:public"],
)
def declare_bazel_toolchains(
*,
go_toolchain_repo,
host_goarch,
host_goos,
major,
minor,
patch,
prerelease,
sdk_type,
prefix = ""):
"""Declares toolchain targets for each platform."""
sdk_version_label = Label("//go/toolchain:sdk_version")
native.config_setting(
name = prefix + "match_all_versions",
flag_values = {
sdk_version_label: "",
},
visibility = ["//visibility:private"],
)
native.config_setting(
name = prefix + "match_major_version",
flag_values = {
sdk_version_label: major,
},
visibility = ["//visibility:private"],
)
native.config_setting(
name = prefix + "match_major_minor_version",
flag_values = {
sdk_version_label: major + "." + minor,
},
visibility = ["//visibility:private"],
)
native.config_setting(
name = prefix + "match_patch_version",
flag_values = {
sdk_version_label: major + "." + minor + "." + patch,
},
visibility = ["//visibility:private"],
)
# If prerelease version is "", this will be the same as ":match_patch_version", but that's fine since we use match_any in config_setting_group.
native.config_setting(
name = prefix + "match_prerelease_version",
flag_values = {
sdk_version_label: major + "." + minor + "." + patch + prerelease,
},
visibility = ["//visibility:private"],
)
native.config_setting(
name = prefix + "match_sdk_type",
flag_values = {
sdk_version_label: sdk_type,
},
visibility = ["//visibility:private"],
)
selects.config_setting_group(
name = prefix + "sdk_version_setting",
match_any = [
":" + prefix + "match_all_versions",
":" + prefix + "match_major_version",
":" + prefix + "match_major_minor_version",
":" + prefix + "match_patch_version",
":" + prefix + "match_prerelease_version",
":" + prefix + "match_sdk_type",
],
visibility = ["//visibility:private"],
)
for p in PLATFORMS:
if p.cgo:
# Don't declare separate toolchains for cgo_on / cgo_off.
# This is controlled by the cgo_context_data dependency of
# go_context_data, which is configured using constraint_values.
continue
cgo_constraints = (
"@io_bazel_rules_go//go/toolchain:cgo_off",
"@io_bazel_rules_go//go/toolchain:cgo_on",
)
constraints = [c for c in p.constraints if c not in cgo_constraints]
native.toolchain(
# keep in sync with generate_toolchain_names
name = prefix + "go_" + p.name,
toolchain_type = GO_TOOLCHAIN,
exec_compatible_with = [
"@io_bazel_rules_go//go/toolchain:" + host_goos,
"@io_bazel_rules_go//go/toolchain:" + host_goarch,
],
target_compatible_with = constraints,
target_settings = [":" + prefix + "sdk_version_setting"],
toolchain = go_toolchain_repo + "//:go_" + p.name + "-impl",
)