2016-08-30 4 views
0

Ich verbrachte einige Tage, dieses Problem zu entdecken, und ich würde gerne meinen Fund hier posten.Gradle ANTLR4-Plugin in Android App: Build fehlschlägt

Ich baue eine Android-App mit mehreren Modulen, von denen eines das ANTLR-Plugin verwendet. Während das Modul mit ANTLR OK baut, da es ein Java-Modul ist, schlägt das Android-Modul in transformClassesWithDexForDebug Aufgabe:

* What went wrong: 
Execution failed for task ':Android:transformClassesWithDexForDebug'. 
> com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: java.lang.RuntimeException: Translation has been interrupted 

Wenn ich versuche, build.gradle zu ermöglichen multiDexEnabled in ich eine andere Meldung:

* What went wrong: 
Execution failed for task ':Android:transformClassesWithJarMergingForDebug'. 
> com.android.build.api.transform.TransformException: java.util.zip.ZipException: duplicate entry: org/abego/treelayout/Configuration$AlignmentInLevel.class 

Einige Antworten hier schlägt vor, Java-RAM für Dexing zu erhöhen, Abhängigkeiten wie Google-Play-Bibliothek zu reduzieren - das habe ich gemacht, aber keine Freude.

hier gehen build.gradle Proben verwendet:

ANTLR4 Modul:

apply plugin: 'antlr' 
apply plugin: 'java' 
apply plugin: 'maven' 

sourceCompatibility = 1.7 
targetCompatibility = 1.7 

final GENERATED_MAIN = "src-gen/main/java" 
final GENERATED_TEST = "src-gen/test/java" 

sourceSets { 
    main { 
     java { srcDirs += [GENERATED_MAIN] } 
    } 
    main { 
     java { srcDirs += [GENERATED_TEST] } 
    } 
} 

repositories { 
    mavenCentral() 
} 

dependencies { 
    antlr("org.antlr:antlr4:4.5") { 
     exclude group: 'org.antlr', module:'antlr-runtime' 
//  exclude group: 'org.antlr', module:'antlr4-runtime' 
     exclude group: 'org.antlr', module:'ST4' 
    } 
    compile ('com.yuvalshavit:antlr-denter:1.0') { 
     exclude group: 'org.antlr', module:'antlr4-runtime' 
    } 
    testCompile group: 'junit', name: 'junit', version:'4.11' 
} 

generateGrammarSource.doFirst { 
    outputDirectory = new File(GENERATED_MAIN) 
} 
generateGrammarSource.doLast { 
    moveAntlrGeneratedFilesToTheirPackages(source, GENERATED_MAIN) 
} 
generateTestGrammarSource.doFirst { 
    outputDirectory = new File(GENERATED_TEST) 
} 
generateTestGrammarSource.doLast { 
    moveAntlrGeneratedFilesToTheirPackages(source, GENERATED_TEST) 
} 

def moveAntlrGeneratedFilesToTheirPackages(FileTree grammarFiles, generatedFolder) { 
    grammarFiles.each {File file -> 
     final grammarName = file.name.lastIndexOf('.')>=0 ? file.name[0 .. file.name.lastIndexOf('.')-1] : file.name 
     final grammarPackage = extractPackageNameFromGrammerFile(file) 
     copy { 
      from generatedFolder 
      include "${grammarName}*.*" 
      into generatedFolder + "/" + grammarPackage.replaceAll("\\.", "/") 
     } 
    } 
    project.delete fileTree(generatedFolder).include('*.*') 
} 

def extractPackageNameFromGrammerFile(File grammarFile) { 
    def grammarPackage = "unknown.package" 
    def packageRegex = ~/[ ]*package[ ]*([a-zA-Z]+[a-zA-Z0-9.-_]*)[ ]*;/ 
    grammarFile.eachLine { line -> 
     def matcher = packageRegex.matcher(line) 
     if (matcher.find()){ 
      grammarPackage = matcher.group(1) 
     } 
    } 
    return grammarPackage 
} 

android Modul:

apply plugin: 'com.android.application' 

