I have a project which uses kapt for annotation processing and code generation (based on the annotations). It works in the main sources, but not in the test sources.
Some sources (e.g. how to use kapt in androidTest scope) suggest to run gradle kaptTest, but this does not work either. It reports the task as "Up to date", even directly after a clean. Maybe this suggestion is unique to android.
I downloaded the example project from https://github.com/JetBrains/kotlin-examples/tree/master/gradle/kotlin-code-generation, added an annotation usage in the test sources and I got the same behaviour there. It works well for the main sources and it does not work for the test sources.
The only odd thing in the output is:
> Task :example:compileKotlin
Using kotlin incremental compilation
w: [kapt] Sources output directory is not specified, skipping annotation processing
but as you can see, this is not the test sources, but the main sources, and the annotation processor is applied on those.
I added a printout in the annotation processor. It does show up for compileKotlin, but not for compileTestKotlin.
So, what is the magic trick to make kapt work on test sources?
PS: I guess someone is going to ask for my build.gradle. It is identical to the one from the example I linked, so if you can make it work for the example, I can integrate into my buildfile.
PPS: Only similar question I found is Kotlin's kapt plugin for gradle does not work for custom source set (JMH), and they suggest to issue a bug report. So maybe it is a bug in the kapt-gradle-plugin?
Some sources (e.g. how to use kapt in androidTest scope) suggest to run gradle kaptTest, but this does not work either.
You misunderstood the suggestion. It says kaptTest should be used in place of kapt in the dependencies block, as described here, not that you should run Gradle differently. OTOH, the documentation also specifically says
Note that kaptAndroidTest and kaptTest extends kapt, so you can just provide the kapt dependency and it will be available both for production sources and tests.
So there indeed seems to be a bug there.
I've linked this question in https://youtrack.jetbrains.com/issue/KT-21891. I didn't want to file a separate bug because I don't know which Gradle/Kotlin/Kotlin Gradle plugin/etc. you had.
As suggested above, kaptTest should be added in gradle for the annotations in test folder to be processed by kapt.
for example for dagger hilt, add this to your app gradle :
kaptTest("com.google.dagger:hilt-android-compiler:$hiltVersion")
or for moshi, when you use annotations like #JsonClass(generateAdapter = true) in a file in test folder, you should add this to gradle dependencies so that kapt processes the annotation and generate the class :
kaptTest("com.squareup.moshi:moshi-kotlin-codegen:$moshiVersion")
Related
we are currently checking, whether we can switch from Eclipse to IntelliJ as an IDE.
In this project we are using gradle multi projects whose structure looks something like this:
Project
|-ProjectA
|-ProjectAImpl
|-main*
|-ProjectATest
|-test*
|-ProjectB
|-ProjectBImpl
|-main*
|-ProjectBTest
|-test*
= Source set or in IntelliJ it seems a module.
The ProjectBTest has a dependency to ProjectATest, which is configured as
compile project(":ProjectA:ProjectATest")
This always worked properly with Eclipse but in IntelliJ I'm having the problem, that the ProjectBTest is configured such, that it is looking for a module named "Project.ProjectA.ProjectATest.main", instead of "Project.ProjectA.ProjectATest.test"
This module can obviously not be found, leading to a lot of compiler errors.
Can maybe somebody give me a hint how I can tell IntelliJ or gradle here to take the proper module?
Thank you very much.
This is standard Gradle functionality. Unless you have other Gradle customizations (like feature variants or changing the source directories for a source set), project dependencies will naturally target the main source set.
There are several ways to solve this, but two primary ones that stand out to me:
Use Gradle's Java test fixtures.
The "test" source set is not naturally inheritable in any way in Gradle. There is no built-in consumable configuration that provides test classes to downstream projects. However, Java test fixtures allow you to use a separate testFixtures source set which is shareable. To do this, you would do the following:
Add the java-test-fixtures plugin to all projects which need to produce shared test sources
Move your shared test sources to <project directory>/src/testFixtures (ideally this would include as few actual test classes as possible, but rather just shareable test logic instead)
Change your dependency references to point to the upstream project(s)' test fixtures artifact: testImplementation(testFixtures(project(":ProjectA:ProjectATest"))
Register a tests configuration which includes the test classes as an output.
project.configurations.register("tests") {
extendsFrom(project.configurations[JavaPlugin.TEST_RUNTIME_CONFIGURATION_NAME])
}
tasks.register("testJar", Jar::class) {
classifier.set("test-classes")
from(project.the<SourceSetContainer>()[SourceSet.TEST_SOURCE_SET_NAME].output)
}
project.artifacts.add("tests", project.tasks.named("testJar"))
Downstream projects:
dependencies {
compile(project(":ProjectA:ProjectATest", "tests"))
}
None of the above code is tested. It may require some adjustments.
Java test fixtures are a supported way to produce shareable test sources, so they should be preferred, but the tests configuration may be quicker to implement, depending on your use case.
I have a Gradle composite build project which contains a custom Gradle plugin. This project builds fine when using Gradle CLI, but IntelliJ fails.
I tried a few different variations on the plugin version within the resolutionStrategy block: org.test:test-plugin:0.0.1 and test-plugin:test-plugin.gradle.plugin:0.0.1 as described here: https://docs.gradle.org/current/userguide/plugins.html#sec:plugin_markers - both of those work from the CLI; changing to invalid values ("blah:blah") causes a failure.
I've made a sample Github project that contains the code to reproduce, here: https://github.com/mwmitchell/intellij-gradle-plugin-composite-build-bug along with instructions to reproduce and a workaround. The workaround is something that's not really feasible for me, as it requires repeating configuration code (dependencies, plugins etc.) and I have many, many projects that require the same/common configuration.
I would expect IntelliJ to load the project successfully, just like the CLI does. It seems like IntelliJ is loading the sub-project (:project-1:library-a) before the parent (:project-1), such that the java-library is not actually applied to the sub-project when it's evaluated.
Thanks for the sample project! Indeed, it is an issue in IntelliJ IDEA, see this ticket.
Gradle projects can have only one settings.gradle. You can include subproject "library-a" with include 'project-1:library-a' in the main settings.gradle.
I have a Kotlin dependency that I wrote and am now trying to use it in a separate project. When I add it to the other project variables declared like val hits = 0 can not be referenced by using the variable hits but by using getHits() which would make sense if I was using java in the second project but I am not. In other Kotlin projects I have worked on in the past this was not an issue and the only thing that I can think of that is different in the build is that I have set transitive = false on the gradle dependency because that was causing another issue. Anyway I am confused on what this would be caused by and appreciate any help, thanks!
In the Intellij decompiler is was considering a class that I know was written in Kotlin a java class so I tried to change some things. The problem was one of two things:
I was using the maven plugin for gradle.
I had both a compileKotlin and a compileJava when I was only using Kotlin.
I belive that the problem was caused by the former because I have used both compileKotlin and compileJava fine together before but I had never used the maven plugin but I added it because something else was complaining that it needed it.
I wrote a custom Gradle task to encapsulate a Java application, https://github.com/ndw/xmlcalabash1-gradle
It's a fairly simple extension of org.gradle.api.internal.ConventionTask cobbled together somewhat quickly. It's entirely possible that I'm just doing it wrong.
It's been working just fine for a while now. I've used it in several projects. However, for the particular build.gradle that I'm writing now, I need to make additional classes available to it.
After much frustration and complete failure to get additional jars into the classpath, I went back and updated my application class so that it would print out its classpath. That revealed that when this task runs, the classpath consists of only /usr/lib/gradle/4.4.1/lib/gradle-launcher-4.4.1.jar. I conclude that some alternate class loader must be in use because the task does successfully load the core application classes.
Can anyone tell me how to make more jars available to my task? None of my web search foo has lead me to an answer.
Oh, for the love of all things. I left 'classpath' out of the dependencies in the buildscript closure. #facepalm.
I'm setting up a (java) maven project that depends on a library (Jettison, among others) that is in the Maven repo. Jettison, in turn, depends on stax. I need to run a tool (Jar Jar Links) on stax (to change the namespace). How do I alter the rules for a transitive dependency in a maven project? My transitive dependencies are being included in my target folder using the copy-dependencies goal (I assume this is how things are usually done). I assume that this is the point where the plugin would be run on the transitively-generated artifact.
Extra question: I don't need this at this point but how would I go about altering the source in the transitive dependency? I can get the jar of the source with mvn dependency:sources but, from there, I'm not sure what the right approach is.
Victory!
Seems at least two people are even more clueless about Maven than me so let me explain what I'm doing before I report the fix at the bottom of this post (spoiler alert: it looks to be a bug in JarJar).
Android uses Java but its missing a lot of the java core (specifically, javax classes). The Android DEX compiler (which converts .jars to Android .dex files) won't even allow you to compile things in the java.* or javax.* namespace because it'll (usually) break stuff. However, in some (many) cases, there are routines that you might want to include -- specifically because they are used by existing libraries. The most legendary is StAX, which is why Google posted an example of how to include it here in the Dalvik repo's wiki. The example uses JarJar... with ant. Transitive dependencies are not really an issue when you aren't using a repo so they are not addressed in the wiki.
I was able to get JarJar to run on my source with Maven but without changing the namespaces in the dependencies (and transitive dependencies), that's worthless. Hence my question.
I thought that the copy-dependencies plugin might be useful for... copying the dependencies and running a transforming plugin in the process. Copying dependencies is mentioned as a step in the official "Maven in 5 minutes" doc so it seemed like a good start but maybe the the people who wrote the official docs don't know how to use it :-) . Either way, it it didn't help -- there is no simple way I could see to transform the jars as it copies.
Using the verbose spew from Maven, I was able to see that Jar Jar was in fact processing my jars properly... and then throwing out the result. It would have packaged the converted classes from the transitive dependencies in my artifact with the rest of my code but, instead, it "Excluded" them. Jar Jar parameters are basically undocumented and most of the tags aren't even listed in the docs but all of the examples I could find use a section with wild-cards that tell it what classes to hold onto. At least I thought (think?) that's what the section is for. Instead, it seems to randomly throw out stuff. Basically, the section is busted. For example, I had:
<keep>
<pattern>com.example.**</pattern>
</keep>
...thinking that this would keep classes that began with com.example. Wrong. It keeps whatever the hell it wants. I tried a million things in that spot until one worked:
<keep>
<pattern>*.**</pattern>
</keep>
This only keeps the classes I wanted -- the classes it updated and the originals of the ones that it didnt touch. Note that ** doesn't even work. This is version 1.8 of the JarJar plugin (the version most poms Ive found use).
Back to work.