Skip to content

Conversation

@minkuan88
Copy link
Contributor

@minkuan88 minkuan88 commented Jan 6, 2026

Summary

Add KSP (Kotlin Symbol Processing) support to Grazel.

What's New

  • Auto-detect processor classes from JAR metadata
  • Generate kt_ksp_plugin rules in root BUILD.bazel
  • Emit plugins attribute on android_library, android_binary, and kotlin_library targets
  • Separate ksp_maven repository for processor dependencies
  • Configuration cache compatible

Test Plan

  • Added Moshi KSP testing to sample-android, sample-android-library, and sample-kotlin-library

@minkuan88 minkuan88 force-pushed the ksp-support-modules branch from df25ba1 to 2797a31 Compare January 8, 2026 18:20
@minkuan88 minkuan88 changed the title Add complete KSP plugin support with auto-detection and configuration Add KSP Plugin Support Jan 8, 2026
- Add KspExtension DSL with nested compiler and processor configuration
- Support version catalog references for processor configuration
- Auto-detect processor_class from JAR's META-INF/services file
- Configure generates_java and target_embedded_compiler per processor
- Generate kt_ksp_plugin rules in root BUILD.bazel with all attributes
- Add KspProcessorClassExtractor for reading processor classes from JARs
- Fix Groovy closure delegation for nested DSL blocks
- Add kspConfiguration support to Variant interface for extracting KSP deps
- Emit plugins attribute on android_library/android_binary targets
- Add KSP scope to ResolveDependenciesResult for separate dependency tracking
- Resolve KSP configurations (*KotlinProcessorClasspath) in ResolveVariantDependenciesTask
- Aggregate KSP deps across all variants into single kspResult in ComputeWorkspaceDependencies
- Generate ksp_maven maven_install from aggregated KSP dependencies
- Add calculateRepositoriesIncludingTransitives to extract repos from transitive deps
- Update KspRules to reference @ksp_maven instead of @maven for processor deps
- Only include direct KSP processors in artifacts, let Bazel resolve transitives
@minkuan88 minkuan88 force-pushed the ksp-support-modules branch from 2797a31 to 94cadce Compare January 9, 2026 05:34
Move KSP-related code out of GradleProjectInfo to ensure the implementation
is configuration cache compatible. KSP processors are now built directly
from WorkspaceDependencies in RootBazelFileBuilder.

Changes:
- Move KspProcessor data class to KspRules.kt
- Remove hasKsp and kspDependencies from GradleProjectInfo interface
- Add buildKspProcessors() method in RootBazelFileBuilder
- Add collectKspPluginDeps() to DependenciesDataSource for module-level KSP deps
- Update GenerateRootBazelScriptsTask to pass workspaceDependencies
@minkuan88 minkuan88 force-pushed the ksp-support-modules branch from 94cadce to da72ecb Compare January 9, 2026 05:39
- Moshi is simpler than Room (just @JsonClass annotation)
- Added MoshiModel.kt with User data class for KSP generation
- Added verifyKspCodeGeneration() in MainActivity to verify
  KSP-generated UserJsonAdapter works at compile time
- Updated ksp_maven to use moshi-kotlin-codegen processor
- Verified both Gradle and Bazel builds pass
Similar to PR grab#159, this optimizes configuration time by skipping
expensive KSP resolution for projects/variants without KSP deps.

- Add hasKspDependencies() to check project's base ksp configuration
- Conditionally process KSP configs only when dependencies exist
- Skip processor class extraction and resolution when not needed
Extend KSP support to pure Kotlin (JVM) library modules by wiring up
the plugin extraction in KotlinProjectDataExtractor and passing plugins
through to the generated kotlin_library targets.

Changes:
- Add plugins field to KotlinProjectData
- Extract KSP plugins via collectKspPluginDeps() in extractor
- Pass plugins to KotlinLibraryTarget in builder

Also add KSP/Moshi testing to sample modules:
- sample-kotlin-library: Add KotlinConfig data class with @JsonClass
- sample-android-library: Add @JsonClass to User (alongside @parcelize)
@minkuan88 minkuan88 force-pushed the ksp-support-modules branch from 30beffa to 4d1d730 Compare January 10, 2026 04:11
// Format: "group:name:version:repository:requiresJetifier:jetifierSource"
artifacts.flatMap { it.dependencies }
.mapNotNull { depNotation ->
val parts = depNotation.split(":")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets unify this parsing under https://github.com/grab/grazel/blob/master/grazel-gradle-plugin/src/main/kotlin/com/grab/grazel/gradle/dependencies/model/ResolveDependenciesResult.kt#L76 in one place. These is a chance this may drift and hard to catch later on

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

888dd6c addresses this

* @param coordinate Maven coordinate in format "group:artifact"
*/
fun processor(coordinate: String, block: KspProcessorConfig.() -> Unit) {
processors.getOrPut(coordinate) { KspProcessorConfig() }.apply(block)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a validation for the coordinate so that unexpected input don't crash the parsing later on

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

b662d48 addresses this

val hasKsp = hasKspDependencies(variant, project)

// Collect KSP direct dependencies only if variant has KSP deps
val directDependenciesKsp: org.gradle.api.provider.Provider<Map<String, String>>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider fixing imports

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

888dd6c addresses this

}

// Check if variant has KSP dependencies before processing
val hasKsp = hasKspDependencies(variant, project)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably worth moving all ksp related to new function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

b662d48 addresses this

processorClasses = kspConfigurationProvider.map { configs ->
configs
.filter { it.isCanBeResolved }
.flatMap { KspProcessorClassExtractor.extractProcessorClasses(it).entries }
Copy link
Collaborator

@arunsampathkumar-grabtaxi arunsampathkumar-grabtaxi Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this is quite heavy to run in configuration phase (although this happens inside a provider) , the classes can be computed as part of task itself and just declare the configurations as input to the task.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will address this in a separate PR


// Check if project has any KSP dependencies declared
// The 'ksp' configuration is the base config that variant-specific configs extend from
val kspConfig = project.configurations.findByName("ksp")
Copy link
Collaborator

@arunsampathkumar-grabtaxi arunsampathkumar-grabtaxi Jan 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will force resolve the configuration and bad for performance, we are computing it already in grazelVariant.kspConfiguration, can use that directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will address this is a separate PR

@@ -0,0 +1,29 @@
/*
* Copyright 2022 Grabtaxi Holdings PTE LTD (GRAB)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets update this for new code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

888dd6c addresses this

Use ResolvedDependency::from to centralize coordinate parsing instead
of manually splitting notation strings. Also fix copyright year.
- Add validateCoordinate() for processor coordinate input
- Extract KSP logic into collectKspDependencyInfo() function
- Add KspDependencyInfo data class to encapsulate KSP state
- Clean up imports in ResolveVariantDependenciesTask
@minkuanlim-grabtaxi minkuanlim-grabtaxi merged commit 92f9634 into grab:master Jan 13, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants