So my project structure looks like this: My root project contains the settings, tasks and configs. In addition is has a subprojects folder which contains all subprojects. I have created a task on the root project that depends on some code in a subproject X. Is it possible to call a method from subproject x inside that task definition?
My code looks like this :
lazy val rootSettings: Seq[Setting[_]] = Seq (someRootTask := { //I need to call an object from a subproject here..})
I tried to use the reflection api with no success:
import scala.reflect.runtime.{universe => u }
lazy val docSettings: Seq[Setting[_]] = Seq(
rootTask := {
val subproject = baseDirectory.in(playApp).value.getAbsolutePath
val mirror = u.runtimeMirror(getClass.getClassLoader)
val clazz = mirror.staticModule(subproject+"/" +"controllers.pckg.obj" )
val cm = mirror.reflectModule(clazz)
val instanceMirror = mirror.reflect(cm.instance)
val methodName ="sayHi"
val methodSymbol = u.typeOf[instanceMirror.type].declaration(u.newTermName(methodName)).asMethod
val method = instanceMirror.reflectMethod(methodSymbol)
method.apply()
}
)
// still can't point to the object i want to call.
The code above throws an error. It can't find the object, i know its path but i can't reference to it as package.class from the root project.
Reference scala file from build.sbt
If I understood correctly your project looks like
root
project
build.properties
build.sbt
subproject1
src
main
scala
com.example.package1
App.scala
subproject2
src
main
scala
com.example.package2
build.sbt
In project/build.sbt
I can write
Compile / unmanagedSourceDirectories += baseDirectory.value / ".." / "subproject1" / "src" / "main" / "scala"
Suppose subproject1/src/main/scala/com/example/package1/App.scala
is
package com.example.package1
object App {
def foo(): Unit = println("foo")
}
Then in root build.sbt
I can call foo
name := "sbtdemo"
version := "0.1"
ThisBuild / scalaVersion := "2.13.4"
lazy val sampleUnitTask = taskKey[Unit]("A sample unit task.")
lazy val rootSettings: Seq[Setting[_]] = Seq(
sampleUnitTask := {
com.example.package1.App.foo()
}
)
lazy val root = project
.in(file("."))
.dependsOn(subproject1, subproject2)
.settings(rootSettings)
lazy val subproject1 = project
.in(file("subproject1"))
lazy val subproject2 = project
.in(file("subproject2"))
If in sbt shell I run root/sampleUnitTask
it prints foo
.
I created Play project with sbt new playframework/play-scala-seed.g8
. Everything seems to work. I added project/build.sbt
and subproject1/src/main/scala/com/example/package1/App.scala
as above. Then with the following root build.sbt
name := """playframeworkdemo"""
organization := "com.example"
version := "1.0-SNAPSHOT"
lazy val sampleUnitTask = taskKey[Unit]("A sample unit task.")
lazy val rootSettings: Seq[Setting[_]] = Seq(
sampleUnitTask := {
com.example.package1.App.foo()
}
)
lazy val root = (project in file(".")).enablePlugins(PlayScala)
.dependsOn(subproject1, subproject2)
.settings(rootSettings)
ThisBuild / scalaVersion := "2.13.3"
libraryDependencies += guice
libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "5.0.0" % Test
// Adds additional packages into Twirl
//TwirlKeys.templateImports += "com.example.controllers._"
// Adds additional packages into conf/routes
// play.sbt.routes.RoutesKeys.routesImport += "com.example.binders._"
lazy val subproject1 = project
.in(file("subproject1"))
lazy val subproject2 = project
.in(file("subproject2"))
root/sampleUnitTask
executed in sbt shell prints foo
.