Bazel 在 Windows 上的使用指南:最佳实践与 C++/Java/Python 工具链配置
2026/9/17 6:33:54 网站建设 项目流程

Bazel 在 Windows 上的使用指南:最佳实践与 C++/Java/Python 工具链配置

【免费下载链接】bazela fast, scalable, multi-language and extensible build system项目地址: https://gitcode.com/GitHub_Trending/ba/bazel

本文是 Bazel 在 Windows 平台上的实战配置指南,系统覆盖路径长度规避、符号链接启用、Shell 环境选择、无 Bash(MSYS2)构建约束,以及基于 MSVC / Clang-cl 的 C++ 工具链、Java 与 Python 构建的完整配置方法。读完本文,你将能在 Windows 上稳定运行 Bazel,并针对 C++(含 DLL 与 ARM64)、Java、Python 目标正确配置工具链与构建参数。

本文对应仓库中的当前版本文档为 docs/configure/windows.mdx,安装步骤请参见 docs/install/windows.mdx。

已知问题追踪

Windows 相关的 Bazel 问题在 GitHub 上以area-Windows标签标记。如果你在 Windows 上遇到构建异常,建议先检索该标签下的 open issue,很可能已经有人遇到并提交了相同的问题;也可以在提交新 issue 时使用该标签以帮助维护者快速分类。

最佳实践

规避长路径限制

Windows 上部分工具(包括 MSVC 编译器)存在最大路径长度限制(传统上为 260 个字符)。当output_user_root位于深层目录时,构建产物路径很容易触顶该限制导致编译失败。

规避方法是为 Bazel 指定一个短小的输出目录。在bazelrc中通过startup级的--output_user_root标志设置:

startup --output_user_root=C:/tmp

--output_user_root属于启动选项(startup option),它决定 Bazel 服务端输出根目录的位置(output_user_root之下再按output_base组织具体工作区输出)。从 src/main/cpp/startup_options.cc 的启动选项解析逻辑可以看出,这类 startup 标志必须在服务端启动前生效,因此必须写在bazelrcstartup段,而不能放在build段。将输出根放到盘符根目录(如C:/tmp)可显著缩短绝对路径长度。

启用符号链接支持

部分 Bazel 功能要求在 Windows 上能够创建文件符号链接(file symlink),有两种途径获得该能力:

  • 开启 Windows开发者模式(Developer Mode):适用于 Windows 10 版本 1703 及更新版本;
  • 或以管理员身份运行 Bazel。

获得符号链接创建能力后,可以启用以下功能:

  • --windows_enable_symlinks(startup 选项,见 src/main/cpp/startup_options.h 中windows_enable_symlinks字段的注释:"Whether to create symbolic links on Windows for files. Requires developer mode to be enabled.",即“是否在 Windows 上为文件创建符号链接,需要开启开发者模式”);
  • --enable_runfiles(build 选项)。

方便起见,可在bazelrc中加入以下两行:

startup --windows_enable_symlinks build --enable_runfiles

注意:在 Windows 上创建符号链接是开销较大的操作。--enable_runfiles可能创建大量文件符号链接(runfiles 树),因此仅在确实需要时才启用该功能。从 BazelRuleClassProvider.java 的源码可以看到,当 runfiles 未启用时,Bazel 会为所有 action 设置RUNFILES_MANIFEST_ONLY=1环境变量,告诉运行中的二进制文件改用 manifest 文件而非 runfiles 树来定位数据依赖;一旦启用--enable_runfiles,该变量消失,二进制文件行为随之改变,这也是它会影响 action 缓存的原因。

在哪种 Shell 中运行 Bazel

建议:从命令提示符(cmd.exe)或 PowerShell 运行 Bazel。

不要bash运行 Bazel——无论是 MSYS2 shell、Git Bash、Cygwin 还是其他 Bash 变体。虽然大多数场景下 Bazel 可以工作,但部分功能存在缺陷,例如从 MSYS2 中用 Ctrl+C 中断构建不可靠。

此外,如果在 MSYS2 下运行,需要禁用 MSYS2 的自动路径转换(MSYS2 argument conversion),否则 MSYS 会把形如//foo:bar这样“看起来像 Unix 路径”的命令行参数自动转换为 Windows 路径,破坏 Bazel 的标签解析。

