openlang

Kotlin DSL로 옮기자 서브프로젝트가 implementation을 못 찾는다

오래된 멀티 프로젝트 빌드를 Groovy DSL에서 Kotlin DSL로 옮기는 중입니다. 루트 build.gradle에는 이런 블록이 있었습니다.

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

루트는 기계적으로 옮겼습니다.

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

순서대로 정리하겠습니다.

루트 스크립트는 컴파일됩니다. 여기는 문제가 없습니다.

서브프로젝트 core/build.gradle.kts에서는 dependencies 안의 implementation(project(":util")) 줄이 implementation을 찾지 못한다는 unresolved reference로 스크립트 컴파일을 멈춥니다. Groovy에서는 같은 줄이 잘 돌았습니다.

설명이 안 되는 건 세 번째입니다. 같은 파일 맨 위에 plugins { id("java-library") }를 넣으면 에러가 사라집니다. 루트가 이미 그 플러그인을 적용하고 있는데도 말입니다. 플러그인도 같고 프로젝트도 같은데 왜 접근자만 없어지는 겁니까? 그리고 서브프로젝트마다 plugins 블록을 반복하는 게 정말 의도된 해법입니까?

영어에서 번역원문 보기

이어지는 대화 2

서로의 근거를 따라
  1. 고유 링크

    plugins 블록에 넣는 게 맞아요. 다만 서브프로젝트마다 복사하지는 마세요.

    Gradle은 그 스크립트 자신의 plugins 블록이 적용한 것만 보고 접근자를 만들어요. apply(plugin = ...)나 루트의 subprojects 블록처럼 다른 길로 들어온 플러그인은 실행할 때는 멀쩡히 동작하지만 접근자는 안 생겨요. 문서에도 딱 그 경우들이 적혀 있어요.

    subprojects 블록은 지우고 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"))
    }

    서브프로젝트의 plugins 블록이 컨벤션 플러그인을 적용하고, 그게 java-library를 끌고 오니까 접근자도 같이 생겨요.

    영어에서 번역원문 보기
  2. 고유 링크

    최종 형태로는 동의해요. 다만 일부 서브프로젝트가 아직 루트 블록에서 플러그인을 받는 동안에는, Kotlin DSL에 접근자 없이 쓰는 대체 방법이 있어요.

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

    읽기는 더 나쁘고, 문자열에 오타가 나면 빌드를 실행할 때에야 드러나요(모르는 configuration 이름은 스크립트 컴파일이 아니라 그 시점에 실패해요). 옮기는 동안에는 감수할 만한 비용이지만 그 뒤까지 남길 건 아니에요.

    영어에서 번역원문 보기

같은 질문의 다른 갈래

  1. 일부러 망가뜨린 패키지가 tryEval을 통과했다

    오버레이의 패키지마다 builtins.tryEval을 씌우고 실패하는 것만 나열하는 작은 점검 스크립트를 짰어요. 그런데 전부 괜찮다고 나왔어요. 의존성 목록에 throw를 넣어 일부러 망가뜨린 패키지까지요. 항목을 끝까지…

    답글 4nix
  2. for_each 키는 이름표가 아니라 주소다

    for_each 키를 이름표로 보면 안 된다. 리소스 주소의 절반이다. terraform_data.queue["prod-orders"] 같은 주소로 state가 객체를 추적한다. 키를 바꾸면 plan은 이름이 바뀌었다고 보지…

    답글 6hcl
  3. 정지 이벤트에서 소비자를 띄우는 규칙

    멈춘 프로세스를 끝난 것으로 치는 감독 규칙에 대해 질문을 받았는데, 작은 재현 하나면 문제가 바로 보여요. 셸 단계가 입력 파일을 쓰고, 그 뒤에 소비자가 예약돼 있어요. 쓰는 쪽이 중간에 일시 정지돼요. 감독자는 정지 이…