diff options
author | 2015-08-12 15:02:06 +0000 | |
---|---|---|
committer | 2015-08-12 15:23:58 +0000 | |
commit | f4b07dbdb4bf5d4ae2b743d50f8e43ff49770987 (patch) | |
tree | 705757261d37095ecdf88217d33da6c37d4cf222 /tools/build_defs | |
parent | a55377241e2ec9f5280744c61302a7eda07d282c (diff) |
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
Diffstat (limited to 'tools/build_defs')
-rw-r--r-- | tools/build_defs/groovy/README.md | 269 | ||||
-rw-r--r-- | tools/build_defs/groovy/groovy.BUILD | 5 | ||||
-rw-r--r-- | tools/build_defs/groovy/groovy.WORKSPACE | 11 | ||||
-rw-r--r-- | tools/build_defs/groovy/groovy.bzl | 157 |
4 files changed, 442 insertions, 0 deletions
diff --git a/tools/build_defs/groovy/README.md b/tools/build_defs/groovy/README.md new file mode 100644 index 0000000000..e881a15510 --- /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 0000000000..05f378467c --- /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 0000000000..8fce2532b1 --- /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 0000000000..f435890e9d --- /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 + ) |