android { 
    compileSdkVersion 23 
    buildToolsVersion "23.0.2" 

    defaultConfig { 
     applicationId "<some package name here>" 
     minSdkVersion 14 
     targetSdkVersion 22 
//  multiDexEnabled true 
    } 


    dexOptions { 
//  javaMaxHeapSize "4g" 
    preDexLibraries = false 
    } 

    lintOptions { 
      abortOnError false 
    } 

    sourceSets { 
     main { 
      manifest.srcFile 'AndroidManifest.xml' 
      java.srcDirs = ['src'] 
      resources.srcDirs = ['src'] 
      aidl.srcDirs = ['iadl'] 
      renderscript.srcDirs = ['src'] 
      res.srcDirs = ['res'] 
      assets.srcDirs = ['assets'] 
     } 
    } 

} 

dependencies { 
    compile project(':texas-board') // this references the ANTLR module mentioned above 
    ... 
} 

root build.gradle:

buildscript { 
    repositories { 
     jcenter() 
    mavenCentral() 
    } 

    dependencies { 
     classpath 'com.android.tools.build:gradle:2.1.2' 
    } 
} 

Analyseabhängigkeiten (gradle dependencies) zeigt, dass das Problem ist, dass antlr gradle Plugin org.abego.treelayout Klassen sowohl über antlr4 Bibliothek für die Kompilierung verwendet wird, umfasst und antlr4-Laufzeit:

+--- project :texas-board 
| \--- project :rules_engine 
|   +--- org.antlr:antlr4:4.5 
|   | +--- org.antlr:antlr4-runtime:4.5 
|   | | \--- org.abego.treelayout:org.abego.treelayout.core:1.0.1 
|   | \--- org.antlr:antlr-runtime:3.5.2 
|   \--- com.yuvalshavit:antlr-denter:1.0 

wieder einmal - die Sache ist, dass die org.abego.treelayout Klassen vorhanden sind beide in org.antlr:antlr4:4.5, org.antlr:antlr4-runtime:4.5 und wahrscheinlich sogar in org.abego.treelayout:org.abego.treelayout.core:1.0.1. Ich vermute, dass es ein Fehler mit dem AntiLR4-Plugin für Gradle ist - sie haben diese Klassen fälschlicherweise im Hauptpaket hinzugefügt, während sie nur in Abhängigkeiten stehen sollten. Wahrscheinlich sollte ich einen Bug an den Plugin-Tracker senden.

Darüber hinaus fügt Antlr4-Plugin sogar Antlr3-Laufzeitabhängigkeit, die org.abego.treelayout Klassen ebenfalls neu definieren (so dass ich auch ausgeschlossen).

Während Java-Anwendungen zusätzliche Kopien von Java-Klassen akzeptieren (sie nehmen die erste von Classpath glaube ich), Android-Plugin scheitert in Dex-Stufe Bericht Fehler oben erwähnt.

Antwort

0

war meine Lösung doppelte Abhängigkeiten zu entfernen:

apply plugin: 'antlr' 
apply plugin: 'java' 
apply plugin: 'maven' 

sourceCompatibility = 1.7 
targetCompatibility = 1.7 

final GENERATED_MAIN = "src-gen/main/java" 
final GENERATED_TEST = "src-gen/test/java" 

sourceSets { 
    main { 
     java { srcDirs += [GENERATED_MAIN] } 
    } 
    main { 
     java { srcDirs += [GENERATED_TEST] } 
    } 
} 

repositories { 
    mavenCentral() 
} 

dependencies { 
    antlr("org.antlr:antlr4:4.5") { 
     exclude group: 'org.antlr', module:'antlr-runtime' 
     exclude group: 'org.antlr', module:'antlr4-runtime' 
     exclude group: 'org.antlr', module:'ST4' // just in case :-) 
    } 
    compile ('com.yuvalshavit:antlr-denter:1.0') { 
     // denter library also has dependency on antlr4-runtime ... 
     exclude group: 'org.antlr', module:'antlr4-runtime' 
    } 
    testCompile group: 'junit', name: 'junit', version:'4.11' 
} 
... 

Ich bin offen für jede bessere Lösung Sie vorschlagen können - ich bin nicht gut mit gradle.

Verwandte Themen