Search code examples
cmakebazelmonolithic

Single or multiple bazel WORKSPACE should be used for monolithic repo?


We put all products and libraries in one monolithic git repository. Its layout looks like this:

- FooProduct
- BarProduct
- BazLibrary
- 3rd_party
 |- fftw
 |- msgpack
 |- zlib

At current, we are using CMake to control the build. As CMake has separated config, generate and build phase, it would take extremely long time to run if you generate all things together. To avoid this, we give top-level CMakeLists.txt for each part, and referring peer projects by up-level add_subirectory calls. For example:

# FooProduct/CMakeLists.txt
project(FooProduct)
add_subdirectory(../BazLibrary sibling/BazLibrary)
add_subdirectory(../3rd_party/zlib sibling/3rd_party/zlib)
......

Now we are evaluating Bazel, and I immediately got the question: should I only place one single WORKSPACE at top dir of the git repo?

- WORKSPACE
- FooProduct
- BarProduct
- BazLibrary
- 3rd_party
 |- fftw
 |- msgpack
 |- zlib

Or put many WORKSPACE files in each product/library and referring each other using local_repository rule?

- FooProduct
 |- WORKSPACE
- BarProduct
 |- WORKSPACE
- BazLibrary
 |- WORKSPACE
- 3rd_party
 |- fftw
   |- WORKSPACE
 |- msgpack
   |- WORKSPACE
 |- zlib
   |- WORKSPACE

Solution

  • Single workspace or source/build tree by definition only has one (top-level) WORKSPACE. In theory you could place WORKSPACE branches of your tree, but one obvious source of confusion would be, you could not reach project targets when running bazel from directories where another WORKSPACE is along the path between cwd and project root. While you would not really be gaining anything in return.

    If you wanted to distribute your configuration across multiple directories (or even submodules), you can add Starlark (.bzl) files with macros ("functions") defining corresponding repository rule targets (external dependencies) anywhere in your tree (such as //3rd_party/...) and load and execute corresponding corresponding definitions in your (project) WORKSPACE file.

    But that would be more of an organizational matter (e.g. different people/groups maintaining different dependencies; or just keeping files small), effectively it works (is ultimately evaluated) just like having one big WORKSPACE file.

    If the external dependency is referred to as a source and BUILD description. It really does not matter whether it was pulled from entirely different repo or sits in the same tree. It needs to be rebuild, but also gets cached, either way.