不带 Bash(MSYS2)使用 Bazel

不带 Bash 执行 bazel build

Bazel 1.0 之前的版本构建部分规则强制要求 Bash。从 Bazel 1.0 开始,除非目标属于以下情形,否则任何规则都可以在没有 Bash 的情况下构建

  • genrule:因为 genrule 会执行 Bash 命令;
  • sh_binarysh_test规则:这些规则本质上需要 Bash;
  • 使用ctx.actions.run_shell()ctx.resolve_command()的 Starlark 规则。

不过,genrule常被用于简单的复制文件、写文本文件等任务。与其使用genrule(从而引入对 Bash 的依赖),不如在 bazel-skylib 仓库中寻找更合适的规则(例如copy_filewrite_file)。这些规则在 Windows 上构建时不依赖 Bash

不带 Bash 执行 bazel test

Bazel 1.0 之前,任何bazel test都需要 Bash。从 Bazel 1.0 开始,除以下情况外,任何规则都可以无 Bash 测试:

  • 使用了--run_under
  • 测试规则本身需要 Bash(因为其可执行文件是 shell 脚本)。
不带 Bash 执行 bazel run

同样,从 Bazel 1.0 开始,除以下情况外,任何规则都可以无 Bash 运行:

  • 使用了--run_under--script_path
  • 测试规则本身需要 Bash(因为其可执行文件是 shell 脚本)。
sh_binary、sh_* 规则与 ctx.actions.run_shell() 的 Bash 依赖

构建和测试sh_*规则,以及构建和测试使用ctx.actions.run_shell()ctx.resolve_command()的 Starlark 规则时,仍然需要 Bash。这一限制不仅适用于你项目中的规则,也适用于项目所依赖的外部仓库(即使是传递依赖)中的规则。

未来的版本可能会提供使用 Windows Subsystem for Linux(WSL)构建这些规则的选项,但当前 Bazel-on-Windows 子团队并未将其列为优先事项。

设置环境变量

在 Windows 命令提示符(cmd.exe)中设置的环境变量仅在该命令提示符会话中生效。启动新的cmd.exe后需要重新设置。若希望每次启动cmd.exe都自动生效,可在“控制面板 > 系统属性 > 高级 > 环境变量...”对话框中将其加入用户变量系统变量

在 Windows 上构建

用 MSVC 构建 C++

用 MSVC 构建 C++ 目标,需要准备:

  • Visual C++ 编译器(安装指引见 docs/install/windows.mdx 的“Installing compilers and language runtimes”小节:推荐 Build Tools for Visual Studio 2019,同时支持 Visual C++ Build Tools 2017 及更新版本加 Windows 10 SDK);
  • (可选)BAZEL_VCBAZEL_VC_FULL_VERSION环境变量。

Bazel 会自动检测系统中的 Visual C++ 编译器。若需要指定某个特定的 VC 安装,可设置以下环境变量:

Visual Studio 2017 与 2019:设置BAZEL_VC,可选地再设置BAZEL_VC_FULL_VERSION

  • BAZEL_VC:Visual C++ Build Tools 的安装目录

    set BAZEL_VC=C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC
  • BAZEL_VC_FULL_VERSION(可选,仅 Visual Studio 2017 和 2019):Visual C++ Build Tools 的完整版本号。若安装了多个版本的 Build Tools,可通过它选择精确版本,否则 Bazel 默认选择最新版本。

    set BAZEL_VC_FULL_VERSION=14.16.27023

Visual Studio 2015 或更早版本:仅设置BAZEL_VC(不支持BAZEL_VC_FULL_VERSION)。

  • BAZEL_VC:Visual C++ Build Tools 的安装目录

    set BAZEL_VC=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC

还需要Windows SDK。Windows SDK 提供构建 Windows 应用程序(包括 Bazel 自身)所需的头文件与库文件。默认使用系统安装的最新版 Windows SDK,也可以通过BAZEL_WINSDK_FULL_VERSION指定版本:

  • 可使用完整的 Windows 10 SDK 版本号,例如10.0.10240.0
  • 或指定8.1使用 Windows 8.1 SDK(Windows 8.1 SDK 只有一个版本);
  • 请确保指定的 Windows SDK 确实已安装。

