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

common --lockfile_mode=off

# Skip Bazel's auto-detection of the host C/C++ toolchain. We register the
# hermetic LLVM toolchain explicitly in MODULE.bazel for all platforms and
# don't want rules_cc's auto-detected `local_config_cc` to compete with it.
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 @@ -89,6 +95,9 @@ build:windows --host_per_file_copt=external/protobuf\\+.*@/w
# For build stamping
common --enable_platform_specific_config
common:linux --host_platform=//:local_linux_gnu
# 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_gnullvm

# rules_rs 0.0.90 bundles a newer rules_rust whose cargo build-script runner
Expand Down
96 changes: 89 additions & 7 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,24 @@ 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.3",
)

bazel_dep(name = "rules_android", version = "0.7.2")
bazel_dep(name = "rules_closure", version = "0.16.0")
bazel_dep(name = "rules_dotnet", version = "0.21.5")

Expand All @@ -41,6 +59,16 @@ bazel_dep(name = "rules_proto", version = "7.1.0")
bazel_dep(name = "rules_ruby", version = "0.26.0")
bazel_dep(name = "rules_rs", version = "0.0.90")

# 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")

single_version_override(
module_name = "rules_jvm_external",
patch_strip = 1,
Expand Down Expand Up @@ -389,23 +417,42 @@ 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")

# Register the hermetic LLVM exec toolchain for every platform we build on so
# that the C/C++ toolchain used for exec-config targets (process_wrapper, cargo
# build scripts, etc.) is fully version-pinned and reproducible.
#
# macOS is now viable because the Rust TLS stack uses `ring` (pure Rust + light
# C, no system-framework deps) instead of `aws-lc-rs` / `aws-lc-sys`, which
# previously required CoreServices and compiler-rt from the Xcode sysroot.
#
# Windows uses the gnullvm ABI (PE binary, MSVCRT runtime) rather than MSVC
# because the hermetic LLVM toolchain ships everything needed for gnullvm
# targets without a separately-provisioned Visual Studio installation.
llvm_toolchains.exec(
arch = "x86_64",
os = "windows",
os = "linux",
)
llvm_toolchains.exec(
arch = "aarch64",
os = "windows",
os = "linux",
)
llvm_toolchains.exec(
arch = "x86_64",
os = "macos",
)
llvm_toolchains.exec(
arch = "aarch64",
os = "macos",
)
llvm_toolchains.exec(
arch = "x86_64",
os = "macos",
os = "windows",
)
llvm_toolchains.exec(
arch = "aarch64",
os = "windows",
)
use_repo(llvm_toolchains, "llvm_toolchains")

Expand All @@ -418,25 +465,60 @@ 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 `readme.md` but their source uses `include_str!("../readme.md")`.
# Bazel's Rust sandbox only includes `.rs` source files — not auxiliary data files
# like README — so the include_str! fails at compile time regardless of case. We
# patch out the doc attribute entirely; no documentation needed in a Bazel build.
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"],
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
19 changes: 19 additions & 0 deletions common/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,25 @@ 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"),
("macos", "x86_64"),
("windows", "aarch64"),
("windows", "x86_64"),
]
]

# Are we creating a stamped build?
config_setting(
name = "stamp",
Expand Down
74 changes: 57 additions & 17 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,25 +11,63 @@ 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"),
("macos", "x86_64"),
("windows", "aarch64"),
("windows", "x86_64"),
]
]

# The Rust selenium-manager cannot be built from source on Windows (pending the
# @llvm toolchain migration)
alias(
name = "selenium-manager-windows",
actual = "@download_sm_windows//file",
filegroup(
name = "selenium-manager-files",
srcs = [
":selenium-manager-linux-aarch64",
":selenium-manager-linux-x86_64",
":selenium-manager-macos-aarch64",
":selenium-manager-macos-x86_64",
":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 @@ -77,14 +77,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
Loading