2011-10-19 74 views
12

我正在将一个遗留的jar项目转换为SBT,并且出于难以解决的奇怪原因,此项目在其中包含“javax/servlet/Servlet.class”。所以我需要以某种方式从由package-bin生成的jar文件中排除此类。我该怎么做到这一点?最好我想排除使用通配符(即javax。*)。SBT:从Jar中排除类

的SBT组件插件看起来像它的功能,将做到这一点,但我担心的是依靠SBT装配意味着我的JAR项目将无法在船型多模块项目(即工作,如果我把它作为战争文件中的依赖关系,那么需要告知战争项目在依赖jar项目上运行程序集而不是程序包bin - 但我可能会在这里弄错)。

回答

13

每个任务都声明其使用的其他任务和设置。您可以使用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类的对。

+0

这是一个比我自己的更好的解决方案,也是一个很好的答案,因为它还设法澄清了一些核心SBT概念。 –

+0

请注意,〜=没有记录在0.13页面上,解释存在于0.12文档中http://www.scala-sbt.org/0.12.4/docs/Getting-Started/More-About-Settings.html –

+0

语法为0.13 (编译,packageBin):= { (映射到(Compile,packageBin))。value.filter {case(file,toPath)=> toPath!=“javax/servlet/Servlet.class “ } }''' –

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生命周期的第二个目标。