要求BAZEL_WINSDK_FULL_VERSION仅受 VC 2017 和 2019 支持。独立的 VC 2015 Build Tools 不支持选择 Windows SDK,需要完整的 Visual Studio 2015 安装,否则BAZEL_WINSDK_FULL_VERSION会被忽略。

set BAZEL_WINSDK_FULL_VERSION=10.0.10240.0

环境就绪后,即可构建 C++ 目标。用仓库中的示例项目试构建:

C:\projects\bazel> bazel build //examples/cpp:hello-world C:\projects\bazel> bazel-bin\examples\cpp\hello-world.exe

示例目标定义在 examples/cpp/BUILD:cc_library(name = "hello-lib")编译 hello-lib.cc,cc_binary(name = "hello-world")依赖它并输出可执行文件。Windows 上构建产物即为bazel-bin\examples\cpp\hello-world.exe

默认构建产物面向x64架构。如需构建ARM64架构,使用:

--platforms=//:windows_arm64 --extra_toolchains=@local_config_cc//:cc-toolchain-arm64_windows

可在MODULE.bazel中引入@local_config_cc

bazel_dep(name = "rules_cc", version = "0.1.1") cc_configure = use_extension("@rules_cc//cc:extensions.bzl", "cc_configure_extension") use_repo(cc_configure, "local_config_cc")

构建与使用动态链接库(DLL)可参考仓库示例 examples/windows/dll:其 windows_dll_library.bzl 定义了一个宏,内部通过cc_binary(linkshared = 1)产出.dll,再借助cc_import桥接出可供其他cc_*规则deps引用的导入库目标;examples/windows/dll/BUILD 同时演示了两种使用方式——运行时显式加载hellolib.dll(通过data依赖)与通过导入库隐式链接(deps = [":hellolib"])。

命令行长度限制:为避免 Windows 命令行长度限制问题,可通过--features=compiler_param_file启用编译器参数文件(response/param file)特性,将过长参数写入文件而非命令行。

用 Clang 构建 C++

从 Bazel 0.29.0 开始支持使用 LLVM 的 MSVC 兼容编译器驱动clang-cl.exe构建。

要求:使用 Clang 构建时,必须同时安装 LLVM 和 Visual C++ Build Tools——虽然编译器是clang-cl.exe,但链接仍需使用 Visual C++ 的库。

Bazel 可以自动检测系统中的 LLVM 安装,也可以通过BAZEL_LLVM显式指定:

  • BAZEL_LLVM:LLVM 的安装目录

    set BAZEL_LLVM=C:\Program Files\LLVM

启用 Clang 工具链的配置方式取决于 Bazel 版本,以及使用的是 Bzlmod 还是 WORKSPACE。


