Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions .bazelci/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,24 @@ buildifier:
# As a regression test for #225, check that wheel targets still build when
# their package path is qualified with the repo name.
- "@rules_python//examples/wheel/..."
# Tasks can merge these into their own build_flags or test_flags with `<<:`.
# To change a merged flag, such as a tag filter, list it again: Bazel uses the
# last value.
build_flags: &reusable_config_build_flags
? "--experimental_repository_cache_hardlinks=false"
? "--keep_going"
? "--build_tag_filters=-integration-test"
? "--verbose_failures"
# Among other things, makes missing Visual Studio ARM64 build tools an
# error on Windows; see .bazelrc. test_flags repeat it so that `bazel test`
# reuses the build's analysis cache.
? "--config=ci"
test_targets:
- "--"
- "..."
test_flags:
test_flags: &reusable_config_test_flags
? "--test_tag_filters=-integration-test"
? "--config=ci"
.common_workspace_flags_min_bazel: &common_workspace_flags_min_bazel
build_flags:
? "--experimental_repository_cache_hardlinks=false"
Expand Down Expand Up @@ -245,8 +253,8 @@ tasks:
- "--"
- "//tests/..."
test_flags:
<<: *reusable_config_test_flags
? "--keep_going"
? "--test_tag_filters=-integration-test"
ubuntu_workspace:
<<: *reusable_config
<<: *common_workspace_flags
Expand Down Expand Up @@ -299,21 +307,23 @@ tasks:
platform: windows
bazel: ${{ bazel }}
test_flags:
<<: *reusable_config_test_flags
? "--test_tag_filters=-integration-test,-fix-windows"
rbe_min:
<<: *minimum_supported_version
<<: *reusable_config
name: "RBE: Ubuntu, minimum Bazel"
platform: rbe_ubuntu2404
build_flags:
? "--experimental_repository_cache_hardlinks=false"
<<: *reusable_config_build_flags
# BazelCI sets --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1,
# which prevents cc toolchain autodetection from working correctly
# on Bazel 5.4 and earlier. To workaround this, manually specify the
# build kite cc toolchain.
? "--extra_toolchains=@buildkite_config//config:cc-toolchain"
? "--build_tag_filters=-docs"
test_flags:
<<: *reusable_config_test_flags
? "--test_tag_filters=-integration-test,-acceptance-test,-docs"
# BazelCI sets --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1,
# which prevents cc toolchain autodetection from working correctly
Expand All @@ -328,6 +338,7 @@ tasks:
# See https://github.com/bazelbuild/rules_python/issues/2499
bazel: 8.x
test_flags:
<<: *reusable_config_test_flags
? "--test_tag_filters=-integration-test,-acceptance-test"
? "--extra_toolchains=@buildkite_config//config:cc-toolchain"

Expand Down
10 changes: 8 additions & 2 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,19 @@ common --disk_cache=~/.cache/bazel/bazel-disk-cache
common --repository_cache=~/.cache/bazel/bazel-repo-cache
# Hardlinks save disk space and copy time when unpacking repositories
common --experimental_repository_cache_hardlinks=true
# To work around bug on bazel 7
common:ci --experimental_repository_cache_hardlinks=false
# Drop `experimental_` prefix once Bazel 7 is no longer supported
common --experimental_downloader_config=downloader_config.cfg
common --http_timeout_scaling=10.0
common --experimental_repository_downloader_retries=10

# BazelCI's default and RBE bzlmod jobs pass --config=ci; see
# .bazelci/presubmit.yml.
# To work around bug on bazel 7
common:ci --experimental_repository_cache_hardlinks=false
# Make missing Visual Studio ARM64 build tools an error on Windows x86_64; see
# dev/release_artifacts/BUILD.bazel.
common:ci --//dev/release_artifacts:require_msvc_arm64=true

# Additional config to use for readthedocs builds.
# See .readthedocs.yml for additional flags that can only be determined from
# the runtime environment.
Expand Down
19 changes: 15 additions & 4 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,11 @@ register_toolchains(
dev_dependency = True,
)

