Introduce a Bazel build system#1280
Conversation
|
Hi @taku910, This is Carbo. I'd love to hear your thoughts on this PR. I use SentencePiece from a Bazel-based project, and this PR upstreams the Bazel build I have been running there: a bzlmod I'm happy to maintain the Bazel build long-term, keeping the dependency pins in sync with CMake, following Bazel/BCR releases, and fixing any breakage the CI surfaces. The PR is marked as draft for discussion; the include-path change it requires (dropping the google3-style |
Add a bzlmod-based Bazel build alongside the existing CMake build. It
covers the runtime and trainer libraries, the five spm_* command line
tools, and a spm_test target running the full unit test suite, with a
GitHub Actions workflow that builds and tests on Linux (x86_64 and
arm64), macOS, and Windows.
All third-party dependencies are resolved from the Bazel Central
Registry instead of the vendored copies, which remain in the tree for
CMake:
- abseil-cpp, pinned to the same version as the GIT_TAG in
CMakeLists.txt;
- protobuf: the .pb.cc/.pb.h files are regenerated from src/*.proto at
build time, equivalent to the SPM_PROTOBUF_PROVIDER=package CMake
configuration (enabled through the existing _USE_EXTERNAL_PROTOBUF
support);
- darts-clone 0.32h.bcr.1, an upstream v0.32h build that carries the
compatibility helpers (copy_array, validate) of the copy vendored
here;
- esaxx 20250106.1.bcr.1, an upstream build that exports esa.hxx and
carries the index_type(0) template-deduction fix of the copy vendored
here, without which the int64_t instantiation used by
--train_extremely_large_corpus does not compile.
The sources now include third-party headers by the canonical paths the
upstream projects export ("absl/...", "darts.h", "esa.hxx") instead of
the google3-style "third_party/..." paths, for two reasons. First, in
the open-source Bazel ecosystem dependencies export canonical include
paths, and OSS trees of TensorFlow, protobuf, and gRPC all consume
Abseil as "absl/..."; keeping the internal prefix forces every build
system to maintain an adaptation layer (previously the third_party/absl
symlink and the install-time header rewriting in CMake). Second, Bazel
builds without sandboxing on Windows, where quote-include resolution
physically picks up the vendored in-tree files at the literal
"third_party/..." paths, shadowing the module headers and failing
strict inclusion checks; only the canonical paths behave identically on
all platforms. As a side effect, CMake's symlink machinery and
cmake/modify_headers.cmake are no longer needed, and the installed
public headers are content-equivalent to what the rewrite script used
to generate.
|
Thank you. Maintaining both Bazel and CMake is not feasible, especially given our current bandwidth constraints. Therefore, I would like to make the transition to Bazel an exclusive one. With today's AI coding tools, I believe the migration itself shouldn't be too difficult. On the other hand, there is a potential issue where Bazel lacks sufficient support from package maintainers like those for Debian, and often isn't provided upstream. This is currently happening with Mozc, where the Ubuntu package is still relying on patches from the old GYP-based branch, leaving it about two years behind upstream. Since there is no clear answer yet, It would be nice to create an issue and consolidate the feedback there. |
|
Thank you. I agree that distro packaging is an important concern, and that is one reason I think Bazel support is useful as an additional build path alongside the existing CMake build. This PR uses Bzlmod/BCR, which is convenient for Bazel consumers, while CMake remains the path that Linux distribution/package maintainers already understand and can patch. Distribution builds often need no-network builds, declared packaged build dependencies, system libraries, shared-library packaging, pkg-config/CMake metadata, etc., so keeping CMake available continues to serve that use case. This dual-build approach also matches the direction of several Google C++ OSS libraries. Abseil documents Bazel and CMake as official build systems; GoogleTest has both Bazel and CMake quickstarts and follows the Google Foundational C++ Support Policy; gRPC uses Bazel as primary but still supports CMake for C++; RE2 and Highway also support both. Google’s own C++ support policy notes that CMake is dominant externally while Bazel is essential for Google, and suggests supporting Bazel and CMake as the practical minimum. I’m happy to help maintain the Bazel build long-term: keep dependency pins aligned with CMake, follow Bazel/BCR changes, maintain the Bazel CI, investigate and fix Bazel-specific breakages, and review future Bazel-related PRs/issues when they come up. |
Adds [SentencePiece](https://github.com/google/sentencepiece) v0.2.1 as a new module. The Bazel build definitions are taken from the upstream PR google/sentencepiece#1280 (not yet merged), adapted for the 0.2.1 release tarball: - `overlay/BUILD.bazel` + `overlay/src/BUILD.bazel`: root aliases, `//src:sentencepiece` (runtime), `//src:sentencepiece_train` (trainer), and the `spm_{train,encode,decode,normalize,export_vocab}` CLIs. The protobuf code is regenerated from `src/*.proto` at build time (matching the `SPM_PROTOBUF_PROVIDER=package` CMake configuration). `defines = ["_USE_EXTERNAL_ABSL"]` selects the external-absl branch of `error.cc`, which defines the `--minloglevel` flag (normally supplied by the vendored mini-absl shim's `flag.cc`), matching the `SPM_ABSL_PROVIDER=module|package` CMake configurations. - `patches/use_bcr_dependency_includes.patch`: rewrites `#include "third_party/absl/..."` → `"absl/..."`, `"third_party/darts_clone/darts.h"` → `"darts.h"`, and `"third_party/esaxx/esa.hxx"` → `"esa.hxx"` so the sources resolve against the BCR modules (abseil-cpp, [email protected], [email protected]) instead of the vendored copies. - The release tarball is a Python sdist, so `strip_prefix` is `sentencepiece-0.2.1/sentencepiece`. It does not ship the `data/` directory, so the upstream `spm_test` target is not included. Instead, the overlay adds a `bcr_tests/` test module (`bcr_test_module` in presubmit) with an in-memory train → encode → decode roundtrip `cc_test`; presubmit also verifies all library and CLI targets on Linux/macOS/Windows with C++17 flags. Locally verified: all targets build (Bazel 9.1.1), the `bcr_tests` roundtrip test passes, `spm_train`/`spm_encode` work end to end, and `bcr_validation.py --check [email protected]` passes.
Adds [SentencePiece](https://github.com/google/sentencepiece) v0.2.2, following up on #9552 ([email protected]). Same approach as 0.2.1, with the Bazel build definitions taken from the upstream PR google/sentencepiece#1280 (not yet merged), adapted for the 0.2.2 release tarball: - `overlay/BUILD.bazel` + `overlay/src/BUILD.bazel`: root aliases, `//src:sentencepiece` (runtime), `//src:sentencepiece_train` (trainer), and the `spm_{train,encode,decode,normalize,export_vocab}` CLIs. The protobuf code is regenerated from `src/*.proto` at build time (matching the `SPM_PROTOBUF_PROVIDER=package` CMake configuration). - `patches/use_bcr_dependency_includes.patch`: rewrites `#include "third_party/absl/..."` → `"absl/..."`, `"third_party/darts_clone/darts.h"` → `"darts.h"`, and `"third_party/esaxx/esa.hxx"` → `"esa.hxx"` so the sources resolve against the BCR modules (abseil-cpp, [email protected], [email protected]) instead of the vendored copies. - The release tarball is a Python sdist, so `strip_prefix` is `sentencepiece-0.2.2/sentencepiece`. It does not ship the `data/` directory, so the upstream `spm_test` target is not included. Instead, the overlay adds a `bcr_tests/` test module (`bcr_test_module` in presubmit) with an in-memory train → encode → decode roundtrip `cc_test`; presubmit also verifies all library and CLI targets on Linux/macOS/Windows with C++17 flags. Differences from 0.2.1: 0.2.2 uses `init.cc` (renamed from `error.cc`), migrated to absl::Status/log (more abseil-cpp deps, no `_USE_EXTERNAL_ABSL` define needed), and its `MODULE.bazel` pins abseil-cpp 20260526.0 to match the `GIT_TAG` in `CMakeLists.txt`. Locally verified: all targets build (Bazel 9.1.1), the `bcr_tests` roundtrip test passes, and `bcr_validation.py --check [email protected]` passes.
Describe the change
This PR adds a bzlmod-based Bazel build system alongside the existing CMake build. It covers the runtime and trainer libraries, the five
spm_*command line tools, and aspm_testtarget that runs the full unit test suite (equivalent to the CMakespm_testbuilt with-DSPM_BUILD_TEST=ON), plus a GitHub Actions workflow that builds and tests with Bazel on Linux (x86_64/arm64), macOS, and Windows. Usage is documented indoc/bazel.md.External dependencies. All third-party code is resolved from the Bazel Central Registry; nothing is vendored into the Bazel build (the vendored copies under
third_party/andsrc/builtin_pbremain in the tree for CMake, whose behavior is unchanged):GIT_TAGinCMakeLists.txt;.pb.cc/.pb.hfiles are regenerated fromsrc/*.protoat build time viaproto_library/cc_proto_library, equivalent to theSPM_PROTOBUF_PROVIDER=packageCMake configuration and enabled through the existing_USE_EXTERNAL_PROTOBUFsupport;0.32h.bcr.1— upstream v0.32h plus the compatibility helpers (copy_array(),validate()) that the copy vendored here carries;20250106.1.bcr.1with your fixes.Why the
third_party/include prefix had to go. The sources now include third-party headers by the canonical paths the upstream projects export ("absl/...","darts.h","esa.hxx") instead of the google3-style"third_party/..."paths, for two reasons:third_party/abslis the real repository path, but in the open-source Bazel ecosystem dependencies export canonical include paths, and the OSS trees of TensorFlow, protobuf, and gRPC all consume Abseil as"absl/...". Keeping the internal prefix forces every build system to maintain an adaptation layer — in this repository that is thethird_party/abslsymlink created at configure time plus the install-time header rewriting incmake/modify_headers.cmake; a Bazel build would need an equivalent layer of generated forwarding headers."third_party/..."paths. They shadow the module headers and fail Bazel's strict inclusion checks, which we hit in CI; only the canonical prefix-free paths behave identically across all platforms.As a side effect, the CMake symlink machinery and
cmake/modify_headers.cmakeare no longer needed: the abseil-cpp checkout root and the vendoreddarts_clone/esaxxdirectories are put on the include path directly, and the public headers are installed as-is (content-equivalent to what the rewrite script used to generate).The optional CMake features
SPM_ENABLE_NFKC_COMPILE,SPM_ENABLE_TCMALLOC,SPM_ENABLE_BENCHMARK, andSPM_NLCODEC_BPEhave no Bazel equivalent yet; this is noted in the docs.Link to a related Issue
None. Opened as a draft for discussion.
Testing Information
bazel build //...andbazel test //src:spm_test(all 164 test cases) pass on Linux x86_64, Linux arm64, macOS, and Windows via the included GitHub Actions workflow, which also smoke-testsspm_train/spm_encodeend to end (latest green run).ctest,cmake --install) passes; the installedsentencepiece_processor.h/sentencepiece_trainer.hcarry the sameabsl/...includes the deleted rewrite script used to generate.spm_trainondata/botchan.txt, vocab 1000, thenspm_encode).