GALA provides a dependency management system similar to Go modules, using gala.mod and gala.sum files to track dependencies and their checksums. The key difference from Go is that GALA projects only need gala.mod - no go.mod is required in your project folder.
Initialize and build a GALA project:
# Create a new project
mkdir myproject && cd myproject
# Initialize gala.mod
gala mod init github.com/user/myproject
# Add dependencies
gala mod add github.com/example/gala-utils@v1.2.3
gala mod add github.com/google/uuid@v1.6.0 --go
# Create your GALA source file
cat > main.gala <<'EOF'
package main
import "github.com/google/uuid"
func main() {
Println("Hello from GALA!")
Println(s"UUID: ${uuid.New().String()}")
}
EOF
# Build and run
gala build
./myproject
Your project structure (no go.mod needed!):
myproject/
gala.mod # Module manifest
gala.sum # Dependency checksums
main.gala # Your GALA code
myproject.exe # Built binary (after gala build)
For Bazel projects, gala mod tidy generates the necessary go.mod and go.sum files:
# Initialize
gala mod init github.com/user/myproject
# Add dependencies
gala mod add github.com/example/gala-utils@v1.2.3
gala mod add github.com/google/uuid@v1.6.0 --go
# Sync dependencies (generates go.mod and go.sum for Bazel)
gala mod tidy
# Build with Bazel
bazel build //:myapp
The gala.mod file declares your module’s path, GALA version, and dependencies.
module github.com/user/myproject
gala 1.0
require (
github.com/example/utils v1.2.3
github.com/example/math v2.0.0
github.com/google/uuid v1.6.0 // go
)
require (
github.com/example/indirect v1.0.0 // indirect
)
replace github.com/example/utils => ../local-utils
exclude github.com/example/deprecated v0.9.0
| Directive | Description |
|---|---|
module |
Declares the module path |
gala |
Minimum GALA version required |
require |
Declares a dependency |
replace |
Substitutes a module with another (local or remote) |
exclude |
Prevents a specific version from being used |
| Comment | Meaning |
|---|---|
// indirect |
Transitive dependency (not directly imported) |
// go |
Go package (not GALA) - will not be transpiled |
The gala.sum file contains cryptographic checksums for each dependency to ensure integrity.
github.com/example/utils v1.2.3 h1:abc123def456...
github.com/example/utils v1.2.3/gala.mod h1:xyz789...
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
Each line contains:
/gala.mod)h2: covers every regular file of the module except VCS metadata (.git and the like), byte for byte, so data files a build embeds are verified too; symbolic links are not part of a module and are not fetched. A fetch records the files it stored, and the hash covers exactly those: a build never writes into the module cache, and a source file added to a cached module afterwards fails gala mod verify. h1: is the earlier module scheme and covers only .gala/.go sources, gala.mod, go.sum and BUILD.bazel; existing h1: module lines still verify, and gala mod tidy rewrites them as h2:. /gala.mod lines hash that one file and keep the h1: prefix.Compatibility: gala versions before
h2:reject agala.sumthat contains anh2:line (“invalid hash format”). Theirgala mod verifyfails, and theirgala mod add/gala mod updaterewritegala.sumfrom scratch, dropping every other entry. Everyone working on a project, and its CI, should use a gala that understandsh2:beforegala mod tidyrewrites itsgala.sum.gala builddoes not readgala.sumand is unaffected. Current gala accepts anyh<N>:scheme when readinggala.sum, and stops instead of rewriting agala.sumit cannot parse.
Build a GALA project to a binary.
# Build with default output name (project directory name)
gala build
# Build with custom output name (no .exe added)
gala build -o myapp
# Cross-compile: GOOS/GOARCH pass through to go build
GOOS=linux GOARCH=arm64 gala build -o myapp-linux-arm64
# Build with verbose output
gala build -v
What happens:
.gala files to Go in a workspace at ~/.gala/build/<hash>/~/.gala/go/pkg/mod/go build to produce the binary in your project directoryOutput name: as with go build, a -o name never gets an extension added. The default name gets .exe only when the target OS (GOOS, or the host when unset) is Windows.
Auto-fetch: gala build automatically downloads GALA dependencies listed in gala.mod that are not yet cached locally. No manual gala mod download step is needed.
Build and run a GALA project.
# Build and run
gala run
# Pass arguments to the program
gala run -- arg1 arg2
# Verbose mode
gala run -v
Clean build artifacts.
# Clean the workspace for this project
gala clean
# Clean all GALA caches
gala clean --all
# Clean stale workspaces (projects that no longer exist)
gala clean --stale
Write a GALA project as a plain Go module, so a Go program can import it with go get and build it with plain go build, without GALA.
# Export the project in the current directory
gala export --out ../mylib-go
# Under another module path (default: the project's module path)
gala export --out ../mylib-go --go-module github.com/me/mylib-go
# With a dev build: pin the standard library version, and also write a local module proxy
gala export --out ../mylib-go --stdlib-version v0.0.0-local.1 \
--proxy ../goproxy --version v0.1.0
What happens:
gala build does for a librarygala.mod or Bazel files) to --out, with imports of GALA’s standard library rewritten to the published Go module go.gala.fyi/stdlibgo.mod that requires go.gala.fyi/stdlib at this gala’s version, plus every Go module the code needs, as go mod tidy resolves them for the build, including modules a hand-written .go file reaches only through another dependency. Its go directive is the newer of the one generated code needs and the project’s own go.mod’sRun it in the project root: it always exports the whole project. --out must be empty, and outside the project and any Bazel workspace. --go-module must be a path the go command can download (its first element is a domain). A main package is exported with a warning, since Go code cannot import it. Not supported yet: packages that import another GALA module, and a gala.mod that replaces a Go module (a published module’s replace directives do not apply to the programs that import it). Publishing the export and using it from Go: Using GALA from a plain Go module.
A Go module that commits the output of a few .gala files, rather than exporting a whole project, uses gala transpile --stdlib-module go.gala.fyi/stdlib instead: it writes the same standard library imports for each generated file. See Committing transpiled files to a plain Go module.
Write GALA’s standard library, as embedded in this gala binary, as one plain Go module. GALA releases publish it as go.gala.fyi/stdlib; use this command to try a build before it is released.
gala stdlib export --go-module go.gala.fyi/stdlib --out ../stdlib-go \
--proxy ../goproxy --version v0.0.0-local.1
--proxy also writes the module, as version --version, in the layout GOPROXY=file://<dir> serves.
Initialize a new gala.mod file.
# Auto-detect module path from go.mod or directory name
gala mod init
# Explicit module path
gala mod init github.com/user/project
Creates:
gala.mod with module declarationgala.sum fileAdd a dependency to your module.
# Add latest version
gala mod add github.com/example/utils
# Add specific version
gala mod add github.com/example/utils@v1.2.3
# Add compatible version (caret constraint)
gala mod add github.com/example/utils@^1.0.0
# Add Go dependency (not GALA)
gala mod add github.com/google/uuid@v1.6.0 --go
The command will:
gala.mod with the dependencygala.sum with checksumsRemove a dependency from your module.
gala mod remove github.com/example/utils
Update dependencies to their latest versions.
# Update all dependencies
gala mod update
# Update specific dependency
gala mod update github.com/example/utils
# Update to specific version
gala mod update github.com/example/utils@v2.0.0
Synchronize gala.mod with your source code imports.
gala mod tidy
This command:
go.mod and go.sum with Go dependenciesgala mod tidy handles both single-line and multi-line import blocks, and recognizes known GALA dependencies (like std, collection_immutable, etc.) automatically.
Print the dependency tree.
gala mod graph
Output:
github.com/user/myproject
├── github.com/example/utils@v1.2.3
│ └── github.com/example/common@v1.0.0
└── github.com/example/math@v2.0.0
Verify that dependencies match their checksums in gala.sum.
gala mod verify
GALA supports two build modes: standalone (without Bazel) and Bazel-based.
When you run gala build, GALA:
~/.gala/build/<hash>/ (hash is derived from your project path)~/.gala/stdlib/v<version>/gala.mod (not marked // go) is transpiled from .gala source in the module cache to .gen.go files in ~/.gala/build/<hash>/deps/.gala files to .gen.go files in ~/.gala/build/<hash>/gen/ (gala test writes an x_test.gala to x_test.gen_test.go, which Go compiles only into that package’s tests)go.mod in the workspace with absolute paths to dependencies~/.gala/go/pkg/mod/go build to create the binaryKey benefits:
.go files needed in the module cacheFor Bazel projects:
gala mod tidy to generate go.mod and go.sum (Go dependencies only)bazel build //:targetAll GALA caches are stored in ~/.gala/:
~/.gala/
build/ # Build workspaces (per-project)
<hash>/ # Workspace for a specific project
gen/ # Transpiled .gen.go files from your project
deps/ # Transpiled GALA library dependencies
github.com/user/lib@v1.0.0/ # Each dep gets its own directory
math.gen.go # Transpiled Go output
go.mod # Generated go.mod for the dep
go.mod # Generated go.mod with absolute paths
go.sum # Generated go.sum
stdlib/ # Stdlib versions
vdev/ # Development version
std/ # Standard library packages
go_interop/
collection_immutable/
collection_mutable/
concurrent/
pkg/mod/ # GALA package cache (source)
github.com/example/utils@v1.2.3/ # Cached GALA modules (.gala source)
go/pkg/mod/ # Go package cache (GOMODCACHE)
github.com/google/uuid@v1.6.0/ # Cached Go modules
| Directory | Purpose |
|---|---|
build/<hash>/gen/ |
Transpiled .gen.go files from your project |
build/<hash>/deps/ |
Transpiled GALA library dependencies |
stdlib/v<version>/ |
GALA standard library |
pkg/mod/ |
GALA module cache: each module’s full tree minus VCS metadata. GALA_CACHE moves it; gala build and the gala mod commands both use that location |
go/pkg/mod/ |
Go module cache |
GALA can depend on Go packages. Mark Go dependencies with // go or use the --go flag:
gala mod add github.com/google/uuid@v1.6.0 --go
In gala.mod:
require (
github.com/google/uuid v1.6.0 // go
)
How it works:
gala.mod but not transpiledgala build and gala test read each Go dependency’s source for its types before transpiling, downloading it first if it is not cached, and go mod tidy fetches it for the Go compile. A GALA library’s own Go dependencies are read the same way when it is built as a dependency, so they need not be repeated in your gala.modgo_deps extension fetches themUsage in GALA code:
package main
import "github.com/google/uuid"
func GenerateID() string = uuid.New().String()
GALA projects can depend on other GALA libraries — packages written in GALA and published as .gala source files.
When you add a GALA dependency (without the --go flag), the module is fetched to the GALA module cache (~/.gala/pkg/mod/ by default; GALA_HOME or GALA_CACHE move it). At build time, gala build automatically transpiles these dependencies to Go before compiling:
gala.mod for GALA dependencies (entries without // go).gala files, the transpiler pipeline runs (parse -> analyze -> transform -> generate).gen.go files and a go.mod are written to ~/.gala/build/<hash>/deps/<module>@<version>/go.mod uses replace directives pointing to the transpiled outputGALA library packages with multiple .gala files are fully supported. The transpiler uses NewGalaAnalyzerWithPackageFiles to enable cross-file type resolution within the dependency.
Dependencies of dependencies are handled automatically:
your-project
├── github.com/user/lib-a@v1.0.0 (GALA — transpiled)
│ └── github.com/user/lib-b@v2.0.0 (GALA — transpiled)
│ └── github.com/google/uuid (Go — downloaded by go mod tidy)
└── github.com/other/lib@v1.0.0 (Go — downloaded by go mod tidy)
go.mod files are generated with correct replace directivesgo.modgala.mod (no .gala files in cache) are skipped — they don’t need transpilation# Add a GALA library dependency
gala mod add github.com/martianoff/gala_demo_pkg@v0.2.3
# Build — the dep is transpiled automatically
gala build -v
Verbose output:
Found 1 GALA dependencies to transpile
Transpiling dependency: github.com/martianoff/gala_demo_pkg@v0.2.3 (2 files)
math.gala -> math.gen.go
utils.gala -> utils.gen.go
Transpiling GALA files...
main.gala -> main.gen.go
GALA provides Bazel rules for dependency management. Dependencies are declared in gala.mod and automatically loaded into Bazel.
.bazelrcThe Bazel rules (rules_gala) and the language module (gala) are both served from a custom Bazel module registry hosted in the rules-gala repo. Point your .bazelrc at it:
common --enable_bzlmod
common --noenable_workspace
build --enable_runfiles
# The custom registry must be listed first so it wins for `rules_gala`
# and `gala`. BCR is the fallback for every other module.
common --registry=https://raw.githubusercontent.com/martianoff/rules-gala/main/
common --registry=https://bcr.bazel.build
# Pass GOROOT and PATH through so the transpiler can use go/importer
# for cross-language Go type inference (function signatures, struct
# fields, method sets).
build --action_env=GOROOT
build --action_env=PATH
module(
name = "myproject",
version = "0.0.1",
)
# GALA Bazel rules + language module.
bazel_dep(name = "rules_gala", version = "0.3.2")
bazel_dep(name = "gala", version = "0.84.1")
# Register the GALA toolchains shipped by the gala language module.
# The main toolchain backs gala_library / gala_binary / gala_test; the
# bootstrap toolchain backs gala_bootstrap_transpile (stdlib only).
register_toolchains(
"@gala//tools/toolchain:gala_toolchain",
"@gala//tools/toolchain:gala_bootstrap_toolchain",
)
# Go rules (required for Go dependencies).
bazel_dep(name = "rules_go", version = "0.59.0")
bazel_dep(name = "gazelle", version = "0.47.0")
# Go dependencies (auto-generated by 'gala mod tidy').
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//:go.mod")
use_repo(go_deps, "com_github_google_uuid")
# GALA dependencies (only if gala.mod lists external GALA modules).
gala = use_extension("@rules_gala//gala:extensions.bzl", "gala")
gala.from_file(gala_mod = "//:gala.mod")
use_repo(gala, "com_github_example_utils")
Important: Run gala mod tidy to generate go.mod and go.sum files that Bazel needs for Go dependencies.
Reference dependencies in the standard deps attribute:
load("@rules_gala//gala:defs.bzl", "gala_library", "gala_binary")
gala_library(
name = "mylib",
src = "mylib.gala",
importpath = "github.com/user/project/mylib",
deps = ["@com_github_example_utils//:utils"],
)
gala_binary(
name = "myapp",
src = "main.gala",
deps = ["@com_github_example_utils//:utils"],
)
Module paths are converted to Bazel repository names:
| Module Path | Repository Name |
|---|---|
github.com/example/utils |
@com_github_example_utils |
gitlab.com/user/lib |
@com_gitlab_user_lib |
GALA supports several version constraint syntaxes:
| Syntax | Meaning | Example |
|---|---|---|
v1.2.3 |
Exact version | Exactly v1.2.3 |
^1.2.3 |
Compatible | >=1.2.3, <2.0.0 |
~1.2.3 |
Approximate | >=1.2.3, <1.3.0 |
>=1.2.3 |
Minimum | At least v1.2.3 |
latest |
Latest stable | Most recent tagged version |
Minimal Version Selection (MVS):
Like Go modules, GALA uses MVS for dependency resolution:
gala.mod and gala.sum to version controlgala mod verify to your CI pipelinegala mod tidy after changing imports// go for claritygo.mod and go.sum (they’re auto-generated but needed by Bazel)For complete working examples of GALA dependency management, see:
gala build| See also: Language Reference | Why GALA? | Code Examples |