抑制 sbt-assembly 中的主类

Posted

技术标签:

【中文标题】抑制 sbt-assembly 中的主类【英文标题】:Suppress main class in sbt-assembly 【发布时间】:2013-08-21 22:07:11 【问题描述】:

在多项目 SBT 构建中,如何显式抑制 SBT-assembly 中的 mainClass 属性?

我进行了广泛的搜索,但似乎无法找到如何防止在多项目构建中由 sbt-assembly 构建的 jar 中设置主类。

在单项目构建中,只要至少有两个类可能被命令行调用,这似乎就可以工作:

import sbt._
import Keys._

import sbtassembly.Plugin._
import sbtassembly.AssemblyUtils._
import AssemblyKeys._

object TestBuild extends Build 
  lazy val buildSettings = Defaults.defaultSettings ++ assemblySettings ++ Seq(
    version := "0.1-SNAPSHOT",
    organization := "com.organization",
    scalaVersion := "2.10.2",
    mergeStrategy in assembly := mergeFirst
  )

  lazy val root = Project(id = "test-assembly",
    base = file("."),
    settings = buildSettings) settings(
    mainClass in assembly := None
  )
  lazy val mergeFirst: String => MergeStrategy =  
    case "reference.conf" | "rootdoc.txt" => MergeStrategy.concat
    case PathList("META-INF", xs @ _*) =>
    (xs map _.toLowerCase) match 
      case ("manifest.mf" :: Nil) | ("index.list" :: Nil) | ("dependencies" :: Nil) =>
      MergeStrategy.discard
      case ps @ (x :: xs) if ps.last.endsWith(".sf") || ps.last.endsWith(".dsa") =>
      MergeStrategy.discard
      case "plexus" :: xs =>
      MergeStrategy.discard
      case "services" :: xs =>
      MergeStrategy.filterDistinctLines
      case ("spring.schemas" :: Nil) | ("spring.handlers" :: Nil) =>
      MergeStrategy.filterDistinctLines
      case _ => MergeStrategy.first
    
    case _ => MergeStrategy.first
  

但是,mainClass := None 似乎甚至没有必要。事实上,即使它留在那里,如果只有一个候选类,清单中仍然会设置一个主类。

不幸的是,在多项目构建中,即使包含一个附加类作为虚拟入口点,我也无法阻止设置主类。

经过一番折腾,我发现可以通过在多个范围内独立设置mainClassNone 来防止设置主类。特别是,这可以解决问题:

mainClass in assembly := None
mainClass in packageBin := None
nainClass in Compile := None
mainClass in run := None

我在文档中找不到此要求,也无法弄清楚为什么这是必要的。设置mainClass in (Compile, run) := None 不起作用。它们确实需要单独确定范围。

这是手动抑制主类的正确方法还是我遗漏了什么?如果不是错误,我认为这应该在某处记录,特别是考虑到单项目和多项目构建之间的行为不一致。

【问题讨论】:

【参考方案1】:

Main-Class 和 jar 中的所有其他属性最终由 packageOptions in assembly 确定,因此您可以从中删除 Package.MainClass,如下所示:

lazy val root = Project(id = "test-assembly",
  base = file("."),
  settings = buildSettings) settings(
  packageOptions in assembly ~=  os => os filterNot _.isInstanceOf[Package.MainClass] 
)

这也适用于多项目构建。

注意:sbt-assembly 会根据源输入的元数据缓存输出 jar,因此测试 assembly 周围的设置需要调用 clean 来清除缓存。

【讨论】:

以上是关于抑制 sbt-assembly 中的主类的主要内容,如果未能解决你的问题,请参考以下文章

invokeLater 和 NetBeans 中的主类

如何检查类的给定实例是不是属于python中的主类? [复制]

抑制警告“类别正在实现一个方法,该方法也将由其主类实现”

OOzie 中 PySpark 作业的主类

更改 AnyLogic 中选择代理的主类参数

在AnyLogic中更改选定代理的主类参数