groovy / groovy-android-gradle-plugin

A Gradle plugin to support the Groovy language for building Android apps
Apache License 2.0
850 stars 116 forks source link

Build failure: signature-polymorphic method called without --min-sdk-version >= 26 #145

Open nathanwharvey opened 7 years ago

nathanwharvey commented 7 years ago

I am getting a strange bug when building, even with a fresh project. The error only occurs when groovy is being compiled. Here is the module's build.gradle:

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'org.codehaus.groovy:groovy-android-gradle-plugin:1.1.0'
    }
}

apply plugin: 'com.android.application'
apply plugin: 'groovyx.android'

androidGroovy {
    options {
        configure(groovyOptions) {
            javaAnnotationProcessing = true
        }
    }
}

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "io.nwh.myapplication"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.3.1'
    testCompile 'junit:junit:4.12'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    compile 'org.codehaus.groovy:groovy:2.4.7:grooid'
}

And here is the project's build.gralde:


buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.4.0-alpha5'
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

I am using Gradle version 3.4.1. Here is the output from building:

$ gradle installDebug
:app:preBuild UP-TO-DATE
:app:resolveDebugDependencies
:app:preDebugBuild
:app:checkDebugManifest
:app:prepareDebugDependencies
:app:compileDebugAidl
:app:compileDebugRenderscript
:app:generateDebugBuildConfig
:app:generateDebugResValues
:app:handleDebugMicroApk
:app:generateDebugResources
:app:mergeDebugResources
:app:processDebugManifest
:app:processDebugResources
:app:generateDebugSources
:app:incrementalDebugJavaCompilationSafeguard
:app:javaPreCompileDebug
:app:compileDebugJavaWithJavac
:app:compileDebugJavaWithJavac - is not incremental (e.g. outputs have changed, no previous execution, etc.).
:app:compileDebugGroovyWithGroovyc
warning: [options] bootstrap class path not set in conjunction with -source 1.7
1 warning
:app:compileDebugNdk NO-SOURCE
:app:compileDebugSources
:app:mergeDebugShaders
:app:compileDebugShaders
:app:generateDebugAssets
:app:mergeDebugAssets
:app:transformClassesWithDexBuilderForDebug
warning: Ignoring InnerClasses attribute for an anonymous inner class
                                                                      (groovyjarjarantlr.build.ANTLR$1) that doesn't come with an
associated EnclosingMethod attribute. This class was probably produced by a
compiler that did not target the modern .class file format. The recommended
solution is to recompile the class from source, using an up-to-date compiler
and without specifying any "-target" type options. The consequence of ignoring
this warning is that reflective operations on this class will incorrectly
indicate that it is *not* an inner class.
Unable to pre-dex 'C:\Users\Nathan\.gradle\caches\modules-2\files-2.1\org.codehaus.groovy\groovy\2.4.7\b4b263e2106bac49c2eb21f6737f9b6e45e24a4a\groovy-2.4.7-grooid.jar' to 'C:\Users\Nathan\Documents\Flags2\app\build\intermediates\transforms\dexBuilder\debug\jars\40000\10\groovy-2.4.7-grooid_5a2004fbc80cc406e9adac10d01fb1c4aeb1d6e6.jar'
Dex: Error converting bytecode to dex:WithDexBuilderForDebug
Cause: signature-polymorphic method called without --min-sdk-version >= 26
    UNEXPECTED TOP-LEVEL EXCEPTION:
signature-polymorphic method called without --min-sdk-version >= 26

