简体   繁体   English

SBT:如何使一个任务依赖于多项目构建中的另一个任务,而不是在根项目中运行?

[英]SBT: How to make one task depend on another in multi-project builds, and not run in the root project?

For my multi-project build, I'm trying to create a verify task that just results in scct:test and then scalastyle being executed in order. 对于我的多项目构建,我正在尝试创建一个只导致scct:test的验证任务,然后按顺序执行scalastyle。 I would like scct:test to execute for all the subprojects, but not the top-level project. 我想scct:test来执行所有子项目,但不是顶层项目。 (If it executes for the top-level project, I get "timed out waiting for coverage report" from scct, since there's no source and no tests in that project.) What I had thought to do was to create verify as a task with dependencies on scct:test and scalastyle. (如果它是针对顶级项目执行的,我会从scct中“等待覆盖率报告超时”,因为该项目中没有源代码和任何测试。)我想要做的是创建一个验证任务依赖于scct:test和scalastyle。 This has turned out to be fairly baroque. 事实证明这是相当巴洛克式的。 Here is my Build.scala from my top-level project/ directory: 这是我的顶级项目/目录中的Build.scala:

object MyBuild extends Build {
  val verifyTask = TaskKey[Unit]("verify", "Compiles, runs tests via scct:test and then runs scalastyle")
  val scctTestTask = (test in ScctPlugin.Scct).scopedKey
  val scalastyleTask = PluginKeys.scalastyleTarget.scopedKey

  lazy val root = Project("rootProject",
                      file("."),
                      settings =  Defaults.defaultSettings ++
                                  ScalastylePlugin.Settings ++
                                  ScctPlugin.instrumentSettings ++
                                  ScctPlugin.mergeReportSettings ++
                                  Seq(
                                    verifyTask in Global := {},
                                    verifyTask <<= verifyTask.dependsOn(scctTestTask, scalastyleTask)
                                  )
              ) aggregate(lift_webapp, selenium_tests)

  lazy val subproject_1 = Project(id = "subproject_1", base = file("subproject_1"))

  lazy val subproject_2 = Project(id = "subproject_2", base = file("subproject_2"))
}

However, the verify task only seems to exist for the root project; 但是,验证任务似乎只存在于根项目中; when I run it I don't see the same task being run in the subprojects. 当我运行它时,我看不到在子项目中运行相同的任务。 This is exactly the opposite of what I want; 这与我想要的完全相反; I'd like to issue sbt verify and have scct:test and scalastyle run in each of the subprojects but not in the top-level project. 我想发布sbt verify并在每个子项目中运行scct:test和scalastyle,但不在顶级项目中运行。 How might I go about doing that? 我该怎么做呢?

solution 1: define verifyTask in subprojects 解决方案1:在子项目中定义verifyTask

First thing to note is that if you want some task ( verify , test , etc) to run in some projects, you need to define them scoped to the subprojects. 首先要注意的是,如果您想在某些项目中运行某些任务( verifytest等),则需要将它们定义为子项目的范围。 So in your case, the most straightforward thing to do this is to define verifyTask in subproject_1 and subproject_2 . 因此,在您的情况下,最直接的做法是在subproject_1subproject_2定义verifyTask

lazy val scalaTest = "org.scalatest" %% "scalatest" % "3.0.4"

lazy val verify = taskKey[Unit]("verify")
def verifySettings = Seq(
  skip in verify := false,
  verify := (Def.taskDyn {
    val sk = (skip in verify).value
    if (sk) Def.task { println("skipping verify...") }
    else (test in Test)
  }).value
)

lazy val root = (project in file("."))
  .aggregate(sub1, sub2)
  .settings(
    verifySettings,
    scalaVersion in ThisBuild := "2.12.4",
    skip in verify := true
  )

lazy val sub1 = (project in file("sub1"))
  .settings(
    verifySettings,
    libraryDependencies += scalaTest % Test
  )

lazy val sub2 = (project in file("sub2"))
  .settings(
    verifySettings,
    libraryDependencies += scalaTest % Test
  )

solution 2: ScopeFilter 解决方案2:ScopeFilter

There was a recent Reddit thread that mentioned this question, so I'll post what I've done there. 最近有一个Reddit主题提到了这个问题,所以我会发布我在那里所做的事情。 If you want to manually aggregate on some subprojects, there's also a technique called ScopeFilter . 如果要手动聚合某些子项目,还有一种称为ScopeFilter的技术。

Note that I am using sbt 1.x here, but it should work with sbt 0.13 some minor change. 请注意,我在这里使用sbt 1.x,但它应该与sbt 0.13一起使用一些小的改动。

lazy val packageAll = taskKey[Unit]("package all the projects")
lazy val myTask = inputKey[Unit]("foo")

lazy val root = (project in file("."))
  .aggregate(sub1, sub2)
  .settings(
    scalaVersion in ThisBuild := "2.12.4",
    packageAll := {
      (packageBin in Compile).all(nonRootsFilter).value
      ()
    },
    myTask := {
      packageAll.value
    }
  )

lazy val sub1 = (project in file("sub1"))

lazy val sub2 = (project in file("sub2"))

def nonRootsFilter = {
  import sbt.internal.inc.ReflectUtilities
  def nonRoots: List[ProjectReference] =
    allProjects filter {
      case LocalProject(p) => p != "root"
      case _               => false
    }
  def allProjects: List[ProjectReference] =
    ReflectUtilities.allVals[Project](this).values.toList map { p =>
      p: ProjectReference
    }
  ScopeFilter(inProjects(nonRoots: _*), inAnyConfiguration)
}

In the above, myTask depends on packageAll , which aggregates (packageBin in Compile) for all non-root subprojects. 在上面, myTask依赖于packageAll ,它汇总了所有非根子项目(packageBin in Compile) myTask (packageBin in Compile)

sbt:root> myTask
[info] Packaging /Users/xxx/packageall/sub1/target/scala-2.12/sub1_2.12-0.1.0-SNAPSHOT.jar ...
[info] Done packaging.
[info] Packaging /Users/xxx/packageall/sub2/target/scala-2.12/sub2_2.12-0.1.0-SNAPSHOT.jar ...
[info] Done packaging.
[success] Total time: 0 s, completed Feb 2, 2018 7:23:23 PM

I may be wrong, but you are defining the verify task dependency only for the current project. 我可能错了,但您只是为当前项目定义了验证任务依赖项。

Maybe you can try: 也许你可以尝试:

Seq(
   verifyTask in Global := {},
   verifyTask <<= (verifyTask in Global).dependsOn(scctTestTask, scalastyleTask)
)

Or you can add the verifyTask settings to all your modules. 或者,您可以将verifyTask设置添加到所有模块中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM