diff --git a/scala/scala.bzl b/scala/scala.bzl index d189b7a23..179e1b7ba 100644 --- a/scala/scala.bzl +++ b/scala/scala.bzl @@ -128,9 +128,6 @@ def _collect_plugin_paths(plugins): def _compile(ctx, _jars, dep_srcjars, buildijar): jars = _jars - cp_resources = _add_resources_cmd( - ctx, "{out}_tmp".format(out=ctx.outputs.jar.path) - ) ijar_output_path = "" ijar_cmd_path = "" if buildijar: @@ -145,9 +142,6 @@ def _compile(ctx, _jars, dep_srcjars, buildijar): 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, @@ -170,6 +164,8 @@ JavacPath: {javac_path} JavacOpts: {javac_opts} JavaFiles: {java_files} JvmFlags: {jvm_flags} +ResourceSrcs: {resource_src} +ResourceDests: {resource_dest} """.format( out=ctx.outputs.jar.path, # 0 manifest=ctx.outputs.manifest.path, # 1 @@ -185,81 +181,16 @@ JvmFlags: {jvm_flags} javac_path=ctx.file._javac.path, java_files=",".join([f.path for f in java_srcs]), jvm_flags=" ".join(["-J" + flag for flag in ctx.attr.jvm_flags]), + resource_src=",".join([f.path for f in ctx.files.resources]), + resource_dest=",".join([_adjust_resources_path(f.path)[1] for f in ctx.files.resources]), ) - 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 """ - # srcjar_cmd += """-type f -name "*.scala""" - # srcjar_cmd += """ > {out}_args/files_from_jar\n""" -# TODO ADD RESOURCES SUPPORT! -# # add any resources -# {cp_resources} - -# TODO add source jar support -# touch {out}_args/files_from_jar -# mkdir -p {out}_tmp""" + srcjar_cmd + """ -# {out}_args/files_from_jar - + # TODO why this path here? argfile = ctx.new_file( ctx.configuration.bin_dir, "%s_worker_input" % ctx.label.name ) ctx.file_action(output=argfile, content=scalac_args) - # cmd = """ - # cat {scalac_args} > {out}_args/scala_args - # {java} -jar {scalac} {jvm_flags} @{out}_args/scala_args""" + javac_sources_cmd + """ - # """ + 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._jar), - # ijar=ctx.file._ijar.path, - # ) - outs = [ctx.outputs.jar] if buildijar: outs.extend([ctx.outputs.ijar]) @@ -271,20 +202,14 @@ JvmFlags: {jvm_flags} ctx.files.plugins + ctx.files.resources + ctx.files._jdk + - ctx.files._scalac + - ctx.files._jar + ctx.files._scalasdk + [ctx.outputs.manifest, ctx.file._ijar, ctx.file._java, - scalac_args_file, argfile]) - 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, diff --git a/src/java/io/bazel/rulesscala/scalac/CompileOptions.java b/src/java/io/bazel/rulesscala/scalac/CompileOptions.java index 566d05afb..a82b91fb2 100644 --- a/src/java/io/bazel/rulesscala/scalac/CompileOptions.java +++ b/src/java/io/bazel/rulesscala/scalac/CompileOptions.java @@ -20,6 +20,7 @@ public class CompileOptions { final public String javacPath; final public String javacOpts; final public String jvmFlags; + final public Map resourceFiles; public CompileOptions(List args) { Map argMap = buildArgMap(args); @@ -47,6 +48,20 @@ public CompileOptions(List args) { ijarOutput = null; ijarCmdPath = null; } + resourceFiles = getResources(argMap); + } + + private static Map getResources(Map args) { + String[] keys = getCommaList(args, "ResourceSrcs"); + String[] vals = getCommaList(args, "ResourceDests"); + if (keys.length != vals.length) + throw new RuntimeException(String.format("mismatch in resources: keys: %s vals: %s", + getOrEmpty(args, "ResourceSrcs"), getOrEmpty(args, "ResourceDests"))); + HashMap res = new HashMap(); + for(int idx = 0; idx < keys.length; idx++) { + res.put(keys[idx], vals[idx]); + } + return res; } private static HashMap buildArgMap(List lines) { diff --git a/src/java/io/bazel/rulesscala/scalac/ScalaCInvoker.java b/src/java/io/bazel/rulesscala/scalac/ScalaCInvoker.java index 8228e3d46..5c12115a8 100644 --- a/src/java/io/bazel/rulesscala/scalac/ScalaCInvoker.java +++ b/src/java/io/bazel/rulesscala/scalac/ScalaCInvoker.java @@ -31,10 +31,13 @@ import java.io.IOException; import java.io.PrintStream; import java.lang.reflect.Field; +import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.FileSystems; +import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -222,13 +225,15 @@ public static String[] merge(String[]... arrays) { } private static void processRequest(List args) throws Exception { + Path tmpPath = null; + try { if (args.size() == 1 && args.get(0).startsWith("@")) { args = Files.readAllLines(Paths.get(args.get(0).substring(1)), UTF_8); } CompileOptions ops = new CompileOptions(args); Path outputPath = FileSystems.getDefault().getPath(ops.outputName); - Path tmpPath = Files.createTempDirectory(outputPath.getParent(), "tmp"); + tmpPath = Files.createTempDirectory(outputPath.getParent(), "tmp"); String[] constParams = { "-classpath", ops.classpath, @@ -283,6 +288,10 @@ private static void processRequest(List args) throws Exception { throw new RuntimeException("javac process failed!"); } } + /** + * Copy the resources + */ + copyResources(ops.resourceFiles, tmpPath); /** * Now build the output jar */ @@ -306,10 +315,40 @@ private static void processRequest(List args) throws Exception { if(exitCode != 0) { throw new RuntimeException("ijar process failed!"); } - // System.out.println("exitCode = " + exitCode); } - // System.out.println("Success"); } + } + finally { + removeTmp(tmpPath); + } + } + private static void removeTmp(Path tmp) throws IOException { + if (tmp != null) { + Files.walkFileTree(tmp, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); + } + } + private static void copyResources(Map resources, Path dest) throws IOException { + for(Entry e : resources.entrySet()) { + Path source = Paths.get(e.getKey()); + String dstr = e.getValue(); + if (dstr.charAt(0) == '/') dstr = dstr.substring(1); + Path target = dest.resolve(dstr); + File tfile = target.getParent().toFile(); + tfile.mkdirs(); + Files.copy(source, target); + } } public static void main(String[] args) { diff --git a/test/BUILD b/test/BUILD index 10dbdee72..0ef294289 100644 --- a/test/BUILD +++ b/test/BUILD @@ -9,25 +9,25 @@ load("//scala:scala.bzl", # The examples below show how to combine Scala and Java rules. # ScalaBinary is the Scala equivalent of JavaBinary. -# java_binary( -# name = "JavaBinary", -# srcs = ["JavaBinary.java"], -# main_class = "scala.test.JavaBinary", -# deps = [":lib_import"], -# ) - -# # TODO(bazel-team): Allow java rules to depend directly on scala_library. -# # For now, we have to use a java_import proxy. -# java_import( -# name = "lib_import", -# # these are the outputs of the scala_library targets -# jars = [":HelloLib_deploy.jar", -# "OtherLib_deploy.jar", -# "Exported_deploy.jar", -# "Runtime_deploy.jar", -# ], -# runtime_deps = ["org_scala_lang__scala_library", "OtherJavaLib"] -# ) +java_binary( + name = "JavaBinary", + srcs = ["JavaBinary.java"], + main_class = "scala.test.JavaBinary", + deps = [":lib_import"], +) + +# TODO(bazel-team): Allow java rules to depend directly on scala_library. +# For now, we have to use a java_import proxy. +java_import( + name = "lib_import", + # these are the outputs of the scala_library targets + jars = [":HelloLib_deploy.jar", + "OtherLib_deploy.jar", + "Exported_deploy.jar", + "Runtime_deploy.jar", + ], + runtime_deps = ["org_scala_lang__scala_library", "OtherJavaLib"] +) scala_export_to_java( name = "lib_import_2",