Skip to content

Commit 026db6d

Browse files
authored
Add automatic platform detection from inbound crosstool_top and cpu (bazel-contrib#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 <[email protected]>
1 parent 4788714 commit 026db6d

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

go/platform/crosstool.bzl

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Copyright 2020 The Bazel Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
def _match_apple(crosstool_top, cpu):
16+
"""_match_apple will try to detect wether the inbound crosstool/cpu is
17+
targeting the Apple ecosystem. Apple crosstool CPUs are prefixed, so
18+
matching is easy."""
19+
platform = {
20+
"darwin_x86_64": "darwin_amd64",
21+
"ios_arm64": "ios_arm64",
22+
"ios_armv7": "ios_arm",
23+
"ios_i386": "ios_386",
24+
"ios_x86_64": "ios_amd64",
25+
}.get(cpu)
26+
if platform:
27+
return "{}_cgo".format(platform)
28+
return None
29+
30+
def _match_android(crosstool_top, cpu):
31+
"""_match_android will try to detect wether the inbound crosstool is the
32+
Android NDK toolchain. It can either be `//external:android/crosstool` or be
33+
part of the `@androidndk` workspace. After that, translate Android CPUs to
34+
Go CPUs."""
35+
if str(crosstool_top) == "//external:android/crosstool" or \
36+
crosstool_top.workspace_name == "androidndk":
37+
platform_cpu = {
38+
"arm64-v8a": "arm64",
39+
"armeabi-v7a": "arm",
40+
"x86": "386",
41+
"x86_64": "amd64",
42+
}.get(cpu)
43+
if platform_cpu:
44+
return "android_{}_cgo".format(platform_cpu)
45+
return None
46+
47+
def platform_from_crosstool(crosstool_top, cpu):
48+
"""platform_from_crosstool runs matchers against the crosstool_top/cpu pair
49+
to automatically infer the target platform."""
50+
matchers = [
51+
_match_apple,
52+
_match_android,
53+
]
54+
for matcher in matchers:
55+
platform = matcher(crosstool_top, cpu)
56+
if platform:
57+
return "@io_bazel_rules_go//go/toolchain:{}".format(platform)
58+
return None

go/private/rules/transition.bzl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ load(
3636
"@io_bazel_rules_go_name_hack//:def.bzl",
3737
"IS_RULES_GO",
3838
)
39+
load(
40+
"@io_bazel_rules_go//go/platform:crosstool.bzl",
41+
"platform_from_crosstool",
42+
)
3943

4044
def filter_transition_label(label):
4145
"""Transforms transition labels for the current workspace.
@@ -143,6 +147,8 @@ def _go_transition_impl(settings, attr):
143147

144148
goos = getattr(attr, "goos", "auto")
145149
goarch = getattr(attr, "goarch", "auto")
150+
crosstool_top = settings.pop("//command_line_option:crosstool_top")
151+
cpu = settings.pop("//command_line_option:cpu")
146152
_check_ternary("pure", pure)
147153
if goos != "auto" or goarch != "auto":
148154
if goos == "auto":
@@ -155,6 +161,11 @@ def _go_transition_impl(settings, attr):
155161
fail('pure is "off" but cgo is not supported on {} {}'.format(goos, goarch))
156162
platform = "@io_bazel_rules_go//go/toolchain:{}_{}{}".format(goos, goarch, "_cgo" if cgo else "")
157163
settings["//command_line_option:platforms"] = platform
164+
else:
165+
# If not auto, try to detect the platform the inbound crosstool/cpu.
166+
platform = platform_from_crosstool(crosstool_top, cpu)
167+
if platform:
168+
settings["//command_line_option:platforms"] = platform
158169

159170
tags = getattr(attr, "gotags", [])
160171
if tags:
@@ -173,6 +184,8 @@ def _go_transition_impl(settings, attr):
173184
go_transition = transition(
174185
implementation = _go_transition_impl,
175186
inputs = [filter_transition_label(label) for label in [
187+
"//command_line_option:cpu",
188+
"//command_line_option:crosstool_top",
176189
"//command_line_option:platforms",
177190
"@io_bazel_rules_go//go/config:static",
178191
"@io_bazel_rules_go//go/config:msan",

go/tools/builders/stdlib.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ You may need to use the flags --cpu=x64_windows --compiler=mingw-gcc.`)
101101
b.WriteString(sep)
102102
sep = "|"
103103
b.WriteString(regexp.QuoteMeta(f))
104+
// If the flag if -framework, the flag value needs to be in the same
105+
// condition.
106+
if f == "-framework" {
107+
sep = " "
108+
}
104109
}
105110
os.Setenv("CGO_LDFLAGS_ALLOW", b.String())
106111

0 commit comments

Comments
 (0)