2016-08-30 108 views
0

我花了几天的时间发现了这个问题,我想在此发布我的发现。Android应用中的Gradle ANTLR4插件:编译失败

我正在用几个模块构建一个Android应用程序,其中一个使用ANTLR插件。虽然与ANTLR模块构建好了,因为它是一个Java模块,Android的模块中transformClassesWithDexForDebug任务失败:

* 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 

如果我尝试启用multiDexEnabled中的build.gradle我得到不同的信息:

* 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 

这里的一些答案建议增加用于dexing的Java RAM,减少诸如谷歌播放库之类的依赖项 - 我做到了,但没有喜悦。

这里去使用的build.gradle样品:

ANTLR4模块:

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 
} 

机器人模块:

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 
    ... 
} 

根的build.gradle:

buildscript { 
    repositories { 
     jcenter() 
    mavenCentral() 
    } 

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

分析依赖(gradle dependencies)示出的问题是,ANTLR gradle这个插件包括经由用于编译antlr4org.abego.treelayout类和antlr4运行时:

+--- 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 
再次

- 的问题是,所述org.abego.treelayout类同时存在于org.antlr:antlr4:4.5org.antlr:antlr4-runtime:4.5,甚至可能在org.abego.treelayout:org.abego.treelayout.core:1.0.1。我想这是一个用于gradle的antlr4插件的错误 - 他们错误地在主包中添加了这些类,而它们应该只在依赖关系中。可能我应该向插件跟踪器提交一个错误。此外,antlr4插件甚至增加了antlr3运行时依赖关系,它也可以重新定义org.abego.treelayout类(所以我也排除了它)。

虽然Java应用程序接受额外的java类副本(他们采取classpath中的第一个我相信),但android插件在上述dex阶段报告错误时失败。

回答

0

我的解决方法是删除重复的依赖关系:

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' 
} 
... 

我打开的任何更好的解决方案,你可以建议 - 我不擅长与gradle这个。