Project not found when trying to share code between build and app

Greetings. I have a problem with Gradle in Android project. I want to share some filesystem paths or some other classes between build code and application code. I’ve read that it can be achieved with another build that should be included with includeBuild both in application project and in conventions project, and then implemented same way using implementation(...) with Maven coordinates (group and version).

So I’ve come up with a structure like this:

├── project
│ ├── app 
│ │ ├── src
│ │ └── build.gradle.kts
│ │    
│ ├── convention  
│ │ ├── plugins
│ │ │ ├── src  
│ │ │ └── build.gradle.kts
│ │ └── settings.gradle.kts
│ │
│ ├── shared  
│ │ ├── src/../..
│ │ │ ├── ...
│ │ │ └── SharedPaths.kt    <--- Paths to share
│ │ ├── build.gradle.kts    
│ │ └── settings.gradle.kts
└── settings.gradle.kts (project)

So in root project’s settings.gradle i have:

pluginManagement {  
    includeBuild("convention")  
    ...
}
includeBuild("shared")

Convention project’s settings.gradle:

...
includeBuild("../shared")  
rootProject.name = "convention"  
include(":plugins")
...

Shared project’s build.gradle:

group = "com.example"  
version "1.0.0"

Root project’s build.gradle:

dependencies {  
	...
	implementation("com.example:shared:1.0.0")
}

Plugins project’s build.gradle:

dependencies {  
    ...
    implementation("com.example:shared:1.0.0")  
}

And when I try to build project, this error happens:

Execution failed for task ':app:mergeDebugNativeLibs'.
> Could not resolve all files for configuration ':app:debugRuntimeClasspath'.
   > Failed to transform shared.jar (project :shared) to match attributes {artifactType=android-jni, org.gradle.category=library, org.gradle.dependency.bundling=external, org.gradle.jvm.environment=standard-jvm, org.gradle.jvm.version=17, org.gradle.libraryelements=jar, org.gradle.usage=java-runtime, org.jetbrains.kotlin.platform.type=jvm}.
      > project :shared not found.

I found out that error happens when shared project gets included both in conventions and in application modules - when I include it only once - the error is gone.

If I turn off configuration-cache in root gradle.properties project builds fine.

Test projects that I’ve created seemed to run fine, - it is my company’s project that fails. From what I can tell I configure builds all the same.

I also tried dependencySubstitution and it also didn’t help.

I am using AGP-8.13.2, kotlin-2.3.0 and gradle-9.2.1. I tried gradle-9.3.1, to no avail.

Some advice would be greatly appreciated! And thank you in advance.

Build with --stacktrace option
> Task :app:mergeDebugNativeLibs FAILED
Execution failed for task ':app:mergeDebugNativeLibs'.
> Could not resolve all files for configuration ':app:debugRuntimeClasspath'.
   > Failed to transform shared.jar (project :shared) to match attributes {artifactType=android-jni, org.gradle.category=library, org.gradle.dependency.bundling=external, org.gradle.jvm.environment=standard-jvm, org.gradle.jvm.version=17, org.gradle.libraryelements=jar, org.gradle.usage=java-runtime, org.jetbrains.kotlin.platform.type=jvm}.
      > project :shared not found.

* Try:
> Run with --info or --debug option to get more log output.
> Run with --scan to generate a Build Scan (powered by Develocity).
> Get more help at https://help.gradle.org.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':app:mergeDebugNativeLibs'.
	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:38)
	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:209)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
	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:166)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
	at org.gradle.execution.plan.DefaultNodeExecutor.executeLocalTaskNode(DefaultNodeExecutor.java:55)
	at org.gradle.execution.plan.DefaultNodeExecutor.execute(DefaultNodeExecutor.java:34)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:355)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:343)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.lambda$execute$0(DefaultTaskExecutionGraph.java:339)
	at org.gradle.internal.operations.CurrentBuildOperationRef.with(CurrentBuildOperationRef.java:84)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:339)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:328)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:459)
	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:376)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
	at org.gradle.internal.concurrent.AbstractManagedExecutor$1.run(AbstractManagedExecutor.java:47)
