Scala SBT:从Jar中排除类

Scala SBT:从Jar中排除类,scala,sbt,Scala,Sbt,我正在将一个遗留jar项目转换为SBT,由于一些不容易解决的奇怪原因,这个项目内部带有“javax/servlet/servlet.class”。因此,我需要以某种方式将这个类从package bin生成的jar文件中排除。我如何做到这一点?。我最好不使用通配符(即javax.*) SBT assembly插件看起来确实有这样的功能,但我担心依赖SBT assembly意味着我的jar项目无法在多模块项目中工作(也就是说,如果我将其作为依赖项包含在war文件中,那么war项目需要被告知在依赖ja

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


SBT assembly插件看起来确实有这样的功能,但我担心依赖SBT assembly意味着我的jar项目无法在多模块项目中工作(也就是说,如果我将其作为依赖项包含在war文件中,那么war项目需要被告知在依赖jar项目上运行汇编,而不是包bin——但我可能在这里弄错了)。

我提出了这个解决方案,它定义了一个新的编译任务,该任务依赖于以前的编译任务(因此,有效地允许我在编译源代码之后和打包之前立即进行连接)

def mySettings={
//向标准编译任务添加功能
inConfig(编译)(Seq(编译中编译
log.warn(“删除匹配的资源:+file.getAbsolutePath())
IO.delete(文件)
}
分析
})) ++
Seq(名称:=“MyProject”,版本:=“1.0”,exportJars:=true)
}
def recursiveListFiles(f:File,r:Regex):数组[File]={
val这些=f.listFiles
val good=this.filter(f=>r.findFirstIn(f.getName).isDefined)
好的++这些.filter(u.isDirectory).flatMap(递归列表文件(u,r))
}

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

每个任务声明了它使用的其他任务和设置。您可以使用
检查
来确定这些输入,如最近的教程样式中所述

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

因此,要修改
packageBin
任务的映射,请从默认映射中筛选出不希望包含的路径:

mappings in (Compile,packageBin) ~= { (ms: Seq[(File, String)]) =>
  ms filter { case (file, toPath) =>
    toPath != "javax/servlet/Servlet.class"
  }
}
中的映射(Compile,packageBin)
选择主包任务的映射(与测试源或packageSrc任务相反)

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


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

这是一个比我自己的解决方案好得多的解决方案,也是一个非常好的答案,因为它还成功地澄清了一些核心SBT概念。请注意,~=没有在0.13页上记录,解释存在于(Compile,packageBin)中的0.12文档语法中:={(Compile,packageBin中的映射)).value.filter{case(file,toPath)=>toPath!=“javax/servlet/servlet.class”}
mappings in (Compile,packageBin) ~= { (ms: Seq[(File, String)]) =>
  ms filter { case (file, toPath) =>
    toPath != "javax/servlet/Servlet.class"
  }
}