【问题标题】:Sbt: call subproject's source code from root projectSbt:从根项目调用子项目的源代码
【发布时间】:2021-03-14 03:28:58
【问题描述】:

所以我的项目结构如下所示:我的根项目包含设置、任务和配置。此外还有一个包含所有子项目的子项目文件夹。我在根项目上创建了一个任务,该任务依赖于子项目 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 引用。

【问题讨论】:

  • @Dmytro Mitin,感谢您的及时回复,不,它没有帮助,因为我在 .斯卡拉文件。所以即使我将子项目的对象添加到插件中的非托管源目录。 Sbt。编译器会抛出一个语法错误,我尝试调用它无法解决的 thr 对象。我什至不能首先导入它
  • 也不适用于反射。
  • 你不需要反思。

标签: scala playframework sbt scala-reflect


【解决方案1】:

Reference scala file from build.sbt

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

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")
}

然后在rootbuild.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


我使用sbt new playframework/play-scala-seed.g8 创建了 Play 项目。一切似乎都奏效了。我如上所述添加了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

【讨论】:

  • 我有两个问题:1/我的子项目是一个play应用,我知道play会覆盖sbt默认设置,所以sbt在app/文件夹中搜索而不是src/main/我指向子项目吗/app/ 而不是 unmanagedSourceDirs 中的 subproject/src/main ? 2/ 我没有真正使用 .sbt 文件,而是 Build.scala 文件。因此,如果我想直接在那里调用 com.package dir 它无法解析它需要以某种方式导入的包名称,还是我在编译时忽略该错误?
  • 我无法编译项目,因为我想在任务定义中引用的包未解析
  • @Helix112 关于你的问题 1. 对于像src/main/scalaapp responsible 这样的目录是参数scalaSource。如果在 sbt shell 中运行scalaSource,它会打印出.../app,但subproject1/scalaSource 会打印出.../subproject1/src/main/scala。所以 Play 会为 root 项目更改 scalaSource,但不会为您创建的子项目更改 scalaSource
  • @Helix112 所以在project/build.sbt 中,如果您没有将scalaSource 更改为subproject1,则应保留Compile / unmanagedSourceDirectories += baseDirectory.value / ".." / "subproject1" / "src" / "main" / "scala"
  • 感谢您提供的信息丰富的答案。我的意思是子项目本身是一个播放应用程序,而不是根项目。无论如何,我将其称为 .../subproject1/app。现在,在将该路径添加到非托管 src 之后,Dir sbt 在子项目类中引发了一个新错误:对象 x 不是包 com 的成员。例子。我稍后再试一次并回复你
猜你喜欢
  • 2013-10-14
  • 2016-06-03
  • 2014-06-18
  • 2015-02-02
  • 2017-02-28
  • 1970-01-01
  • 2014-03-19
  • 1970-01-01
  • 2019-07-28
相关资源
最近更新 更多