Skip to content

Monorepo Setup

This guide walks you through setting up a monorepo with multiple languages managed by Bazelle.

Overview

By the end of this guide, you’ll have:

  • A Bazel monorepo with Go, Kotlin, and Python
  • Automatic BUILD file generation
  • Shared libraries across languages

Prerequisites

Project Structure

We’ll create this structure:

  • Directorymy-monorepo/
    • MODULE.bazel
    • BUILD.bazel
    • Directoryservices/
      • Directoryapi/ (Go service)
        • main.go
      • Directoryauth/ (Kotlin service)
        • Directorysrc/main/kotlin/
          • Auth.kt
    • Directorylibs/
      • Directoryutils/ (Go library)
        • utils.go
      • Directoryml/ (Python library)
        • model.py
    • Directoryproto/
      • api.proto

Step-by-Step Setup

  1. Create the project directory

    Terminal window
    mkdir my-monorepo && cd my-monorepo
  2. Initialize with Bazelle

    Terminal window
    bazelle init --name my-monorepo

    This creates MODULE.bazel and BUILD.bazel with detected languages.

  3. Enable additional languages

    Edit the root BUILD.bazel:

    BUILD.bazel
    # gazelle:prefix github.com/myorg/my-monorepo
    # gazelle:kotlin_enabled true
    # gazelle:python_enabled true
  4. Create the Go service

    Terminal window
    mkdir -p services/api
    services/api/main.go
    package main
    import (
    "fmt"
    "github.com/myorg/my-monorepo/libs/utils"
    )
    func main() {
    fmt.Println(utils.Hello("API"))
    }
  5. Create the Go library

    Terminal window
    mkdir -p libs/utils
    libs/utils/utils.go
    package utils
    func Hello(name string) string {
    return "Hello from " + name
    }
  6. Create the Kotlin service

    Terminal window
    mkdir -p services/auth/src/main/kotlin/com/myorg/auth
    services/auth/src/main/kotlin/com/myorg/auth/Auth.kt
    package com.myorg.auth
    class AuthService {
    fun authenticate(token: String): Boolean {
    return token.isNotEmpty()
    }
    }
  7. Create the Python library

    Terminal window
    mkdir -p libs/ml
    libs/ml/model.py
    def predict(data: list) -> float:
    """Simple prediction function."""
    return sum(data) / len(data) if data else 0.0
  8. Generate all BUILD files

    Terminal window
    bazelle update

    Bazelle will generate BUILD files for all directories:

    Updating BUILD files...
    ✓ services/api/BUILD.bazel (go_binary)
    ✓ services/auth/BUILD.bazel (kt_jvm_library)
    ✓ libs/utils/BUILD.bazel (go_library)
    ✓ libs/ml/BUILD.bazel (py_library)
  9. Build and test

    Terminal window
    # Build everything
    bazel build //...
    # Run the Go service
    bazel run //services/api
    # Test everything
    bazel test //...

Generated BUILD Files

Here’s what Bazelle generates:

services/api/BUILD.bazel
load("@rules_go//go:def.bzl", "go_binary")
go_binary(
name = "api",
srcs = ["main.go"],
deps = ["//libs/utils"],
visibility = ["//visibility:public"],
)

Development Workflow

Watch Mode

During development, use watch mode to auto-update BUILD files:

Terminal window
bazelle watch

Now when you add or modify source files, BUILD files update automatically.

Adding Dependencies

When you add a new import:

  1. Add the import to your source file
  2. Run bazelle update (or let watch mode handle it)
  3. Bazelle detects the dependency and adds it to deps

Keeping BUILD Files in Sync

Before committing, verify BUILD files are up to date:

Terminal window
bazelle update --check

Add this to your pre-commit hook or CI pipeline.

Next Steps