openlang

After the Kotlin DSL move, subprojects can no longer find implementation

Moving an old multi-project build from the Groovy DSL to the Kotlin DSL. The root build.gradle had this block.

subprojects {
    apply plugin: 'java-library'
    repositories { mavenCentral() }
}

The root I converted mechanically.

subprojects {
    apply(plugin = "java-library")
    repositories { mavenCentral() }
}

In order, then.

The root script compiles. No problem there.

In the subproject core/build.gradle.kts, the line implementation(project(":util")) inside dependencies stops script compilation with an unresolved reference to implementation. The same line worked under Groovy.

Case three is the one I can't explain. Put plugins { id("java-library") } at the top of that same file and the error goes away, even though the root was already applying the plugin. Same plugin, same project, so why do only the accessors disappear? And is repeating a plugins block in every subproject really the intended fix?

后续讨论 2

顺着彼此的依据读下去
  1. 固定链接

    Plugins block, yes. Not copied into every subproject though.

    Gradle builds the accessors from what that script's own plugins block applies. A plugin that arrives any other way, apply(plugin = ...) or a root subprojects block, works fine at run time and gets no accessors. The docs list exactly those cases.

    Delete the subprojects block and put one convention plugin in buildSrc.

    // buildSrc/build.gradle.kts
    plugins {
        `kotlin-dsl`
    }
    repositories { gradlePluginPortal() }
    
    // buildSrc/src/main/kotlin/java-conventions.gradle.kts
    plugins {
        `java-library`
    }
    repositories { mavenCentral() }
    
    // core/build.gradle.kts
    plugins {
        id("java-conventions")
    }
    dependencies {
        implementation(project(":util"))
    }

    The subproject's plugins block applies the convention plugin, that pulls in java-library, and the accessors come with it.

  2. 固定链接

    Agreed as the end state. While some subprojects still get the plugin from the root block, though, the Kotlin DSL has a fallback that needs no accessors.

    dependencies {
        "implementation"(project(":util"))
    }
    configure<JavaPluginExtension> {
        toolchain.languageVersion.set(JavaLanguageVersion.of(17))
    }

    It reads worse, and a typo in the string only shows up when the build runs (an unknown configuration name fails at that point, not during script compilation). That cost is fine for the length of the migration and not after it.

同一个问题的其他角度

  1. Launching the consumer on a stopped event

    Got a question about a supervisor rule that treats a stopped process as a finished one, and a tiny repro makes the problem ob…

    回复 17最近活动 bashpython
  2. What does a --hash line actually pin?

    A requirements file with --hash on every line installs cleanly on my laptop and fails with a hash mismatch in a fresh Linux c…

    回复 8最近活动 python
  3. for_each keys are addresses, not labels

    A for_each key isn't a label. It's half of the resource address, terraform_data.queue["prod-orders"], and the state tracks th…

    回复 6最近活动 hcl