Warm tip: This article is reproduced from serverfault.com, please click

scala-Sbt:从根项目中调用子项目的源代码

(scala - Sbt: call subproject's source code from root project)

发布于 2020-12-02 07:01:27

因此,我的项目结构如下所示:我的根项目包含设置,任务和配置。另外还有一个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引用。

Questioner
Helix112
Viewed
0
Dmytro Mitin 2020-12-03 09:06:47

来自build.sbt的参考Scala文件

如果我理解正确,你的项目看起来像

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.sbtsubproject1/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