google / ksp

Kotlin Symbol Processing API
https://github.com/google/ksp
Apache License 2.0
2.81k stars 265 forks source link

Add support for variant aware KSP arguments #861

Open runningcode opened 2 years ago

runningcode commented 2 years ago

I would like to provide variant specific KSP arguments. For example, I would like kspDebug and kspRelease to have different arguments.

An example use case is Room or DeepLinkDispatch. Both are kotlin symbol processors which write output to a directory. The directoy must be task specific so that kspDebug and kspRelease do not write to the same directory. Two tasks which write to the same directory disable up-to-date checks and caching in Gradle because the build becomes non-deterministic.

For reference, Java annotation processors and KAPT both provide a way of passing task specific arguments to the annotation processors.

ting-yuan commented 2 years ago

One solution might be exposing variant info to processors and let them pick the arguments but I'm sure there are better ways. Can you share what KAPT and Java annotation processor's approaches are?

runningcode commented 2 years ago

Good question. KAPT pulls them out of the java annotation processor options here

The Gradle Java plugin has a way of passing compilerArgumentProviders via the dsl.

I think we need to think about how all these work holistically. The approach that KAPT had to pull the arguments from the javacompile options might not make sense for KSP since the arguments would not affect the outcome of javacompile tasks nor KotlinCompile tasks.

We should also think about this in concert with this PR.

neetopia commented 2 years ago

should this be closed now that linked PR is merged?

ting-yuan commented 2 years ago

Nope, the merged PR is related but not solving this.

runningcode commented 2 years ago

This also probably needs to be resolved first before a variant aware API compatible with the latest versions of AGP can be created: https://issuetracker.google.com/issues/223367107

neetopia commented 2 years ago

I might not have full context on this issue, what's the current status?

runningcode commented 2 years ago

Forget my comment above. It is not needed since we will not be passing arguments from AGP's CommandLineArgumentProvider to KSP.

This issue to add support for variant aware KSP arguments has no status update.

TomBell-Trove commented 1 year ago

Would love this. I want to pass an arg to my processor which varies based on my Android build variant to alter its behaviour during production builds.

Is there a workaround to achieve this in the meantime? It seems that just plonking a differing ksp() in each variant's block isn't enough, the final invocation wins.

nak5ive commented 1 year ago

I may have a workaround for this.

KSP offers the ability to get information about files it creates via the CodeGenerator.generatedFile collection (warning: completely undocumented). I was able to pull information about the current variant / sourceset by inspecting the path data after creating a marker resource file. something like:

private fun CodeGenerator.collectVariantName(fileName: String): String {
  createNewFileByPath(Dependencies(false), fileName, "txt")
  return generatedFile.first().run {
    val (variantName) = Regex("ksp/(.+)/resources").find(absolutePath)!!.destructured
    variantName.replace("UnitTest", "")
      .also { writeText(it) }
  }
}

Having to generate a dummy file isn't great, but it works. Call it at the top of process() and then you can pick a name-spaced argument, like:

ksp {
  arg("some.argument.debug", "debug value")
  arg("some.argument.release", "release value")
}

I raised an issue to expose some config data to the processor that would hopefully make this sort of workaround unnecessary.

kazemcodes commented 4 months ago

I may have a workaround for this.

KSP offers the ability to get information about files it creates via the CodeGenerator.generatedFile collection (warning: completely undocumented). I was able to pull information about the current variant / sourceset by inspecting the path data after creating a marker resource file. something like:

private fun CodeGenerator.collectVariantName(fileName: String): String {
  createNewFileByPath(Dependencies(false), fileName, "txt")
  return generatedFile.first().run {
    val (variantName) = Regex("ksp/(.+)/resources").find(absolutePath)!!.destructured
    variantName.replace("UnitTest", "")
      .also { writeText(it) }
  }
}

Having to generate a dummy file isn't great, but it works. Call it at the top of process() and then you can pick a name-spaced argument, like:

ksp {
  arg("some.argument.debug", "debug value")
  arg("some.argument.release", "release value")
}

I raised an issue to expose some config data to the processor that would hopefully make this sort of workaround unnecessary.

https://github.com/google/ksp/issues/1850 is it possible to also get project directory using your code?