# A Rust toolchain to cross-compile the release artifacts for 32-bit Windows
# from Windows x86_64, with MSVC's x86 tools. Unlike the Linux ones, it isn't
# registered here: no default toolchain targets 32-bit Windows, and rules_rust
# registers it.
# Rust toolchains to cross-compile the release artifacts for 32-bit and Arm
# Windows from Windows x86_64, with MSVC's cross tools; the Arm one needs
# Visual Studio's optional ARM64 build tools. Unlike the Linux ones, they
# aren't registered here: no default toolchain targets these platforms from
# Windows x86_64, and rules_rust registers them.
rust.repository_set(
# As above, its x86_64 toolchain's name must sort after the default one's.
# On Windows, rules_rust names toolchains after a hash of the full name:
Expand All @@ -250,6 +251,16 @@ rust.repository_set(
versions = ["1.97.1"],
)

# Another target for the same set; the first tag sets the shared attributes.
rust.repository_set(
name = "rust_release_windows",
target_compatible_with = [
"@platforms//cpu:aarch64",
"@platforms//os:windows",
],
target_triple = "aarch64-pc-windows-msvc",
)

# Use the Rust-based build tools when developing rules_python itself.
register_toolchains(
"//dev/dev_only_toolchains:exe_zip_maker_toolchain",
Expand Down
3 changes: 3 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ The release workflow also builds `//dev/release_artifacts:artifacts_for_release`
for each platform to verify it builds. For now, the files aren't attached to
the release, so a failed "Build tools" job doesn't block it.

Presubmit builds it for every platform too: natively on each CI host, and
through `//dev/release_artifacts:cross_compiled_artifacts` for the others.

### Manually publishing to PyPI

If PyPI publishing failed or was skipped during the main release, the PyPI
Expand Down
10 changes: 7 additions & 3 deletions dev/platforms/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@
# aarch64 macOS file. s390x isn't covered yet: Rust ships no musl std for it,
# and a static glibc build needs a C cross toolchain.
#
# Linux x86_64 hosts cross-compile for the musl ones, and Windows x86_64 hosts
# for i686-pc-windows-msvc, with the Rust toolchains in MODULE.bazel. The
# others are built on hosts that match them.
# Linux x86_64 hosts can cross-compile for the musl ones, Windows x86_64 hosts
# for the other Windows ones (Arm needs Visual Studio's ARM64 build tools), and
# macOS arm64 hosts for x86_64-apple-darwin, with the Rust toolchains in
# MODULE.bazel and rules_rust's defaults.
# //dev/release_artifacts:cross_compiled_artifacts cross-compiles them all; the
# release workflow builds aarch64-pc-windows-msvc and x86_64-apple-darwin on
# hosts that match them instead.

package(default_visibility = ["//:__subpackages__"])

Expand Down
98 changes: 97 additions & 1 deletion dev/release_artifacts/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED") # buildifier: disable=bzl-visibility
load(":release_files.bzl", "release_files")
load(
":cc_toolchain_available_config_setting.bzl",
"cc_toolchain_available_config_setting",
)
load(":release_files.bzl", "cross_compiled_files", "release_files")

package(default_visibility = ["//:__subpackages__"])

Expand All @@ -14,8 +19,99 @@ release_files(
tags = [] if BZLMOD_ENABLED else ["manual"],
)

# artifacts_for_release for the other platforms in dev/platforms that the host
# can cross-compile for, so that builds of //... on each host cover them. The
# select()s match the target platform, which is the host's unless --platforms
# is set. Arm Windows needs its own select(): Windows x86_64 hosts can match
# both is_windows_x86_64 and is_windows_x86_64_with_msvc_arm64, and in a single
# select() that ambiguous match would be an error.
#
# To reproduce a failure, build artifacts_for_release with
# --platforms=//dev/platforms:<triple>; see build.sh. If a platform's build
# breaks presubmit without a related change, tag this target "manual" until
# it's fixed.
cross_compiled_files(
name = "cross_compiled_artifacts",
src = ":artifacts_for_release",
platforms = select({
":is_linux_x86_64": [
"//dev/platforms:aarch64-unknown-linux-musl",
"//dev/platforms:armv7-unknown-linux-musleabihf",
"//dev/platforms:i686-unknown-linux-musl",
"//dev/platforms:powerpc64le-unknown-linux-musl",
"//dev/platforms:riscv64gc-unknown-linux-musl",
],
":is_macos_aarch64": ["//dev/platforms:x86_64-apple-darwin"],
":is_windows_x86_64": ["//dev/platforms:i686-pc-windows-msvc"],
"//conditions:default": [],
}) + select({
":is_windows_x86_64_with_msvc_arm64": [
"//dev/platforms:aarch64-pc-windows-msvc",
],
"//conditions:default": [],
}),
# See artifacts_for_release.
tags = [] if BZLMOD_ENABLED else ["manual"],
)

# Matches on Windows x86_64 if Visual Studio's optional ARM64 build tools
# (Microsoft.VisualStudio.Component.VC.Tools.ARM64) are installed, so that the
# C++ toolchain for Windows arm64 works. Without them, aarch64-pc-windows-msvc
# is skipped, or the build fails if require_msvc_arm64 is set. After installing
# them, run `bazel fetch --configure --force` so that rules_cc detects them.
cc_toolchain_available_config_setting(
name = "is_windows_x86_64_with_msvc_arm64",
constraint_values = [
"@platforms//cpu:x86_64",
"@platforms//os:windows",
],
platform = "//dev/platforms:aarch64-pc-windows-msvc",
required_flag = ":require_msvc_arm64",
)

# BazelCI sets this through --config=ci (see .bazelrc). Its Windows images have
# the ARM64 build tools, so losing them fails the build instead of going
# unnoticed. It has no effect unless the target platform is Windows x86_64.
bool_flag(
name = "require_msvc_arm64",
build_setting_default = False,
)

config_setting(
name = "is_linux_x86_64",
constraint_values = [
"@platforms//cpu:x86_64",
"@platforms//os:linux",
],
)

config_setting(
name = "is_macos_aarch64",
constraint_values = [
"@platforms//cpu:aarch64",
"@platforms//os:macos",
],
)

config_setting(
name = "is_windows_x86_64",
constraint_values = [
"@platforms//cpu:x86_64",
"@platforms//os:windows",
],
)

bzl_library(
name = "release_files",
srcs = ["release_files.bzl"],
deps = ["//python/private:common_labels"],
)

bzl_library(
name = "cc_toolchain_available_config_setting",
srcs = ["cc_toolchain_available_config_setting.bzl"],
deps = [
"@bazel_skylib//rules:common_settings",
"@rules_cc//cc:find_cc_toolchain_bzl",
],
)
122 changes: 122 additions & 0 deletions dev/release_artifacts/cc_toolchain_available_config_setting.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
"""Config setting for whether a C++ toolchain can build for a platform."""

load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load(
"@rules_cc//cc:find_cc_toolchain.bzl",
"find_cc_toolchain",
"use_cc_toolchain",
)

_ProbeInfo = provider(
doc = "The result of looking for a C++ toolchain.",
fields = {"available": "bool: whether a usable C++ toolchain was found."},
)

def _probe_impl(ctx):
cc_toolchain = find_cc_toolchain(ctx, mandatory = False)

# rules_cc registers its Windows toolchains even if their tools are
# missing, and then runs an error script instead of them, e.g.
# vc_installation_error_arm64.bat or clang_installation_error.bat.
available = cc_toolchain != None and (
"installation_error" not in cc_toolchain.compiler_executable
)
return [_ProbeInfo(available = available)]

_probe = rule(
implementation = _probe_impl,
toolchains = use_cc_toolchain(mandatory = False),
)

def _platform_transition_impl(_settings, attr):
return {"//command_line_option:platforms": str(attr.platform)}

_platform_transition = transition(
implementation = _platform_transition_impl,
inputs = [],
outputs = ["//command_line_option:platforms"],
)

def _cc_toolchain_available_impl(ctx):
for constraint in ctx.attr.constraint_values:
if not ctx.target_platform_has_constraint(
constraint[platform_common.ConstraintValueInfo],
):
return [config_common.FeatureFlagInfo(value = "no")]

# With a transition, ctx.attr.probe is a list.
available = ctx.attr.probe[0][_ProbeInfo].available
required = (
ctx.attr.required_flag != None and
ctx.attr.required_flag[BuildSettingInfo].value
)
if required and not available:
fail((
"{} is set, but no usable C++ toolchain can build for {}. " +
"Install one, or unset the flag."
).format(ctx.attr.required_flag.label, ctx.attr.platform.label))
return [config_common.FeatureFlagInfo(value = "yes" if available else "no")]

_cc_toolchain_available = rule(
implementation = _cc_toolchain_available_impl,
attrs = {
"constraint_values": attr.label_list(
providers = [platform_common.ConstraintValueInfo],
),
"platform": attr.label(
mandatory = True,
providers = [platform_common.PlatformInfo],
),
"probe": attr.label(
cfg = _platform_transition,
mandatory = True,
providers = [_ProbeInfo],
),
"required_flag": attr.label(providers = [BuildSettingInfo]),
},
)

def cc_toolchain_available_config_setting(
name,
platform,
constraint_values = None,
required_flag = None,
visibility = None):
"""Matches if a usable C++ toolchain can build for `platform`.

Toolchain resolution for `platform` finds the toolchain, so the result
reflects the registered toolchains and execution platforms. A toolchain
that runs one of rules_cc's error scripts instead of a compiler isn't
usable.

Args:
name: The name of the `config_setting`.
platform: The platform to look for a C++ toolchain for.
constraint_values: Constraint values that the target platform must
also have, as in `config_setting`.
required_flag: The label of a `bool_flag`. When it's true and the
target platform has `constraint_values`, a missing or unusable
toolchain fails the build instead of not matching.
visibility: The visibility of the `config_setting`.
"""
constraint_values = constraint_values or []

_probe(
name = name + "_probe",
tags = ["manual"],
visibility = ["//visibility:private"],
)
_cc_toolchain_available(
name = name + "_flag",
constraint_values = constraint_values,
platform = platform,
probe = ":" + name + "_probe",
required_flag = required_flag,
tags = ["manual"],
visibility = ["//visibility:private"],
)
native.config_setting(
name = name,
flag_values = {":" + name + "_flag": "yes"},
visibility = visibility,
)
Loading
Loading