Caused by: org.gradle.api.internal.artifacts.ivyservice.TypedResolveException: Could not resolve all files for configuration ':app:debugRuntimeClasspath'.
	at org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactSetToFileCollectionFactory$NameBackedResolutionHost.consolidateFailures(ArtifactSetToFileCollectionFactory.java:194)
	at org.gradle.api.internal.artifacts.configurations.ResolutionHost.rethrowFailuresAndReportProblems(ResolutionHost.java:75)
	at org.gradle.api.internal.artifacts.configurations.ResolutionBackedFileCollection.maybeThrowResolutionFailures(ResolutionBackedFileCollection.java:86)
	at org.gradle.api.internal.artifacts.configurations.ResolutionBackedFileCollection.visitContents(ResolutionBackedFileCollection.java:76)
	at org.gradle.api.internal.file.AbstractFileCollection.visitStructure(AbstractFileCollection.java:361)
	at org.gradle.api.internal.file.CompositeFileCollection.lambda$visitContents$0(CompositeFileCollection.java:112)
	at org.gradle.api.internal.file.collections.UnpackingVisitor.add(UnpackingVisitor.java:66)
	at org.gradle.api.internal.file.collections.UnpackingVisitor.add(UnpackingVisitor.java:99)
	at org.gradle.api.internal.file.DefaultFileCollectionFactory$ResolvingFileCollection.visitChildren(DefaultFileCollectionFactory.java:311)
	at org.gradle.api.internal.file.CompositeFileCollection.visitContents(CompositeFileCollection.java:112)
	at org.gradle.api.internal.file.AbstractFileCollection.getFiles(AbstractFileCollection.java:124)
	at org.gradle.api.internal.file.AbstractFileCollection.iterator(AbstractFileCollection.java:165)
	at org.gradle.api.internal.file.FilteredFileCollection.iterator(FilteredFileCollection.java:80)
	at com.google.common.collect.ImmutableSet.copyOf(ImmutableSet.java:224)
	at org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection$2.visitCollection(DefaultConfigurableFileCollection.java:426)
	at org.gradle.api.internal.file.AbstractFileCollection.visitContents(AbstractFileCollection.java:366)
	at org.gradle.api.internal.file.AbstractFileCollection.visitStructure(AbstractFileCollection.java:361)
	at org.gradle.api.internal.file.CompositeFileCollection.lambda$visitContents$0(CompositeFileCollection.java:112)
	at org.gradle.api.internal.file.collections.UnpackingVisitor.add(UnpackingVisitor.java:66)
	at org.gradle.api.internal.file.collections.UnpackingVisitor.add(UnpackingVisitor.java:99)
	at org.gradle.api.internal.file.DefaultFileCollectionFactory$ResolvingFileCollection.visitChildren(DefaultFileCollectionFactory.java:311)
	at org.gradle.api.internal.file.CompositeFileCollection.visitContents(CompositeFileCollection.java:112)
	at org.gradle.api.internal.file.AbstractFileCollection.visitStructure(AbstractFileCollection.java:361)
	at org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection.lambda$calculateFinalizedValue$1(DefaultConfigurableFileCollection.java:423)
	at org.gradle.api.internal.file.collections.UnpackingVisitor.add(UnpackingVisitor.java:66)
	at org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection$UnresolvedItemsCollector.visitContents(DefaultConfigurableFileCollection.java:635)
	at org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection.calculateFinalizedValue(DefaultConfigurableFileCollection.java:423)
	at org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection.finalizeNow(DefaultConfigurableFileCollection.java:125)
	at org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection.lambda$visitChildren$2(DefaultConfigurableFileCollection.java:447)
	at org.gradle.api.internal.provider.ValueState.finalizeOnReadIfNeeded(ValueState.java:142)
	at org.gradle.api.internal.file.collections.DefaultConfigurableFileCollection.visitChildren(DefaultConfigurableFileCollection.java:447)
	at org.gradle.api.internal.file.CompositeFileCollection.visitContents(CompositeFileCollection.java:112)
	at org.gradle.api.internal.file.AbstractFileCollection.visitStructure(AbstractFileCollection.java:361)
	at org.gradle.api.internal.file.CompositeFileCollection.lambda$visitContents$0(CompositeFileCollection.java:112)
	at org.gradle.api.internal.file.collections.UnpackingVisitor.add(UnpackingVisitor.java:66)
	at org.gradle.api.internal.file.collections.UnpackingVisitor.add(UnpackingVisitor.java:91)
	at org.gradle.api.internal.file.DefaultFileCollectionFactory$ResolvingFileCollection.visitChildren(DefaultFileCollectionFactory.java:311)
	at org.gradle.api.internal.file.CompositeFileCollection.visitContents(CompositeFileCollection.java:112)
	at org.gradle.api.internal.file.AbstractFileCollection.visitStructure(AbstractFileCollection.java:361)
	at org.gradle.api.internal.file.CompositeFileCollection.lambda$visitContents$0(CompositeFileCollection.java:112)
	at org.gradle.api.internal.tasks.PropertyFileCollection.visitChildren(PropertyFileCollection.java:48)
	at org.gradle.api.internal.file.CompositeFileCollection.visitContents(CompositeFileCollection.java:112)
	at org.gradle.api.internal.file.AbstractFileCollection.visitStructure(AbstractFileCollection.java:361)
	at org.gradle.internal.fingerprint.impl.DefaultFileCollectionSnapshotter.snapshot(DefaultFileCollectionSnapshotter.java:48)
	at org.gradle.internal.execution.impl.DefaultInputFingerprinter$InputCollectingVisitor.visitInputFileProperty(DefaultInputFingerprinter.java:153)
	at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep$1.visitInputFileProperty(AbstractSkipEmptyWorkStep.java:109)
	at org.gradle.api.internal.tasks.execution.TaskExecution.visitRegularInputs(TaskExecution.java:332)
	at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.lambda$fingerprintPrimaryInputs$2(AbstractSkipEmptyWorkStep.java:105)
	at org.gradle.internal.execution.impl.DefaultInputFingerprinter.fingerprintInputProperties(DefaultInputFingerprinter.java:79)
	at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.fingerprintPrimaryInputs(AbstractSkipEmptyWorkStep.java:100)
	at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.execute(AbstractSkipEmptyWorkStep.java:57)
	at org.gradle.internal.execution.steps.AbstractSkipEmptyWorkStep.execute(AbstractSkipEmptyWorkStep.java:38)
	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.HandleStaleOutputsStep.execute(HandleStaleOutputsStep.java:75)
	at org.gradle.internal.execution.steps.HandleStaleOutputsStep.execute(HandleStaleOutputsStep.java:41)
	at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.lambda$execute$0(AssignMutableWorkspaceStep.java:35)
	at org.gradle.api.internal.tasks.execution.TaskExecution$4.withWorkspace(TaskExecution.java:297)
	at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.execute(AssignMutableWorkspaceStep.java:31)
	at org.gradle.internal.execution.steps.AssignMutableWorkspaceStep.execute(AssignMutableWorkspaceStep.java:22)
	at org.gradle.internal.execution.steps.ChoosePipelineStep.execute(ChoosePipelineStep.java:40)
	at org.gradle.internal.execution.steps.ChoosePipelineStep.execute(ChoosePipelineStep.java:23)
	at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.lambda$execute$2(ExecuteWorkBuildOperationFiringStep.java:67)
	at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.execute(ExecuteWorkBuildOperationFiringStep.java:67)
	at org.gradle.internal.execution.steps.ExecuteWorkBuildOperationFiringStep.execute(ExecuteWorkBuildOperationFiringStep.java:39)
	at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:46)
	at org.gradle.internal.execution.steps.IdentityCacheStep.execute(IdentityCacheStep.java:34)
	at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:44)
	at org.gradle.internal.execution.steps.IdentifyStep.execute(IdentifyStep.java:31)
	at org.gradle.internal.execution.impl.DefaultExecutionEngine$1.execute(DefaultExecutionEngine.java:64)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:132)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:121)
	at org.gradle.api.internal.tasks.execution.ProblemsTaskPathTrackingTaskExecuter.execute(ProblemsTaskPathTrackingTaskExecuter.java:41)
	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)
	... 23 more
