将依赖jar包绑定到输出jar包中



我正在使用一个从目录加载插件作为jar的应用程序。插件的布局如下:

plugin.myplugin.jar/
  com.xxx.xxx/<compiled classes for plugin>
  META-INF/MANIFEST.MF (defines the main entry point for the plugin)
  lib/
     com.fasterxml.jackson.core.jackson-core-2.3.1.jar
     ...
     ...
     com.netflix.rxjava.rxjava-core-0.16.1.jar
     ...
     <all dependencies used by the plugin in their original jar format>

我可以通过使用sbt-native-packager插件手动生成顶级的plugin.myplugin.jar,然后使用类似7-zip的东西将jar从target/universal/stage/lib复制到plugin.myplugin.jar中的lib目录中。手动执行此操作…但是我正在尝试自动化这个任务,目前我有点不知所措,不知道如何覆盖sbt-native-packager任务或编写自己的任务来完成这个任务。什么好主意吗?

这就是如何使用纯SBT 0.13实现您想要的。X(该示例通常适用于旧版本,但可能必须使用不同的操作符)。

build.sbt

import Path.flat
libraryDependencies ++= Seq(
  "com.fasterxml.jackson.core" % "jackson-core" % "2.3.1",
  "com.netflix.rxjava" % "rxjava-core" % "0.16.1"
  // maybe more dpendencies
)
packageOptions in (Compile, packageBin) +=
        Package.ManifestAttributes("PluginMainClass" -> "com.xxx.xxx.Class")
// this will copy all managed jars to the ./lib in your jar
mappings in (Compile, packageBin) ++= {
  val cp = (managedClasspath in Compile).value.files
  cp pair flatRebase("/lib")
}
// this will move all your compiled classes to folder ./com.xxx.xxx in your jar
mappings in (Compile, packageBin) ++= {
  val compiledClasses = (products in Compile).value ** "*.class"
  val classDirectoryBase = (classDirectory in Compile).value
  compiledClasses pair rebase(classDirectoryBase, "com.xxx.xxx")
}

然后您可以使用package来构建jar。在上面的例子中,jar看起来像这样:

  Length      Date    Time    Name
---------  ---------- -----   ----
      301  2014-05-09 20:13   META-INF/MANIFEST.MF
        0  2014-05-09 20:13   /lib/
  7126003  2013-09-27 11:44   /lib/scala-library.jar
   197986  2013-12-28 02:01   /lib/jackson-core-2.3.1.jar
   663553  2014-01-15 08:17   /lib/rxjava-core-0.16.1.jar
---------                     -------
  7987843                     5 files

清单是这样的

Manifest-Version: 1.0
Implementation-Vendor: default
Implementation-Title: q-23553321
Implementation-Version: 0.1-SNAPSHOT
Implementation-Vendor-Id: default
PluginMainClass: com.xxx.xxx.Class // MAIN CLASS OF THE PLUGIN
Specification-Vendor: default
Specification-Title: q-23553321
Specification-Version: 0.1-SNAPSHOT

编辑

是否有可能在多模块构建中获得编译的类虽然?IE如果我有/模块/X,Y,Z,我想要编译的类从那些捆绑在"com.xxx. com.xxx"下的项目中。藏物中的Xxx"?

一般的答案是肯定的,如果类是唯一的。要做到这一点,可以使用作用域。在build.sbt中,用以下内容替换类的映射:

// define the configuration axis
val anyProjectsCompile = ScopeFilter(inAnyProject, inConfigurations(Compile))
// we want to have class directory and products together to use rebase in the next step
val classDirectoryProducts = Def.task {
  (classDirectory.value, products.value)
}
mappings in (Compile, packageBin) ++= {
  classDirectoryProducts.all(anyProjectsCompile).value.flatMap { case (classDir, prods) =>
    val compiledClasses = (prods ** "*.class").get
    compiledClasses pair rebase(classDir, "com.xxx.xxx")
  }
}

最新更新