java.lang.RuntimeException: com.android.dx.cf.code.SimException: signature-polymorphic method called without --min-sdk-version >= 26
        at com.android.ide.common.internal.WaitableExecutor.waitForTasksWithQuickFail(WaitableExecutor.java:183)
        at com.android.builder.dexing.DexArchiveBuilder.processOutputs(DexArchiveBuilder.java:95)
        at com.android.builder.dexing.DexArchiveBuilder.convert(DexArchiveBuilder.java:78)
        at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransformCallable.lambda$cacheMissAction$0(DexArchiveBuilderTransformCallable.java:240)
        at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransformCallable$$Lambda$1022/1324664455.run(Unknown Source)
        at com.android.builder.utils.FileCache.lambda$createFile$1(FileCache.java:260)
        at com.android.builder.utils.FileCache$$Lambda$1033/1397556199.call(Unknown Source)
        at com.android.builder.utils.FileCache.lambda$null$5(FileCache.java:443)
        at com.android.builder.utils.FileCache$$Lambda$1089/840087435.accept(Unknown Source)
        at com.android.builder.utils.SynchronizedFile.doActionWithMultiProcessLocking(SynchronizedFile.java:265)
        at com.android.builder.utils.SynchronizedFile.write(SynchronizedFile.java:232)
        at com.android.builder.utils.FileCache.lambda$queryCacheEntry$6(FileCache.java:415)
        at com.android.builder.utils.FileCache$$Lambda$1037/1858463036.accept(Unknown Source)
        at com.android.builder.utils.SynchronizedFile.doActionWithMultiProcessLocking(SynchronizedFile.java:265)
        at com.android.builder.utils.SynchronizedFile.read(SynchronizedFile.java:215)
        at com.android.builder.utils.FileCache.queryCacheEntry(FileCache.java:391)
        at com.android.builder.utils.FileCache.createFile(FileCache.java:273)
        at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransformCallable.getFromCacheAndCreateIfMissing(DexArchiveBuilderTransformCallable.java:187)
        at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransformCallable.call(DexArchiveBuilderTransformCallable.java:149)
        at com.android.build.gradle.internal.transforms.DexArchiveBuilderTransformCallable.call(DexArchiveBuilderTransformCallable.java:53)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
Caused by: com.android.dx.cf.code.SimException: signature-polymorphic method called without --min-sdk-version >= 26
        at com.android.dx.cf.code.Simulator$SimVisitor.visitConstant(Simulator.java:684)
        at com.android.dx.cf.code.BytecodeArray.parseInstruction(BytecodeArray.java:764)
        at com.android.dx.cf.code.Simulator.simulate(Simulator.java:101)
        at com.android.dx.cf.code.Ropper.processBlock(Ropper.java:790)
        at com.android.dx.cf.code.Ropper.doit(Ropper.java:745)
        at com.android.dx.cf.code.Ropper.convert(Ropper.java:350)
        at com.android.dx.dex.cf.CfTranslator.processMethods(CfTranslator.java:285)
        at com.android.dx.dex.cf.CfTranslator.translate0(CfTranslator.java:141)
        at com.android.dx.dex.cf.CfTranslator.translate(CfTranslator.java:95)
        at com.android.builder.dexing.DexArchiveBuilderCallable.translateClass(DexArchiveBuilderCallable.java:87)
        at com.android.builder.dexing.DexArchiveBuilderCallable.call(DexArchiveBuilderCallable.java:70)
        at com.android.builder.dexing.DexArchiveBuilderCallable.call(DexArchiveBuilderCallable.java:40)
        ... 6 more
:app:transformClassesWithDexBuilderForDebug FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:transformClassesWithDexBuilderForDebug'.
> com.android.build.api.transform.TransformException: java.lang.RuntimeException: java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.util.concurrent.ExecutionException: com.android.builder.utils.FileCache$FileCreatorException: com.android.builder.dexing.DexArchiveBuilder$DexBuilderException: Unable to convert input to dex archive.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 7.949 secs

I also tried copying the sample app and got the same error.

AndrewReitz commented 7 years ago

This appears to be a change to an internal class in gradle that this plugin depends on. The change is in 3.5 and 3.4.1 still continues to work as a current work around. I will be updating tests and the source to NO longer depend on the internal gradle classes as this is the second time its caused the plugin to break.

AndrewReitz commented 7 years ago

Turns out the breaking change was from Gradle 3.2 to 3.3 where an interface had a method added to it.

