diff --git a/.bazelrc b/.bazelrc index 9f038f213..2a4340b37 100644 --- a/.bazelrc +++ b/.bazelrc @@ -10,6 +10,12 @@ common --define=SOME_VAR=SOME_VALUE common --@pypi//venv=aspect_rules_py common --incompatible_enable_cc_toolchain_resolution +# Strip target-scoped Starlark flags from exec config so they don't affect +# CC toolchain selection for exec tools (e.g. prevents experimental_stub_libgcc_s +# from causing the LLVM CC toolchain to select Linux x86-64 on a macOS exec host). +# Flags that must propagate to exec config use scope = "universal" (e.g. @pypi//venv). +# This flag is the default in Bazel 10 (incompatible_exclude_starlark_flags_from_exec_config). +common --incompatible_exclude_starlark_flags_from_exec_config common --@toolchains_llvm_bootstrapped//config:experimental_stub_libgcc_s common --@rules_cc//cc/toolchains/args/archiver_flags:use_libtool_on_macos=false diff --git a/.bazelversion b/.bazelversion index 6adf95a25..456c34730 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1,4 +1,4 @@ -8.5.1 +9.0.1 # The first line of this file is used by Bazelisk and Bazel to be sure # the right version of Bazel is used to build and test this repo. # This also defines which version is used on CI. diff --git a/MODULE.bazel b/MODULE.bazel index e7a09ab1c..93de4a479 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -8,15 +8,15 @@ module( # NOTE: when publishing to BCR, we patch this to True, as we publish pre-built binaries along with our releases. IS_RELEASE = False -bazel_dep(name = "bazel_features", version = "1.38.0") +bazel_dep(name = "bazel_features", version = "1.42.1") bazel_dep(name = "bazel_lib", version = "3.0.0") -bazel_dep(name = "bazel_skylib", version = "1.4.2") +bazel_dep(name = "bazel_skylib", version = "1.8.2") bazel_dep(name = "platforms", version = "1.0.0") -bazel_dep(name = "rules_cc", version = "0.2.16") +bazel_dep(name = "rules_cc", version = "0.2.17") bazel_dep(name = "rules_pkg", version = "1.1.0") bazel_dep(name = "rules_python", version = "1.9.0") bazel_dep(name = "rules_shell", version = "0.6.1") -bazel_dep(name = "tar.bzl", version = "0.5.5") +bazel_dep(name = "tar.bzl", version = "0.6.0") bazel_dep(name = "with_cfg.bzl", version = "0.14.1") bazel_lib_toolchains = use_extension("@tar.bzl//tar:extensions.bzl", "toolchains") diff --git a/e2e/.bazelrc b/e2e/.bazelrc index 9759bc6ce..670304266 100644 --- a/e2e/.bazelrc +++ b/e2e/.bazelrc @@ -1,11 +1,3 @@ -common --incompatible_enable_cc_toolchain_resolution -common --@toolchains_llvm_bootstrapped//config:experimental_stub_libgcc_s -common --@rules_cc//cc/toolchains/args/archiver_flags:use_libtool_on_macos=false - -# Don't try and auto detect the cc toolchain, as we use our own llvm toolchains. -common --repo_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 -common --repo_env=BAZEL_NO_APPLE_CPP_TOOLCHAIN=1 - # Configure a default venv # common --@pypi//venv=say @@ -13,3 +5,14 @@ common --repo_env=BAZEL_NO_APPLE_CPP_TOOLCHAIN=1 # supports-path-mapping. Actions that declare the execution requirement get # configuration-stripped cache keys; those that don't still work normally. build --experimental_output_paths=strip + +# LLVM toolchain configuration (used for OCI crossbuild tests). +# Applied unconditionally so the toolchain is properly configured on both +# macOS and Linux exec platforms. +common --repo_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1 +common --repo_env=BAZEL_NO_APPLE_CPP_TOOLCHAIN=1 +common --incompatible_enable_cc_toolchain_resolution +common --@llvm//config:experimental_stub_libgcc_s +common --@rules_cc//cc/toolchains/args/archiver_flags:use_libtool_on_macos=false +common --enable_platform_specific_config +common:linux --host_platform=//:local_gnu_platform diff --git a/e2e/BUILD.bazel b/e2e/BUILD.bazel new file mode 100644 index 000000000..d99290381 --- /dev/null +++ b/e2e/BUILD.bazel @@ -0,0 +1,7 @@ +platform( + name = "local_gnu_platform", + constraint_values = [ + "@llvm//constraints/libc:gnu.2.28", + ], + parents = ["@platforms//host"], +) diff --git a/e2e/MODULE.bazel b/e2e/MODULE.bazel index f974ca391..02b62f982 100644 --- a/e2e/MODULE.bazel +++ b/e2e/MODULE.bazel @@ -2,13 +2,13 @@ bazel_dep(name = "aspect_rules_py") bazel_dep(name = "bazel_features", version = "1.38.0") -bazel_dep(name = "bazel_skylib", version = "1.4.2") +bazel_dep(name = "bazel_skylib", version = "1.8.2") bazel_dep(name = "bazel_lib", version = "3.0.0") bazel_dep(name = "rules_cc", version = "0.2.16") bazel_dep(name = "tar.bzl", version = "0.5.5") bazel_dep(name = "rules_python", version = "1.9.0") bazel_dep(name = "platforms", version = "1.0.0") -bazel_dep(name = "toolchains_llvm_bootstrapped", version = "0.3.1") +bazel_dep(name = "llvm", version = "0.7.0") bazel_dep(name = "rules_oci", version = "2.2.7") bazel_dep(name = "rules_rust", version = "0.68.1") bazel_dep(name = "rules_shell", version = "0.4.1") @@ -47,6 +47,11 @@ use_repo(interpreters, "python_interpreters") register_toolchains("@python_interpreters//:all") +register_toolchains( + "@llvm//toolchain:all", + dev_dependency = True, +) + # For the OCI tests # {{{ oci = use_extension("@rules_oci//oci:extensions.bzl", "oci") diff --git a/py/private/toolchain/tools.bzl b/py/private/toolchain/tools.bzl index 7a3cb4ca2..b7288a98c 100644 --- a/py/private/toolchain/tools.bzl +++ b/py/private/toolchain/tools.bzl @@ -105,17 +105,40 @@ py_tool_toolchain = rule( }, ) -def source_toolchain(name, toolchain_type, bin): +# Variant for exec-side tools (e.g. unpack): forces bin into exec config so +# the binary is compiled for the build host, not the target/test-trimmed config. +# Without cfg="exec", Bazel analyzes toolchain targets in the same configuration +# as the requesting rule, which on macOS with experimental_stub_libgcc_s set +# produces an ELF binary instead of Mach-O. +exec_py_tool_toolchain = rule( + implementation = _toolchain_impl, + attrs = { + "bin": attr.label( + mandatory = True, + allow_single_file = True, + cfg = "exec", + ), + "template_var": attr.string( + mandatory = True, + ), + }, +) + +def source_toolchain(name, toolchain_type, bin, exec_tool = False): """Makes vtool toolchain and repositories Args: name: Override the prefix for the generated toolchain repositories. toolchain_type: Toolchain type reference. bin: the rust_binary target + exec_tool: if True, use exec_py_tool_toolchain so the binary is built + in exec config (required for tools that run during the build, such + as unpack). Target-side tools (venv, shim) should leave this False. """ toolchain_rule = "{}_toolchain_source".format(name) - py_tool_toolchain( + tool_rule = exec_py_tool_toolchain if exec_tool else py_tool_toolchain + tool_rule( name = toolchain_rule, bin = bin, template_var = "{}_BIN".format(name.upper()), diff --git a/py/private/toolchain/unpack/BUILD.bazel b/py/private/toolchain/unpack/BUILD.bazel index d7ad9ec27..b8a400cfd 100644 --- a/py/private/toolchain/unpack/BUILD.bazel +++ b/py/private/toolchain/unpack/BUILD.bazel @@ -3,5 +3,6 @@ load("//py/private/toolchain:tools.bzl", "source_toolchain") source_toolchain( name = "unpack", bin = "//py/tools/unpack_bin", + exec_tool = True, toolchain_type = "//py/private/toolchain:unpack_toolchain_type", ) diff --git a/py/tools/py/src/venv.rs b/py/tools/py/src/venv.rs index c2ee70472..012862d3e 100644 --- a/py/tools/py/src/venv.rs +++ b/py/tools/py/src/venv.rs @@ -831,15 +831,6 @@ fn has_internal_symlinks(dir: &Path) -> bool { .any(|e| e.file_type().is_symlink()) } -fn would_create_symlink_cycle(src: &Path, dest: &Path) -> bool { - let src_has_links = has_internal_symlinks(src); - let dest_parent_has_links = dest.parent() - .map(|p| has_internal_symlinks(p)) - .unwrap_or(false); - - src_has_links && dest_parent_has_links -} - /// Post-processing pass that replaces groups of file-level `Symlink` commands /// with a single `SymlinkDir` when all files in a top-level package directory /// come from the same source root and contain no native extensions. diff --git a/py/tools/unpack_bin/BUILD.bazel b/py/tools/unpack_bin/BUILD.bazel index d180e722f..2fcc77e68 100644 --- a/py/tools/unpack_bin/BUILD.bazel +++ b/py/tools/unpack_bin/BUILD.bazel @@ -1,12 +1,28 @@ +load("@rules_rust//rust:defs.bzl", "rust_binary") load("//bazel/release:release.bzl", "release") -load("//bazel/rust:defs.bzl", "rust_binary") +load("//bazel/rust:defs.bzl", "rust_opt_binary") load("//bazel/rust:multi_platform_rust_binaries.bzl", "multi_platform_rust_binaries") +# Plain rust_binary for the source toolchain: fast dev builds. +# exec_py_tool_toolchain (py/private/toolchain/tools.bzl) applies cfg="exec" +# to build this binary in exec config for the build host. rust_binary( name = "unpack", - srcs = [ - "src/main.rs", + srcs = ["src/main.rs"], + crate_features = ["bazel"], + deps = [ + "//py/tools/py", + "@aspect_rules_py__crates//:clap", + "@aspect_rules_py__crates//:miette", ], +) + +# Optimized variant for release artifacts — applies symbol stripping and LTO. +# Used only by multi_platform_rust_binaries (release builds), never as an exec tool. +rust_opt_binary( + name = "unpack_opt", + srcs = ["src/main.rs"], + crate_features = ["bazel"], deps = [ "//py/tools/py", "@aspect_rules_py__crates//:clap", @@ -16,7 +32,7 @@ rust_binary( multi_platform_rust_binaries( name = "bins", - target = ":unpack", + target = ":unpack_opt", ) alias( diff --git a/py/tools/venv_bin/BUILD.bazel b/py/tools/venv_bin/BUILD.bazel index 8b1353346..de581ff9a 100644 --- a/py/tools/venv_bin/BUILD.bazel +++ b/py/tools/venv_bin/BUILD.bazel @@ -1,12 +1,24 @@ +load("@rules_rust//rust:defs.bzl", "rust_binary") load("//bazel/release:release.bzl", "release") -load("//bazel/rust:defs.bzl", "rust_binary") +load("//bazel/rust:defs.bzl", "rust_opt_binary") load("//bazel/rust:multi_platform_rust_binaries.bzl", "multi_platform_rust_binaries") +# Plain rust_binary for the source toolchain: fast dev builds. rust_binary( name = "venv", - srcs = [ - "src/main.rs", + srcs = ["src/main.rs"], + crate_features = ["bazel"], + deps = [ + "//py/tools/py", + "@aspect_rules_py__crates//:clap", + "@aspect_rules_py__crates//:miette", ], +) + +rust_opt_binary( + name = "venv_opt", + srcs = ["src/main.rs"], + crate_features = ["bazel"], deps = [ "//py/tools/py", "@aspect_rules_py__crates//:clap", @@ -16,7 +28,7 @@ rust_binary( multi_platform_rust_binaries( name = "bins", - target = ":venv", + target = ":venv_opt", ) alias( diff --git a/py/tools/venv_shim/BUILD.bazel b/py/tools/venv_shim/BUILD.bazel index a9ba4c2a0..684a4e7ad 100644 --- a/py/tools/venv_shim/BUILD.bazel +++ b/py/tools/venv_shim/BUILD.bazel @@ -1,12 +1,24 @@ +load("@rules_rust//rust:defs.bzl", "rust_binary") load("//bazel/release:release.bzl", "release") -load("//bazel/rust:defs.bzl", "rust_binary") +load("//bazel/rust:defs.bzl", "rust_opt_binary") load("//bazel/rust:multi_platform_rust_binaries.bzl", "multi_platform_rust_binaries") +# Plain rust_binary for the source toolchain: fast dev builds. rust_binary( name = "shim", - srcs = [ - "src/main.rs", + srcs = ["src/main.rs"], + crate_features = ["bazel"], + deps = [ + "//py/tools/runfiles", + "@aspect_rules_py__crates//:miette", + "@aspect_rules_py__crates//:which", ], +) + +rust_opt_binary( + name = "shim_opt", + srcs = ["src/main.rs"], + crate_features = ["bazel"], deps = [ "//py/tools/runfiles", "@aspect_rules_py__crates//:miette", @@ -16,7 +28,7 @@ rust_binary( multi_platform_rust_binaries( name = "bins", - target = ":shim", + target = ":shim_opt", ) alias( diff --git a/uv/private/constraints/venv/BUILD.bazel b/uv/private/constraints/venv/BUILD.bazel index df9a33ee4..bcb5975a3 100644 --- a/uv/private/constraints/venv/BUILD.bazel +++ b/uv/private/constraints/venv/BUILD.bazel @@ -3,5 +3,11 @@ load("@bazel_skylib//rules:common_settings.bzl", "string_flag") string_flag( name = "venv", build_setting_default = "", + # "universal" causes this flag to propagate through exec transitions so + # that exec-configured tools (e.g. Gazelle) that depend on a Python venv + # see the same venv selection as the target configuration. + # Required when --incompatible_exclude_starlark_flags_from_exec_config is + # active (default in Bazel 10; bazelbuild/bazel#26909). + scope = "universal", visibility = ["//visibility:public"], )