Caused by: org.gradle.api.internal.artifacts.transform.TransformException: Failed to transform shared.jar (project :shared) to match attributes {artifactType=android-jni, org.gradle.category=library, org.gradle.dependency.bundling=external, org.gradle.jvm.environment=standard-jvm, org.gradle.jvm.version=17, org.gradle.libraryelements=jar, org.gradle.usage=java-runtime, org.jetbrains.kotlin.platform.type=jvm}.
	at org.gradle.api.internal.artifacts.transform.TransformedProjectArtifactSet.visit(TransformedProjectArtifactSet.java:95)
	at org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ParallelResolveArtifactSet$VisitingSet$StartVisitAction.visitResults(ParallelResolveArtifactSet.java:100)
	at org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ParallelResolveArtifactSet$VisitingSet.visit(ParallelResolveArtifactSet.java:69)
	at org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactSetToFileCollectionFactory$PartialSelectedArtifactSet.visitFiles(ArtifactSetToFileCollectionFactory.java:275)
	at org.gradle.api.internal.artifacts.configurations.ResolutionBackedFileCollection.visitContents(ResolutionBackedFileCollection.java:75)
	... 98 more
Caused by: java.lang.IllegalArgumentException: project :shared not found.
	at org.gradle.api.internal.project.DefaultProjectStateRegistry.stateFor(DefaultProjectStateRegistry.java:151)
	at org.gradle.api.internal.artifacts.transform.DefaultTransformInvocationFactory.determineProducerProject(DefaultTransformInvocationFactory.java:174)
	at org.gradle.api.internal.artifacts.transform.DefaultTransformInvocationFactory.createInvocation(DefaultTransformInvocationFactory.java:88)
	at org.gradle.api.internal.artifacts.transform.TransformStep.lambda$createInvocation$2(TransformStep.java:79)
	at org.gradle.internal.Try$Success.map(Try.java:170)
	at org.gradle.api.internal.artifacts.transform.TransformStep.createInvocation(TransformStep.java:69)
	at org.gradle.api.internal.artifacts.transform.TransformStepNode$InitialTransformStepNode$TransformInitialArtifact$1.transform(TransformStepNode.java:250)
	at org.gradle.api.internal.artifacts.transform.TransformStepNode$TransformStepBuildOperation.call(TransformStepNode.java:381)
	at org.gradle.api.internal.artifacts.transform.TransformStepNode$TransformStepBuildOperation.call(TransformStepNode.java:360)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:209)
	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:204)
	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:166)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:53)
	at org.gradle.api.internal.artifacts.transform.TransformStepNode$AbstractTransformArtifacts.calculateValue(TransformStepNode.java:354)
	at org.gradle.api.internal.artifacts.transform.TransformStepNode$AbstractTransformArtifacts.calculateValue(TransformStepNode.java:334)
	at org.gradle.internal.model.CalculatedValueContainer$CalculationState.lambda$attachValue$0(CalculatedValueContainer.java:227)
	at org.gradle.internal.Try.ofFailable(Try.java:46)
	at org.gradle.internal.model.CalculatedValueContainer$CalculationState.attachValue(CalculatedValueContainer.java:222)
	at org.gradle.internal.model.CalculatedValueContainer.finalizeIfNotAlready(CalculatedValueContainer.java:195)
	at org.gradle.internal.model.CalculatedValueContainer.run(CalculatedValueContainer.java:181)
	at org.gradle.api.internal.artifacts.transform.TransformStepNode.execute(TransformStepNode.java:183)
	at org.gradle.execution.plan.DefaultNodeExecutor.execute(DefaultNodeExecutor.java:31)
	... 10 more

