Skip to content

Commit

Permalink
WIP -- have the jar creator code inlined
Browse files Browse the repository at this point in the history
  • Loading branch information
ianoc-stripe committed Sep 11, 2016
1 parent 0a1ad35 commit f11926a
Show file tree
Hide file tree
Showing 5 changed files with 271 additions and 145 deletions.
302 changes: 163 additions & 139 deletions scala/scala.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -21,35 +21,43 @@ _srcjar_filetype = FileType([".srcjar"])
# TODO is there a way to derive this from the above?
_scala_srcjar_filetype = FileType([".scala", ".srcjar", ".java"])


def _adjust_resources_path(path):
dir_1, dir_2, rel_path = path.partition("resources")
if rel_path:
return dir_1 + dir_2, rel_path
(dir_1,dir_2,rel_path) = path.partition("java")
if rel_path:
return dir_1 + dir_2, rel_path
return "", path
# Here we are looking to find out the offset of this resource inside
# any resources folder. We want to return the root to the resources folder
# and then the sub path inside it
dir_1, dir_2, rel_path = path.partition("resources")
if rel_path:
return dir_1 + dir_2, rel_path

# The same as the above but just looking for java
(dir_1, dir_2, rel_path) = path.partition("java")
if rel_path:
return dir_1 + dir_2, rel_path
return "", path


def _add_resources_cmd(ctx, dest):
res_cmd = ""
for f in ctx.files.resources:
c_dir, res_path = _adjust_resources_path(f.path)
target_path = res_path
if res_path[0] != "/":
target_path = "/" + res_path
res_cmd += "\nmkdir -p $(dirname {out_dir}{target_path})\ncp {c_dir}{res_path} {out_dir}{target_path}".format(
out_dir=dest,
res_path=res_path,
target_path=target_path,
c_dir=c_dir)
return res_cmd
res_cmd = ""
for f in ctx.files.resources:
c_dir, res_path = _adjust_resources_path(f.path)
target_path = res_path
if res_path[0] != "/":
target_path = "/" + res_path
res_cmd += "\nmkdir -p $(dirname {out_dir}{target_path})\ncp {c_dir}{res_path} {out_dir}{target_path}".format(
out_dir=dest,
res_path=res_path,
target_path=target_path,
c_dir=c_dir)
return res_cmd


def _get_jar_path(paths):
for p in paths:
path = p.path
if path.endswith("/jar_deploy.jar"):
return path
return None
for p in paths:
path = p.path
if path.endswith("/jar_deploy.jar"):
return path
return None

def _get_scalac_jar_path(paths):
for p in paths:
Expand Down Expand Up @@ -107,124 +115,140 @@ def _collect_plugin_paths(plugins):
paths += [f.path for f in p.files]
return paths


def _compile(ctx, _jars, dep_srcjars, buildijar):
jars = _jars
cp_resources = _add_resources_cmd(ctx, "{out}_tmp".format(out=ctx.outputs.jar.path))
ijar_cmd = ""
if buildijar:
ijar_cmd = "\n{ijar} {out} {ijar_out}".format(
ijar=ctx.file._ijar.path,
out=ctx.outputs.jar.path,
ijar_out=ctx.outputs.ijar.path)
jars = _jars
cp_resources = _add_resources_cmd(ctx, "{out}_tmp".format(out=ctx.outputs.jar.path))
ijar_cmd = ""
if buildijar:
ijar_cmd = "\n{ijar} {out} {ijar_out}".format(
ijar=ctx.file._ijar.path,
out=ctx.outputs.jar.path,
ijar_out=ctx.outputs.ijar.path)

java_srcs = _java_filetype.filter(ctx.files.srcs)
sources = _scala_filetype.filter(ctx.files.srcs) + java_srcs
srcjars = _srcjar_filetype.filter(ctx.files.srcs)
all_srcjars = set(srcjars + list(dep_srcjars))
# look for any plugins:
plugins = _collect_plugin_paths(ctx.attr.plugins)
plugin_arg = ",".join(list(plugins))

