【问题标题】:Gradle + Annotations + Flavors = won't run annotations processorGradle + Annotations + Flavors = 不会运行注释处理器
【发布时间】:2013-10-13 22:43:19
【问题描述】:

我有一个使用注释处理器 (Android Annotations) 生成代码的 Gradle 构建脚本。在我添加新的 Pro Flavor 之前,构建一直很好。我可以构建 Free 风格,但是当我构建 Pro 风格时,注释处理器不会运行。这会导致代码丢失,构建失败。

这是我的脚本:

buildscript {
    repositories {
        maven { url 'http://repo1.maven.org/maven2' }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.5.+'
    }
}
apply plugin: 'android'

repositories {
    mavenCentral()
    maven {
        url 'https://oss.sonatype.org/content/repositories/snapshots/'
    }
}


ext.androidAnnotationsVersion = '3.0-SNAPSHOT';

configurations {
    apt
}


dependencies {
    compile files('libs/android-support-v13.jar')
    compile fileTree(dir: 'libs', include: '*.jar')
    apt "org.androidannotations:androidannotations:${androidAnnotationsVersion}"
    compile "org.androidannotations:androidannotations-api:${androidAnnotationsVersion}"
}

android {
    compileSdkVersion 17
    buildToolsVersion "17.0.0"


    defaultConfig {
        minSdkVersion 7
        targetSdkVersion 17

        versionCode 29
        versionName "2.0.3"
        packageName "com.MyCompany.MyApp"

    }

    productFlavors {
        free {
            buildConfig "final public static boolean PRO_VERSION = false;"
        }
        pro {
            packageName "com.MyCompany.MyApp.Pro"
            versionName (versionName + ".Pro")
            buildConfig "final public static boolean PRO_VERSION = true;"
        }
    }

    buildTypes {
        release {
            buildConfig "final public static String BASE_URL = \"http://data.MyCompany.com/\";", \
                        "final public static String APP_NAME = \"com.MyCompany.MyApp\";"
        }
        debug {
            buildConfig "final public static String BASE_URL = \"http://192.168.1.15/GDM/\";", \
                        "final public static String APP_NAME = \"com.MyCompany.MyApp\";"
        }
    }

}

def getSourceSetName(variant) {
    return new File(variant.dirName).getName();
}

android.applicationVariants.all { variant ->
    def aptOutputDir = project.file("build/source/apt")
    def aptOutput = new File(aptOutputDir, variant.dirName)
    println "****************************"
    println "variant: ${variant.name}"
    println "manifest:  ${variant.processResources.manifestFile}"
    println "aptOutput:  ${aptOutput}"
    println "****************************"

    android.sourceSets[getSourceSetName(variant)].java.srcDirs+= aptOutput.getPath()

    variant.javaCompile.options.compilerArgs += [
            '-processorpath', configurations.apt.getAsPath(),
            '-AandroidManifestFile=' + variant.processResources.manifestFile,
            '-s', aptOutput
    ]

    variant.javaCompile.source = variant.javaCompile.source.filter { p ->
        return !p.getPath().startsWith(aptOutputDir.getPath())
    }

    variant.javaCompile.doFirst {
        aptOutput.mkdirs()
    }
}

在构建 free 变体时,注释处理器会按照 gradle 输出中的以下指示运行:

Note: Starting AndroidAnnotations annotation processing

在构建 Pro 变体时,注释处理器不运行,因此对生成代码的引用失败。

奇怪的是,我发现(真的是偶然的)如果我从脚本中删除packageName "com.MyCompany.MyApp.Pro"....注释处理器会运行并且它会正确构建。我需要更新 Google Play 的包名。

在 android studio 中查看时,您可以看到 apt(注释处理工具)显示 Pro 版本处于活动状态,即使我有 FreeDebug 构建选择的变体。我不确定这是否表明存在问题,或者这是否只是 beta android studio(Android Studio 版本:0.2.13)的问题。因此,请持保留态度。

我是 gradle 构建系统的新手,但我认为我已经掌握了窍门。我一遍又一遍地查看脚本,我不明白为什么注释处理器没有为 pro 变体运行。除了使用 --info 和 --debug 参数运行包装器之外,我还不知道如何调试这些问题。

