SBT:从 Jar 中排除类

发布于 2024-12-10 11:21:00 字数 420 浏览 0 评论 0原文

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

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

I am converting a legacy jar project to SBT and for strange reasons that are not easily solved, this project comes with "javax/servlet/Servlet.class" inside it. So I need to somehow exclude this class from the jar file generated by package-bin. How do I accomplish this ?. Preferably I would like to exclude using a wildcard (i.e. javax.*).

The SBT assembly plugin does look like it has features that will do this, but I am worried that relying on sbt assembly means that my jar project will not work in a muliti module project (i.e. if I include it as a dependency in a war file then the war projects needs to be told to run assembly on the dependent jar project rather than package-bin - but I may be mistaken here).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦里泪两行 2024-12-17 11:21:00

每个任务都声明它使用的其他任务和设置。您可以使用 inspect 来确定这些输入,如检查设置中所述 以及 John Cheng 最近发表的教程式博客文章

在本例中,packageBin 使用的相关任务是 mappingsmappings 任务收集要包含在 jar 中的文件并将它们映射到 jar 中的路径。 映射文件 解释了一些背景,但结果是 映射 生成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 的先前值的结果”。 (有关详细信息,请参阅有关设置的更多信息。)

过滤器会删除所有对其中路径对应于 Servlet 类。

Each task declares the other tasks and settings that it uses. You can use inspect to determine these inputs as described on Inspecting Settings and in a recent tutorial-style blog post by John Cheng.

In this case, the relevant task used by packageBin is mappings. The mappings task collects the files to be included in the jar and maps them to the path in the jar. Some background is explained on Mapping Files, but the result is that mappings produces a value of type Seq[(File, String)]. Here, the File is the input file providing the content and the String is the path in the jar.

So, to modify the mappings for the packageBin task, filter out the paths from the default mappings that you don't want to include:

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

mappings in (Compile,packageBin) selects the mappings for the main package task (as opposed to test sources or the packageSrc task).

x ~= f means "set x to the result of applying function f to the previous value of x". (See More About Settings for details.)

The filter drops all pairs where the path corresponds to the Servlet class.

娇妻 2024-12-17 11:21:00

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

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 生命周期。

I came up with this solution, it defines a new compile task which depends on the previous compile task (thus effectively allowing me to hook in right after the source is compiled and before it's packaged)

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))
}

Its a little bit more complicated than what I had hoped but it allows me to do all sorts of modifications prior to packaging (in this case searching the target folder deleting all class files that matches a regular expression). Also it accomplished my second goal of sticking with the default SBT lifecycle.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文