1. deduplicate file appears in two different jar:
If multiple files share the same relative path (e.g. a resource named application.conf
in multiple dependency JARs), the default strategy is to verify that all candidates have the same contents and error out otherwise.
The you need use the merge strategy.
reference: https://github.com/sbt/sbt-assembly
This behavior can be configured on a per-path basis using either one of the following built-in strategies or writing a custom one:
MergeStrategy.deduplicate
is the default described aboveMergeStrategy.first
picks the first of the matching files in classpath orderMergeStrategy.last
picks the last oneMergeStrategy.singleOrError
bails out with an error message on conflictMergeStrategy.concat
simply concatenates all matching files and includes the resultMergeStrategy.filterDistinctLines
also concatenates, but leaves out duplicates along the wayMergeStrategy.rename
renames the files originating from jar filesMergeStrategy.discard
simply discards matching files
The mapping of path names to merge strategies is done via the setting assemblyMergeStrategy
which can be augmented as follows:
assemblyMergeStrategy in assembly := {
case PathList("javax", "servlet", xs @ _*) => MergeStrategy.first
case PathList(ps @ _*) if ps.last endsWith ".html" => MergeStrategy.first
case "application.conf" => MergeStrategy.concat
case "unwanted.txt" => MergeStrategy.discard
case x =>
val oldStrategy = (assemblyMergeStrategy in assembly).value
oldStrategy(x)
}
NOTE:
assemblyMergeStrategy in assembly
expects a function. You can't doassemblyMergeStrategy in assembly := MergeStrategy.first
!- Some files must be discarded or renamed otherwise to avoid breaking the zip (due to duplicate file name) or the legal license. Delegate default handling to
(assemblyMergeStrategy in assembly)
as the above pattern matching example.
By the way, the first case pattern in the above using PathList(...)
is how you can pick javax/servlet/*
from the first jar. If the default MergeStrategy.deduplicate
is not working for you, that likely means you have multiple versions of some library pulled by your dependency graph. The real solution is to fix that dependency graph. You can work around it by MergeStrategy.first
but don't be surprised when you see ClassNotFoundException
.
Here is the default:
val defaultMergeStrategy: String => MergeStrategy = {
case x if Assembly.isConfigFile(x) =>
MergeStrategy.concat
case PathList(ps @ _*) if Assembly.isReadme(ps.last) || Assembly.isLicenseFile(ps.last) =>
MergeStrategy.rename
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.deduplicate
}
case _ => MergeStrategy.deduplicate
}
Custom MergeStrategy
s can find out where a particular file comes from using the sourceOfFileForMerge
method on sbtassembly.AssemblyUtils
, which takes the temporary directory and one of the files passed into the strategy as parameters.
Third Party Merge Strategy Plugins
Support for special-case merge strategies beyond the generic scope can be provided by companion plugins, below is a non-exhaustive list:
- Log4j2 Plugin Caches (
Log4j2Plugins.dat
): https://github.com/idio/sbt-assembly-log4j2
2. 使用IDEA SBT console, run command: assembly, then error occurs: Java OutOfMemory
需要增大JVM可用内存:
调大 IDEA settings 中sbt -> VM parameters -> -Xmx1024M
调大 SBT_HOME/conf/sbtconfig.txt 中 -Xmx1024M
reference: http://blog.csdn.net/pengych_321/article/details/52004860