【问题标题】:Bundle dependency jars into output jar将依赖 jar 包捆绑到输出 jar 中
【发布时间】:2014-06-26 12:39:05
【问题描述】:

我正在使用一个将插件作为 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,然后将 jar 从 target/universal/stage/lib 复制到 plugin.myplugin 中的 lib 目录中。 jar 使用类似 7-zip 的东西。手动执行此操作...但我正在尝试自动执行此任务,目前我对如何覆盖 sbt-native-packager 任务或自己编写来执行此操作有点茫然。有什么想法吗?

【问题讨论】:

标签: scala sbt


【解决方案1】:

这就是您如何使用纯 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 如果我有 /modules/X,Y,Z 并且我想要编译的类 来自工件中“com.xxx.xxx”下捆绑的那些项目?

如果类是唯一的,一般答案是肯定的。为此,您可以使用Scopes。在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")
  }
}

【讨论】:

  • 这几乎正是我一直在尝试做的@lpiepiora。是否可以在多模块构建中获取已编译的类? IE 如果我有 /modules/X,Y,Z 并且我希望那些项目中的编译类捆绑在工件中的“com.xxx.xxx”下?
  • 现在我已经在 Compile
  • @steveturner 看看我更新的答案,我认为它会更好地扩展。这个想法是使用范围来查找正确的文件。
  • 这很好用。谢谢你的帮助!我正在做 'compiledClasses pair relativeTo(classDir) ' 而不是变基
猜你喜欢
  • 2016-07-20
  • 2012-11-01
  • 2013-11-02
  • 2015-11-24
  • 1970-01-01
  • 1970-01-01
  • 2011-10-12
  • 2019-09-03
  • 1970-01-01
相关资源
最近更新 更多