|
15 | 15 | load("@io_bazel_rules_go_bazel_features//:features.bzl", "bazel_features") |
16 | 16 | load("//go/private:go_mod.bzl", "version_from_go_mod") |
17 | 17 | load("//go/private:nogo.bzl", "DEFAULT_NOGO", "NOGO_DEFAULT_EXCLUDES", "NOGO_DEFAULT_INCLUDES", "go_register_nogo") |
18 | | -load("//go/private:sdk.bzl", "detect_host_platform", "go_download_sdk_rule", "go_host_sdk_rule", "go_multiple_toolchains", "go_wrap_sdk_rule") |
| 18 | +load("//go/private:sdk.bzl", "detect_host_platform", "fetch_sdks_by_version", "go_download_sdk_rule", "go_host_sdk_rule", "go_multiple_toolchains", "go_wrap_sdk_rule") |
19 | 19 |
|
20 | 20 | def host_compatible_toolchain_impl(ctx): |
21 | 21 | ctx.file("BUILD.bazel") |
@@ -190,6 +190,10 @@ def _go_sdk_impl(ctx): |
190 | 190 | first_host_compatible_toolchain = None |
191 | 191 | host_detected_goos, host_detected_goarch = detect_host_platform(ctx) |
192 | 192 | toolchains = [] |
| 193 | + |
| 194 | + sdks_by_version = getattr(ctx, "facts", None) or {} |
| 195 | + used_versions = {} |
| 196 | + |
193 | 197 | for module in ctx.modules: |
194 | 198 | # Apply wrapped toolchains first to override specific platforms from the |
195 | 199 | # default toolchain or any downloads. |
@@ -252,18 +256,14 @@ def _go_sdk_impl(ctx): |
252 | 256 | index = index, |
253 | 257 | ) |
254 | 258 |
|
255 | | - # Keep in sync with the other calls to `go_download_sdk_rule` above and below. |
256 | | - go_download_sdk_rule( |
| 259 | + _download_sdk( |
| 260 | + module_ctx = ctx, |
| 261 | + sdks_by_version = sdks_by_version, |
| 262 | + used_versions = used_versions, |
257 | 263 | name = name, |
258 | 264 | goos = download_tag.goos, |
259 | 265 | goarch = download_tag.goarch, |
260 | | - sdks = download_tag.sdks, |
261 | | - experiments = download_tag.experiments, |
262 | | - patches = download_tag.patches, |
263 | | - patch_strip = download_tag.patch_strip, |
264 | | - urls = download_tag.urls, |
265 | | - version = download_tag.version, |
266 | | - strip_prefix = download_tag.strip_prefix, |
| 266 | + download_tag = download_tag, |
267 | 267 | ) |
268 | 268 |
|
269 | 269 | if (not download_tag.goos or download_tag.goos == host_detected_goos) and (not download_tag.goarch or download_tag.goarch == host_detected_goarch): |
@@ -297,18 +297,14 @@ def _go_sdk_impl(ctx): |
297 | 297 | suffix = "_{}_{}".format(goos, goarch), |
298 | 298 | ) |
299 | 299 |
|
300 | | - # Keep in sync with the other calls to `go_download_sdk_rule` above. |
301 | | - go_download_sdk_rule( |
| 300 | + _download_sdk( |
| 301 | + module_ctx = ctx, |
| 302 | + sdks_by_version = sdks_by_version, |
| 303 | + used_versions = used_versions, |
302 | 304 | name = default_name, |
303 | 305 | goos = goos, |
304 | 306 | goarch = goarch, |
305 | | - sdks = download_tag.sdks, |
306 | | - experiments = download_tag.experiments, |
307 | | - patches = download_tag.patches, |
308 | | - patch_strip = download_tag.patch_strip, |
309 | | - urls = download_tag.urls, |
310 | | - version = download_tag.version, |
311 | | - strip_prefix = download_tag.strip_prefix, |
| 307 | + download_tag = download_tag, |
312 | 308 | ) |
313 | 309 |
|
314 | 310 | toolchains.append(struct( |
@@ -370,7 +366,18 @@ def _go_sdk_impl(ctx): |
370 | 366 | ) |
371 | 367 |
|
372 | 368 | if bazel_features.external_deps.extension_metadata_has_reproducible: |
373 | | - return ctx.extension_metadata(reproducible = True) |
| 369 | + kwargs = { |
| 370 | + "reproducible": True, |
| 371 | + } |
| 372 | + |
| 373 | + # See _download_sdk below for details on these facts. |
| 374 | + if hasattr(ctx, "facts"): |
| 375 | + kwargs["facts"] = { |
| 376 | + version: sdk_info |
| 377 | + for version, sdk_info in sdks_by_version.items() |
| 378 | + if version in used_versions |
| 379 | + } |
| 380 | + return ctx.extension_metadata(**kwargs) |
374 | 381 | else: |
375 | 382 | return None |
376 | 383 |
|
@@ -400,6 +407,37 @@ def _left_pad_zero(index, length): |
400 | 407 | fail("index must be non-negative") |
401 | 408 | return ("0" * length + str(index))[-length:] |
402 | 409 |
|
| 410 | +def _download_sdk(*, module_ctx, sdks_by_version, used_versions, name, goos, goarch, download_tag): |
| 411 | + version = download_tag.version |
| 412 | + sdks = download_tag.sdks |
| 413 | + if version and not sdks: |
| 414 | + # Avoid a download without a known digest in the SDK repo rule by fetching the SDKs filename |
| 415 | + # and digest here. When using a version of Bazel that supports module extension facts, this |
| 416 | + # info will be persisted in the lockfile, allowing for truly airgapped builds with an |
| 417 | + # up-to-date lockfile and download (formerly repository) cache. |
| 418 | + if version not in sdks_by_version: |
| 419 | + # Lazily fetch the information about all SDKs so that we avoid the download if the facts |
| 420 | + # already contain all the versions we care about. |
| 421 | + sdks_by_version.clear() |
| 422 | + sdks_by_version.update(fetch_sdks_by_version(module_ctx)) |
| 423 | + if version not in sdks_by_version: |
| 424 | + fail("go_sdk: no SDKs found for version {} requested by".format(version), download_tag) |
| 425 | + used_versions[version] = True |
| 426 | + sdks = sdks_by_version[version] |
| 427 | + |
| 428 | + go_download_sdk_rule( |
| 429 | + name = name, |
| 430 | + goos = goos, |
| 431 | + goarch = goarch, |
| 432 | + sdks = sdks, |
| 433 | + experiments = download_tag.experiments, |
| 434 | + patches = download_tag.patches, |
| 435 | + patch_strip = download_tag.patch_strip, |
| 436 | + urls = download_tag.urls, |
| 437 | + version = download_tag.version, |
| 438 | + strip_prefix = download_tag.strip_prefix, |
| 439 | + ) |
| 440 | + |
403 | 441 | go_sdk_extra_kwargs = { |
404 | 442 | # The choice of a host-compatible SDK is expressed in repository rule attribute values and |
405 | 443 | # depends on host OS and architecture. |
|
0 commit comments