Ubuntu 22.04 安装 Bazel 9.3.0 指南

Ubuntu 22.04 实测安装 Bazel 9.3.0:官方 APT 仓库主线与 Bazelisk 对照双方案、自带 JRE 验证、C++ 冒烟工程从 0 构建与运行、多版本管理与卸载清理,命令与回显逐条实测(2026-10-20)。

BazelBazel构建工具2026/10/20

Ubuntu 22.04 安装 Bazel 9.3.0 指南

目标:在 Ubuntu 22.04 服务器上从零安装 Bazel 9.3.0(官方 APT 仓库主线方案),并对照安装 Bazelisk 版本管理器;完成 C++ 冒烟工程的构建验证,覆盖多版本管理、升级与卸载。全部命令与回显均在 Ubuntu 22.04.4 LTS(x86_64)真实环境逐条实测,实测日期 2026-10-20。

一、环境信息

  • 操作系统:Ubuntu 22.04.4 LTS(Jammy),x86_64,12 核 CPU / 32GB 内存,root 用户
  • Bazel:9.3.0(官方 APT 仓库 storage.googleapis.com/bazel-apt,2026-10-20 时最新稳定版)
  • Bazelisk:v1.28.1(对照方案,经 npm 源 @bazel/bazelisk 与官方二进制两种形态验证)
  • C/C++ 编译器:gcc/g++ 11.4.0(Ubuntu 22.04 默认仓库版本)
  • 实测工程目录:/opt/data/quzuo/tmp/bazel/demo-app(冒烟工程,收工后保留供复查;读者可任选自己的工作目录)
  • Java:未安装系统 Java——Bazel 9.3.0 自带私有 JRE(Azul OpenJDK 25.0.2+10-LTS,实测见第七节验证)

二、前置条件

安装 Bazel 本体前,先补齐两块前置:一是 APT 工具链与下载工具(官方安装步骤的第一条命令),二是 C/C++ 编译器(冒烟工程是 C++ 目标,需要 gcc/g++)。

apt install apt-transport-https curl gnupg -y

实测回显(输出节选;实测时本机 curl 由 7.81.0-1ubuntu1.29 升级到 7.81.0-1ubuntu1.30,其余依赖已就位):

正在设置 curl (7.81.0-1ubuntu1.30) ...
正在处理用于 man-db (2.10.2-1) 的触发器 ...
正在处理用于 libc-bin (2.35-0ubuntu3.15) 的触发器 ...

编译器检查(Bazel 构建 C++ 目标时按工具链自动探测本地编译器):

gcc --version | head -1
g++ --version | head -1

实测回显:

gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0
g++ (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

⚠️ 注意:Bazel 9.3.0 运行本身不需要 Java(自带 JRE,验证见 7.5 节);只有当项目需要构建 Java 代码时才需要另装 JDK(官方建议 apt install default-jdk,来源:bazel.build/install/ubuntu,查询日期 2026-10-20)。

三、版本选型说明

版本实查结论(查询日期 2026-10-20):

  1. 上游最新稳定版:GitHub Releases Atom 流(github.com/bazelbuild/bazel/releases.atom)显示最新正式版为 9.3.0(发布于 2026-10-07);下一 major 的候选 10.0.0rc1(2026-10-08)与滚动预发布 10.0.0-pre.20261006.3(2026-10-14)仍在测试期;上一 LTS 维护线为 8.8.1(2026-09-24)。
  2. 官方 APT 仓库可装版本:添加源后 apt-cache policy bazel 显示候选版本即 9.3.0,与上游最新稳定版一致;源内同时提供版本化包(bazel-9.3.0、bazel-8.8.1、bazel-9.2.0、bazel-9.1.1、bazel-9.1.0、bazel-9.0.2、bazel-8.8.0 等)。
  3. 支持平台:官方文档明确支持 Ubuntu 22.04 (LTS)、20.04 (LTS)、18.04 (LTS)(来源:bazel.build/install/ubuntu,查询日期 2026-10-20)。
  4. 官方推荐:Ubuntu 平台官方推荐用 Bazelisk 安装(版本管理器),APT 仓库为并列可选方案(同上来源)。

💡 技术拓展:APT 仓库源配置中的组件名 jdk1.8 只是历史遗留命名,官方特别说明它「与支持的或包含的 JDK 版本无关」,Bazel 发布包对 Java 版本无感知,改名反而会破坏既有用户——配置时原样照抄即可(来源:bazel.build/install/ubuntu,查询日期 2026-10-20)。

结论:本篇主线为方案 A(官方 APT 仓库)安装 9.3.0,方案 B(Bazelisk)作为版本管理器对照方案。二选一或并存皆可,对比见第六节。

四、方案 A:官方 APT 仓库安装(主线)

本方案为官方文档给出的 APT 仓库三步法:加 GPG 公钥 → 加软件源 → 安装。以下每一步都在实测环境执行并记录了真实回显。

4.1 安装 GPG 公钥

下载 Bazel 官方发布公钥并转换为 APT 可用的 keyring 格式:

curl -fsSL https://releases.bazel.build/bazel-release.pub.gpg | gpg --dearmor > /usr/share/keyrings/bazel-archive-keyring.gpg

该命令本身无成功输出。用 file 验证落盘的公钥内容:

file /usr/share/keyrings/bazel-archive-keyring.gpg

实测回显:

/usr/share/keyrings/bazel-archive-keyring.gpg: OpenPGP Public Key Version 4, Created Tue May 24 18:19:37 2016, RSA (Encrypt or Sign, 4096 bits); User ID; Signature; OpenPGP Certificate

4.2 添加 Bazel 软件源

echo "deb [arch=amd64 signed-by=/usr/share/keyrings/bazel-archive-keyring.gpg] https://storage.googleapis.com/bazel-apt stable jdk1.8" | tee /etc/apt/sources.list.d/bazel.list

实测回显(tee 同时打印写入内容):

deb [arch=amd64 signed-by=/usr/share/keyrings/bazel-archive-keyring.gpg] https://storage.googleapis.com/bazel-apt stable jdk1.8

刷新包索引:

apt update

实测回显(输出节选;实测机器上另有其他软件源的无关告警,已省略):

命中:2 https://storage.googleapis.com/bazel-apt stable InRelease
正在读取软件包列表...

💡 说明:若 apt update 报「无法获得锁 /var/lib/apt/lists/lock」,说明有其他 apt 进程正在运行,等其结束再重试即可(实测中出现过该锁占用,等待锁释放后重跑成功)。

4.3 确认可装版本

apt-cache policy bazel

实测回显:

bazel:
  已安装:(无)
  候选: 9.3.0
  版本列表:
     9.3.0 500
        500 https://storage.googleapis.com/bazel-apt stable/jdk1.8 amd64 Packages
     9.2.0 500
        500 https://storage.googleapis.com/bazel-apt stable/jdk1.8 amd64 Packages

4.4 安装并验证

apt install bazel -y

实测回显(输出节选):

获取:1 https://storage.googleapis.com/bazel-apt stable/jdk1.8 amd64 bazel amd64 9.3.0 [68.3 MB]
已下载 68.3 MB,耗时 5秒 (12.9 MB/s)
正在选中未选择的软件包 bazel。
(正在读取数据库 ... 系统当前共安装有 224767 个文件和目录。)
准备解压 .../archives/bazel_9.3.0_amd64.deb  ...
正在解压 bazel (9.3.0) ...
正在设置 bazel (9.3.0) ...

验证安装与包内文件布局:

which bazel && ls -la /usr/bin/bazel*

实测回显:

/usr/bin/bazel
-rwxr-xr-x 1 root root     8963  1月  1  2000 /usr/bin/bazel
-rwxr-xr-x 1 root root 77023347  1月  1  2000 /usr/bin/bazel-real
dpkg -L bazel

实测回显:

/usr
/usr/bin
/usr/bin/bazel
/usr/bin/bazel-real
/etc
/etc/bash_completion.d
/etc/bash_completion.d/bazel
/usr/share
/usr/share/zsh
/usr/share/zsh/vendor-completions

💡 说明:/usr/bin/bazel 是一个约 9KB 的启动器脚本,/usr/bin/bazel-real(约 77MB)才是 Bazel 本体。启动器支持 $USE_BAZEL_VERSION 环境变量与工作区 .bazelversion 文件,并优先查找与自身同目录的 bazel-<版本> 命名二进制(如第八节安装的 /usr/bin/bazel-8.8.1);找不到时回落到 bazel-real。包内还附带 bash/zsh 补全脚本。

版本验证:

bazel --version

实测回显:

bazel 9.3.0
bazel version

实测回显(首行 stderr 警告为自带 JRE 的 JVM 提示,属正常现象,见 7.5 节解释):

OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
Build label: 9.3.0
Build target: @@//src/main/java/com/google/devtools/build/lib/bazel:BazelServer
Build time: Wed Oct 07 14:46:24 2026 (1791384384)
Build timestamp: 1791384384
Build timestamp as int: 1791384384

Build time: Wed Oct 07 14:46:24 2026 与 Releases Atom 流中 9.3.0 的发布日期(2026-10-07)一致,确认装到的就是当前最新稳定版。

五、方案 B:Bazelisk 安装(版本管理器,官方推荐)

Bazelisk 是 Bazel 官方维护的版本管理器:按项目的 .bazelversion 自动下载并运行对应版本的 Bazel,适合多项目、多 Bazel 版本并存的机器。本节给出两种安装来源:npm(实测全流程)与 GitHub 二进制(官方 README 方式)。

5.1 npm 方式安装(实测)

npm install -g @bazel/bazelisk

实测回显:

added 1 package in 2s

npm 包内自带各平台二进制(bazelisk-linux_amd64 等),安装后在 npm 全局 bin 目录生成 bazelisk 与 bazel 两个入口:

which bazel bazelisk

实测回显:

/root/.nvm/versions/node/v24.21.0/bin/bazel
/root/.nvm/versions/node/v24.21.0/bin/bazelisk

⚠️ 注意(实测踩坑):npm 方式会把 bazel 命令入口也放进 npm 全局 bin 目录。当 npm 全局 bin 在 PATH 中先于 /usr/bin 时,which bazel 会指向 npm 的入口而遮蔽方案 A 安装的 /usr/bin/bazel。若要保留 APT 版本为默认 bazel,应避免两者混装,或卸载 npm 包(npm uninstall -g @bazel/bazelisk)。本篇实测中即遇到了该遮蔽,随后卸载 npm 包恢复。

5.2 GitHub 二进制方式(官方 README 方式)

官方 bazelisk README 的安装方式是从 GitHub Releases 页下载对应平台二进制并放置到 PATH 内(如 /usr/local/bin/bazelisk),发布件命名形如 bazelisk-linux-amd64(来源:bazelbuild/bazelisk 官方 README,2026-10-20 经 npm 源 @bazel/bazelisk 核对):

# 从 https://github.com/bazelbuild/bazelisk/releases 页获取最新 bazelisk-linux-amd64
curl -Lo /usr/local/bin/bazelisk <releases 页展示的最新版下载 URL>
chmod +x /usr/local/bin/bazelisk

⚠️ 注意:实测当日 GitHub 下载链路在实验网络不可达(直连被拒、代理握手被断),上述下载命令未能当场实测,故不硬编码具体版本号 URL,请从 Releases 页获取;作为等价验证,本篇将官方发布的同版本二进制(v1.28.1,与 npm 包一致)落位 /usr/local/bin/bazelisk 后完成了实测:

cp bazelisk-linux-amd64 /usr/local/bin/bazelisk && which bazelisk

实测回显:

/usr/local/bin/bazelisk
USE_BAZEL_VERSION=9.3.0 bazelisk version

实测回显:

Bazelisk version: v1.28.1
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
Build label: 9.3.0

Bazelisk version: v1.28.1 确认 bazelisk 本体;Build label: 9.3.0 确认其拉起的 Bazel 版本(首次运行会自动下载该版本 Bazel 到用户缓存)。

5.3 Bazelisk 的版本解析与缓存

按官方 README(2026-10-20 核对),Bazelisk 决定「用哪个 Bazel 版本」的优先级为:

  1. 环境变量 USE_BAZEL_VERSION;
  2. 工作区根的 .bazeliskrc 文件中的 USE_BAZEL_VERSION;
  3. 当前目录或任意父目录的 .bazelversion 文件;
  4. 以上皆无时解析 latest(最新稳定版)。

实测多版本切换(下载 8.8.1 并运行):

USE_BAZEL_VERSION=8.8.1 bazelisk version

实测回显:

Bazelisk version: v1.28.1
WARNING: Invoking Bazel in batch mode since it is not invoked from within a workspace (below a directory having a MODULE.bazel file).
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
Build label: 8.8.1
Build target: @@//src/main/java/com/google/devtools/build/lib/bazel:BazelServer
Build time: Thu Sep 24 20:14:55 2026 (1790280895)

Build time: Thu Sep 24 20:14:55 2026 与 Releases Atom 流中 8.8.1 的发布时间(2026-09-24)吻合。下载的 Bazel 二进制缓存在用户缓存目录,多版本共存不重复下载:

du -sh ~/.cache/bazelisk/

实测回显:

136M    /root/.cache/bazelisk/

⚠️ 注意(实测踩坑):不指定 USE_BAZEL_VERSION 且工作区无 .bazelversion 时,bazelisk 需要访问 Google Cloud Storage 的版本清单接口解析 latest。实测在受限网络下得到如下报错——若生产环境存在同样的出网限制,用 USE_BAZEL_VERSION 或 .bazelversion 锁定版本即可绕开版本清单查询:

2026/10/20 13:19:28 could not download Bazel: could not resolve the version 'latest' to an actual version number: unable to determine latest version: could not list Bazel versions in GCS bucket: could not list GCS objects at https://www.googleapis.com/storage/v1/b/bazel/o?delimiter=/: could not fetch https://www.googleapis.com/storage/v1/b/bazel/o?delimiter=/: unable to complete 1 requests to https://www.googleapis.com/storage/v1/b/bazel/o?delimiter=/ within 30s. Most recent failure: Get "https://www.googleapis.com/storage/v1/b/bazel/o?delimiter=/": dial tcp 172.217.112.4:443: i/o timeout

六、方案对比与选择建议

维度方案 A:官方 APT 仓库方案 B:Bazelisk
安装形态系统包管理器托管,apt 统一升级独立二进制(npm 包或 GitHub 发布件),用户级
版本策略bazel 包始终最新稳定版;bazel-<版本> 包并存多版本按工作区 .bazelversion/USE_BAZEL_VERSION 精确锁定,多版本秒切
每项目版本锁定可用版本化包 + /usr/bin/bazel 启动器读 .bazelversion 实现原生支持(这就是它的核心能力)
系统集成bash/zsh 补全脚本随包附带无系统集成
离线/受限网络一次配源后走内网可达的 storage.googleapis.com首次解析 latest 需访问 GCS 清单(可锁定版本绕开)
卸载apt remove 一条命令删除二进制与 ~/.cache/bazelisk
官方态度官方并列方案官方推荐方式(bazel.build/install)

选择建议:单版本、系统级管理的服务器选方案 A;多项目、多 Bazel 版本并存的开发机选方案 B;两者也可并存——APT 装一个稳定基线,bazelisk 按项目切换。若机器的 npm 全局 bin 在 PATH 前列且同机保留 APT 版本,注意 5.1 节的遮蔽坑。

七、冒烟工程:从 0 构建并运行第一个 C++ 目标

安装完成后必须用真实工程验证工具链闭环。本节从空目录开始构建一个含库、二进制、单测的最小工程,全部命令与回显为实测(实测路径 /opt/data/quzuo/tmp/bazel/demo-app,读者可任选自己的目录)。

7.1 创建工程文件

mkdir -p /opt/data/quzuo/tmp/bazel/demo-app && cd /opt/data/quzuo/tmp/bazel/demo-app

MODULE.bazel——工作区标记 + 模块声明 + 外部依赖声明(Bzlmod 机制):

module(
    name = "demo_app",
    version = "1.0.0",
)

bazel_dep(name = "rules_cc", version = "0.2.26")
bazel_dep(name = "googletest", version = "1.18.0.bcr.1")

💡 技术拓展:bazel_dep() 从 Bazel 中央注册库(BCR,bcr.bazel.build)解析依赖。rules_cc 提供 C++ 规则,版本取 BCR 当前最新(0.2.26,实查 bcr.bazel.build/modules/rules_cc/metadata.json,2026-10-20);googletest 提供 gtest 测试框架(BCR 版本 1.18.0.bcr.1,同日实查)。Bazel 8 起原生 cc 规则已移除、必须经 load 使用(见 7.4 排障实录一),因此 rules_cc 是 C++ 工程的必备依赖。

BUILD——包内目标声明(库 + 二进制 + 测试):

load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_cc//cc:cc_test.bzl", "cc_test")

cc_library(
    name = "greet",
    srcs = ["greet.cc"],
    hdrs = ["greet.h"],
)

cc_binary(
    name = "hello",
    srcs = ["main.cc"],
    deps = [":greet"],
)

cc_test(
    name = "greet_test",
    srcs = ["greet_test.cc"],
    deps = [
        ":greet",
        "@googletest//:gtest_main",
    ],
)

greet.h:

#ifndef GREET_H_
#define GREET_H_

#include <string>

// 返回对指定对象的问候语。
std::string greet(const std::string& thing);

#endif  // GREET_H_

greet.cc:

#include "greet.h"

std::string greet(const std::string& thing) { return "Hello, " + thing + "!"; }

main.cc:

#include <cstdlib>
#include <iostream>
#include <string>

#include "greet.h"

int main(int argc, char** argv) {
  std::string who = (argc > 1) ? argv[1] : "Bazel";
  std::cout << greet(who) << std::endl;
  return EXIT_SUCCESS;
}

(greet_test.cc 的 gtest 用例见命令篇的测试章节,不影响本节构建主线。)

7.2 首次构建(含依赖拉取)

bazel build //:hello

实测回显(首次构建需拉取 BCR 依赖并配置 C++ 工具链):

Analyzing: target //:hello (5 packages loaded, 6 targets configured)
Analyzing: target //:hello (14 packages loaded, 8 targets configured)
Analyzing: target //:hello (81 packages loaded, 429 targets configured)
INFO: Analyzed target //:hello (93 packages loaded, 550 targets configured).
INFO: Found 1 target...
Target //:hello up-to-date:
  bazel-bin/hello
INFO: Elapsed time: 20.773s, Critical Path: 0.25s
INFO: 8 processes: 5 internal, 3 linux-sandbox.
INFO: Build completed successfully, 8 total actions

real    0m20.855s

验证产物为可执行 ELF:

ls -la bazel-bin/hello && file bazel-bin/hello

实测回显:

-r-xr-xr-x 1 root root 20552 10月 20 13:27 bazel-bin/hello
bazel-bin/hello: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=f772cc5bfdbd58ef9508cdc2cf44b83e331ef188, not stripped

7.3 运行与增量验证

bazel run //:hello

实测回显(输出节选):

INFO: Running command line: bazel-bin/hello
Hello, Bazel!

带参数运行:

bazel run //:hello -- World

实测回显(输出节选):

INFO: Running command line: bazel-bin/hello <args omitted>
Hello, World!

无改动的增量重建(Bazel 服务器复用分析结果,动作全部命中缓存):

time bazel build //:hello

实测回显:

INFO: Elapsed time: 0.096s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total actions

real    0m0.142s

首次 20.8 秒、增量 0.14 秒——这正是 3.x 所述客户端-服务器模型与缓存的直观体现。

7.4 排障实录(真实踩坑,逐条复现)

实录一:Bazel 9 已移除原生 cc 规则。 用旧教材写法(BUILD 直接写 cc_library 不加 load)首次构建,实测报错全文:

ERROR: Traceback (most recent call last):
        File "/opt/data/quzuo/tmp/bazel/demo-app/BUILD", line 1, column 11, in <toplevel>
                cc_library(
        File "/virtual_builtins_bzl/bazel/exports.bzl", line 40, column 9, in _removed_rule_failure
Error in fail:
         This rule has been removed from Bazel. Please add a `load()` statement for it.
         This can also be done automatically by running:
         buildifier --lint=fix <path-to-BUILD-or-bzl-file>
WARNING: Target pattern parsing failed.
ERROR: Skipping '//:hello': no such target '//:hello': target 'hello' not declared in package '' defined by /opt/data/quzuo/tmp/bazel/demo-app/BUILD
ERROR: Build did NOT complete successfully

定位:报错明确指出规则已被移除、需要 load()。修复:在 BUILD 顶部加三条 load(见 7.1 节 BUILD 文件头三行)。

实录二:@rules_cc 仓库不可见。 加了 load 后再次构建,实测报错:

ERROR: Skipping '//:hello': error loading package '': Unable to find package for @@[unknown repo 'rules_cc' requested from @@]//cc:cc_binary.bzl: The repository '@@[unknown repo 'rules_cc' requested from @@]' could not be resolved: No repository visible as '@rules_cc' from main repository.
ERROR: Build did NOT complete successfully

定位:Bzlmod 下外部仓库必须先在 MODULE.bazel 声明。修复:加入 bazel_dep(name = "rules_cc", version = "0.2.26")(版本经 BCR 实查)。修复后构建成功(7.2 节回显)。

7.5 Java 运行时说明(自带 JRE 实测验证)

Bazel 9.3.0 无需系统 Java。三重实测证据:

  1. 实测机未安装任何系统 Java(java -version 报 command not found),但 bazel --version、bazel build、bazel run 全部正常(见上文回显);
  2. bazel version 的回显带出 OpenJDK 64-Bit Server VM warning——Bazel 启动的是自带的 OpenJDK 虚拟机;
  3. bazel info 直接给出自带 JRE 的位置与版本:
bazel info java-home && bazel info java-runtime && bazel info java-vm

实测回显:

java-home: /root/.cache/bazel/_bazel_root/install/bf018ed227128835327c556cff5c0ff0/embedded_tools/jdk
java-runtime: OpenJDK Runtime Environment (build 25.0.2+10-LTS) by Azul Systems, Inc.
java-vm: OpenJDK 64-Bit Server VM (build 25.0.2+10-LTS, mixed mode) by Azul Systems, Inc.

即自带的是 Azul Systems 构建的 OpenJDK 25.0.2+10-LTS,位于 Bazel 安装基目录(install base)内,与系统 Java 完全隔离。

八、多版本管理与升级

8.1 版本化包并存(方案 A 路线)

官方 APT 仓库提供 bazel-<版本> 命名包,可与 bazel 主包并存:

apt install bazel-8.8.1 -y

实测回显(输出节选):

正在解压 bazel-8.8.1 (8.8.1) ...
正在设置 bazel-8.8.1 (8.8.1) ...
ls -la /usr/bin/bazel /usr/bin/bazel-8.8.1 /usr/bin/bazel-real

实测回显:

-rwxr-xr-x 1 root root     8963  1月  1  2000 /usr/bin/bazel
-rwxr-xr-x 1  997  997 64823995  9月 25 05:21 /usr/bin/bazel-8.8.1
-rwxr-xr-x 1 root root 77023347  1月  1  2000 /usr/bin/bazel-real

💡 说明:版本化包是单一完整二进制(64.8MB,无启动器),命名即版本,直接运行不影响主包:

/usr/bin/bazel-8.8.1 --version

实测回显:

bazel 8.8.1

8.2 工作区级锁定:.bazelversion

在工程根放一个 .bazelversion 文件即可锁定该项目使用的 Bazel 版本(启动器与 bazelisk 都认它)。实测:

cd /opt/data/quzuo/tmp/bazel/demo-app && echo 8.8.1 > .bazelversion && bazel version | grep 'Build label'

实测回显:

Build label: 8.8.1

删除后恢复主包版本:

rm .bazelversion && bazel version | grep 'Build label'

实测回显:

Build label: 9.3.0

机制解释:/usr/bin/bazel 启动器读到 .bazelversion 中的 8.8.1 后,查找自身同目录的 /usr/bin/bazel-8.8.1 并执行——这正是 4.4 节所说的启动器行为,也是「APT 多版本 + 工作区锁定」的组合用法。bazelisk 方案下同一文件同样生效(见 5.3 节解析顺序)。

8.3 升级

方案 A(官方文档建议的常规升级方式,来源:bazel.build/install/ubuntu,查询日期 2026-10-20):

apt update && apt full-upgrade

官方说明「bazel 包始终安装最新稳定版」,升级即随系统常规更新完成;需要旧版本并存时用 8.1 节的版本化包。

方案 B(bazelisk):删除 USE_BAZEL_VERSION 或改写各工程的 .bazelversion 即可,bazelisk 首次运行时自动下载新版本;也可用 latest-1、4.x 等浮动标签(来源:bazelisk 官方 README,2026-10-20 核对)。

九、常见问题(FAQ)

Q1:Bazel 需要单独安装 Java 吗? 不需要。9.3.0 自带 Azul OpenJDK 25 JRE(7.5 节实测证据);只有构建 Java 代码时才需要 apt install default-jdk(来源:官方 Ubuntu 安装文档)。

Q2:apt update 时 bazel 源报 NO_PUBKEY/签名错误? 确认 4.1 节公钥已转换为 keyring 并与 4.2 节 signed-by= 路径一致(/usr/share/keyrings/bazel-archive-keyring.gpg)。实测按官方步骤操作未出现该问题。

Q3:Arm(arm64)机器能装吗? 官方 APT 仓库不含 arm64 发布件,也无二进制安装器;官方指引是改用 Bazelisk 或从源码编译(来源:bazel.build/install/ubuntu,查询日期 2026-10-20)。

Q4:bazel --version 秒回、没有 JVM 启动感? --version 由客户端启动器直接应答;完整版本信息用 bazel version(会触达服务器进程,回显含 Build label/Build time)。两者输出不同属正常。

Q5:首次构建卡在下载依赖或报下载失败? 首次构建需要从 BCR 及其源地址拉取 rules_cc 等模块(实测约 20 秒完成)。出网受限时:已在有网机器构建过的,可迁移仓库缓存(bazel info repository_cache 给出的默认路径 /root/.cache/bazel/_bazel_root/cache/repos/v1,整体拷贝到新机器同路径即可,实测迁移后离线构建成功);bazelisk 场景用 USE_BAZEL_VERSION 绕开版本清单查询(5.3 节实录)。

Q6:启动器脚本 bazel 与 bazel-real 有何区别? 见 4.4 节说明——bazel 是支持 .bazelversion/USE_BAZEL_VERSION/版本化包查找的启动器,bazel-real 是真实二进制;日常一律用 bazel。

十、卸载与清理

完全卸载分三步:卸载包 → 删软件源 → 删公钥(用户缓存目录按需删除)。

apt remove -y bazel bazel-8.8.1

实测回显(输出节选):

正在卸载 bazel (9.3.0) ...
正在卸载 bazel-8.8.1 (8.8.1) ...
ls /usr/bin/bazel*

实测回显:

ls: cannot access '/usr/bin/bazel*': No such file or directory

删除软件源与公钥(命令执行成功无输出):

rm /etc/apt/sources.list.d/bazel.list
rm /usr/share/keyrings/bazel-archive-keyring.gpg
apt update

可选清理(删除后重新构建需重新拉取依赖与 Bazel 二进制):

rm -rf ~/.cache/bazel      # 输出基目录/仓库缓存/服务器进程数据
rm -rf ~/.cache/bazelisk   # bazelisk 下载的各版本 Bazel 二进制

💡 说明:本篇实测环境收工时按上述步骤清理了全局残留(软件源、公钥、npm 全局的 @bazel/bazelisk),冒烟工程与实验产物保留在工作区 /opt/data/quzuo/tmp/bazel/ 下备查。

十一、参考链接

  1. 官方 Ubuntu 安装文档:https://bazel.build/install/ubuntu(安装步骤与平台支持,查询日期 2026-10-20)
  2. 官方版本策略:https://bazel.build/release/versioning(查询日期 2026-10-20)
  3. GitHub Releases Atom 流:https://github.com/bazelbuild/bazel/releases.atom(版本实查,2026-10-20)
  4. Bazelisk 官方仓库:https://github.com/bazelbuild/bazelisk(README 经 npm 源 @bazel/bazelisk 核对,2026-10-20)
  5. Bazel 中央注册库:https://bcr.bazel.build(rules_cc 0.2.26 / googletest 1.18.0.bcr.1 实查,2026-10-20)
  6. 本专栏认知篇:《Bazel 9.3.0 介绍与选型指南》