【问题标题】:How to create a custom package task to jar a subset of classes in SBT如何创建自定义包任务以在 SBT 中 jar 类的子集
【发布时间】:2014-09-08 12:22:45
【问题描述】:

我正在尝试定义一个单独的包任务而不修改编译配置中的原始任务。这个新任务将仅打包符合 API 的类的子集,我们需要能够与其他团队共享这些类,以便他们可以为我们的应用程序编写插件。所以最终结果将是两个 jar,一个包含完整的应用程序,另一个包含类的子集。

我通过创建一个名为 pluginApi 的不同配置来解决这个问题,并在这个新配置中重新定义 packageBin 任务,这样它就不会改变 packageBin 的原始定义。这个想法取自这里:

How to create custom "package" task to jar up only specific package in SBT?

在我的 build.stb 我有:

lazy val PluginApi = config("pluginApi") extend(Compile) describedAs("Custom plugin api configuration")

lazy val root = project in file(".") overrideConfigs (PluginApi)

这有效地创建了我的新配置,我可以调用

sbt pluginApi:packageBin

它以与 compile:packageBin 相同的方式生成完整的 jar。然后我尝试修改新 packageBin 任务中的映射:

mappings in (PluginApi, packageBin) ~= { (ms: Seq[(File, String)]) =>
  ms filter { case (file, toPath) =>
    toPath.startsWith("some/path/defining/api")
  }
}

但这没有任何效果。我认为原因是对 pluginApi:packageBin 的调用被委托给 compile:packageBin 而不是克隆任务。

我可以在新范围内重新定义一个新的 packageBin,例如:

packageBin in PluginApi := {

}

但是,我必须重写所有 packageBin 功能,而不是重用现有代码。另外,万一重写是不可避免的,我不确定该实现会如何。

有人可以提供一个关于如何实现这一目标的示例吗?

【问题讨论】:

    标签: scala sbt


    【解决方案1】:

    你可以这样做

    lazy val PluginApi = config("pluginApi").extend(Compile)
    
    inConfig(PluginApi)(Defaults.compileSettings) // you have to have standard
    
    mappings in (PluginApi, packageBin) := {
      val original = (mappings in (PluginApi, packageBin)).value
      original.filter { case (file, toPath) => toPath.startsWith("some/path/defining/api") }
    }
    
    unmanagedSourceDirectories in PluginApi := (unmanagedSourceDirectories in Compile).value
    

    请注意,如果您将源代码保存在 src/main/scala 中,则必须在新创建的配置中覆盖 unmanagedSourceDirectories

    通常unmanagedSourceDirectories 包含配置名称。例如。 src/pluginApi/scalasrc/pluginApi/java

    【讨论】:

    • 感谢您的回答。我收到此代码错误:[info] 错误:value 只能在任务定义宏中的任务上调用,例如 :=、+=、++= 或 Def.task。在线 val original = ((PluginApi, packageBin) 中的映射).value。知道如何解决这个问题吗?
    • @Miquel 不用担心,如果它适合您,请点赞/接受,如果不适合请告诉我。
    • 我上面描述的问题是一个错字。代码编译并运行,但我得到了完整的 jar,没有发生过滤。知道为什么吗?
    • 好的,看来我没有正确复制代码,我从头开始重新开始,它可以工作,非常感谢并为造成的混乱道歉
    • 有趣的是,虽然该解决方案很有效,但命令 sbt clean compile package pluginApi:packageBin 将编译所有类两次。正如@lpiepiora 建议的那样,将所有用于共享的类都放在配置目录(src/pluginApi/scala)中可能会更好
    【解决方案2】:

    我也遇到过类似的问题(每个项目不止一个 jar)。我们的项目使用 ant - 在这里你可以做到,你会重复自己很多次。

    但是,我得出的结论是,这种情况(一个项目有 2 个 JAR)实际上可以通过拆分项目来简化 - 即从中制作 2 个模块。 这样,我不必“与”假设 project==artifact 的工具(如 sbt,也许是 maven?,IDEA 的默认设置,...)。 作为奖励点,编译器帮助我验证我的依赖项是否正确,即我没有意外地使我的 API 包依赖于实现包 - 当一起编译所有内容并且只在 JAR 步骤中拆分类时,你确实运行在您的设置中获得无效依赖项的风险,您只会在测试时看到,因为在编译期间所有内容都被编译在一起。

    【讨论】:

      猜你喜欢
      • 2023-03-14
      • 2017-06-15
      • 1970-01-01
      • 2019-11-24
      • 2021-11-29
      • 1970-01-01
      • 2012-01-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多