6

I'm trying to switch to using Kotlin DSL to get dependencies versions from an object Kotlin file instead of gradle files. When I do a gradle sync it is unable to resolve reference, but I'm able to click on file (Libraries) from build.gradle.kts . I haven't made any other changes to build.gradle or settings.gradle . The issue isn't specific to Jackson and I tried this in multiple projects and read documentation and searched for answers before posting the question.

I get a build.gradle.kts:15:20: Unresolved reference: Libraries

This is the structure of my project

build.gradle
settings.gradle
+buildSrc
    build.gradle.kts
    +src
        +main
            +kotlin
                Libraries.kt

This is the my build.gradle.kts file

import org.gradle.kotlin.dsl.`kotlin-dsl`

plugins {
    `kotlin-dsl`
    java
    `java-gradle-plugin`
}


repositories {
    mavenCentral()
}

dependencies {
    implementation(Libraries.Jackson.core)
//    implementation(Libraries.anotherJackson)
}

This is the kotlin Libraries.kt file

object Libraries {
    val Jackson = JacksonLibraries
    const val anotherJackson = "com.fasterxml.jackson.core:jackson-core:2.11.1"

}

object JacksonLibraries {
    const val core = "com.fasterxml.jackson.core:jackson-core:${Versions.Jackson.core}"
}

object Versions {
    object Jackson {
        const val core = "2.11.1"
        const val annotations = "2.11.1"
        const val databind = "2.11.1"
    }
}

If I try it without the Libraries file it works fine.

implementation("com.fasterxml.jackson.core:jackson-core:2.11.1")

But neither of these two work

implementation(Libraries.Jackson.core)
implementation(Libraries.anotherJackson)

Thanks in advance!

  • Does it work if you add `import Libraries` to the top of your root `build.gradle.kts`? – aSemy Mar 17 '22 at 23:00
  • Thanks but unfortunately, that doesn't fix the issue. – ConnectionistSystems Mar 18 '22 at 15:52
  • Ah, I think I see now. Are you trying to access `buildSrc/src/main/kotlin/Libraries.kt` in `buildSrc/build.gradle.kts`? Because that's not possible, and isn't necessary. – aSemy Mar 18 '22 at 19:47
  • @aSemy Would you please elaborate on why it is not possible? Also, I need Libraries to access dependencies names and version implementation. Do you have an alternative suggestion? Here are some sample tutorials online where it was implemented. https://medium.com/android-dev-hacks/kotlin-dsl-gradle-scripts-in-android-made-easy-b8e2991e2ba https://betterprogramming.pub/gradle-dependency-management-with-buildsrc-and-kotlin-dsl-1de958eab166 https://proandroiddev.com/better-dependencies-management-using-buildsrc-kotlin-dsl-eda31cdb81bf – ConnectionistSystems Mar 18 '22 at 20:41
  • 2
    Basically it's not possible to use `buildSrc/src/main/kotlin/Libraries.kt` in `buildSrc/build.gradle.kts` for the same reason you can't use `/src/main/kotlin/Libraries.kt` in `/build.gradle.kts`. The Gradle build scripts are used to build a project, so they can't use the output of the same project. However `buildSrc` [is treated as included build](https://docs.gradle.org/current/userguide/organizing_gradle_projects.html#sec:build_sources), so the contents of `buildSrc/src/main/...` will be available in `/build.gradle.kts`. – aSemy Mar 19 '22 at 12:13
  • 3
    It's possible to share versions between `buildSrc/build.gradle.kts` and `/build.gradle.kts` with [Version Catalogs](https://stackoverflow.com/q/67795324/4161471) or logic with [composite builds](https://docs.gradle.org/current/userguide/composite_builds.html#composite_build_intro), but I'm not clear on which you want. Could you explain a bit more about what you want to achieve? Are you planning on writing a Gradle task or plugin that needs the Jackson library? Do you just want to align versions, or do you also want to share logic? – aSemy Mar 19 '22 at 12:21
  • Thanks @aSemy for your explanation. I assigned a bounty to this question and I'm trying to give it to you, I think I might have to wait 7 days. I did manage to link to Libraries file when implementing from root/app/build.gradle Ultimately I have the following situation. We have multiple microservices application, each with its own build.gradle. I will have these libraries added to an SDK and where each build will link to the Libraries file which I will put in the SDK (an implemented library) and get the dependency versions. The SDK only contains java/kotlin files. Not sure of a better way? – ConnectionistSystems Mar 21 '22 at 13:42

1 Answers1

6

Are you trying to access ./buildSrc/src/main/kotlin/Libraries.kt in ./buildSrc/build.gradle.kts? Because that's not possible, and isn't necessary.

Basically it's not possible to use ./buildSrc/src/main/kotlin/Libraries.kt in ./buildSrc/build.gradle.kts for the same reason you can't use <root>/src/main/kotlin/Libraries.kt in ./<root>/build.gradle.kts. The Gradle build scripts can't use the output of the projects they're trying to build.

However buildSrc is treated as included build, so the contents of ./buildSrc/src/main/... will be available in <root>/build.gradle.kts

Version alignment

Version Catalogs

It's possible to share versions between ./buildSrc/build.gradle.kts and <root>/build.gradle.kts with Version Catalogs.

The libs.versions.toml file is the easiest way to do this.

In short,

  1. Use Gradle 7.4+
  2. Create a <root>/gradle/libs.versions.toml file
  3. Define your dependencies, e.g.
    [versions]
    groovy = "3.0.5"
    
    [libraries]
    groovy-core = { module = "org.codehaus.groovy:groovy", version.ref = "groovy" }
    
  4. In <root>/build.gradle.kts, or any <root>/settings.gradle.kts include(...)-ed subproject, you can now access the dependencies (you might need to refresh IntelliJ a few times for the auto-complete to load).
    dependencies {
      implementation(libs.groovy.core)
    }
    

You can use the same Version Catalog in any project by loading the file. If you wanted to host it and download it, that would work too!

Version Platform

If you want to align versions across several separated projects, you can follow the documentation here: https://docs.gradle.org/current/userguide/platforms.html

Version Platforms are a little more structured than Version Catalogs. They're kind of like Gradle's versions of Maven BOMs, except they're more flexible of course!

In short,

  1. Create a Gradle project, and apply the Java Platform Plugin and Maven Publish Plugin
  2. Define your constraints
  3. Publish it to a Maven repo
  4. Apply it to any project as a platform dependency
    dependencies {
      implementation(platform("my.company:our-own-version-platform:1.2.3"))
    
      // no need for a version, if our-own-version-platform provides it!
      implementation("org.codehaus.groovy:groovy") 
    }
    
aSemy
  • 5,485
  • 2
  • 25
  • 51
  • 2
    so after going the `libs.versions.toml` path I'm able to reference the versions/dependencies in `buildSrc/build.gradle.kts` but not in `buildSrc/src/main/kotlin/...` files – I added the definition to `buildSrc/settings.gradle.kts`, is there another place I need to put it? – kassim Apr 05 '22 at 13:38
  • That's not officially supported yet ([GitHub issue](https://github.com/gradle/gradle/issues/15383)). Either set up a Version Platform (which can use the `libs.versions.toml`), or try [a workaround](https://melix.github.io/blog/2021/03/version-catalogs-faq.html#_but_how_can_i_use_the_catalog_in_plugins_defined_in_buildsrc) – aSemy Apr 05 '22 at 13:49