Resource transformers for sbt-assembly plugin
Add to project/plugins.sbt
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.10")
addSbtPlugin("com.sandinh" % "sbt-shade" % "0.1.0")
For example, to shade the following dependencies:
netty-tcnative-boringssl-static
jackson-core
jackson-databind
jackson-module-afterburner
you need add to build.sbt
import sbtassembly.shadeplugin.ResourceTransformer.{Rename, Discard}
val myAssemblySettings = inTask(assembly)(
Seq(
assemblyShadeRules := Seq(
"io.netty",
"com.fasterxml.jackson"
).map { p =>
ShadeRule.rename(s"$p.**" -> "com.couchbase.client.core.deps.@0").inAll
},
assemblyMergeStrategy := {
case PathList("META-INF", "io.netty.versions.properties") => MergeStrategy.concat
// https://stackoverflow.com/a/55557287/457612
case "module-info.class" => MergeStrategy.discard
case x => assemblyMergeStrategy.value(x)
},
shadeResourceTransformers ++= Seq(
Rename(
"libnetty_tcnative_linux_x86_64.so" -> "libcom_couchbase_client_core_deps_netty_tcnative_linux_x86_64.so",
"libnetty_tcnative_osx_x86_64.jnilib" -> "libcom_couchbase_client_core_deps_netty_tcnative_osx_x86_64.jnilib",
"netty_tcnative_windows_x86_64.dll" -> "com_couchbase_client_core_deps_netty_tcnative_windows_x86_64.dll"
).inDir("META-INF/native"),
Discard(
"com.fasterxml.jackson.core.JsonFactory",
"com.fasterxml.jackson.core.ObjectCodec",
"com.fasterxml.jackson.databind.Module"
).inDir("META-INF/services")
)
)
)
val otherSettings = ...
lazy val `core-io` = project
.settings(myAssemblySettings ++ otherSettings: _*)
Note the use of shadeResourceTransformers ++= Seq(Rename(..), Discard(..)
For example, com.couchbase.client:core-io
lib want to shade the libraries above into core-io-<version>.jar
But keep other libs as normal dependencies (not shade):
import sbtassembly.shadeplugin.ShadePluginUtils._
lazy val `core-io-deps` = project
.settings(
libraryDependencies := coreIoShadedDeps,
publish / skip := true,
// https://www.scala-sbt.org/1.x/docs/Howto-Classpaths.html#Use+packaged+jars+on+classpaths+instead+of+class+directories
// exportJars so in dependent projects, we can compute assemblyExcludedJars based on this Project / artifactPath
exportJars := true
)
val coreIoAssemblySettings = commonAssemblySettings ++ inTask(assembly)(
Seq(
// shade only core-io-deps and selfJar (core-io)
assemblyExcludedJars := {
val cp = fullClasspath.value
val depJar = (`core-io-deps` / assembly / assemblyOutputPath).value
val selfJar = (Compile / packageBin / artifactPath).value
val includedJars = Set(depJar, selfJar)
cp.filterNot { entry =>
includedJars contains entry.data
}
}
)
)
lazy val `core-io` = project
.settings(coreIoAssemblySettings: _*)
.enableAssemblyPublish()
.settings(
libraryDependencies ++= coreIoDeps,
exportJars := true,
Compile / unmanagedJars += {
(`core-io-deps` / assembly).value
(`core-io-deps` / assembly / assemblyOutputPath).value
}
)
lazy val `scala-implicits` = project
.disablePlugins(AssemblyPlugin)
.settings(
libraryDependencies ++= scalaImplicitsDeps,
exportJars := true,
publish / skip := true
)
.dependsOn(`core-io`)
val scalaClientAssemblySettings = commonAssemblySettings ++ inTask(assembly)(
Seq(
// shade scala-java8-compat, scala-implicits and selfJar (scala-client)
assemblyExcludedJars := ...
)
)
lazy val `scala-client` = project
.settings(scalaModuleSettings ++ scalaClientAssemblySettings: _*)
.enableAssemblyPublish()
.settings(
libraryDependencies ++= scalaClientDeps
)
.dependsOn(`core-io`, `scala-implicits`)
.removePomDependsOn(`scala-implicits`)
.removePomDependsOn(scalaJava8Compat)
Note the use of enableAssemblyPublish
and removePomDependsOn
which is defined in ShadePluginUtils.ShadeProjectOps
Add the following settings:
project.settings(
autoScalaLibrary := false, // exclude scala-library from dependencies
crossPaths := false // drop off Scala suffix from artifact names and publish path
)
- clone
- using IntelliJ
- Set IntelliJ using scalafmt code formatter
- sbt
+scripted
- Add
Project.removePomDependsOn(moduleIDs: ModuleID*)