Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve the deploy jar creation #85

Merged
merged 4 commits into from
Aug 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 18 additions & 15 deletions scala/scala.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -233,25 +233,27 @@ def _compile_or_empty(ctx, jars, srcjars, buildijar):
return struct(ijar=ijar, class_jar=ctx.outputs.jar)

def _build_deployable(ctx, jars):
cmd = "rm -rf {out}_tmp\n"
cmd += "mkdir -p {out}_tmp\n"
for jar in jars:
cmd += "unzip -o {jar} -d {{out}}_tmp >/dev/null\n".format(jar=jar.path)
cmd += "{java} -jar {jar} -m {manifest} {out} {out}_tmp\n"
cmd += "rm -rf {out}_tmp\n"

cmd = cmd.format(
out=ctx.outputs.deploy_jar.path,
jar=_get_jar_path(ctx.files._jar),
java=ctx.file._java.path,
manifest=ctx.outputs.manifest.path)
# the _jar_bin program we call below expects one optional argument:
# -m is the argument to pass a manifest to our jar creation code
# the next argument is the path manifest itself
# the manifest is set up by methods that call this function (see usages
# of _build_deployable and note that they always first call write_manifest).
# that is what creates the manifest content
#
# following the manifest argument and the manifest, the next argument is
# the output path for the target jar
#
# finally all the rest of the arguments are jars to be flattened into one
# fat jar
args = ["-m", ctx.outputs.manifest.path, ctx.outputs.deploy_jar.path]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does -m stand for? Obviously a noob question but maybe should be a constant? a bit of a magic symbol?

args.extend([j.path for j in jars])
ctx.action(
inputs=list(jars) + ctx.files._jdk + ctx.files._jar + [ctx.outputs.manifest],
inputs=list(jars) + [ctx.outputs.manifest],
outputs=[ctx.outputs.deploy_jar],
command=cmd,
executable=ctx.executable._jar_bin,
mnemonic="ScalaDeployJar",
progress_message="scala deployable %s" % ctx.label,
arguments=[])
arguments=args)

def write_manifest(ctx):
# TODO(bazel-team): I don't think this classpath is what you want
Expand Down Expand Up @@ -471,6 +473,7 @@ _implicit_deps = {
"_java": attr.label(executable=True, default=Label("@bazel_tools//tools/jdk:java"), single_file=True, allow_files=True),
"_javac": attr.label(executable=True, default=Label("@bazel_tools//tools/jdk:javac"), single_file=True, allow_files=True),
"_jar": attr.label(executable=True, default=Label("//src/java/io/bazel/rulesscala/jar:jar_deploy.jar"), allow_files=True),
"_jar_bin": attr.label(executable=True, default=Label("//src/java/io/bazel/rulesscala/jar")),
"_jdk": attr.label(default=Label("//tools/defaults:jdk"), allow_files=True),
}

Expand Down
16 changes: 13 additions & 3 deletions src/java/io/bazel/rulesscala/jar/JarCreator.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,13 @@ public boolean addEntry(String entryName, String fileName) {
*
* @param directory the directory to add to the jar
*/
public void addDirectory(String directory) {
addDirectory(null, new File(directory));
public void addDirectory(File directory) {
addDirectory(null, directory);
}

public void addJar(File file) {
jarEntries.put(file.getAbsolutePath(), file.getAbsolutePath());
}
/**
* Adds the contents of a directory to the Jar file. All files below this
* directory will be added to the Jar file using the prefix and the name
Expand Down Expand Up @@ -189,7 +192,14 @@ public static void main(String[] args) {
JarCreator createJar = new JarCreator(output);
createJar.setManifestFile(manifestFile);
for (int i = (idx+1); i < args.length; i++) {
createJar.addDirectory(args[i]);
String thisName = args[i];
File f = new File(thisName);
if (JarHelper.isJar(f)) {
createJar.addJar(f);
}
else {
createJar.addDirectory(f);
}
}
createJar.setCompression(true);
createJar.setNormalize(true);
Expand Down
72 changes: 56 additions & 16 deletions src/java/io/bazel/rulesscala/jar/JarHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,18 @@

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.zip.CRC32;
import java.util.zip.ZipException;

/**
* A simple helper class for creating Jar files. All Jar entries are sorted alphabetically. Allows
Expand Down Expand Up @@ -61,6 +64,10 @@ public JarHelper(String filename) {
jarFile = filename;
}

public static boolean isJar(File file) {
return file.getName().endsWith(".jar") && (file.isFile());
}

/**
* Enables or disables the Jar entry normalization.
*
Expand Down Expand Up @@ -170,6 +177,33 @@ protected void writeManifestEntry(byte[] content) throws IOException {
}
}

/**
* This copies the contents of jarFile into out
* This is a static method to make it clear what is mutated (and it
* was written by someone who really likes to minimize state changes).
*/
static private void copyJar(JarFile nameJf, Set<String> names, JarOutputStream out) throws IOException {
byte[] buffer = new byte[2048];
for (Enumeration<JarEntry> e = nameJf.entries(); e.hasMoreElements();) {
JarEntry existing = e.nextElement();
String name = existing.getName();
if (!names.contains(name)) {
JarEntry outEntry = new JarEntry(name);
outEntry.setTime(existing.getTime());
outEntry.setSize(existing.getSize());
out.putNextEntry(outEntry);
InputStream in = nameJf.getInputStream(existing);
while (0 < in.available()) {
int read = in.read(buffer);
out.write(buffer, 0, read);
}
in.close();
out.closeEntry();
names.add(name);
}
}
}

/**
* Copies file or directory entries from the file system into the jar.
* Directory entries will be detected and their names automatically '/'
Expand All @@ -189,24 +223,30 @@ protected void copyEntry(String name, File file) throws IOException {
System.err.println("adding " + file);
}
// Create a new entry
long size = isDirectory ? 0 : file.length();
JarEntry outEntry = new JarEntry(name);
long newtime = normalize ? normalizedTimestamp(name) : file.lastModified();
outEntry.setTime(newtime);
outEntry.setSize(size);
if (size == 0L) {
outEntry.setMethod(JarEntry.STORED);
outEntry.setCrc(0);
out.putNextEntry(outEntry);
} else {
outEntry.setMethod(storageMethod);
if (storageMethod == JarEntry.STORED) {
outEntry.setCrc(hashFile(file));
if (JarHelper.isJar(file)) {
JarFile nameJf = new JarFile(file);
copyJar(nameJf, names, out);
}
else {
long size = isDirectory ? 0 : file.length();
JarEntry outEntry = new JarEntry(name);
long newtime = normalize ? normalizedTimestamp(name) : file.lastModified();
outEntry.setTime(newtime);
outEntry.setSize(size);
if (size == 0L) {
outEntry.setMethod(JarEntry.STORED);
outEntry.setCrc(0);
out.putNextEntry(outEntry);
} else {
outEntry.setMethod(storageMethod);
if (storageMethod == JarEntry.STORED) {
outEntry.setCrc(hashFile(file));
}
out.putNextEntry(outEntry);
Files.copy(file.toPath(), out);
}
out.putNextEntry(outEntry);
Files.copy(file.toPath(), out);
out.closeEntry();
}
out.closeEntry();
}
}
}
Expand Down