さっしーブログ

埼玉県在住のシステムエンジニアです。基本的には技術的な内容を中心に発信していきます。

sbt-assemblyを使用してjarを生成する際の同名ファイルのマージ指定方法

sbtで実行可能jarを作成した時のこと。

sbt-assemblyを使用して、
sbtコンソールからのコンパイル後に「assembly」をたたいたところ、
クラスファイルやプロパティファイルなどの重複エラーが発生した。

そんで調べてみるとsbtのjar生成時に見つかった重複ファイルは
build.sbtにMergeStrategyという設定を追加してあげることで
どちらのファイルを優先的に選択するか、
または重複ファイルを両方とも削除したりすることができる。

build.sbtに以下の記述を追加する。

大抵のことは以下の式にcaseを追加したり、
「".xml"」などの部分の拡張子を変更してあげて使用すれば大丈夫かと思う。

lazy val sampleAssemblyMergeStrategy = assemblyMergeStrategy in assembly := {
  case PathList(ps @ _*) if ps.last endsWith ".xml" => MergeStrategy.first
  case PathList(ps @ _*) if ps.last endsWith ".class" => MergeStrategy.first
  case PathList(ps @ _*) if ps.last endsWith ".properties" => MergeStrategy.first
  case x =>
  val oldStrategy = (assemblyMergeStrategy in assembly).value
  oldStrategy(x)
}

あとは、「MergeStrategy.first」の部分の「first」は
最初に見つかったものを選択するという意味なのだが、
削除したり結合したりもできるので適宜変更する必要はあるかと思います。

以下に参考としてMergeStrategyの設定値の種類を掲載します。

設定値 説明
MergeStrategy.deduplicate 既定値
MergeStrategy.first クラスパスの順序で最初に一致するファイルを選択します。
MergeStrategy.last クラスパスの順序で最後に一致するファイルを選択します。衝突時にはMergeStrategy.singleOrErrorのエラーメッセージが表示されます。
MergeStrategy.concat 単に一致するすべてのファイルを連結し、結果を含みます。
MergeStrategy.filterDistinctLines 連結されるが、重複は除外されます。
MergeStrategy.rename jarファイルの名前を変更します。
MergeStrategy.discard 一致するファイルを破棄します。

導入方法などは以下のドキュメントを参照すると良いと思います。

github.com

以上