1
1
記事投稿キャンペーン 「2024年!初アウトプットをしよう」

kaptからKSPに移行しようとしてコケました

Last updated at Posted at 2024-01-04

表題のままなのですが、備忘録として解決方法を残しておきます。

Environment

  • Android Studio Hedgehog
  • AGP 8.2.0
  • Hilt 2.50
  • KSP 1.9.21-1.0.16

ちなみにプロジェクトの構造はnowinandroidを参考に作っています。

Problem

HiltがKSPをサポートするようになったので、公式のマイグレーションガイドに従ってkaptからKSPに移行したところ、ビルドでコケてしまいました。

エラー内容
Some problems were found with the configuration of task ':core:api:kspDevelopDebugKotlin' (type 'KspTaskJvm').
- Gradle detected a problem with the following location: '/Users/myname/project/module/build/generated/source/buildConfig/develop/debug/jp/co/project/module/BuildConfig.java'.

* Try:
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.

* Exception is:
org.gradle.internal.execution.WorkValidationException: Some problems were found with the configuration of task ':core:api:kspDevelopDebugKotlin' (type 'KspTaskJvm').
- Gradle detected a problem with the following location: '/Users/myname/project/module/build/generated/source/buildConfig/develop/debug/jp/co/project/module/BuildConfig.java'.

Reason: Task ':core:api:kspDevelopDebugKotlin' uses this output of task ':core:api:generateDevelopDebugBuildConfig' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.

Possible solutions:
1. Declare task ':core:api:generateDevelopDebugBuildConfig' as an input of ':core:api:kspDevelopDebugKotlin'.
2. Declare an explicit dependency on ':core:api:generateDevelopDebugBuildConfig' from ':core:api:kspDevelopDebugKotlin' using Task#dependsOn.
3. Declare an explicit dependency on ':core:api:generateDevelopDebugBuildConfig' from ':core:api:kspDevelopDebugKotlin' using Task#mustRunAfter.

For more information, please refer to https://docs.gradle.org/8.2/userguide/validation_problems.html#implicit_dependency in the Gradle documentation.
- Gradle detected a problem with the following location: '/Users/myname/project/module/build/generated/source'.

Reason: Task ':core:api:kspDevelopDebugKotlin' uses this output of task ':core:api:generateDevelopDebugBuildConfig' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.

Possible solutions:
1. Declare task ':core:api:generateDevelopDebugBuildConfig' as an input of ':core:api:kspDevelopDebugKotlin'.
2. Declare an explicit dependency on ':core:api:generateDevelopDebugBuildConfig' from ':core:api:kspDevelopDebugKotlin' using Task#dependsOn.
3. Declare an explicit dependency on ':core:api:generateDevelopDebugBuildConfig' from ':core:api:kspDevelopDebugKotlin' using Task#mustRunAfter.

For more information, please refer to https://docs.gradle.org/8.2/userguide/validation_problems.html#implicit_dependency in the Gradle documentation.
at org.gradle.internal.execution.WorkValidationException$BuilderWithSummary.build(WorkValidationException.java:133)
at org.gradle.internal.execution.WorkValidationException$BuilderWithSummary.get(WorkValidationException.java:115)
at org.gradle.internal.execution.steps.ValidateStep.throwValidationException(ValidateStep.java:162)
at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:86)
at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:49)
at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:71)
at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:45)
at org.gradle.internal.execution.steps.SkipEmptyWorkStep.executeWithNonEmptySources(SkipEmptyWorkStep.java:177)
at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:86)
at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:53)
at org.gradle.internal.execution.steps.RemoveUntrackedExecutionStateStep.execute(RemoveUntrackedExecutionStateStep.java:32)
at org.gradle.internal.execution.steps.RemoveUntrackedExecutionStateStep.execute(RemoveUntrackedExecutionStateStep.java:21)
at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:38)
at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:36)
at org.gradle.internal.execution.steps.LoadPreviousExecutionStateStep.execute(LoadPreviousExecutionStateStep.java:23)
at org.gradle.internal.execution.steps.CleanupStaleOutputsStep.execute(CleanupStaleOutputsStep.java:75)
at org.gradle.internal.execution.steps.CleanupStaleOutputsStep.execute(CleanupStaleOutputsStep.java:41)
at org.gradle.internal.execution.steps.AssignWorkspaceStep.lambda$execute$0(AssignWorkspaceStep.java:32)
at org.gradle.api.internal.tasks.execution.TaskExecution$4.withWorkspace(TaskExecution.java:293)
at org.gradle.internal.execution.steps.AssignWorkspaceStep.execute(AssignWorkspaceStep.java:30)
at org.gradle.internal.execution.steps.AssignWorkspaceStep.execute(AssignWorkspaceStep.java:21)
at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:37)
at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:27)
at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:47)
at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:34)
at org.gradle.internal.execution.impl.DefaultExecutionEngine$1.execute(DefaultExecutionEngine.java:64)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:146)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:135)
at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:51)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:74)
at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:199)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:73)
at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:42)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:337)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:324)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:317)
at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:303)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:463)
at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:380)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)


BUILD FAILED in 32s
958 actionable tasks: 957 executed, 1 up-to-date

Reason

いろいろ調べた結果、BuildConfig generated class is not visible to KSPに辿り着きました…。

User trying to adopt the KSP version of Dagger & Hilt are running into missing classes issues because the BuildConfig generated class is not an input to KSP. They report the issue to Dagger because it worked fine in KAPT but Dagger does not control the wiring between the BuildConfig generating task and annotation processing tasks.

そういえばエラーが吐かれたモジュールでBuildConfig使ってますね。

該当のモジュールのbuild.gradle.ktsファイルは以下のような感じです。

android {
    namespace = "hogehoge"

    buildFeatures {
        buildConfig = true
    }

    defaultConfig {
        buildConfigField(
            type = "String",
            name = "BASE_URL",
            value = "\"https://fugafuga.net\"",
        )
    }
}

dependencies {
    // 省略
}

エラーでもReason: Task ':core:api:kspDevelopDebugKotlin' uses this output of task ':core:api:generateDevelopDebugBuildConfig' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.と言っているので、どうやら原因はこれっぽいですね。

Solution

該当モジュールのbuild.gradle.ktsファイルにスニペットをありがたくコピペさせていただきました🙏

androidComponents {
    onVariants(selector().all()) { variant ->
        afterEvaluate {
            // This is a workaround for https://issuetracker.google.com/301244513 which depends on internal
            // implementations of the android gradle plugin and the ksp gradle plugin which might change in the future
            // in an unpredictable way.
            val variantNameCapitalized = variant.name.uppercaseFirstChar()
            val buildConfigTaskName = "generate${variantNameCapitalized}BuildConfig"
            val buildConfigTask = this.project.tasks.named(buildConfigTaskName)
                .get() as com.android.build.gradle.tasks.GenerateBuildConfig

            project.tasks.getByName("ksp${variantNameCapitalized}Kotlin") {
                (this as org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool<*>).setSource(
                    buildConfigTask.sourceOutputDir,
                )
            }
        }
    }
}

スニペットを追記したらビルドが通るようになりました🙌

gradleを雰囲気で使っていてよくわかってないので解決に時間がかかってしまいました…。

いつか公式でサポートされるかもしれないですが、いったん応急処置ということで🙏🩹

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1