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

时间:2013-12-23 16:23:01

标签: scala sbt

我在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 个答案:

答案 0 :(得分:10)

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

      Keys.`package` :=  file(""),
packageBin in Global :=  file(""),
   packagedArtifacts :=  Map(),
自从2008年以来,简单的事情就变得不可能了。

答案 1 :(得分:6)

我建议一个解决方法packagebuild.sbt的以下(重新)定义:

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

答案 2 :(得分: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,但在发布时不会导出它。

答案 3 :(得分:1)

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

compile := sbt.inc.Analysis.Empty

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

  

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

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

答案 4 :(得分:0)

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

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

通过更改Compile范围内的任务,默认package任务也会被禁止。