I updated the tests to include 3.5 and before fixing this change they were still passing. So it looks like there is still something else going on in your issues.

Once #146 gets merged in you can try out the 1.2.0-SNAPSHOT and see if it resolves your issue.

nathanwharvey commented 7 years ago

Great, thanks for the quick reply. I am indeed using Gradle 3.4.1 so it's a strange issue. I'll wait for the merge

nathanwharvey commented 7 years ago

@AndrewReitz I see you merged the change, but I don't see a 1.2.0-SNAPSHOT on bintray. I'm still getting errors. I tried switching around my Gradle versions but to no avail. Are the following versions correct?

com.android.tools.build:gradle:2.4.0-alpha5
org.codehaus.groovy:groovy-android-gradle-plugin:1.1.0
buildToolsVersion "25.0.2"
compileSdkVersion 25
AndrewReitz commented 7 years ago

I haven't tested anything using any of the alpha builds since I'm only one person and google seems to change stuff so much. An easy way to test newer version is to just add another row to the data table in the full test spec and run ./gradlew fullTest

For the snapshots you need to use the jcenter's snapshot repo instead of the regular jcenter repo. Directions to add this are on in the README.

yangxinQA commented 7 years ago

how did it solved?

nathanwharvey commented 7 years ago

@yangxinQA Hey, sorry for the late reply, I am just getting back at my app. I solved it for one of my classes by removing @CompileStatic. I also downgraded my build tools. Here are my versions:

com.android.tools.build:gradle:2.3.2
org.codehaus.groovy:groovy-android-gradle-plugin:1.1.0
buildToolsVersion "25.0.2"
compileSdkVersion 25

If that doesn't work for you, I'm afraid I can't help :(. Maybe @AndrewReitz has some more ideas.

AndrewReitz commented 7 years ago

@nathanwharvey are you still seeing this issue?

miffels commented 7 years ago

I have just run into this when trying to use android-spock:2.0.0 with the Android Studio 3.0 preview and com.android.tools.build:gradle:3.0.0-alpha3 that you need to compile Java8. I guess this might be related? I was basically just grabbing the preview from here, configured an API level 25 project as described here, and tried to get the basic sample to run.

nite2 commented 7 years ago

I was experiencing the same issue and i can confirm that using org.codehaus.groovy:groovy-android-gradle-plugin:1.3.0-SNAPSHOT resolves it

AndrewReitz commented 7 years ago

@nite2 The only difference between 1.2.0 and 1.3.0-SNAPSHOT is the version number so I don't think that's what solved the issue. Maybe an update to the gradle android plugin fixed the issue?

nite2 commented 7 years ago

@AndrewReitz I am not saying that this issue wasn't resolved in 1.2.0-SNAPSHOT as you have suggested in previous comment, what i was communicating is that i was having the issue when using version 1.2.0 (not 1.2.0-SNAPSHOT), then upgraded to 1.3.0-SNAPSHOT and the problem was gone. Was the fix #146 included in the "main" 1.2.0 release?

AndrewReitz commented 7 years ago

Yeah, #146 was included. As of right now, the only difference between 1.2.0 and 1.3.0-SNAPSHOT is the version number https://github.com/groovy/groovy-android-gradle-plugin/commits/master.

Strime commented 7 years ago

What about new gradle (4.1) ? I've the same issue

b-demuth commented 7 years ago

I've done a little bit of research and this seems to be caused by a new check in Dalvik, see https://android.googlesource.com/platform/dalvik/+/cdef1ee858fde291205f3da685b2720227d2d42f/dx/src/com/android/dx/cf/code/Simulator.java line 684. When running the gradle build with --stacktrace, you can see that the groovy class org/codehaus/groovy/vmplugin/v7/IndyInterface.java violates this check. Indy here stands for invokeDynamic - on Android, this compiler feature is only supported with minSDK >= 26. It seems to me that even though grooid (the groovy build for Android) is compiled with indy switched off, the indy-related classes still end up in the groovy artifact, thus making my build fail.