Bazel 8 及更新版本

  • 使用 Bzlmod(推荐)

    1. 确保MODULE.bazel中加载了rules_cc并配置 CC 工具链:

      bazel_dep(name = "rules_cc", version = "0.0.17") # Or newer cc_configure = use_extension("@rules_cc//cc:extensions.bzl", "cc_configure_extension") use_repo(cc_configure, "local_config_cc")
    2. 在 BUILD 文件中(例如根 BUILD 文件)定义platform目标:

      platform( name = "x64_windows-clang-cl", constraint_values = [ "@platforms//cpu:x86_64", "@platforms//os:windows", "@bazel_tools//tools/cpp:clang-cl", # Alias to the @rules_cc constraint in Bazel 8+ ], )
    3. 使用以下标志启用该工具链:

      --extra_toolchains=@local_config_cc//:cc-toolchain-x64_windows-clang-cl --extra_execution_platforms=//:x64_windows-clang-cl
  • 使用 WORKSPACE

    1. WORKSPACE文件中加载rules_cc的依赖与工具链:

      load("@rules_cc//cc:repositories.bzl", "rules_cc_dependencies", "rules_cc_toolchains") rules_cc_dependencies() rules_cc_toolchains()
    2. 在 BUILD 文件中(例如根 BUILD 文件)定义platform目标(同 Bzlmod 方式,约束使用@bazel_tools//tools/cpp:clang-cl)。

    3. 使用上述相同的--extra_toolchains/--extra_execution_platforms标志启用工具链。


Bazel 7

注意:在 Bazel 7 中,@bazel_tools//tools/cpp:clang-cl并不是@rules_cc约束的别名。要在 Bazel 7 中配合rules_cc正确使用clang-cl,必须引用@rules_cc仓库内的约束。@rules_cc//cc/private/toolchain:clang-cl这个标签在技术上属于私有 API,但在 Bazel 7 中,为了保证 WORKSPACE 与 Bzlmod 两种配置方式行为一致,它是必需的。

  • 使用 Bzlmod

    1. 按 Bazel 8 示例配置MODULE.bazel

    2. 使用@rules_cc私有约束定义platform目标:

      platform( name = "x64_windows-clang-cl", constraint_values = [ "@platforms//cpu:x86_64", "@platforms//os:windows", "@rules_cc//cc/private/toolchain:clang-cl", # Necessary for Bazel 7 ], )
    3. 使用上述标志启用工具链。

  • 使用 WORKSPACE

    1. WORKSPACE文件中加载rules_cc依赖与工具链。
    2. 使用@rules_cc私有约束定义platform目标(同上)。
    3. 使用上述标志启用工具链。

Bazel 0.29 至 6.x

  • 通过构建标志--compiler=clang-cl启用 Clang 工具链。
  • 如果你的构建将--incompatible_enable_cc_toolchain_resolution设为true,则改用 Bazel 7.0.0 的方案。

Bazel 0.28 及更早版本

  • 不支持 Clang。

构建 Java

构建 Java 目标需要Java SE Development Kit(JDK)(安装指引见 docs/install/windows.mdx:需要 JDK 11 for Windows x64,同时支持 Java 8、9、10)。

在 Windows 上,Bazel 为java_binary规则生成两个输出文件

  • 一个.jar文件;
  • 一个.exe文件——负责为 JVM 设置环境并启动二进制。

用仓库示例项目试构建:

C:\projects\bazel> bazel build //examples/java-native/src/main/java/com/example/myproject:hello-world C:\projects\bazel> bazel-bin\examples\java-native\src\main\java\com\example\myproject\hello-world.exe

示例的java_binary目标定义在 examples/java-native/src/main/java/com/example/myproject/BUILD,入口类为com.example.myproject.Greeter(见 Greeter.java),构建产物在 Windows 上同时生成.jar与可执行的.exe

构建 Python

构建 Python 目标需要Python 解释器(安装指引见 docs/install/windows.mdx)。

在 Windows 上,Bazel 为py_binary规则生成两个输出文件

  • 一个自解压(self-extracting)zip 文件;
  • 一个可执行文件——负责以该 zip 文件为参数启动 Python 解释器。

你可以直接运行可执行文件(.exe扩展名),也可以用 Python 运行自解压 zip 文件:

C:\projects\bazel> bazel build //examples/py_native:bin C:\projects\bazel> bazel-bin\examples\py_native\bin.exe C:\projects\bazel> python bazel-bin\examples\py_native\bin.zip

示例的py_binary目标定义在 examples/py_native/BUILD(bin依赖libfibonacci库),源码见 bin.py。

小结

在 Windows 上用好 Bazel,核心是把握四个要点:一是通过startup --output_user_root缩短路径规避 260 字符限制;二是按需开启开发者模式并配合--windows_enable_symlinks--enable_runfiles(注意其性能开销);三是尽量在cmd.exe/ PowerShell 中运行 Bazel 并规避 MSYS2 的路径自动转换;四是理解无 Bash 构建的边界——除genrulesh_*规则及ctx.actions.run_shell()外,绝大多数目标自 Bazel 1.0 起已不依赖 Bash。C++ 工具链方面,MSVC 的BAZEL_VC/BAZEL_VC_FULL_VERSION/BAZEL_WINSDK_FULL_VERSION与 Clang 的BAZEL_LLVM环境变量可精确控制编译器与 SDK 的选择,而 ARM64 交叉构建与 DLL 支持(见 examples/windows/dll)则为特殊场景提供了完整路径。按此配置,即可在 Windows 上获得与 Linux/macOS 一致、可复现且可扩展的 Bazel 构建体验。

【免费下载链接】bazela fast, scalable, multi-language and extensible build system项目地址: https://gitcode.com/GitHub_Trending/ba/bazel

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询