我已使用 -info-debug 运行 gradle 包装器以获取扩展输出,但那里没有任何内容表明任何其他错误(或缺少项目)直到它到达由缺少生成的代码引起的错误。所以这让我相信这只是 androidannotations 没有使用那个变体运行的事实,这是根本问题。 (即,我不认为这是由上游的某些事情引起的错误,后来被误报了。不过我可能是错的)

我真的很茫然,现在已经坚持了 2 天。

【问题讨论】:

    标签: android gradle android-studio android-annotations annotation-processing


    【解决方案1】:

    我能够解决问题。在仔细查看 gradle 包装器的 -info 输出后,我发现 androidAnnotations 正在尝试运行。错误输出的顺序不正确,因为注释处理消息出现在由引用不存在的代码(由于注释处理失败而不存在)引起的错误之后。

    这是日志:

    :MyCompany:compileProDebug
    ....\src\main\java\com\MyCompany\MyApp\Activities\activityMain.java:14: error: cannot find symbol
    import com.MyCompany.MyApp.Notifications.NotificationSetupActivity_;
                                                    ^
      symbol:   class NotificationSetupActivity_
      location: package com.MyCompany.MyApp.Notifications
    ....\src\main\java\com\MyCompany\MyApp\Activities\activityMain.java:24: error: cannot find symbol
    import com.MyCompany.MyApp.FantasyScores.ActivityScores_;
                                                    ^
      symbol:   class ActivityScores_
      location: package com.MyCompany.MyApp.Scores
    ....\src\main\java\com\MyCompany\MyApp\Activities\activityMain.java:32: error: cannot find symbol
    import com.MyCompany.MyApp.Team.activityTeamSelect_;
                                           ^
      symbol:   class activityTeamSelect_
      location: package com.MyCompany.MyApp.Team
    Note: Starting AndroidAnnotations annotation processing
    Note: AndroidManifest.xml file found: ....\build\manifests\pro\debug\AndroidManifest.xml
    error: The generated com.MyCompany.MyAppPro.R class cannot be found
    Note: Time measurements: [Whole Processing = 190 ms], [Extract Manifest = 129 ms], [Extract Annotations = 49 ms],
    ....\src\main\java\com\MyCompany\MyApp\Activities\activityMain.java:14: error: cannot find symbol
    import com.MyCompany.MyApp.Notifications.NotificationSetupActivity_;
    

    重要的几行是:

    注意:启动AndroidAnnotations注解处理

    注意:找到的 AndroidManifest.xml 文件:....\build\manifests\pro\debug\AndroidManifest.xml

    错误:找不到生成的 com.MyCompany.MyAppPro.R 类

    这些应该首先出现在错误日志中,因为注释处理器在完整编译步骤之前运行,但由于某种原因它们被埋得很深(可能是 androidannotations 处理器中的刷新问题??)

    无论如何,找不到com.MyCompany.MyAppPro.R 的第三行是关键。资源实际上在com.MyCompany.MyApp.R(没有专业版)。经过一番挖掘,我找到了this post,这表明这是 AndroidAnnotations 的一个已知问题。

    我能够通过将'-AresourcePackageName=MyBasePackageName', 参数添加到构建脚本来解决该问题。 注意:这仅在您使用 3.0 快照时有效。最新发布的 AndroidAnnotations 版本不支持 -AresourcePackageName 选项。

    添加参数后,所有变体都正确构建。

    构建脚本的 compilerArgs 部分现在如下所示:

    variant.javaCompile.options.compilerArgs += [
            '-processorpath', configurations.apt.getAsPath(),
            '-AandroidManifestFile=' + variant.processResources.manifestFile,
            '-AresourcePackageName=MyBasePackageName',
            '-s', aptOutput
    ]
    

    希望这将有助于其他人在未来避免这个问题。

    【讨论】:

    • 感谢您分享解决方案。
    • 太棒了!谢谢!有没有办法以编程方式提取基本包名称?
    • 早在 10 月,我就简单地看了看我是否能做到。这不是一件完全显而易见的事情,由于时间紧迫,我没有非常彻底地追求它。理论上应该可以拉进去,但我不知道该怎么做。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-03
    • 2020-05-13
    • 2013-03-13
    • 2017-07-15
    • 2018-07-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多