b-demuth commented 7 years ago

I've just gotten rid of the problem by patching the grooid library (deleted packages "indy" and "vmplugin/v7" and made sure that Option CompilerConfiguration.INVOKEDYNAMIC was false). Quick & dirty but seems to work for now.. Should probably file an issue in the groovy project.

AndrewReitz commented 7 years ago

@b-demuth any chance you can host the patched version somewhere or show us how to do it?

AndrewReitz commented 7 years ago

Created a ticket: https://issues.apache.org/jira/browse/GROOVY-8366 and working on a possible solution.

b-demuth commented 7 years ago

I'm at the droidcon right now, but I'll see if I can host the patched version next week. I literally just deleted said packages and the line "if (Boolean.TRUE.equals(optOptions.get(CompilerConfiguration.INVOKEDYNAMIC))) invokedynamic=true;" in class "WriterController" in the 2_4_X branch of groovy (which was easier for me than setting that parameter in the optOptions :)). Also, I switched off some of the documentation related parts of the build process and jar signing, so my patched version is UNSIGNED. This really is a dirty hack, but I didn't have time to get familiar with the groovy build scripts in order to do this properly. I guess for someone who's already acquainted with the build process, it should be quick and easy to do.

AndrewReitz commented 7 years ago

Cool. I used JarJar to remove the packages right now, haven't tested it. If it works I can submit the PR to Groovy project. Also, going to submit a ticket with build tools team.

SideNote: Were you having issues with the javadocs part of the build process?

AndrewReitz commented 7 years ago

I think another workaround is to use proguard to remove those packages as well.

AndrewReitz commented 7 years ago

Looks like the tools team will not be fixing it. The suggested fix is to "minify" the code (Progaurd) out the method calls that use invoke dynamic. https://issuetracker.google.com/issues/37567710

The good news is that we are getting invoke dynamic on 26+

AndrewReitz commented 7 years ago

Looks like the jarjar rule of zap org.codehaus.groovy.vmplugin.v7.IndyInterface takes care of this. Submitting a PR to groovy soon.

AndrewReitz commented 7 years ago

PR Here: https://github.com/apache/groovy/pull/631

JeremKay commented 7 years ago

I saw update to AGP to 3.0.0 and I try it. It works when I use it in groovy-android-sample-app or in simple app with dependencies only on groovy but when I try on a more complex app with multiples dependencies like Retrofit or Dagger I have an error : Error:Execution failed for task ':app:transformClassesAndResourcesWithProguardForDebug'. Job failed, see logs for details

When I set minifyEnabled to false come back to initial error : signature-polymorphic method called without --min-sdk-version >= 26

Is it mandatory to set minifyEnabled to true to make groovy plugin works ?

AndrewReitz commented 7 years ago

Here's how you can make a groovy jar without the invoke dynamic class included for a workaround until the issue is resolved. https://gist.github.com/AndrewReitz/3e1145d66a8ef3f7b578d8604ecd671c

vincentganneau commented 6 years ago

I've been trying this workaround and the build succeeds. Unfortunately, the application crashes at runtime when calling method evaluate on a GroovyShell instance:

Caused by: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: General error during class generation: can't load this type of class file

java.lang.UnsupportedOperationException: can't load this type of class file at java.lang.ClassLoader.defineClass(ClassLoader.java:300) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:93) at groovy.lang.GroovyClassLoader.access$400(GroovyClassLoader.java:62) at groovy.lang.GroovyClassLoader$ClassCollector.createClass(GroovyClassLoader.java:500)

Any guess?

AndrewReitz commented 6 years ago

@vincentganneau I don't think that's related to this issue. The class files created by groovy are for the JVM, when you load them on an Android device they need to be converted to Dalvik bytecode. Here's an example of how this can be done https://github.com/melix/grooidshell-example. Although I haven't been able to get this to work on newer version of Android.

hyhyhykw commented 5 years ago

add compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } to your module build.gradle