如何在Android Gradle构建文件中配置kapt以生成Java17 Java存根

14

我目前的Android项目显示以下的构建信息:

> Task :shared:resource:kaptGenerateStubsProductionDebugKotlin
'compileProductionDebugJavaWithJavac' task (current target is 17) and 'kaptGenerateStubsProductionDebugKotlin' task (current target is 1.8) jvm target compatibility should be set to the same Java version.
By default will become an error since Gradle 8.0+! Read more: https://kotl.in/gradle/jvm/target-validation
Consider using JVM toolchain: https://kotl.in/gradle/jvm/toolchain

如何配置kapt以在特定版本的Java中生成存根?

我已经尝试过...

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KaptGenerateStubs).configureEach {
    kotlinJavaToolchain.jdk.use(
            "/usr/local/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home",
            JavaVersion.VERSION_17
    )
}

并且

kapt {
    javacOptions {
        option("--target", 17)
    }
}

这些都没有任何影响

在Android项目中,是否可以控制由kapt生成的存根的Java版本?

在启用了kapt3的详细日志记录后,我现在可以看到我已经正确配置了目标

Javac options: {--target=17, --source=17}

另外

[INFO] All Javac options: {-Adagger.fastInit=enabled=-Adagger.fastInit=enabled, -Adagger.hilt.android.internal.disableAndroidSuperclassValidation=true=-Adagger.hilt.android.internal.disableAndroidSuperclassValidation=true, -Adagger.hilt.android.internal.projectType=LIBRARY=-Adagger.hilt.android.internal.projectType=LIBRARY, -ASomeKaptArgument=ArgumentValue=-ASomeKaptArgument=ArgumentValue, -Akapt.kotlin.generated=/Users/frank/github/mobile-android-practiceupdate/shared/resource/build/generated/source/kaptKotlin/productionDebug=-Akapt.kotlin.generated=/Users/frank/github/mobile-android-practiceupdate/shared/resource/build/generated/source/kaptKotlin/productionDebug, -Adagger.hilt.internal.useAggregatingRootProcessor=false=-Adagger.hilt.internal.useAggregatingRootProcessor=false, --target=17, --source=17, -proc:=only, accessInternalAPI=true,.....

然而,我仍然看到上面的构建消息。

为什么kapt忽略了我的javacOptions

要重现此问题:

主项目gradle

plugins {
    id 'com.android.application' version '8.0.0-alpha11' apply false
    id 'com.android.library' version '8.0.0-alpha11' apply false
    id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
    id 'com.google.dagger.hilt.android' version '2.44.2' apply false
}

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

Gradle包装器

#Tue Oct 25 07:38:32 BST 2022
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

Gradle JDK

enter image description here

然后在您的项目中设置Java版本为17,使用kapt来在任何应用程序或子模块中使用room或hilt。

    plugins {
        id 'com.android.application'
        id 'org.jetbrains.kotlin.android'
        id 'dagger.hilt.android.plugin'
        id "org.jetbrains.kotlin.kapt"
    }
    
    android {
        kapt {
            javacOptions {
                option("--target", "17")
            }
        }
        kotlinOptions {
            jvmTarget = '17'
            freeCompilerArgs += [
                    "-Xcontext-receivers",
                    "-opt-in=androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi",
                    "-opt-in=kotlinx.coroutines.ObsoleteCoroutinesApi"]
        }
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_17
            targetCompatibility JavaVersion.VERSION_17
            coreLibraryDesugaringEnabled true
        }
        namespace 'com.my.app'
        compileSdk 33
        buildToolsVersion "33.0.1"
    
        defaultConfig {
            applicationId "com.my.app"
            minSdk 26
            targetSdk 33
            versionCode 3
            versionName "3.0"
    
            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
            vectorDrawables {
                useSupportLibrary true
            }
        }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    flavorDimensions "default"
    productFlavors {
        development {
            dimension "default"
        }
        staging {
            dimension "default"
        }
        production {
            dimension "default"
        }
    }
     buildFeatures {
        compose true
    }
    composeOptions {
        kotlinCompilerExtensionVersion '1.4.0-dev-k1.8.0-33c0ad36f83'
    }
    packagingOptions {
        resources {
            excludes += '/META-INF/{AL2.0,LGPL2.1}'
        }
    }
}

dependencies {

    coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.0'

    implementation 'org.conscrypt:conscrypt-android:2.5.2'

    implementation 'com.google.dagger:hilt-android:2.44.2'
    kapt 'com.google.dagger:hilt-android-compiler:2.44.2'
    kapt 'androidx.hilt:hilt-compiler:1.0.0'

}

