In this article, we’ll walk through setting up your own Bazel repository using bzlmod, the new external dependency system introduced in Bazel 5 and later. We’ll also add a small Go “Hello, World!” project to demonstrate how to include additional projects in a monorepo.
Getting Started
Create a new directory for your Bazel project. For this example, we’ll call it
bazel-intro
.Inside the
bazel-intro
directory, create two files:MODULE.bazel
andBUILD
.
Directory structure so far:
bazel-intro
│
├─ MODULE.bazel
├─ BUILD
About the MODULE.bazel File
According to the official Bazel docs on bzlmod, the MODULE.bazel
file should be at the root of your workspace (where the WORKSPACE
file would normally be). Unlike WORKSPACE
, you do not list all transitive dependencies here—only direct dependencies. Bazel will automatically process the MODULE.bazel
files of your dependencies to find any transitive dependencies. In this example, we don’t need a WORKSPACE
file.
Editing MODULE.bazel for Go Support
Since we’re going to use Go, we need to specify the necessary Bazel dependencies for Go:
bazel_dep(name = "gazelle", version = "0.37.0")
bazel_dep(name = "rules_go", version = "0.48.1")
- gazelle: A build file generator that automatically creates or updates BUILD files for Go projects.
- rules_go: Provides rules to build Go code with Bazel.
You can find more recent versions of these dependencies on the Bazel Registry.
Adding Go Extensions
According to the rules_go and gazelle docs, add the following lines to MODULE.bazel to set up the Go SDK:
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
# Download a suitable Go SDK.
go_sdk.download(version = "1.20.3")
Adding Gazelle Integration and Dependencies
Next, integrate Gazelle:
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//:go.mod")
use_repo(go_deps,
"com_github_gofiber_fiber_v2",
)
Here’s what we did:
- go_deps.from_file(go_mod = "//:go.mod"): Points Gazelle to our Go module file.
- use_repo(go_deps, "com_github_gofiber_fiber_v2"): Registers a Go dependency (github.com/gofiber/fiber/v2) that we’ll use in our example HTTP server.
Note: If you need more dependencies, you can simply list them inside use_repo:
use_repo(go_deps,
"com_github_gofiber_fiber_v2",
"com_github_joho_godotenv"
)
Updating the BUILD File
Now let’s populate the top-level BUILD file to integrate Gazelle:
load("@gazelle//:def.bzl", "gazelle")
gazelle(name = "gazelle")
This sets up Gazelle at the root of our workspace.
Creating a Sample Go Project
Next, we’ll create a simple Go project within our repository to test everything.
Updated directory structure:
bazel-intro
│
├─ MODULE.bazel
├─ BUILD
└─ services
└─ app
└─ main.go
Steps:
- Inside bazel-intro, create a services directory.
- Inside services, create an app directory.
- In the app directory, create a main.go file with the following code:
package main
import (
"log"
"github.com/gofiber/fiber/v2"
)
func main() {
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
log.Fatal(app.Listen(":3000"))
}
Initializing Go Modules
In your terminal, navigate to bazel-intro and initialize a Go module:
go mod init bazel-intro/services
go mod tidy
This creates a go.mod and a go.sum file in the root. Gazelle will use these to understand and update dependencies.
Running Gazelle and Building the Project
- Run Gazelle to generate BUILD files for Go code:
bazel run //:gazelle
- Build all targets:
bazel build //...
- Run the application:
bazel run services/app
If everything goes correctly, you should see the Fiber HTTP server running on port 3000. Open your browser and navigate to http://localhost:3000 to see the “Hello, World!” message.
Conclusion
You’ve successfully set up a Bazel repository using bzlmod, integrated Go support, and created a small service using Fiber. From here, you can add more services, dependencies, and tooling to expand your monorepo.
Happy coding! 🎉
Top comments (0)