Add Skylark rules for groovy_library and groovy_binary.

This is a slightly cleaned-up version of the rules from
https://github.com/ekuefler/bazel-groovy, which my team has been using for a few
months. I'll add the test rules from there separately.

--
Change-Id: I07b5270bfdada5244ed82dee617b4997855747d8
Reviewed-on: https://bazel-review.googlesource.com/#/c/1590/
MOS_MIGRATED_REVID=100476149
diff --git a/tools/build_defs/groovy/README.md b/tools/build_defs/groovy/README.md
new file mode 100644
index 0000000..e881a15
--- /dev/null
+++ b/tools/build_defs/groovy/README.md
@@ -0,0 +1,269 @@
+# Groovy Rules for Bazel
+
+## Overview
+
+These build rules are used for building [Groovy](http://www.groovy-lang.org/)
+projects with Bazel. Groovy libraries may interoperate with and depend on Java
+libraries and vice-versa.
+
+* [Setup](#setup)
+* [Basic Example](#basic-example)
+* [Build Rule Reference](#reference)
+  * [`groovy_library`](#groovy_library)
+  * [`groovy_and_java_library`](#groovy_and_java_library)
+  * [`groovy_binary`](#groovy_binary)
+
+<a name="setup"></a>
+## Setup
+
+To be able to use the Groovy rules, you must make the Groovy binaries available
+to Bazel. The easiest way to do so is by copying the content of
+`groovy.WORKSPACE` to your workspace file and putting `groovy.BUILD` at the root
+or your workspace.
+
+<a name="basic-example"></a>
+## Basic Example
+
+Suppose you have the following directory structure for a simple Groovy and Java
+application:
+
+```
+[workspace]/
+    WORKSPACE
+    app/
+        BUILD
+        GroovyApp.groovy
+    lib/
+        BUILD
+        GroovyLib.groovy
+        JavaLib.java
+```
+
+Then, to build the code under lib/, your `lib/BUILD` can look like this:
+
+```python
+load("/tools/build_rules/groovy/groovy", "groovy_library")
+
+groovy_library(
+    name = "groovylib",
+    srcs = glob(["*.groovy"]),
+    deps = [
+        ":javalib",
+    ],
+)
+
+java_library(
+    name = "javalib",
+    srcs = glob(["*.java"]),
+)
+```
+
+For simplicity, you can combine Groovy and Java sources into a single library
+using `groovy_and_java_library`. Note that this allows the Groovy code to
+reference the Java code, but not vice-versa. Your `lib/BUILD` file would then
+look like this:
+
+```python
+load("/tools/build_rules/groovy/groovy", "groovy_and_java_library")
+
+groovy_and_java_library(
+    name = "lib",
+    srcs = glob(["*.groovy", "*.java"]),
+)
+```
+
+Finally, you can define a binary using `groovy_binary` as follows:
+
+```python
+load("/tools/build_rules/groovy/groovy", "groovy_binary")
+
+groovy_binary(
+    name = "GroovyApp",
+    srcs = glob(["*.groovy"]),
+    main_class = "GroovyApp",
+    deps = [
+         "//lib",
+    ],
+)
+```
+
+You can then build the application with `bazel build //app:GroovyApp` and run it
+with `bazel run //app:GroovyApp`.
+
+<a name="reference"></a>
+## Build Rule Reference [reference]
+
+<a name="groovy_library"></a>
+### `groovy_library`
+
+`groovy_library(name, srcs, deps, **kwargs)`
+
+<table>
+  <thead>
+    <tr>
+      <th>Attribute</th>
+      <th>Description</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <td><code>name</code></td>
+      <td>
+        <code>Name, required</code>
+        <p>A unique name for this rule.</p>
+      </td>
+    </tr>
+    <tr>
+      <td><code>srcs</code></td>
+      <td>
+        <code>List of labels, required</code>
+        <p>List of .groovy source files used to build the library.</p>
+      </td>
+    </tr>
+    <tr>
+      <td><code>deps</code></td>
+      <td>
+        <code>List of labels or .jar files, optional</code>
+        <p>
+          List of other libraries to be included on the compile-time classpath
+          when building this library.
+        </p>
+        <p>
+          These can be either other `groovy_library` targets, `java_library`
+          targets, `groovy_and_java_library` targets, or raw .jar files.
+        </p>
+      </td>
+    </tr>
+    <tr>
+      <td><code>**kwargs</code></td>
+      <td>
+        <code>see <a href="http://bazel.io/docs/build-encyclopedia.html#java_import">java_binary</a></code>
+        <p>
+          The other arguments of this rule will be passed to the `java_import`
+          that wraps the groovy library.
+        </p>
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+<a name="groovy_and_java_library">
+### `groovy_and_java_library`
+
+`groovy_and_java_library(name, srcs, deps, **kwargs)`
+
+<table>
+  <thead>
+    <tr>
+      <th>Attribute</th>
+      <th>Description</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <td><code>name</code></td>
+      <td>
+        <code>Name, required</code>
+        <p>A unique name for this rule.</p>
+      </td>
+    </tr>
+    <tr>
+      <td><code>srcs</code></td>
+      <td>
+        <code>List of labels, required</code>
+        <p>List of .groovy and .java source files used to build the library.</p>
+      </td>
+    </tr>
+    <tr>
+      <td><code>deps</code></td>
+      <td>
+        <code>List of labels or .jar files, optional</code>
+        <p>
+          List of other libraries to be included on the compile-time classpath
+          when building this library.
+        </p>
+        <p>
+          These can be either other `groovy_library` targets, `java_library`
+          targets, `groovy_and_java_library` targets, or raw .jar files.
+        </p>
+      </td>
+    </tr>
+    <tr>
+      <td><code>**kwargs</code></td>
+      <td>
+        <code>see <a href="http://bazel.io/docs/build-encyclopedia.html#java_import">java_binary</a></code>
+        <p>
+          The other arguments of this rule will be passed to the `java_import`
+          that wraps the groovy library.
+        </p>
+      </td>
+    </tr>
+  </tbody>
+</table>
+
+<a name="groovy_binary"></a>
+### `groovy_binary`
+
+`groovy_binary(name, main_class, srcs, deps, **kwargs)`
+
+<table>
+  <thead>
+    <tr>
+      <th>Attribute</th>
+      <th>Description</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <td><code>name</code></td>
+      <td>
+        <code>Name, required</code>
+        <p>A unique name for this rule.</p>
+      </td>
+    </tr>
+    <tr>
+      <td><code>main_class</code></td>
+      <td>
+        <code>String, required</code>
+        <p>
+          The name of either a class containing a `main` method or a Groovy
+          script file to use as an entry point (see
+          <a href="http://www.groovy-lang.org/structure.html#_scripts_versus_classes">
+          here</a> for more details on scripts vs. classes).
+        </p>
+      </td>
+    </tr>
+    <tr>
+      <td><code>srcs</code></td>
+      <td>
+        <code>List of labels, required</code>
+        <p>List of .groovy source files used to build the application.</p>
+      </td>
+    </tr>
+    <tr>
+      <td><code>deps</code></td>
+      <td>
+        <code>List of labels or .jar files, optional</code>
+        <p>
+          List of other libraries to be included on both the compile-time
+          classpath when building this application and the runtime classpath
+          when executing it.
+        </p>
+        <p>
+          These can be `groovy_library` targets, `java_library` targets,
+          `groovy_and_java_library` targets, or raw .jar files.
+        </p>
+      </td>
+    </tr>
+    <tr>
+      <td><code>**kwargs</code></td>
+      <td>
+        <code>see <a href="http://bazel.io/docs/build-encyclopedia.html#java_binary">java_binary</a></code>
+        <p>
+          The other arguments of this rule will be passed to the `java_binary`
+          underlying the `groovy_binary`.
+        </p>
+      </td>
+    </tr>
+  </tbody>
+</table>
diff --git a/tools/build_defs/groovy/groovy.BUILD b/tools/build_defs/groovy/groovy.BUILD
new file mode 100644
index 0000000..05f3784
--- /dev/null
+++ b/tools/build_defs/groovy/groovy.BUILD
@@ -0,0 +1,5 @@
+filegroup(
+    name = "groovyc",
+    srcs = ["groovy-2.4.4/bin/groovyc"],
+    visibility = ["//visibility:public"],
+)
diff --git a/tools/build_defs/groovy/groovy.WORKSPACE b/tools/build_defs/groovy/groovy.WORKSPACE
new file mode 100644
index 0000000..8fce253
--- /dev/null
+++ b/tools/build_defs/groovy/groovy.WORKSPACE
@@ -0,0 +1,11 @@
+new_http_archive(
+  name = "groovy",
+  url = "http://dl.bintray.com/groovy/maven/apache-groovy-binary-2.4.4.zip",
+  sha256 = "a7cc1e5315a14ea38db1b2b9ce0792e35174161141a6a3e2ef49b7b2788c258c",
+  build_file = "tools/build_defs/groovy/groovy.BUILD",
+)
+
+bind(
+  name = "groovy/groovyc",
+  actual = "@groovy//:groovyc",
+)
diff --git a/tools/build_defs/groovy/groovy.bzl b/tools/build_defs/groovy/groovy.bzl
new file mode 100644
index 0000000..f435890
--- /dev/null
+++ b/tools/build_defs/groovy/groovy.bzl
@@ -0,0 +1,157 @@
+# Copyright 2015 Erik Kuefler. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+def _groovy_jar_impl(ctx):
+  """Creates a .jar file from Groovy sources. Users should rely on
+  groovy_library instead of using this rule directly.
+  """
+  class_jar = ctx.outputs.class_jar
+  build_output = class_jar.path + ".build_output"
+
+  # Extract all transitive dependencies
+  # TODO(bazel-team): get transitive dependencies from other groovy libraries
+  all_deps = set(ctx.files.deps)
+  for this_dep in ctx.attr.deps:
+    if hasattr(this_dep, "java"):
+      all_deps += this_dep.java.transitive_runtime_deps
+
+  # Compile all files in srcs with groovyc
+  cmd = "rm -rf %s; mkdir -p %s\n" % (build_output, build_output)
+  cmd += "%s -cp %s -d %s %s\n" % (
+      ctx.file._groovyc.short_path,
+      ":".join([dep.path for dep in all_deps]),
+      build_output,
+      " ".join([src.path for src in ctx.files.srcs]),
+  )
+
+  # Jar them together to produce a single output. To make this work we have
+  # to cd into the output directory, run find to locate all of the generated
+  # class files, pass the result to cut to trim the leading "./", then pass
+  # the resulting paths to the zipper.
+  cmd += "root=`pwd`\n"
+  cmd += "cd %s; $root/%s c ../%s `find . -name '*.class' | cut -c 3-`\n" % (
+      build_output,
+      ctx.executable._jar.path,
+      class_jar.basename,
+  )
+  cmd += "cd $root\n"
+
+  # Clean up temporary output
+  cmd += "rm -rf %s" % build_output
+
+  # Execute the command
+  ctx.action(
+      inputs = ctx.files.srcs + ctx.files.deps + ctx.files._jar,
+      outputs = [class_jar],
+      mnemonic = "Groovyc",
+      command = "set -e;" + cmd,
+      use_default_shell_env = True,
+  )
+
+_groovy_jar = rule(
+    implementation = _groovy_jar_impl,
+    attrs = {
+        "srcs": attr.label_list(
+            mandatory=False,
+            allow_files=FileType([".groovy"])),
+        "deps": attr.label_list(
+            mandatory=False,
+            allow_files=FileType([".jar"])),
+        "_groovyc": attr.label(
+            default=Label("//external:groovy/groovyc"),
+            single_file=True),
+        "_jar": attr.label(
+            default=Label("//third_party/ijar:zipper"),
+            executable=True,
+            single_file=True),
+        },
+    outputs = {
+        "class_jar": "lib%{name}.jar",
+        },
+)
+
+def groovy_library(name, srcs=[], deps=[], **kwargs):
+  """Rule analagous to java_library that accepts .groovy sources instead of
+  .java sources. The result is wrapped in a java_import so that java rules may
+  depend on it.
+  """
+  _groovy_jar(
+      name = name + "-impl",
+      srcs = srcs,
+      deps = deps,
+  )
+  native.java_import(
+      name = name,
+      jars = [name + "-impl"],
+      **kwargs
+  )
+
+
+def groovy_and_java_library(name, srcs=[], deps=[], **kwargs):
+  """Accepts .groovy and .java srcs to create a groovy_library and a
+  java_library. The groovy_library will depend on the java_library, so the
+  Groovy code may reference the Java code but not vice-versa.
+  """
+  groovy_deps = deps
+  jars = []
+
+  # Put all .java sources in a java_library
+  java_srcs = [src for src in srcs if src.endswith(".java")]
+  if java_srcs:
+    native.java_library(
+        name = name + "-java",
+        srcs = java_srcs,
+        deps = deps,
+    )
+    groovy_deps += [name + "-java"]
+    jars += ["lib"  + name + "-java.jar"]
+
+  # Put all .groovy sources in a groovy_library depending on the java_library
+  groovy_srcs = [src for src in srcs if src.endswith(".groovy")]
+  if groovy_srcs:
+    _groovy_jar(
+        name = name + "-groovy",
+        srcs = groovy_srcs,
+        deps = groovy_deps,
+    )
+    jars += ["lib" + name + "-groovy.jar"]
+
+  # Output a java_import combining both libraries
+  native.java_import(
+      name = name,
+      jars = jars,
+      **kwargs
+  )
+
+
+def groovy_binary(name, main_class, srcs=[], deps=[], **kwargs):
+  """Rule analagous to java_binary that accepts .groovy sources instead of .java
+  sources.
+  """
+  all_deps = deps
+  if srcs:
+    groovy_library(
+        name = name + "-lib",
+        srcs = srcs,
+        deps = deps,
+    )
+    all_deps += [name + "-lib"]
+
+  native.java_binary(
+      name = name,
+      main_class = main_class,
+      runtime_deps = all_deps,
+      **kwargs
+  )