首页 文章

在SBT中的多项目构建下使用包生成根项目的工件

提问于
浏览
8

我在SBT中有一个多项目构建配置,它由两个不相互依赖的不同模块组成 . 他们只是(碰巧)属于同一产品 .

项目布局如下:

myLib
  + build.sbt
  + myProject_1
  |    + build.sbt
  |    + src
  |        + ...
  + myProject_2
  |    + build.sbt
  |    + src
  |        + ...
  + project
       + Build.scala

project/Build.scala 包含常见设置,如下所示:

import sbt._
import Keys._

object ApplicationBuild extends Build {

  val appVersion = "1.0-SNAPSHOT"

  val defaultScalacOptions = Seq(
    "-unchecked", "-deprecation", "-feature", "-language:reflectiveCalls",
    "-language:implicitConversions", "-language:postfixOps",
    "-language:dynamics", "-language:higherKinds", "-language:existentials",
    "-language:experimental.macros", "-Xmax-classfile-name", "140")

  val defaultResolvers = Seq(
    "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
  )

  val defaultLibraryDependencies = Seq(
    "org.specs2" %% "specs2" % "1.14" % "test",
    "org.slf4j" % "slf4j-nop" % "1.7.5" % "test"
  )

  val defaultSettings = Defaults.defaultSettings ++ Seq(
    scalacOptions ++= defaultScalacOptions,
    resolvers ++= defaultResolvers,
    libraryDependencies ++= defaultLibraryDependencies
  )
}

根构建文件 build.sbt 只需要将所有内容放在一起[我也尝试删除它..但是子项目不再被编译]:

lazy val myProject_1 = project.in(file("myProject_1"))

lazy val myProject_2 = project.in(file("myProject_2"))

最后这里是 myProject_1/build.sbt [我刚刚省略 myProject_2/build.sbt ,因为它非常相似,并没有为主题提供任何附加值]:

name := "myProject_1"

version := ApplicationBuild.appVersion

ApplicationBuild.defaultSettings

libraryDependencies ++= Seq(
  "commons-codec" % "commons-codec" % "1.8"
)

项目编译成功...但是当我发出命令 sbt package 时,在根目标目录中生成一个空jar:

j3d@gonzo:~/myLib/$ ll target/scala-2.10
drwxrwxr-x 2 j3d j3d 4096 Dez 23 17:13 ./
drwxrwxr-x 5 j3d j3d 4096 Dez 23 17:13 ../
-rw-rw-r-- 1 j3d j3d  273 Dez 23 17:13 brix_2.10-0.1-SNAPSHOT.jar

我错过了什么吗?如何防止SBT生成这个空无用的jar?

5 回答

  • 1

    我使用以下内容

    lazy val root: Project = Project(
      id        = "root",
      base      = file("."),
      aggregate = Seq(proj1, proj2),
      settings  = Project.defaultSettings ++ Seq(
        publishArtifact in (Compile, packageBin) := false, // there are no binaries
        publishArtifact in (Compile, packageDoc) := false, // there are no javadocs
        publishArtifact in (Compile, packageSrc) := false  // there are no sources
      )
    )
    

    这仍然会生成空的打包jar,但在发布时不会导出它 .

  • 6

    我建议在 build.sbt 中使用以下(重新)定义 package 的解决方法:

    Keys.`package` := {
        (Keys.`package` in (a, Compile)).value
        (Keys.`package` in (b, Compile)).value
    }
    

    其中 ab 是(子)模块 .

    lazy val a = project
    
    lazy val b = project
    

    由于 package 是Scala中的关键字,因此需要引用才能解析 .

    它还需要完全限定,因为 package 是由 Keys._sbt._ 导入导入的,默认情况下是 .sbt 构建文件 .

    /Users/jacek/sandbox/so/multi-packageBin/build.sbt:5: error: reference to package is ambiguous;
    it is imported twice in the same scope by
    import Keys._
    and import sbt._
    `package` := {
    ^
    [error] Type error in expression
    

    另请注意,我正在使用SBT 0.13.2-SNAPSHOT (从源代码构建),因此请谨慎使用(但我怀疑它会对任何版本的SBT 0.13+ 产生影响) .

    [multi-packagebin]> */*:sbtVersion
    [info] 0.13.2-SNAPSHOT
    [multi-packagebin]> projects
    [info] In file:/Users/jacek/sandbox/so/multi-packageBin/
    [info]     a
    [info]     b
    [info]   * multi-packagebin
    [multi-packagebin]> package
    [info] Updating {file:/Users/jacek/sandbox/so/multi-packageBin/}a...
    [info] Updating {file:/Users/jacek/sandbox/so/multi-packageBin/}b...
    [info] Resolving org.fusesource.jansi#jansi;1.4 ...
    [info] Done updating.
    [info] Resolving org.scala-lang#scala-reflect;2.10.3 ...
    [info] Packaging /Users/jacek/sandbox/so/multi-packageBin/b/target/scala-2.10/b_2.10-0.1-SNAPSHOT.jar ...
    [info] Done packaging.
    [info] Resolving org.fusesource.jansi#jansi;1.4 ...
    [info] Done updating.
    [info] Packaging /Users/jacek/sandbox/so/multi-packageBin/a/target/scala-2.10/a_2.10-0.1-SNAPSHOT.jar ...
    [info] Done packaging.
    [success] Total time: 1 s, completed Feb 23, 2014 10:12:41 AM
    
  • 0

    这非常难以实现 . 以下一组选项似乎可以实现目标 . 这些选项的子集倾向于通过某些执行路径而不是其他执行路径来抑制根jar,因此如果要查找最小覆盖,请确保'sbt package'和'sbt publishLocal'都不会创建jar . 我花了很长时间才找到这一套,我不愿意进一步迭代 .

    Keys.`package` :=  file(""),
    packageBin in Global :=  file(""),
       packagedArtifacts :=  Map(),
    

    sbt:自2008年以来,简单的事情变得不可能 .

  • 1

    由于我是SBT的新手,我不完全确定这一点的所有含义,但以下似乎可以完成这项工作:

    compile := sbt.inc.Analysis.Empty
    

    覆盖包装任务对我来说似乎不对 . 所以我使用 inspect (加上源代码,因为我不知道最初要查找什么)来找到这些映射的确切来源并找到这些依赖项:

    compile:package - > compile:packageBin - > compile:packageBin :: packageConfiguration - > compile:packageBin :: mappings - > compile:packageBin :: products(由compile:products提供) - > compile:compile

    我不知道为什么要这么困难 . 我的大多数问题都来自于尝试进行多项目构建 .

  • 10

    我将以下设置添加到项目根目录:

    Compile / packageBin := { file("") }
    Compile / packageSrc := { file("") }
    Compile / packageDoc := { file("") }
    

    通过更改 Compile 范围内的任务,还会禁用默认的 package 任务 .

相关问题