|
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") |
@@ -197,6 +197,10 @@ def _go_sdk_impl(ctx): |
197 | 197 | first_host_compatible_toolchain = None |
198 | 198 | host_detected_goos, host_detected_goarch = detect_host_platform(ctx) |
199 | 199 | toolchains = [] |
| 200 | + |
| 201 | + sdks_by_version = getattr(ctx, "facts", None) or {} |
| 202 | + used_versions = {} |
| 203 | + |
200 | 204 | for module in ctx.modules: |
201 | 205 | # Apply wrapped toolchains first to override specific platforms from the |
202 | 206 | # default toolchain or any downloads. |
@@ -261,18 +265,14 @@ def _go_sdk_impl(ctx): |
261 | 265 | index = index, |
262 | 266 | ) |
263 | 267 |
|
264 | | - # Keep in sync with the other calls to `go_download_sdk_rule` above and below. |
265 | | - go_download_sdk_rule( |
| 268 | + _download_sdk( |
| 269 | + module_ctx = ctx, |
| 270 | + sdks_by_version = sdks_by_version, |
| 271 | + used_versions = used_versions, |
266 | 272 | name = name, |
267 | 273 | goos = download_tag.goos, |
268 | 274 | goarch = download_tag.goarch, |
269 | | - sdks = download_tag.sdks, |
270 | | - experiments = download_tag.experiments, |
271 | | - patches = download_tag.patches, |
272 | | - patch_strip = download_tag.patch_strip, |
273 | | - urls = download_tag.urls, |
274 | | - version = download_tag.version, |
275 | | - strip_prefix = download_tag.strip_prefix, |
| 275 | + download_tag = download_tag, |
276 | 276 | ) |
277 | 277 |
|
278 | 278 | if (not download_tag.goos or download_tag.goos == host_detected_goos) and (not download_tag.goarch or download_tag.goarch == host_detected_goarch): |
@@ -306,18 +306,14 @@ def _go_sdk_impl(ctx): |
306 | 306 | suffix = "_{}_{}".format(goos, goarch), |
307 | 307 | ) |
308 | 308 |
|
309 | | - # Keep in sync with the other calls to `go_download_sdk_rule` above. |
310 | | - go_download_sdk_rule( |
| 309 | + _download_sdk( |
| 310 | + module_ctx = ctx, |
| 311 | + sdks_by_version = sdks_by_version, |
| 312 | + used_versions = used_versions, |
311 | 313 | name = default_name, |
312 | 314 | goos = goos, |
313 | 315 | goarch = goarch, |
314 | | - sdks = download_tag.sdks, |
315 | | - experiments = download_tag.experiments, |
316 | | - patches = download_tag.patches, |
317 | | - patch_strip = download_tag.patch_strip, |
318 | | - urls = download_tag.urls, |
319 | | - version = download_tag.version, |
320 | | - strip_prefix = download_tag.strip_prefix, |
| 316 | + download_tag = download_tag, |
321 | 317 | ) |
322 | 318 |
|
323 | 319 | toolchains.append(struct( |
@@ -379,7 +375,18 @@ def _go_sdk_impl(ctx): |
379 | 375 | ) |
380 | 376 |
|
381 | 377 | if bazel_features.external_deps.extension_metadata_has_reproducible: |
382 | | - return ctx.extension_metadata(reproducible = True) |
| 378 | + kwargs = { |
| 379 | + "reproducible": True, |
| 380 | + } |
| 381 | + |
| 382 | + # See _download_sdk below for details on these facts. |
| 383 | + if hasattr(ctx, "facts"): |
| 384 | + kwargs["facts"] = { |
| 385 | + version: sdk_info |
| 386 | + for version, sdk_info in sdks_by_version.items() |
| 387 | + if version in used_versions |
| 388 | + } |
| 389 | + return ctx.extension_metadata(**kwargs) |
383 | 390 | else: |
384 | 391 | return None |
385 | 392 |
|
@@ -409,6 +416,37 @@ def _left_pad_zero(index, length): |
409 | 416 | fail("index must be non-negative") |
410 | 417 | return ("0" * length + str(index))[-length:] |
411 | 418 |
|
| 419 | +def _download_sdk(*, module_ctx, sdks_by_version, used_versions, name, goos, goarch, download_tag): |
| 420 | + version = download_tag.version |
| 421 | + sdks = download_tag.sdks |
| 422 | + if version and not sdks: |
| 423 | + # Avoid a download without a known digest in the SDK repo rule by fetching the SDKs filename |
| 424 | + # and digest here. When using a version of Bazel that supports module extension facts, this |
| 425 | + # info will be persisted in the lockfile, allowing for truly airgapped builds with an |
| 426 | + # up-to-date lockfile and download (formerly repository) cache. |
| 427 | + if version not in sdks_by_version: |
| 428 | + # Lazily fetch the information about all SDKs so that we avoid the download if the facts |
| 429 | + # already contain all the versions we care about. |
| 430 | + sdks_by_version.clear() |
| 431 | + sdks_by_version.update(fetch_sdks_by_version(module_ctx)) |
| 432 | + if version not in sdks_by_version: |
| 433 | + fail("go_sdk: no SDKs found for version {} requested by".format(version), download_tag) |
| 434 | + used_versions[version] = True |
| 435 | + sdks = sdks_by_version[version] |
| 436 | + |
| 437 | + go_download_sdk_rule( |
| 438 | + name = name, |
| 439 | + goos = goos, |
| 440 | + goarch = goarch, |
| 441 | + sdks = sdks, |
| 442 | + experiments = download_tag.experiments, |
| 443 | + patches = download_tag.patches, |
| 444 | + patch_strip = download_tag.patch_strip, |
| 445 | + urls = download_tag.urls, |
| 446 | + version = download_tag.version, |
| 447 | + strip_prefix = download_tag.strip_prefix, |
| 448 | + ) |
| 449 | + |
412 | 450 | go_sdk_extra_kwargs = { |
413 | 451 | # The choice of a host-compatible SDK is expressed in repository rule attribute values and |
414 | 452 | # depends on host OS and architecture. |
|
0 commit comments