这些是我的 gradle.properties 文件

# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx8192m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
android.defaults.buildfeatures.buildconfig=true
kapt.verbose=true
# positive value will enable caching
# use the same value as the number of modules that use kapt
kapt.classloaders.cache.size=5

# disable for caching to work
kapt.include.compile.classpath=false
kapt.incremental.apt=false

Android Studio的版本是:

Android Studio Flamingo | 2022.2.1 Canary 11
Build #AI-222.4459.24.2221.9445173, built on December 30, 2022
Runtime version: 17.0.4.1+0-17.0.4.1b469.62-9127311 x86_64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
macOS 12.6.1
GC: G1 Young Generation, G1 Old Generation
Memory: 4096M
Cores: 12
Metal Rendering is ON
Registry:
    external.system.auto.import.disabled=true
    ide.text.editor.with.preview.show.floating.toolbar=false
    gradle.version.catalogs.dynamic.support=true
    ide.images.show.chessboard=true

Non-Bundled Plugins:
    com.android.aas (3.5.1)
    com.jetbrains.kmm (0.5.1(222)-30)

我已经创建了这个bug 报告,并附上了一个示例android项目。

更新

通过将以下内容添加到我的项目级别的build.gradle文件中,消息消失了:

subprojects {
    tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) {
        kotlinOptions.jvmTarget = "17"
    }
}

1
你能否提供一个 [mre] 或者至少更多关于你的 Gradle 设置的细节,以便我们了解引用信息的原因? - Chriki
如果Jetbrains没有在Kotlin 1.8.0中破坏kapt的kotlinOptions.jvmTarget配置支持并拒绝修复它,这甚至不会成为一个问题:https://youtrack.jetbrains.com/issue/KT-55947/Unable-to-set-kapt-jvm-target-version - Uli
3个回答

16

复现

(注意:Google问题跟踪器不允许下载ZIP文件,您是否在那里勾选了某个复选框来隐藏它?ZIP文件中没有任何机密信息)

因此,使用半相关Gradle问题中提供的示例,我能够通过gradlew assemble进行复现。

调查

此时,我正在寻找kapt任务如何获取Java版本,因为它应该毫不犹豫地选择kotlinOptions { jvmTarget = '17' }

源代码

为此,我需要源代码,但是在使用.gradle文件时无法获得。必须将build.gradle文件转换为build.gradle.kts,以便Android Studio在“外部库>Kotlin脚本依赖项”下导入插件类路径上的JAR文件。这意味着我们可以浏览Kotlin、AGP和Gradle的源代码。因此,我将根目录下的build.gradle更改为build.gradle.kts(导入所有相关插件),使其读取:

plugins {
    id("com.android.application") version "8.0.0-alpha11" apply false
    id("org.jetbrains.kotlin.android") version "1.8.0" apply false
}

(提示:声明一个 AGP 插件就足以锁定所有 com.android.* 插件的版本。)

阅读代码

有问题的任务是 kaptGenerateStubsDebugKotlin,所以任务类名应该包含 GenStub,确实有 org.jetbrains.kotlin.gradle.internal.KaptGenerateStubsTask,它扩展了 KotlinCompile,你好老朋友!KaptGenerateStubsTask.setupCompilerArgs 看起来是一个不错的起点。

调试设置

此时在执行过程中阅读代码并查看值更容易,因此我开始了调试会话:

gradlew cleanKaptGenerateStubsDebugKotlin assemble --no-daemon -Dorg.gradle.debug=true

在Android Studio中,选择Run > Edit Configurations... > + > Remote JVM Debug(默认设置即可)> OK。然后选择刚创建的“Unnamed”运行配置,并按下绿色的bug(Debug)按钮。

调试注意事项

