Bazel expert
Skill kinhluan/rules-quarkus-skills/.agent-skills/bazel-expert
π€ Complete AI expert ecosystem for Modern Java, Quarkus & Bazel development βοΈβ‘οΈ Coverage for Vert.x, GraalVM, Maven/Gradle migration, and more π
npx -y skills add kinhluan/rules-quarkus-skills --skill bazel-expertAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Expert knowledge for writing idiomatic Bazel rules, Starlark best practices, and build performance optimization. Use for Bazel build system questions.
SKILL.md
9.4 KB, as published. Nobody here has run it
bazel-expert
Keyword: bazel | Platforms: gemini,claude,codex
General Bazel & Starlark Expert Skill - Expert guidance on writing idiomatic Bazel rules and optimizing build performance.
Architectural Mandates
- Hermeticity: Actions must only depend on declared inputs
- Granularity: Break large targets into smaller
java_libraryorstarlarkrules - Bzlmod: Always use Bzlmod for external dependency management
- Visibility: Default
visibility = ["//visibility:private"], explicitly widen only as needed
rules_java & Java Toolchains
Toolchain Setup (Bzlmod)
# MODULE.bazel
bazel_dep(name = "rules_java", version = "7.12.4")
java_toolchains = use_extension("@rules_java//java:extensions.bzl", "toolchains")
java_toolchains.toolchain(version = "21")
use_repo(java_toolchains, "remotejdk21_linux")
register_toolchains("@remotejdk21_linux//:jdk")
BUILD.bazel Examples
# Library target with proper granularity
java_library(
name = "user-service",
srcs = glob(["src/main/java/**/*.java"]),
resources = glob(["src/main/resources/**"]),
deps = [
"//common/utils:json-utils",
"@maven//:com_google_guava_guava",
"@maven//:jakarta_inject_jakarta_inject_api",
],
visibility = ["//services:__subpackages__"],
)
# Test target with testonly deps
java_test(
name = "user-service-test",
srcs = glob(["src/test/java/**/*.java"]),
test_class = "com.example.UserServiceTest",
deps = [
":user-service",
"@maven//:org_junit_jupiter_junit_jupiter",
"@maven//:org_assertj_assertj_core",
"@maven//:org_mockito_mockito_core",
],
)
Do vs Don't
# BAD - monolithic target, slow incremental builds
java_library(
name = "everything",
srcs = glob(["src/**/*.java"]),
deps = ["@maven//:all-the-things"],
visibility = ["//visibility:public"],
)
# GOOD - granular targets, fast incremental builds
java_library(
name = "user-model",
srcs = ["src/main/java/com/example/User.java"],
deps = ["@maven//:jakarta_validation_jakarta_validation_api"],
)
java_library(
name = "user-repository",
srcs = ["src/main/java/com/example/UserRepository.java"],
deps = [":user-model", "@maven//:io_quarkus_quarkus_hibernate_orm_panache"],
)
rules_jvm_external (Maven Dependencies)
Setup with Bzlmod
# MODULE.bazel
bazel_dep(name = "rules_jvm_external", version = "6.6")
maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
maven.install(
name = "maven",
artifacts = [
"io.quarkus:quarkus-arc:3.20.1",
"io.quarkus:quarkus-rest:3.20.1",
"com.google.guava:guava:33.4.0-jre",
],
fetch_sources = True,
lock_file = "//:maven_install.json",
)
use_repo(maven, "maven")
BOM Import
maven.install(
name = "maven",
bom_imports = [
"io.quarkus.platform:quarkus-bom:3.20.1",
],
artifacts = [
# Versions managed by BOM - no version needed
"io.quarkus:quarkus-arc",
"io.quarkus:quarkus-rest",
"io.quarkus:quarkus-hibernate-orm-panache",
],
lock_file = "//:maven_install.json",
)
Re-pinning Dependencies
# After adding/updating artifacts in MODULE.bazel:
RULES_JVM_EXTERNAL_REPIN=1 bazelisk run @maven//:pin
Starlark Best Practices
- Avoid Macros for Logic: Use
rulesfor complex logic,macrosfor wrapping - Provider Pattern: Use custom
Providersto pass complex information between rules - Depsets: Always use
depsetsinstead oflistsfor transitive dependencies
Custom Provider Example
QuarkusExtensionInfo = provider(
doc = "Information about a Quarkus extension",
fields = {
"runtime_jars": "depset of runtime JAR Files",
"deployment_jars": "depset of deployment JAR Files",
},
)
def _quarkus_extension_impl(ctx):
runtime = depset(
direct = [ctx.file.runtime_jar],
transitive = [dep[QuarkusExtensionInfo].runtime_jars for dep in ctx.attr.deps],
)
return [QuarkusExtensionInfo(runtime_jars = runtime, deployment_jars = ...)]
Depset Do vs Don't
# BAD - O(NΒ²) when collecting transitive deps
all_jars = []
for dep in ctx.attr.deps:
all_jars += dep[JavaInfo].transitive_runtime_jars.to_list()
# GOOD - O(1) depset merging, lazy evaluation
all_jars = depset(transitive = [
dep[JavaInfo].transitive_runtime_jars for dep in ctx.attr.deps
])
Performance Optimization
- Param Files: Use
ctx.actions.args().use_param_file("@%s")for long command lines - Remote Execution: Ensure rules are compatible with remote execution
- Action Mnemonics: Use descriptive
mnemonicandprogress_messagefor debugging
Build Performance Decision Tree
| Symptom | Diagnosis | Fix |
|---|---|---|
| Full rebuild on small change | Target too coarse | Split into smaller java_library targets |
| Slow first build, fast incremental | Expected behavior | Enable remote cache: --remote_cache=grpc://... |
| Slow even with cache | Cache misses | Run --execution_log_json_file=log.json, check non-hermetic inputs |
| "Argument list too long" | Too many classpath entries | Use ctx.actions.args().use_param_file("@%s") |
| OOM during analysis | Too many targets | Use --host_jvm_args=-Xmx8g, reduce glob() scope |
| Flaky test results | Non-hermetic test | Add tags = ["no-sandbox"] to debug, then fix inputs |
Remote Cache & Execution
# .bazelrc - remote cache setup
build --remote_cache=grpc://cache.example.com:9092
build --remote_upload_local_results=true
build --remote_timeout=60
# Remote execution (requires RBE)
build:remote --remote_executor=grpc://rbe.example.com:8980
build:remote --jobs=200
build:remote --spawn_strategy=remote
Troubleshooting
"no matching toolchains found for //target"
# Diagnosis: Java toolchain not registered
bazel query @rules_java//toolchains:all
# Fix: Register in MODULE.bazel
register_toolchains("@remotejdk21_linux//:jdk")
"dependency not found" after adding to maven.install
# Cause: lock file out of date
RULES_JVM_EXTERNAL_REPIN=1 bazelisk run @maven//:pin
# Verify target name (underscores replace dots/hyphens/colons):
# io.quarkus:quarkus-arc β @maven//:io_quarkus_quarkus_arc
bazel query @maven//:all | grep quarkus
Circular dependency between targets
# BAD - A depends on B, B depends on A
java_library(name = "A", deps = [":B"])
java_library(name = "B", deps = [":A"])
# FIX - Extract shared code into a third target
java_library(name = "shared", srcs = ["Shared.java"])
java_library(name = "A", deps = [":shared"])
java_library(name = "B", deps = [":shared"])
Remote cache not being hit
# Debug: compare action keys
bazel build //target --execution_log_json_file=exec1.json
# Change something, rebuild
bazel build //target --execution_log_json_file=exec2.json
# Diff to find non-hermetic inputs
diff <(jq '.actionKey' exec1.json) <(jq '.actionKey' exec2.json)
Build is hermetic locally but fails on CI
Common causes:
- Absolute paths leaking β use
ctx.actions.args()withmap_eachto relativize - Timestamp in outputs β ensure tools produce deterministic output
- Different host platform β specify
--platforms=//platforms:linux_x86_64 - Missing
dataattribute β runtime files must be declared indata, notsrcs
Decision Trees
When to use macro vs rule
Need custom providers or actions?
YES β Write a rule
NO β Does it wrap existing rules with defaults?
YES β Write a macro
NO β Does it need to inspect file contents or run tools?
YES β Write a rule
NO β Macro is fine
When to use genrule vs custom rule
Is the action a single shell command?
YES β genrule (but avoid for Java - use java_binary + rule)
NO β Custom rule
Does it need to integrate with Java toolchain?
YES β Custom rule (access ctx.toolchains)
NO β genrule may suffice
π Bazel Knowledge Sources
Directive: Use
web_fetchto find the latest macro signatures or Bzlmod extensions if a build fails with toolchain or dependency errors.
- Bzlmod Migration: Bazel External Dependencies Guide - Managing the new MODULE.bazel system.
- Starlark Rule Writing: Rules (Bazel) - Providers, Actions, and toolchains.
- Build Performance: Optimizing Bazel Builds - Profiling and caching.
- Remote Execution: Remote Execution Overview - Scaling builds.
References
- Official Bazel Documentation
- rules_java GitHub Repository
- rules_jvm_external Documentation
- Starlark Language Specification
Skill Interoperability
The bazel-expert π skill provides the core build infrastructure for:
- rules-quarkus π§: Integrates Quarkus build and augmentation logic into the Bazel ecosystem.