因此,我的项目结构如下所示:我的根项目包含设置,任务和配置。另外还有一个subprojects文件夹,其中包含所有子项目。我已经在根项目上创建了一个任务,该任务依赖于子项目X中的某些代码。是否可以从该任务定义内的子项目X中调用方法?
我的代码如下所示:
lazy val rootSettings: Seq[Setting[_]] = Seq (someRootTask := { //I need to call an object from a subproject here..})
我尝试使用反射API失败了:
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.
上面的代码引发错误。它找不到对象,我知道它的路径,但是我不能从根项目中将其作为package.class引用。
如果我理解正确,你的项目看起来像
root
project
build.properties
build.sbt
subproject1
src
main
scala
com.example.package1
App.scala
subproject2
src
main
scala
com.example.package2
build.sbt
在project/build.sbt
我可以写
Compile / unmanagedSourceDirectories += baseDirectory.value / ".." / "subproject1" / "src" / "main" / "scala"
假设subproject1/src/main/scala/com/example/package1/App.scala
是
package com.example.package1
object App {
def foo(): Unit = println("foo")
}
然后build.sbt
我可以在根目录下调用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"))
如果在sbt shell中运行,root/sampleUnitTask
它将打印foo
。
我使用创建了Play项目sbt new playframework/play-scala-seed.g8
。一切似乎都正常。我添加project/build.sbt
和subproject1/src/main/scala/com/example/package1/App.scala
如上所述。然后用下面的根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
在sbt shell打印文件中执行foo
。
我有两个问题:1 /我的子项目是一个play应用程序,我知道play会覆盖sbt默认设置,因此sbt在app /文件夹中搜索,而不是src / main /我是否指向subproject / app /而不是subproject / src / main在unmanagedSourceDirs中?2 /不是真正使用.sbt文件而是Build.scala文件。因此,如果我想直接在其中调用com.package dir,它无法解析需要以某种方式导入的包名称,还是在编译时忽略该错误?
我无法编译项目,因为我想在任务定义中引用的包未解析
@ Helix112关于您的问题1.对于喜欢
src/main/scala
或app
负责的目录是parameterscalaSource
。如果在sbt shell中运行,scalaSource
它会打印.../app
但会subproject1/scalaSource
打印.../subproject1/src/main/scala
。因此scalaSource
,如果root
项目没有更改,则为项目创建更改,但为您创建的子项目更改scalaSource
。@ Helix112因此,如果您没有为进行更改,
project/build.sbt
则应保留Compile / unmanagedSourceDirectories += baseDirectory.value / ".." / "subproject1" / "src" / "main" / "scala"
在其中。scalaSource
subproject1
感谢您提供的信息。我的意思是,子项目本身是一个Play应用程序,而不是根项目。无论如何,我已经将其引用为... / subproject1 / app。现在,在将该路径添加到非托管src之后,Dir sbt在子项目类内引发了一个新错误:对象x不是com包的成员。例子。我稍后再试,然后再回覆给您