setupCompilerArgs的行为:

  • contributeArguments 进行了很多设置
    • args.jvmTarget 最初为 null
    • compilerOptions.jvmTarget.get() 为 17(在这种情况下,compilerOptions 是 kotlinc 任务)
    • (compilerOptions 作为 KotlinJvmCompilerOptionsDefault)。fillDefaultValues(args)清除 args.jvmTarget(已经清除)
    • compilerOptions.fillCompilerArguments(args) 设置 args.jvmTarget = compilerOptions.jvmTarget.orNull?.target(wohoo,我们有了 17!)
  • (compilerOptions as KotlinJvmCompilerOptionsDefault)。fillCompilerArguments(args)
    • 设置 args.jvmTarget = compilerOptions.jvmTarget.orNull?.target(wtf,我们又回到了null

结论

因此,在这一点上,我们知道问题是 Kapt 的不从全局的继承,这听起来像是一个 KGP bug,只有在您的 repro 中使用不同的目标时才会出现。

我很好奇这是在哪里设置的,搜索 jvmTarget.set 只返回了 AndroidProjectHandler,听起来非常相关。查看对 wireExtensionOptionsToCompilation 的调用,它们只设置了 kotlinCompile,而没有设置 kapt 任务。

解决方法

有了这个知识,我唯一看到的选择是

// TODO remove this once https://youtrack.jetbrains.com/issue/KT-.... is fixed
tasks.withType(org.jetbrains.kotlin.gradle.internal.KaptGenerateStubsTask).configureEach {
    kotlinOptions.jvmTarget = '17'
}

(如果您不想引用internal类,请使用Kapt任务的超类KotlinCompile,它将配置更多内容,而不仅仅是有问题的部分。)

报告

请将此问题报告给YouTrack!目前只有JetBrains能够修复此问题。不幸的是,我对修复没有太高的期望,因为Google正在接管KGP的Android部分(早期阶段);希望他们不会重新实现同样的问题。

解决方案

根据JetBrains的建议,这也可以解决该问题,但它强制用户使用相同的JDK和目标字节码版本:

kotlin {
    jvmToolchain(17)
}

注意

Kotlin 1.8 添加了一种新的DSL来设置这些内容,但是目前仅支持任务级别,还不支持模块级别,请参见https://kotlinlang.org/docs/whatsnew18.html#limitations以及该部分上方的大绿色提示。


1
感谢查看,我已经“发现”了一个类似的修复方法,请参见更新的问题。 - Hector
我不确定这是否正确 https://youtrack.jetbrains.com/issue/KTIJ-24311/task-current-target-is-17-and-kaptGenerateStubsProductionDebugKotlin-task-current-target-is-1.8-jvm-target-compatibility-should - Hector
1
更详细的信息可以帮助诊断问题,但由于它链接到这里,我想在那里不需要重复所有这些文本。注意:这是KGP中的一个错误,已在KT项目中跟踪,KTIJ用于IntelliJ问题,这是Gradle问题(它在控制台中重现)。 - TWiStErRob
1
这确实是KGP中的一个错误,但Jetbrains目前拒绝修复。我猜这只是取决于Kotlin开发人员对此有多恼火:https://youtrack.jetbrains.com/issue/KT-55947/Unable-to-set-kapt-jvm-target-version 对我来说,听起来他们在进行1.8.0重构期间遇到了问题,并认为摆脱kapt中的kotlinOptions.jvmTarget支持是一条捷径。 - Uli

1

我已经更新了我的Android Studio版本至

Android Studio Giraffe | 2022.3.1 Canary 1
Build #AI-223.4884.69.2231.9486165, built on January 13, 2023
Runtime version: 17.0.5+0-17.0.5b653.23-9410051 x86_64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
macOS 12.6.1
GC: G1 Young Generation, G1 Old Generation
Memory: 4096M
Cores: 12
Metal Rendering is ON
Registry:
    external.system.auto.import.disabled=true
    ide.text.editor.with.preview.show.floating.toolbar=false
    ide.images.show.chessboard=true

Non-Bundled Plugins:
    com.android.aas (3.5.1)

并升级到gradle

plugins {
    id 'com.android.application' version '8.1.0-alpha01' apply false
    id 'com.android.library' version '8.1.0-alpha01' apply false
    id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
    id 'com.google.dagger.hilt.android' version '2.44.2' apply false
}

tasks.register('clean') {
    delete rootProject.buildDir
}

和Gradle包装器

#Tue Oct 25 07:38:32 BST 2022
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-rc-1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

所有这些操作都导致了我的问题得到了解决。

0
我是一台专业的翻译引擎,请将以下英文内容翻译成中文:

我用以下方法解决了这个问题: 在项目模块的 build.gradle 文件中,我添加了以下插件:

plugins {
    id 'com.android.application' version '8.0.0' apply false
    id 'com.android.library' version '8.0.0' apply false
    id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
    id 'com.google.dagger.hilt.android' version '2.44' apply false
}

那些插件只是提供信息而已,我并没有对它们进行任何操作。
app modulebuild.gradle 文件中,
我没有修改过这个 compileOptions。

compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

我刚刚添加了这个注释

        kotlin {
                // Or shorter:
                jvmToolchain(8)
        }

并注释此注解

//    kotlinOptions {
//        jvmTarget = '1.8'
//    }

在 settings.gradle 文件中,我在文件中间添加了以下代码:
plugins {
    id 'org.gradle.toolchains.foojay-resolver-convention' version '0.4.0'
}

在不同的来源中找到了这些代码片段


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接