From 026db6df5ad760e9002f627bdb4f6b695c04d76a Mon Sep 17 00:00:00 2001 From: Steeve Morin Date: Thu, 1 Jul 2021 23:27:50 +0200 Subject: [PATCH] Add automatic platform detection from inbound crosstool_top and cpu (#2859) When an inbound `crosstool_top` and `cpu` are specified, some platforms can be automatically inferred/detected. Some legacy rules still implement configuration splits on `crosstool_top` and `cpu` instead of platform constaints. This is the case most notably for rules_apple and rules_android. Add a generic platform matching system based on `crostool_top`/`cpu`. Finally, add Apple and Android matchers. Signed-off-by: Steeve Morin --- go/platform/crosstool.bzl | 58 +++++++++++++++++++++++++++++++++ go/private/rules/transition.bzl | 13 ++++++++ go/tools/builders/stdlib.go | 5 +++ 3 files changed, 76 insertions(+) create mode 100644 go/platform/crosstool.bzl diff --git a/go/platform/crosstool.bzl b/go/platform/crosstool.bzl new file mode 100644 index 0000000000..2e75872042 --- /dev/null +++ b/go/platform/crosstool.bzl @@ -0,0 +1,58 @@ +# Copyright 2020 The Bazel 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. + +def _match_apple(crosstool_top, cpu): + """_match_apple will try to detect wether the inbound crosstool/cpu is + targeting the Apple ecosystem. Apple crosstool CPUs are prefixed, so + matching is easy.""" + platform = { + "darwin_x86_64": "darwin_amd64", + "ios_arm64": "ios_arm64", + "ios_armv7": "ios_arm", + "ios_i386": "ios_386", + "ios_x86_64": "ios_amd64", + }.get(cpu) + if platform: + return "{}_cgo".format(platform) + return None + +def _match_android(crosstool_top, cpu): + """_match_android will try to detect wether the inbound crosstool is the + Android NDK toolchain. It can either be `//external:android/crosstool` or be + part of the `@androidndk` workspace. After that, translate Android CPUs to + Go CPUs.""" + if str(crosstool_top) == "//external:android/crosstool" or \ + crosstool_top.workspace_name == "androidndk": + platform_cpu = { + "arm64-v8a": "arm64", + "armeabi-v7a": "arm", + "x86": "386", + "x86_64": "amd64", + }.get(cpu) + if platform_cpu: + return "android_{}_cgo".format(platform_cpu) + return None + +def platform_from_crosstool(crosstool_top, cpu): + """platform_from_crosstool runs matchers against the crosstool_top/cpu pair + to automatically infer the target platform.""" + matchers = [ + _match_apple, + _match_android, + ] + for matcher in matchers: + platform = matcher(crosstool_top, cpu) + if platform: + return "@io_bazel_rules_go//go/toolchain:{}".format(platform) + return None diff --git a/go/private/rules/transition.bzl b/go/private/rules/transition.bzl index d6193651aa..8ce74e2b3f 100644 --- a/go/private/rules/transition.bzl +++ b/go/private/rules/transition.bzl @@ -36,6 +36,10 @@ load( "@io_bazel_rules_go_name_hack//:def.bzl", "IS_RULES_GO", ) +load( + "@io_bazel_rules_go//go/platform:crosstool.bzl", + "platform_from_crosstool", +) def filter_transition_label(label): """Transforms transition labels for the current workspace. @@ -143,6 +147,8 @@ def _go_transition_impl(settings, attr): goos = getattr(attr, "goos", "auto") goarch = getattr(attr, "goarch", "auto") + crosstool_top = settings.pop("//command_line_option:crosstool_top") + cpu = settings.pop("//command_line_option:cpu") _check_ternary("pure", pure) if goos != "auto" or goarch != "auto": if goos == "auto": @@ -155,6 +161,11 @@ def _go_transition_impl(settings, attr): fail('pure is "off" but cgo is not supported on {} {}'.format(goos, goarch)) platform = "@io_bazel_rules_go//go/toolchain:{}_{}{}".format(goos, goarch, "_cgo" if cgo else "") settings["//command_line_option:platforms"] = platform + else: + # If not auto, try to detect the platform the inbound crosstool/cpu. + platform = platform_from_crosstool(crosstool_top, cpu) + if platform: + settings["//command_line_option:platforms"] = platform tags = getattr(attr, "gotags", []) if tags: @@ -173,6 +184,8 @@ def _go_transition_impl(settings, attr): go_transition = transition( implementation = _go_transition_impl, inputs = [filter_transition_label(label) for label in [ + "//command_line_option:cpu", + "//command_line_option:crosstool_top", "//command_line_option:platforms", "@io_bazel_rules_go//go/config:static", "@io_bazel_rules_go//go/config:msan", diff --git a/go/tools/builders/stdlib.go b/go/tools/builders/stdlib.go index bd020095e8..8c03630c80 100644 --- a/go/tools/builders/stdlib.go +++ b/go/tools/builders/stdlib.go @@ -101,6 +101,11 @@ You may need to use the flags --cpu=x64_windows --compiler=mingw-gcc.`) b.WriteString(sep) sep = "|" b.WriteString(regexp.QuoteMeta(f)) + // If the flag if -framework, the flag value needs to be in the same + // condition. + if f == "-framework" { + sep = " " + } } os.Setenv("CGO_LDFLAGS_ALLOW", b.String())