As it complains about project :shared, I’d guess that you have some left-over project(":shared") dependency from a previous try somewhere.

Thanks for the answer! Hmm, I checked pretty thoroughly and can’t find any leftovers that not supposed to be there. Actually we have two production projects with similar structure where I can reproduce this error, so even if there was actually a wrong dependency declaration in both of them, shouldn’t this error happen even with configuration cache turned off? Additionally, I tried to clear most of the Gradle caches and error happens anyway. If I comment one of the dependency declarations or the other, project builds, but not when there are both of them uncommented.

Ah, right, hmmm.

Maybe build the MCVE the other way around?
Strip away stuff from one of the projects where it happens until either it does not happen anymore or you reached an MCVE that you can share.

Here, I created sample project where I managed to reproduce same error.
All that I needed to do is add org.gradle.configuration-cache=true to make it fail build (sorry, I thought it was enabled by default since some Gradle version) . I don’t know if configuration cache is really to blame here, but it is my only lead for now.
I thought it might be discrepancy between AGP and Gradle versions, but setting Gradle version to 8.13 and Kotlin version to 2.1.0 unfortunately changed nothing.

Logs actually always get printed regardless of configuration cache and build fails pretty late on tasks mergeDebugNativeLibs and mergeLibDexDebug.
Now that I think about it, maybe it’s more of an Android problem rather than Gradle problem.

sorry, I thought it was enabled by default since some Gradle version

Not yet, it is “just” per default in the gradle.properties if you use the init task to bootstrap a new project since some versions.

I don’t know if configuration cache is really to blame here, but it is my only lead for now.

I think so.

Now that I think about it, maybe it’s more of an Android problem rather than Gradle problem.

Actually not, you can completely remove Android and Kotlin from the equation and get the very same result, hence your example is not yet “minimal”. :smiley:

This reproduces the behavior you described just as well and you should report it as bug if there is none yet:

./app/build.gradle.kts
plugins {
    alias(libs.plugins.convention.android.application)
    java
}
java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

abstract class Foo : TransformAction<TransformParameters.None> {
    @get:InputArtifact
    abstract val inputArtifact: Provider<FileSystemLocation>

