SBT:从Jar中排除课程

时间:2011-10-19 09:18:43

标签: scala sbt

我正在将遗留jar项目转换为SBT,并且出于不容易解决的奇怪原因,该项目内部带有“ javax / servlet / Servlet.class ”。所以我需要以某种方式从 package-bin 生成的jar文件中排除这个类。我该如何做到这一点?我希望排除使用通配符(即 javax。* )。

SBT程序集插件看起来确实具有可以执行此操作的功能,但我担心依赖 sbt程序集意味着我的jar项目将无法在多个模块项目中工作(即,我将它作为一个依赖项包含在war文件中,然后需要告诉war项目在依赖jar项目上运行 assembly 而不是 package-bin - 但我可能是这里错了。)

2 个答案:

答案 0 :(得分:15)

每个任务都声明它使用的其他任务和设置。您可以使用inspect来确定这些输入,如Inspecting Settings和最近的教程式blog post by John Cheng所述。

在这种情况下,packageBin使用的相关任务是mappingsmappings任务收集要包含在jar中的文件,并将它们映射到jar中的路径。在Mapping Files上解释了一些背景知识,但结果是mappings生成了Seq[(File, String)]类型的值。这里,File是提供内容的输入文件,String是jar中的路径。

因此,要修改packageBin任务的映射,请过滤掉您不想包含的默认映射的路径:

mappings in (Compile,packageBin) ~= { (ms: Seq[(File, String)]) =>
  ms filter { case (file, toPath) =>
    toPath != "javax/servlet/Servlet.class"
  }
}

mappings in (Compile,packageBin)选择主包任务的映射(而不是测试源或packageSrc任务)。

x ~= f表示“将x设置为将函数f应用于x的前一个值的结果”。 (有关详细信息,请参阅More About Settings。)

过滤器删除路径对应于Servlet类的所有对。

答案 1 :(得分:2)

我想出了这个解决方案,它定义了一个新的编译任务,它取决于之前的编译任务(从而有效地允许我在源编译之后和打包之前挂钩)

def mySettings = {
  // add functionality to the standard compile task 
  inConfig(Compile)(Seq(compile in Compile <<= (target,streams,compile in Compile) map{
    (targetDirectory, taskStream, analysis) =>
      import taskStream.log
      // this runs after compile but before package-bin
      recursiveListFiles(targetDirectory, ".*javax.*".r) foreach { 
        file =>
          log.warn("deleting matched resource: " + file.getAbsolutePath())
          IO.delete(file)
      }
      analysis
    })) ++
    Seq(name := "MyProject", version := "1.0", exportJars := true)
}

def recursiveListFiles(f: File, r: Regex): Array[File] = {
  val these = f.listFiles
  val good = these.filter(f => r.findFirstIn(f.getName).isDefined)
  good ++ these.filter(_.isDirectory).flatMap(recursiveListFiles(_, r))
}

它比我希望的要复杂一点,但它允许我在打包之前进行各种修改(在这种情况下搜索目标文件夹,删除与正则表达式匹配的所有类文件)。此外,它实现了我坚持默认SBT生命周期的第二个目标。