# Set up the args to pass to scalac because they can be too long for bash
scalac_args_file = ctx.new_file(ctx.outputs.jar, ctx.label.name + "_scalac_args") # noqa

compiler_classpath = '{scalalib}:{scalacompiler}:{scalareflect}:{jars}'.format( # noqa
scalalib=ctx.file._scalalib.path,
scalacompiler=ctx.file._scalacompiler.path,
scalareflect=ctx.file._scalareflect.path,
jars=":".join([j.path for j in jars]),
)

java_srcs = _java_filetype.filter(ctx.files.srcs)
sources = _scala_filetype.filter(ctx.files.srcs) + java_srcs
srcjars = _srcjar_filetype.filter(ctx.files.srcs)
all_srcjars = set(srcjars + list(dep_srcjars))
# look for any plugins:
plugins = _collect_plugin_paths(ctx.attr.plugins)
plugin_arg = ""
if (len(plugins) > 0):
plugin_arg = " ".join(["-Xplugin:%s" % p for p in plugins])

# Set up the args to pass to scalac because they can be too long for bash
scalac_args_file = ctx.new_file(ctx.outputs.jar, ctx.label.name + "_scalac_args")
scalac_args = """{scala_opts} {plugin_arg} -classpath {scalalib}:{scalacompiler}:{scalareflect}:{jars} -d {out}_tmp {files}""".format(
scala_opts=" ".join(ctx.attr.scalacopts),
scalalib=ctx.file._scalalib.path,
scalacompiler=ctx.file._scalacompiler.path,
scalareflect=ctx.file._scalareflect.path,
plugin_arg = plugin_arg,
jars=":".join([j.path for j in jars]),
files=" ".join([f.path for f in sources]),
out=ctx.outputs.jar.path
# these are args that our launcher app is going to consume
# and will not be passed to scalac
pre_pargs = '{out} {manifest}'.format(
out=ctx.outputs.jar.path, # 0
manifest=ctx.outputs.manifest.path, # 1
)
scalac_args = """{pre_pargs} {scala_opts} {plugin_arg} {cp} {files}""".format( # noqa
pre_pargs=pre_pargs,
scala_opts=",".join(ctx.attr.scalacopts), # 2
plugin_arg=plugin_arg, # 3
cp=compiler_classpath, # 4
files=",".join([f.path for f in sources]), # 5
)
ctx.file_action(output=scalac_args_file, content=scalac_args)
javac_sources_cmd = ""
compile_java_srcs = len(java_srcs) != 0
if (compile_java_srcs):
# Set up the args to pass to javac because they can be
# too long for bash
javac_args_file = ctx.new_file(
ctx.outputs.jar,
ctx.label.name + "_javac_args")

javac_args = """{javac_opts} -classpath "{jars}:{out}_tmp" -d {out}_tmp {files}""".format( # noqa
javac_opts=" ".join(ctx.attr.javacopts),
jars=":".join([j.path for j in jars]),
files=" ".join([f.path for f in java_srcs]),
out=ctx.outputs.jar.path
)
ctx.file_action(output=javac_args_file, content=javac_args)
javac_sources_cmd = """
cat {javac_args} {{out}}_args/files_from_jar > {{out}}_args/java_args
{javac} {{jvm_flags}} @{{out}}_args/java_args""".format(
javac_args=javac_args_file.path,
javac=ctx.file._javac.path
)

srcjar_cmd = ""
if len(all_srcjars) > 0:
srcjar_cmd = "\nmkdir -p {out}_tmp_expand_srcjars\n"
for srcjar in all_srcjars:
# Note: this is double escaped because we need to do one format call
# per each srcjar, but then we are going to include this in the bigger format
# call that is done to generate the full command

#TODO would like to be able to switch >/dev/null, -v, etc based on the user's settings
srcjar_cmd += """
unzip -o {srcjar} -d {{out}}_tmp_expand_srcjars >/dev/null
""".format(srcjar = srcjar.path)
srcjar_cmd += """find {out}_tmp_expand_srcjars -type f -name "*.scala" > {out}_args/files_from_jar\n"""

cmd = """
rm -rf {out}_args
rm -rf {out}_tmp
rm -rf {out}_tmp_expand_srcjars
set -e
mkdir -p {out}_args
touch {out}_args/files_from_jar
mkdir -p {out}_tmp""" + srcjar_cmd + """
cat {scalac_args} {out}_args/files_from_jar > {out}_args/scala_args
{java} -jar {scalac} {jvm_flags} @{out}_args/scala_args""" + javac_sources_cmd + """
# add any resources
{cp_resources}
""" + ijar_cmd
cmd = cmd.format(
cp_resources=cp_resources,
java=ctx.file._java.path,
jvm_flags=" ".join(["-J" + flag for flag in ctx.attr.jvm_flags]),
scalac=_get_scalac_jar_path(ctx.files._scalac),
scalac_args=scalac_args_file.path,
out=ctx.outputs.jar.path,
manifest=ctx.outputs.manifest.path,
jar=_get_jar_path(ctx.files.__deploy_jar),
ijar=ctx.file._ijar.path,
)
ctx.file_action(output = scalac_args_file, content = scalac_args)
javac_sources_cmd = ""
compile_java_srcs = len(java_srcs) != 0
if (compile_java_srcs):
# Set up the args to pass to javac because they can be too long for bash
javac_args_file = ctx.new_file(ctx.outputs.jar, ctx.label.name + "_javac_args")
javac_args = """{javac_opts} -classpath "{jars}:{out}_tmp" -d {out}_tmp {files}""".format(
javac_opts=" ".join(ctx.attr.javacopts),
jars=":".join([j.path for j in jars]),
files=" ".join([f.path for f in java_srcs]),
out=ctx.outputs.jar.path
outs = [ctx.outputs.jar]
if buildijar:
outs.extend([ctx.outputs.ijar])
ins = (list(jars) +
list(dep_srcjars) +
list(srcjars) +
list(sources) +
ctx.files.srcs +
ctx.files.plugins +
ctx.files.resources +
ctx.files._jdk +
ctx.files._scalac +
ctx.files.__deploy_jar +
ctx.files._scalasdk +
[ctx.outputs.manifest,
ctx.file._ijar,
ctx.file._java,
scalac_args_file])
if compile_java_srcs:
ins.extend([javac_args_file])
ctx.action(
inputs=ins,
outputs=outs,
command=cmd,
# executable=ctx.executable._scalac,
mnemonic="Scalac",
progress_message="scala %s" % ctx.label,
execution_requirements={"supports-workers": "1"},
arguments=["@" + ctx.outputs.jar.path + "_args/scala_args"],
)
ctx.file_action(output = javac_args_file, content = javac_args)
javac_sources_cmd = """
cat {javac_args} {{out}}_args/files_from_jar > {{out}}_args/java_args
{javac} {{jvm_flags}} @{{out}}_args/java_args""".format(javac_args = javac_args_file.path,javac=ctx.file._javac.path)

srcjar_cmd = ""
if len(all_srcjars) > 0:
srcjar_cmd = "\nmkdir -p {out}_tmp_expand_srcjars\n"
for srcjar in all_srcjars:
# Note: this is double escaped because we need to do one format call
# per each srcjar, but then we are going to include this in the bigger format
# call that is done to generate the full command

#TODO would like to be able to switch >/dev/null, -v, etc based on the user's settings
srcjar_cmd += """
unzip -o {srcjar} -d {{out}}_tmp_expand_srcjars >/dev/null
""".format(srcjar = srcjar.path)
srcjar_cmd += """find {out}_tmp_expand_srcjars -type f -name "*.scala" > {out}_args/files_from_jar\n"""

cmd = """
rm -rf {out}_args
rm -rf {out}_tmp
rm -rf {out}_tmp_expand_srcjars
set -e
mkdir -p {out}_args
touch {out}_args/files_from_jar
mkdir -p {out}_tmp""" + srcjar_cmd + """
cat {scalac_args} {out}_args/files_from_jar > {out}_args/scala_args
{java} -jar {scalac} {jvm_flags} @{out}_args/scala_args""" + javac_sources_cmd + """
# add any resources
{cp_resources}
{java} -jar {jar} -m {manifest} {out} {out}_tmp
rm -rf {out}_args
rm -rf {out}_tmp
rm -rf {out}_tmp_expand_srcjars
""" + ijar_cmd
cmd = cmd.format(
cp_resources=cp_resources,
java=ctx.file._java.path,
jvm_flags=" ".join(["-J" + flag for flag in ctx.attr.jvm_flags]),
scalac=_get_scalac_jar_path(ctx.files._scalac),
scalac_args=scalac_args_file.path,
out=ctx.outputs.jar.path,
manifest=ctx.outputs.manifest.path,
jar=_get_jar_path(ctx.files.__deploy_jar),
ijar=ctx.file._ijar.path,
)
outs = [ctx.outputs.jar]
if buildijar:
outs.extend([ctx.outputs.ijar])
ins = (list(jars) +
list(dep_srcjars) +
list(srcjars) +
list(sources) +
ctx.files.srcs +
ctx.files.plugins +
ctx.files.resources +
ctx.files._jdk +
ctx.files._scalac +
ctx.files.__deploy_jar +
ctx.files._scalasdk +
[ctx.outputs.manifest,
ctx.file._ijar,
ctx.file._java,
scalac_args_file])
if compile_java_srcs:
ins.extend([javac_args_file])
ctx.action(
inputs=ins,
outputs=outs,
command=cmd,
mnemonic="Scalac",
progress_message="scala %s" % ctx.label,
arguments=[])

def _compile_or_empty(ctx, jars, srcjars, buildijar):
# We assume that if a srcjar is present, it is not empty
Expand Down Expand Up @@ -482,7 +506,7 @@ _implicit_deps = {
"_scalareflect": attr.label(default=Label("@scala//:lib/scala-reflect.jar"), single_file=True, allow_files=True),
"_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),
"__deploy_jar": attr.label(executable=True, default=Label("//src/java/io/bazel/rulesscala/jar:jar_deploy.jar"), allow_files=True),
"__deploy_jar": attr.label(executable=True, default=Label("//src/java/io/bazel/rulesscala/jar:binary_deploy.jar"), allow_files=True),
"_jdk": attr.label(default=Label("//tools/defaults:jdk"), allow_files=True),
}

Expand Down
10 changes: 9 additions & 1 deletion src/java/io/bazel/rulesscala/jar/BUILD
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
java_binary(name = "jar",
java_library(name = "jar",
srcs = ["JarCreator.java", "JarHelper.java"],
visibility = ["//visibility:public"],
)


java_binary(name = "binary",
runtime_deps = [
":jar",
],
main_class = "io.bazel.rulesscala.jar.JarCreator",
visibility = ["//visibility:public"],
)
23 changes: 23 additions & 0 deletions src/java/io/bazel/rulesscala/jar/JarCreator.java
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,29 @@ public void execute() throws IOException {
}
}

public static void buildJar(String[] args) throws IOException {
if (args.length < 1) {
System.err.println("usage: CreateJar [-m manifest] output [root directories]");
System.exit(1);
}

int idx = 0;
String manifestFile = null;
if (args[0].equals("-m")) {
manifestFile = args[1];
idx = 2;
}
String output = args[idx];
JarCreator createJar = new JarCreator(output);
createJar.setManifestFile(manifestFile);
for (int i = (idx+1); i < args.length; i++) {
createJar.addDirectory(args[i]);
}
createJar.setCompression(true);
createJar.setNormalize(true);
createJar.execute();
}

/**
* A simple way to create Jar file using the JarCreator class.
*/
Expand Down
1 change: 1 addition & 0 deletions src/java/io/bazel/rulesscala/scalac/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ java_binary(name = "scalac",
"@scala//:lib/scala-reflect.jar",
"@scala//:lib/scala-compiler.jar",
"@scala//:lib/scala-xml_2.11-1.0.4.jar",
"//src/java/io/bazel/rulesscala/jar",
],
visibility = ["//visibility:public"],
)
Loading

0 comments on commit f11926a

Please sign in to comment.