    override fun transform(outputs: TransformOutputs) {
        outputs.file(inputArtifact)
    }
}

configurations.compileClasspath {
    attributes {
        attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, "foo")
    }
}

dependencies {
    registerTransform(Foo::class) {
        from.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, "jar")
        to.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, "foo")
    }
    implementation("com.example:shared:1.0.0")
}

./app/src/main/java/com/example/sharedclasstest/MainActivity.java
package com.example.sharedclasstest;

import com.example.shared.SharedClass;

class MainActivity {
    void onCreate() {
        System.out.println("Activity:" + SharedClass.INTEGER);
    }
}

./build.gradle.kts

./convention/plugins/build.gradle.kts
plugins {
    `java-gradle-plugin`
}

java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

dependencies {
    implementation("com.example:shared:1.0.0")
}

gradlePlugin {
    plugins {
        // conventions
        register("AndroidApplication") {
            id = libs.plugins.convention.android.application.get().pluginId
            implementationClass = "AndroidApplicationConventionPlugin"
        }
    }
}

./convention/plugins/src/main/java/AndroidApplicationConventionPlugin.java
import com.example.BuildLogicClass;
import com.example.shared.SharedClass;
import org.gradle.api.Plugin;
import org.gradle.api.Project;

class AndroidApplicationConventionPlugin implements Plugin<Project> {
    @Override
    public void apply(Project target) {
        System.out.println("Plugin: " + new BuildLogicClass().testBuild());
        System.out.println("Plugin direct: " + SharedClass.INTEGER);

    }
}

./convention/plugins/src/main/java/com/example/BuildLogicClass.java
package com.example;

import com.example.shared.SharedClass;

public class BuildLogicClass {
    public int testBuild() {
        return SharedClass.INTEGER;
    }
}

./convention/settings.gradle.kts
pluginManagement {
    repositories {
        google {
            content {
                includeGroupByRegex("com\\.android.*")
                includeGroupByRegex("com\\.google.*")
                includeGroupByRegex("androidx.*")
            }
        }
        mavenCentral()
        gradlePluginPortal()
    }
}

dependencyResolutionManagement {

    repositories {
        google()
        mavenCentral()
    }

    versionCatalogs {
        create("libs") {
            from(files("../gradle/libs.versions.toml"))
        }
    }
}

includeBuild("../shared")

rootProject.name = "convention"
include(":plugins")
./settings.gradle.kts
pluginManagement {

    includeBuild("convention")

    repositories {
        google {
            content {
                includeGroupByRegex("com\\.android.*")
                includeGroupByRegex("com\\.google.*")
                includeGroupByRegex("androidx.*")
            }
        }
        mavenCentral()
        gradlePluginPortal()
    }
}

dependencyResolutionManagement {

    repositoriesMode = RepositoriesMode.FAIL_ON_PROJECT_REPOS

    repositories {
        google()
        mavenCentral()
    }
}

includeBuild("shared")
rootProject.name = "SharedClassTest"
include(":app")
./shared/build.gradle.kts
plugins {
    java
}
java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

group = "com.example"
version "1.0.0"

./shared/settings.gradle.kts
pluginManagement {
    repositories {
        google {
            content {
                includeGroupByRegex("com\\.android.*")
                includeGroupByRegex("com\\.google.*")
                includeGroupByRegex("androidx.*")
            }
        }
        mavenCentral()
        gradlePluginPortal()
    }
}

dependencyResolutionManagement {

    repositories {
        google()
        mavenCentral()
    }

    versionCatalogs {
        create("libs") {
            from(files("../gradle/libs.versions.toml"))
        }
    }
}

rootProject.name = "shared"
./shared/src/main/java/com/example/shared/SharedClass.java
package com.example.shared;

public class SharedClass {
    public static int INTEGER = 10;
}

Also if you reusing the CC entry by rerunning the build after it failed, you also see that shared is not built. I guess this is somehow because shared is used in the included build and in the including build and CC somehow gets confused about that.

Sound definitely like a Gradle bug to me.

Also with Gradle 7.6.6 it works just fine and just breaks since 8.0.
I’m actually slightly surprised noone else hit that bug before.
But well, most probably do not share code between build logic and production logic, there should not be too many use-cases for that.

Thank you for your time and detailed answer. I filed an issue on GitHub and referenced your code there. I will mark your answer as a solution for a time being, until one day it gets fixed.

1 Like

My paste was not complete though, e. g. the version catalog and properties file were not included, as I didn’t change them.