mirror of https://github.com/sbt/sbt.git
Use jarjar library from pants (WIP) (#102)
Seems more maintained than https://github.com/shevek/jarjar
This commit is contained in:
parent
759d0bff9a
commit
0400b537f4
14
build.sbt
14
build.sbt
|
|
@ -133,19 +133,13 @@ lazy val `sbt-pgp-coursier` = project
|
|||
|
||||
lazy val `sbt-shading` = project
|
||||
.in(file("modules/sbt-shading"))
|
||||
.enablePlugins(ScriptedPlugin, ShadingPlugin)
|
||||
.enablePlugins(ScriptedPlugin)
|
||||
.dependsOn(`sbt-coursier`)
|
||||
.settings(
|
||||
plugin,
|
||||
shading,
|
||||
libraryDependencies += "io.get-coursier.jarjar" % "jarjar-core" % "1.0.1-coursier-1" % "shaded",
|
||||
// dependencies of jarjar-core - directly depending on these so that they don't get shaded
|
||||
libraryDependencies ++= Seq(
|
||||
"com.google.code.findbugs" % "jsr305" % "3.0.2",
|
||||
"org.ow2.asm" % "asm-commons" % "7.0",
|
||||
"org.ow2.asm" % "asm-util" % "7.0",
|
||||
"org.slf4j" % "slf4j-api" % "1.7.26"
|
||||
),
|
||||
libraryDependencies += ("org.pantsbuild" % "jarjar" % "1.7.2")
|
||||
.exclude("org.apache.maven", "maven-plugin-api")
|
||||
.exclude("org.apache.ant", "ant"),
|
||||
scriptedDependencies := {
|
||||
scriptedDependencies.value
|
||||
// TODO Get dependency projects automatically
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
package org.pantsbuild.jarjar.util;
|
||||
|
||||
// adapted from https://github.com/pantsbuild/jarjar/blob/57845dc73d3e2c9b916ae4a788cfa12114fd7df1/src/main/java/org/pantsbuild/jarjar/util/StandaloneJarProcessor.java
|
||||
// - made it accepted a List<File> rather than a single File
|
||||
// - added argument ignoreDuplicateEntries
|
||||
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
public class CoursierJarProcessor
|
||||
{
|
||||
public static void run(File[] from, File to, JarProcessor proc, boolean ignoreDuplicateEntries) throws IOException {
|
||||
byte[] buf = new byte[0x2000];
|
||||
|
||||
final File tmpTo = File.createTempFile("jarjar", ".jar");
|
||||
Set<String> entries = new HashSet<>();
|
||||
|
||||
FileOutputStream fos = null;
|
||||
JarOutputStream out = null;
|
||||
try {
|
||||
fos = new FileOutputStream(tmpTo);
|
||||
BufferedOutputStream buffered = new BufferedOutputStream(fos);
|
||||
out = new JarOutputStream(buffered);
|
||||
|
||||
for (File from0 : from) {
|
||||
JarFile in = null;
|
||||
try {
|
||||
in = new JarFile(from0);
|
||||
Enumeration<JarEntry> e = in.entries();
|
||||
while (e.hasMoreElements()) {
|
||||
EntryStruct struct = new EntryStruct();
|
||||
JarEntry entry = e.nextElement();
|
||||
struct.name = entry.getName();
|
||||
struct.time = entry.getTime();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
IoUtil.pipe(in.getInputStream(entry), baos, buf);
|
||||
struct.data = baos.toByteArray();
|
||||
if (proc.process(struct)) {
|
||||
if (entries.add(struct.name)) {
|
||||
entry = new JarEntry(struct.name);
|
||||
entry.setTime(struct.time);
|
||||
entry.setCompressedSize(-1);
|
||||
out.putNextEntry(entry);
|
||||
out.write(struct.data);
|
||||
} else if (struct.name.endsWith("/")) {
|
||||
// TODO(chrisn): log
|
||||
} else if (!ignoreDuplicateEntries) {
|
||||
throw new DuplicateJarEntryException(from0.getAbsolutePath(), struct.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (in != null)
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (out != null)
|
||||
out.close();
|
||||
if (fos != null)
|
||||
fos.close();
|
||||
}
|
||||
|
||||
// delete the empty directories
|
||||
IoUtil.copyZipWithoutEmptyDirectories(tmpTo, to);
|
||||
tmpTo.delete();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -4,12 +4,9 @@ import java.io.{File, FileInputStream}
|
|||
import java.util.jar.JarInputStream
|
||||
import java.util.zip.{ZipEntry, ZipInputStream}
|
||||
|
||||
import com.tonicsystems.jarjar.classpath.ClassPath
|
||||
import com.tonicsystems.jarjar.transform.JarTransformer
|
||||
import com.tonicsystems.jarjar.transform.config.ClassRename
|
||||
import com.tonicsystems.jarjar.transform.jar.DefaultJarProcessor
|
||||
import coursier.core.{Configuration, Orders}
|
||||
import sbt.file
|
||||
import org.pantsbuild.jarjar._
|
||||
import org.pantsbuild.jarjar.util.CoursierJarProcessor
|
||||
|
||||
object Shading {
|
||||
|
||||
|
|
@ -191,17 +188,22 @@ object Shading {
|
|||
baseJar.getName.stripSuffix(".jar") + "-shading.jar"
|
||||
)
|
||||
|
||||
val processor = new DefaultJarProcessor
|
||||
def rename(from: String, to: String): Rule = {
|
||||
val rule = new Rule
|
||||
rule.setPattern(from)
|
||||
rule.setResult(to)
|
||||
rule
|
||||
}
|
||||
|
||||
for (namespace <- shadeNamespaces)
|
||||
processor.addClassRename(new ClassRename(namespace + ".**", shadingNamespace + ".@0"))
|
||||
val nsRules = shadeNamespaces.toVector.sorted.map { namespace =>
|
||||
rename(namespace + ".**", shadingNamespace + ".@0")
|
||||
}
|
||||
val clsRules = toShadeClasses.map { cls =>
|
||||
rename(cls, shadingNamespace + ".@0")
|
||||
}
|
||||
|
||||
for (cls <- toShadeClasses)
|
||||
processor.addClassRename(new ClassRename(cls, shadingNamespace + ".@0"))
|
||||
|
||||
val transformer = new JarTransformer(outputJar, processor)
|
||||
val cp = new ClassPath(file(sys.props("user.dir")), (baseJar +: toShadeJars).toArray)
|
||||
transformer.transform(cp)
|
||||
val processor = JJProcessor(nsRules ++ clsRules, verbose = true, skipManifest = false)
|
||||
CoursierJarProcessor.run((baseJar +: toShadeJars).toArray, outputJar, processor.proc, true)
|
||||
|
||||
outputJar
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
package org.pantsbuild.jarjar
|
||||
|
||||
// from https://github.com/sbt/sbt-assembly/blob/17786404117889e5a8225c97b9b7639160fb91e8/src/main/scala/org/pantsbuild/jarjar/JJProcessor.scala
|
||||
|
||||
import org.pantsbuild.jarjar.util.{EntryStruct, JarProcessor}
|
||||
|
||||
import scala.collection.JavaConverters._
|
||||
|
||||
class JJProcessor(val proc: JarProcessor) {
|
||||
|
||||
def process(entry: EntryStruct): Boolean = proc.process(entry)
|
||||
|
||||
def getExcludes(): Set[String] = {
|
||||
val field = proc.getClass().getDeclaredField("kp")
|
||||
field.setAccessible(true)
|
||||
val keepProcessor = field.get(proc)
|
||||
|
||||
if (keepProcessor == null) Set()
|
||||
else {
|
||||
val method = proc.getClass().getDeclaredMethod("getExcludes")
|
||||
method.setAccessible(true)
|
||||
method.invoke(proc).asInstanceOf[java.util.Set[String]].asScala.toSet
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
object JJProcessor {
|
||||
|
||||
def apply(patterns: Seq[PatternElement], verbose: Boolean, skipManifest: Boolean): JJProcessor =
|
||||
new JJProcessor(new MainProcessor(patterns.asJava, verbose, skipManifest))
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue