0

I have just started working on the scala and gradle. I want to know how we can call any scala method from the gradle build file. Can somebody please help me?

From comment: I want to run multiple files present in a directory. So in order to get all the files in the directory, I have written a method in scala. That method I am trying to call from build.gradle file

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
Ritika Garg
  • 77
  • 1
  • 6
  • I doubt this is possible. What exactly do you want to do? – Luis Miguel Mejía Suárez Sep 25 '20 at 13:01
  • 1
    For sbt https://stackoverflow.com/questions/61959688/reference-scala-file-from-build-sbt/ – Dmytro Mitin Sep 25 '20 at 13:02
  • @LuisMiguelMejíaSuárez I want to run multiple files present in a directory. So in order to get all the files in the directory, I have written a method in scala. That method I am trying to call from build.gradle file – Ritika Garg Sep 25 '20 at 13:05
  • @DmytroMitin, I am not using sbt – Ritika Garg Sep 25 '20 at 13:07
  • @RitikaGarg I understand. I just guess that the question linked can be relevant. Can similar thing be done with Gradle? Sbt is [recursive](https://www.scala-sbt.org/1.x/docs/Organizing-Build.html#sbt+is+recursive). Can Gradle build be done "recursively"? At least some code can be run in Gradle scripts https://docs.gradle.org/current/userguide/tutorial_using_tasks.html I guess additional source directory also can be added in Gradle. – Dmytro Mitin Sep 25 '20 at 13:12
  • **Gradle** just recently got support for being written in **Kotlin** in case that helps you. I doubt **Gradle** will support **Scala** methods and syntax since it is the default build tool of one of the main competitors of **Scala** _(I am referring to **Kotlin**)_ and it is a minority in the **Scala** ecosystem. – Luis Miguel Mejía Suárez Sep 25 '20 at 13:17
  • @LuisMiguelMejíaSuárez Regarding reasons we've already discussed in that question that sharing some code between build time and compile-time/runtime of the main code can be usefel for multi-staging programmimg, metaprogramming. – Dmytro Mitin Sep 25 '20 at 13:23
  • @LuisMiguelMejíaSuárez *"I doubt Gradle will support Scala methods and syntax..."* But there is interop of JVM-based languages (Java, Scala, Kotlin, Groovy...) Can Scala method be called from Gradle build file written in Kotlin/Groovy? – Dmytro Mitin Sep 25 '20 at 13:30
  • 1
    @DmytroMitin Probably if one manages to compile the **Scala** code into bytecode _(i.e. `.class`)_ and put then on the classpath that **Gradle** uses then you should be able to call it _(theoretically speaking)_. The problem is more how to create that bytecode and put them in the classpath, there probably was a reason for the **Kotlin** support to be made by the official maintainers _(and giving a quick look, it seems it uses **Kotlin** reflection)_ also see [this](https://docs.gradle.org/current/userguide/kotlin_dsl.html#sec:interoperability) so even if possible, it seems hard. – Luis Miguel Mejía Suárez Sep 25 '20 at 13:38
  • 1
    @LuisMiguelMejíaSuárez *"Probably if one manages to compile the Scala code into bytecode (i.e. `.class`) and put then on the classpath that Gradle uses then you should be able to call it"* You were right. Actually it's not so hard. You can look at my answer. – Dmytro Mitin Sep 25 '20 at 15:53

1 Answers1

1

Gradle allows to specify dependencies of build script itself inside buildscript{ dependencies { ... } } (not to be confused with project dependencies inside ordinary dependencies { ... }).

For example here I added Shapeless dependency and used an HList in build.gradle

build.gradle

buildscript{
    dependencies {
        classpath group: 'com.chuusai', name: 'shapeless_2.13', version: '2.4.0-M1'
    }
}

plugins {
    id 'java'
    id 'scala'
    id 'application'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    // compile group: ...
}

application {
    mainClassName = 'App'
}

import shapeless.*

task hello {
    doLast {    
        HList l = new $colon$colon(1, new $colon$colon("a", new HNil$()))
        println l
    }
}

Terminal

$ ./gradlew hello

Output

> Task :hello
1 :: a :: HNil

BUILD SUCCESSFUL in 457ms
1 actionable task: 1 executed

So you can compile your Scala sources, package classes into jar, publish it locally and specify your local dependency in

buildscript{
    dependencies {
        classpath group: 'yourOrganization', name: 'yourArtifact', version: 'yourVersion'
    }
}

and then call methods from your Scala code in build.gradle.

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
  • 1
    Cool! now the problem is that probably OP do not want to publish a jar to maven just to call one function. Would it be possible to add such function to some file and force gradle to build that file and include it? – Luis Miguel Mejía Suárez Sep 25 '20 at 16:23
  • @LuisMiguelMejíaSuárez I didn't mean `publish` to Maven, I meant `publishLocal` (using sbt terminology). – Dmytro Mitin Sep 25 '20 at 16:40
  • 2
    Oh right, my bad, but still one would have to do that manually? – Luis Miguel Mejía Suárez Sep 25 '20 at 16:48
  • 1
    @LuisMiguelMejíaSuárez By the way, it's funny that in Groovy 3.0.5 all following declarations work `$colon$colon l = new ...` `$colon$colon l = new...` `$colon$colon> l = new...` `HList l = new...` `def l = new...` while in Groovy 2.5.10 only the last 2 declarations work. And I used Gradle 6.3 based on Groovy 2.5.10. So probably Groovy-Scala interop of generics was improved in later versions of Groovy. – Dmytro Mitin Sep 27 '20 at 12:44
  • 1
    Scala-Java interop of generics also appeared not from the very beginning. Java generics became visible to Scala in Scala 2.7.0, Scala generics became visible to Java in Scala 2.7.2 https://www.scala-lang.org/download/changelog.html – Dmytro Mitin Sep 27 '20 at 12:44