blob: 65ac581b9e8f5ce09aa66b68e06ebf3c19229aef [file]
# protoc-gen-clojure — a protoc/buf plugin that emits Clojure.
#
# The dependency split here is deliberate and is what makes this module cheap to
# consume. Everything needed to RUN the plugin from Bazel is a normal dep;
# everything needed to BUILD it from Clojure source is a dev_dependency.
#
# A consumer uses the prebuilt native binary (see clojure/extensions.bzl), so it
# never needs rules_clj, a JVM toolchain, or GraalVM to generate one .clj file.
# That also sidesteps a hard BCR constraint: a published module's non-dev deps
# must all resolve from BCR, and rules_clj is not published there yet. As a
# dev_dependency it is ignored entirely when this module is consumed, and the
# git_override below only applies when this module is the root — exactly the
# semantics we want.
#
# 0.2.0, not 0.1.1: the public load paths moved from //bazel to //clojure, so
# every consumer's `load` and `use_extension` lines change.
#
# No compatibility_level: Bazel 9.2 reports it as a no-op slated for removal
# ("The attribute 'compatibility_level' in module() is a no-op"), so declaring it
# buys nothing but a warning. No bazel_compatibility either: the BCR presubmit
# matrix (8.x and 9.x, mirrored by CI) is the real compatibility claim.
module(
name = "protoc_gen_clojure",
version = "0.5.0",
)
bazel_dep(name = "platforms", version = "1.1.0")
bazel_dep(name = "bazel_skylib", version = "1.9.0")
# For @protobuf//:protoc, which clojure_proto_library drives, and for the
# ProtoInfo provider it reads. Bazel 9 removed ProtoInfo from the Starlark
# globals, so it has to come from the module.
bazel_dep(name = "protobuf", version = "35.1")
# --- build-only, from here down --------------------------------------------
# Stardoc, for the generated API reference in //docs. bazel.build/rules/deploying
# asks for exactly this: rules documented with docstrings, rendered automatically,
# and the Markdown kept in the repo so it cannot drift. The drift guard is
# //docs:update_docs_*_test, wired the same way as the golden files in //test.
bazel_dep(name = "stardoc", version = "0.8.1", dev_dependency = True)
bazel_dep(name = "rules_java", version = "9.7.1", dev_dependency = True)
bazel_dep(name = "rules_jvm_external", version = "7.1", dev_dependency = True)
bazel_dep(name = "rules_shell", version = "0.8.0", dev_dependency = True)
# Builds the module source archive that BCR serves (//bazel/dev:module_archive). pkg_tar
# rather than `tar -czf`: deterministic bytes, and immune to BSD-vs-GNU tar
# differences between a local run and CI.
bazel_dep(name = "rules_pkg", version = "1.3.0", dev_dependency = True)
# The container image for BSR remote plugin execution (//bazel/dev:image).
# rules_img rather than a Dockerfile: hermetic, no Docker daemon, and it consumes
# the native binary straight from the build graph.
#
# dev_dependency, together with the pull below — a consumer never builds images,
# and a non-dev repo rule referencing a dev-only module would make @rules_img
# invisible to them and break module resolution outright.
bazel_dep(name = "rules_img", version = "0.3.19", dev_dependency = True)
pull = use_repo_rule("@rules_img//img:pull.bzl", "pull")
# base-debian12, not static-debian12: GraalVM's Linux output is dynamically linked,
# so the image needs glibc. `static` has none, which is what made the old
# `FROM scratch` Dockerfile unable to start the plugin at all.
#
# Pinned by digest because a tag is mutable; `latest` here only records where the
# digest came from.
pull(
name = "distroless_base",
dev_dependency = True,
digest = "sha256:62730825d3cf03571e0a1b8f014748de94d0404500f063593b614c23da38841d",
registry = "gcr.io",
repository = "distroless/base-debian12",
tag = "latest",
)
# write_source_files: the golden-file pattern as a rule. Replaces a hand-rolled
# pair of scripts that did the same diff-and-update dance, including my own
# guards against a vacuously passing comparison.
bazel_dep(name = "aspect_bazel_lib", version = "2.22.5", dev_dependency = True)
# Hermetic buf for the distribution test, so CI needs no buf-setup-action and the
# version cannot drift from what we claim to support. Pinned for the same reason
# clj-grpc pins it: buf older than ~1.60 rejects edition 2024 outright with
# 'edition value "2024" not recognized'.
bazel_dep(name = "rules_buf", version = "0.5.4", dev_dependency = True)
# Lint, wired as ordinary Bazel tests (see bazel/lint/linters.bzl), so CI needs no
# separate lint job and `bazel test //...` covers protos and shell.
bazel_dep(name = "aspect_rules_lint", version = "2.7.2", dev_dependency = True)
# buildifier, for Starlark. Reachable through the FORMAT path (//bazel/dev:format,
# //bazel/dev:format_test) but not through a lint_test: the lint aspect looks for the
# binary in runfiles, where the buildifier_prebuilt extension's repos are not
# visible. Wiring buildifier into format only is the usual way around it.
bazel_dep(name = "buildifier_prebuilt", version = "8.5.1.3", dev_dependency = True)
buf = use_extension("@rules_buf//buf:extensions.bzl", "buf", dev_dependency = True)
buf.toolchains(version = "v1.72.0")
use_repo(buf, "rules_buf_toolchains")
# GraalVM comes from rules_clj, which fetches a pinned SDK and registers it as a
# toolchain of its own — separate from the Java toolchain, so a build that makes no
# native binary downloads nothing.
#
# This replaces a rules_graalvm dependency that had to be git_override'd because its
# newest BCR release does not load on Bazel 9, plus a local native_image rule that
# existed because rules_graalvm's own rule routes through apple_support and crashes
# Bazel on macOS with "Multiple entries with same key: SDKROOT". Both problems are
# now rules_clj's, solved once, in one place.
native_toolchains = use_extension(
"@rules_clj//clojure:extensions.bzl",
"native_toolchains",
dev_dependency = True,
)
native_toolchains.graalvm(version = "21.0.2")
use_repo(native_toolchains, "graalvm")
register_toolchains(
"@graalvm//:toolchain",
dev_dependency = True,
)
# rules_clj: the Clojure ruleset this project builds with. Still a dev_dependency —
# a consumer gets the prebuilt native binary and needs no Clojure at all — and still
# overridden, because rules_clj is not in the BCR yet.
#
# DELETE THE OVERRIDE once it is accepted there. That is the whole point of the
# version being pinned below: the day the registry has 0.1.0, removing these four
# lines is the entire change.
bazel_dep(name = "rules_clj", version = "0.1.0", dev_dependency = True)
git_override(
module_name = "rules_clj",
branch = "main",
remote = "https://github.com/bpalermo/rules_clj.git",
)
maven = use_extension(
"@rules_jvm_external//:extensions.bzl",
"maven",
dev_dependency = True,
)
maven.install(
name = "maven",
artifacts = [
"org.clojure:clojure:1.12.0",
# The plugin's entire runtime surface: parse a CodeGeneratorRequest,
# probe editions, write a CodeGeneratorResponse. Edition 2024 gencode
# needs the 4.x runtime.
"com.google.protobuf:protobuf-java:4.35.1",
],
known_contributing_modules = ["protobuf"],
)
# clojure -> spec.alpha -> clojure is a real cycle in the Maven metadata and
# Bazel's analysis phase rejects it. Cutting the back-edge resolves it; clojure
# itself is pinned above, so nothing leaves the classpath.
maven.artifact(
name = "maven",
artifact = "spec.alpha",
exclusions = ["org.clojure:clojure"],
group = "org.clojure",
version = "0.5.238",
)
maven.artifact(
name = "maven",
artifact = "core.specs.alpha",
exclusions = ["org.clojure:clojure"],
group = "org.clojure",
version = "0.4.74",
)
use_repo(maven, "maven")