What does it mean to register an artifact transform in Gradle, and what do `from` and `to` describe?
answer
- dependencies.registerTransform(Type) { }
- from = inputs, to = outputs
- attributes describe artifact shape
- declarative, lazy, cached
- variant-matching inserts the rule
basics
~10 sYou call dependencies.registerTransform(MyTransform) { ... } and declare from.attribute(...) and to.attribute(...). Gradle uses those attributes to know which artifacts the transform can convert and what it produces.
solid answer
~40 sRegistering a transform tells Gradle there is a rule that can convert an artifact from one set of attributes to another. You call `dependencies.registerTransform(MyTransformAction::class) { from.attribute(ARTIFACT_TYPE, "jar"); to.attribute(ARTIFACT_TYPE, "classes") }`. The `from` attribute container describes the artifacts the transform consumes (its inputs), and `to` describes what it produces. Gradle's variant-matching engine then knows that whenever a consumer requests the `to` attributes but only the `from` variant is available, it can insert this transform to bridge the gap. Registration is declarative — it does not run anything; it just adds the rule to the project's set of available transforms. The actual conversion happens lazily, only when a resolution actually requests the target attributes.
code
kotlin · 8 linesval artifactType = Attribute.of("artifactType", String::class.java)
dependencies {
registerTransform(Unzip::class) {
from.attribute(artifactType, "jar")
to.attribute(artifactType, "classes")
}
}go deeper
Know it's dependencies.registerTransform(Type) { from.attribute(...); to.attribute(...) } and that from = inputs, to = outputs.
Explain that from/to drive variant matching and that registration is declarative and lazy, with outputs cached.
Discuss how the matching engine can chain transforms automatically and how artifactType is implicit from file extension.
Frame transforms as a way to keep cross-cutting artifact processing out of build logic and reproducible/cacheable across a large build.
## What registration is An **artifact transform** is a rule that converts a resolved artifact (a file) from one *shape* to another. The shape is described by Gradle **attributes** — typed key/value pairs attached to variants and artifacts (e.g. `artifactType`, or custom ones like `minified`). Registration is the act of *declaring that such a rule exists*. You do it on the `dependencies` block: ```kotlin dependencies { registerTransform(Unzip::class) { from.attribute(ARTIFACT_TYPE_ATTRIBUTE, "jar") to.attribute(ARTIFACT_TYPE_ATTRIBUTE, "classes") } } ``` `registerTransform(Type) { ... }` takes the **TransformAction** class and a configuration block exposing two attribute containers: - **`from`** — the attributes of the artifacts this transform *consumes*. It is the precondition: an artifact must match these to be eligible. - **`to`** — the attributes of the artifacts this transform *produces*. It is the postcondition: after running, the output is tagged with these. ## How matching uses from/to Gradle has a single **variant-matching** engine. When you resolve a configuration and request a target attribute set, Gradle looks for a variant that already matches. If none does, it searches the registered transforms for a chain whose `from` matches an available variant and whose `to` matches what you asked for. It can even **chain** multiple transforms (A→B then B→C) automatically. The `ARTIFACT_TYPE_ATTRIBUTE` (`Attribute<String>` named `artifactType`) is the most common one because every artifact has an implicit `artifactType` derived from its file extension (`jar`, `aar`, `zip`, ...). ## Registration is declarative and lazy `registerTransform` does **not** execute the transform. It only adds the rule. The TransformAction runs **on demand**, and only when some resolution actually requests the `to` attributes — typically through an `artifactView`. Outputs are cached, so a given input/parameters pair is transformed once. ## Parameters If your transform needs configuration, the action implements `TransformAction<Parameters>` and you set `parameters { ... }` inside the registration block. Registration is where parameter *values* are bound; the action body reads them.
- Does calling registerTransform run the transform immediately?No. Registration only adds the rule. The TransformAction executes lazily, only when a resolution actually requests the `to` attributes, and the result is cached.
- What attribute is most commonly used in from/to?`artifactType` (a built-in `Attribute<String>`), because every artifact has an implicit artifactType from its file extension — jar, aar, zip, etc.
Registering a transform is like telling a kitchen 'I can turn raw beans (from) into ground coffee (to)' — the rule exists, but nobody grinds anything until an order for ground coffee comes in.
saying these in an interview costs you the question
- Saying registerTransform executes the transform immediately.
- Confusing `from`/`to` with input/output files — they are attribute sets, not paths.
- Claiming you must request transforms manually; Gradle inserts them automatically during matching.