Skip to content
Draft
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
12 changes: 11 additions & 1 deletion .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ try-import %workspace%/.bazelrc.windows.local

common --lockfile_mode=off

# Skip Bazel's auto-detection of the host C/C++ toolchain. We register the
# LLVM hermetic toolchain explicitly in MODULE.bazel and don't want
# rules_cc's auto-detected `local_config_cc` to influence toolchain
# resolution on developer hosts or CI runners.
common --repo_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1
common --repo_env=BAZEL_NO_APPLE_CPP_TOOLCHAIN=1

# Bazel 8 compatibility flags. We should find ways to avoid needing these
common --legacy_external_runfiles

Expand Down Expand Up @@ -78,7 +85,10 @@ build:windows --host_per_file_copt=external/protobuf\\+.*@/w
# For build stamping
common --enable_platform_specific_config
common:linux --host_platform=//:local_linux_gnu
common:windows --host_platform=//:local_windows_gnullvm
# The LLVM toolchain doesn't ship libgcc_s; this stub satisfies Rust's
# glibc stdlib link dependency when LLVM is the host C++ toolchain.
common:linux --@llvm//config:experimental_stub_libgcc_s=True
common:windows --host_platform=//:local_windows_msvc
build:linux --workspace_status_command=scripts/build-info.sh
build:macos --workspace_status_command=scripts/build-info.sh
build:windows --workspace_status_command="powershell.exe scripts/build-info.ps1"
Expand Down
28 changes: 27 additions & 1 deletion BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,33 @@ platform(
platform(
name = "local_windows_gnullvm",
constraint_values = [
"@rules_rs//rs/platforms/constraints:windows_gnullvm",
"@llvm//constraints/windows/abi:gnullvm",
# Rust's `x86_64-pc-windows-gnullvm` and `aarch64-pc-windows-gnullvm`
# toolchains both link against MSVCRT (see rustc's `windows_gnullvm`
# spec), and rules_rs encodes that as a `windows/crt:msvcrt`
# constraint on the toolchain. Without it here, no rust toolchain
# matches the host platform on Windows and `bazel test //rust/...`
# fails with "No matching toolchains found".
"@llvm//constraints/windows/crt:msvcrt",
],
parents = ["@platforms//host"],
)

# Native Windows host platform. Used as `--host_platform` on Windows
# runners so native rust builds go through `x86_64-pc-windows-msvc` (which
# the Windows runners have installed as part of Visual Studio) rather
# than `x86_64-pc-windows-gnullvm`. The gnullvm path drags in LLVM's
# bootstrap-process-wrapper Starlark transition, which puts
# `process_wrapper` in a different exec config than proc-macro deps and
# trips rustc with `can't find crate for time_macros / scroll_derive`
# style errors. Cross-compile targets in //rust still transition to the
# gnullvm rules_rs platforms so non-Windows hosts can produce PE binaries
# without a Windows SDK.
platform(
name = "local_windows_msvc",
constraint_values = [
"@llvm//constraints/windows/abi:msvc",
"@llvm//constraints/windows/crt:msvcrt",
],
parents = ["@platforms//host"],
)
Expand Down
88 changes: 82 additions & 6 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ bazel_dep(name = "bazel_features", version = "1.45.0")
bazel_dep(name = "bazel_skylib", version = "1.9.0")
bazel_dep(name = "buildifier_prebuilt", version = "8.5.1")
bazel_dep(name = "contrib_rules_jvm", version = "0.32.0")
bazel_dep(name = "llvm", version = "0.7.9")
bazel_dep(name = "llvm", version = "0.8.0")
bazel_dep(name = "package_metadata", version = "0.0.7")
bazel_dep(name = "platforms", version = "1.0.0")

Expand All @@ -26,6 +26,23 @@ single_version_override(
version = "33.5",
)

# We set `--@llvm//config:experimental_stub_libgcc_s=True` in .bazelrc so the
# LLVM cc toolchain doesn't try to resolve a `-lgcc_s` it doesn't ship. In
# v0.8.0 the `experimental_stub_libgcc_s` bool_flag isn't marked
# `scope = "universal"`, so the flag value on the target config doesn't
# propagate to exec config and tool builds (process_wrapper,
# //rust:_selenium-manager-bin) still fail to link. The patch adds
# `scope = "universal"` so the flag does propagate; can be dropped once
# hermeticbuild/hermetic-llvm#544 lands.
single_version_override(
module_name = "llvm",
patch_strip = 1,
patches = [
"//third_party/bazel:llvm_libgcc_s_universal_scope.patch",
],
version = "0.8.0",
)

bazel_dep(name = "rules_android", version = "0.7.1")
bazel_dep(name = "rules_closure", version = "0.15.0")
bazel_dep(name = "rules_dotnet", version = "0.21.5")
Expand All @@ -40,7 +57,17 @@ bazel_dep(name = "rules_pkg", version = "1.2.0")
bazel_dep(name = "rules_python", version = "1.9.0")
bazel_dep(name = "rules_proto", version = "7.1.0")
bazel_dep(name = "rules_ruby", version = "0.25.0")
bazel_dep(name = "rules_rs", version = "0.0.61")
bazel_dep(name = "rules_rs", version = "0.0.76")

# Native C libraries pulled in by the `*-sys` crates that the Selenium
# Manager Rust binary depends on. Pointing each `*-sys` crate at its
# BCR-hosted cc_library (per rules_rs's `bazel mod tidy` suggestion) lets
# the C source build with the LLVM cc toolchain — which is target-libc
# aware, so the same crate compiles correctly for both the host and the
# musl cross-compile targets.
bazel_dep(name = "bzip2", version = "1.0.8.bcr.3")
bazel_dep(name = "xz", version = "5.4.5.bcr.8")
bazel_dep(name = "zstd", version = "1.5.7.bcr.1")

# Use latest rules_jvm_external for Bazel 9 compatibility
single_version_override(
Expand Down Expand Up @@ -405,7 +432,6 @@ use_repo(rust_toolchains, "default_rust_toolchains")

register_toolchains("@default_rust_toolchains//:all")

# TODO: Register only Windows exec for now, full @llvm migration can be done as followup.
llvm_toolchains = use_extension("@llvm//extensions:toolchain.bzl", "toolchain")
llvm_toolchains.exec(
arch = "x86_64",
Expand All @@ -415,6 +441,18 @@ llvm_toolchains.exec(
arch = "aarch64",
os = "windows",
)
llvm_toolchains.exec(
arch = "aarch64",
os = "macos",
)
llvm_toolchains.exec(
arch = "x86_64",
os = "linux",
)
llvm_toolchains.exec(
arch = "aarch64",
os = "linux",
)
use_repo(llvm_toolchains, "llvm_toolchains")

register_toolchains("@llvm_toolchains//:all")
Expand All @@ -426,25 +464,63 @@ crate.from_cargo(
cargo_toml = "//rust:Cargo.toml",
platform_triples = [
"aarch64-apple-darwin",
"aarch64-pc-windows-gnullvm",
"aarch64-pc-windows-msvc",
"aarch64-unknown-linux-gnu",
"aarch64-unknown-linux-musl",
"x86_64-apple-darwin",
"x86_64-pc-windows-gnullvm",
"x86_64-pc-windows-msvc",
"x86_64-unknown-linux-gnu",
"x86_64-unknown-linux-musl",
],
)

# Both crates ship a `README.md` (uppercase) but their source code uses
# `include_str!("../readme.md")`. The mismatch is invisible on macOS's
# case-insensitive default filesystem but breaks any case-sensitive host
# (Linux, RBE). Patch the source so the case matches what the archive
# actually contains.
crate.annotation(
crate = "windows-link",
patch_args = ["-p1"],
patches = ["//third_party/bazel:windows_link_readme_case.patch"],
)
crate.annotation(
crate = "windows-targets",
patch_args = ["-p1"],
patches = ["//third_party/bazel:windows_targets_readme_case.patch"],
# Only the 0.53 line has this case mismatch; 0.52.x ships a lowercase
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, they regressed it? wild

# readme.md that matches the include_str! call.
version = "0.53.4",
)

# Point the `*-sys` crates at the BCR cc_library packages so their cargo
# build scripts don't run. The `inject_repo` calls below make the
# corresponding repos visible to the crate extension. (Auto-suggested by
# `bazel mod tidy` against rules_rs's well-known annotations.)
crate.annotation(
crate = "bzip2-sys",
gen_build_script = "on",
gen_build_script = "off",
deps = ["@bzip2//:bz2"],
)
crate.annotation(
crate = "lzma-sys",
gen_build_script = "on",
gen_build_script = "off",
deps = ["@xz//:lzma"],
)
crate.annotation(
crate = "zstd-sys",
gen_build_script = "on",
gen_build_script = "off",
deps = ["@zstd"],
)

inject_repo(crate, "bzip2")

inject_repo(crate, "xz")

inject_repo(crate, "zstd")

use_repo(crate, "crates")

selenium_manager_artifacts = use_extension("//common:selenium_manager.bzl", "selenium_manager_artifacts")
Expand Down
18 changes: 18 additions & 0 deletions common/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@ config_setting(
constraint_values = ["@platforms//os:windows"],
)

# Per-(OS, arch) host config_settings.
[
config_setting(
name = "{}_{}".format(os, arch),
constraint_values = [
"@platforms//os:{}".format(os),
"@platforms//cpu:{}".format(arch),
],
)
for (os, arch) in [
("linux", "aarch64"),
("linux", "x86_64"),
("macos", "aarch64"),
("windows", "aarch64"),
("windows", "x86_64"),
]
]

# Are we creating a stamped build?
config_setting(
name = "stamp",
Expand Down
73 changes: 55 additions & 18 deletions common/manager/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
load("//common:defs.bzl", "copy_file")

package(
default_visibility = [
"//dotnet/src/webdriver:__pkg__",
Expand All @@ -9,26 +11,61 @@ package(
],
)

# Tree of every cross-built Selenium Manager binary, laid out as
# `<os>-<arch>/selenium-manager[.exe]`. Language packagers that can ship
# directories (Ruby gem data, npm package files, Python wheel data) take
# this directly; tools that only handle individual files (Java resources,
# nuget pack) consume the per-arch single-file targets below.
alias(
name = "selenium-manager-linux",
actual = select({
"//common:use_pinned_browser": "@download_sm_linux//file",
"//conditions:default": "//rust:selenium-manager-linux",
}),
name = "selenium-manager-bundle",
actual = "//rust:selenium-manager-bundle",
)

alias(
name = "selenium-manager-macos",
actual = select({
"//common:use_pinned_browser": "@download_sm_macos//file",
"//conditions:default": "//rust:selenium-manager-macos",
}),
)
# Single-file targets per (os, arch) — same binaries the bundle contains,
# but as individual files (each output at `<os>-<arch>/selenium-manager[.exe]`)
# for tools whose resource attrs don't expand tree artifacts (Java
# `resources`, nuget_pack `files`).
#
# On Windows hosts the cross-compile chain through rules_rs's LLVM
# toolchain currently fails for proc-macro deps, so we fall back to the
# native rust_binary for the host's architecture (via `//rust:_selenium-manager-bin`)
# and stub the rest. Release jars/nupkgs are built on Linux, where every
# entry is real.
[
copy_file(
name = "selenium-manager-{}-{}".format(os, arch),
src = select({
"//common:windows_aarch64": (
"//rust:_selenium-manager-bin" if (os, arch) == ("windows", "aarch64") else "//rust:_selenium-manager-stub"
),
"//common:windows_x86_64": (
"//rust:_selenium-manager-bin" if (os, arch) == ("windows", "x86_64") else "//rust:_selenium-manager-stub"
),
"//conditions:default": "//rust:_bundle_member_{}_{}".format(os, arch),
}),
out = "{}-{}/selenium-manager{}".format(
os,
arch,
".exe" if os == "windows" else "",
),
is_executable = True,
)
for (os, arch) in [
("linux", "aarch64"),
("linux", "x86_64"),
("macos", "aarch64"),
("windows", "aarch64"),
("windows", "x86_64"),
]
]

alias(
name = "selenium-manager-windows",
actual = select({
"//common:use_pinned_browser": "@download_sm_windows//file",
"//conditions:default": "//rust:selenium-manager-windows",
}),
filegroup(
name = "selenium-manager-files",
srcs = [
":selenium-manager-linux-aarch64",
":selenium-manager-linux-x86_64",
":selenium-manager-macos-aarch64",
":selenium-manager-windows-aarch64",
":selenium-manager-windows-x86_64",
],
)
16 changes: 16 additions & 0 deletions common/manager/defs.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
load("@aspect_bazel_lib//lib:copy_directory.bzl", "copy_directory")

def selenium_manager_bundle(name, out, **kwargs):
"""Copies the cross-compiled Selenium Manager bundle tree into this package.

Args:
name: rule name
out: destination path within the package's output tree
**kwargs: forwarded to copy_directory (e.g. visibility)
"""
copy_directory(
name = name,
src = "//common/manager:selenium-manager-bundle",
out = out,
**kwargs
)
18 changes: 13 additions & 5 deletions dotnet/private/nuget_pack.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,22 @@ def nuget_pack_impl(ctx):

working_dir = ctx.label.name + "-working-dir"

# Copy files directly into the working directory layout (no intermediate zip)
# Copy files directly into the working directory layout (no intermediate zip).
# Tree artifacts (directories produced e.g. by copy_to_directory) are copied
# recursively into the destination directory.
copy_cmds = []
for (file, rel_path) in layout.items():
dest = working_dir + "/" + rel_path
copy_cmds.append("mkdir -p \"$(dirname '{dest}')\" && cp '{src}' '{dest}'".format(
dest = dest,
src = file.path,
))
if file.is_directory:
copy_cmds.append("mkdir -p '{dest}' && cp -R '{src}'/. '{dest}'".format(
dest = dest,
src = file.path,
))
else:
copy_cmds.append("mkdir -p \"$(dirname '{dest}')\" && cp '{src}' '{dest}'".format(
dest = dest,
src = file.path,
))

cmd_parts = [
"rm -rf '%s'" % working_dir,
Expand Down
Loading