Add Jsonnet rules to Bazel.
RELNOTES: Add Jsonnet rules to Bazel
--
MOS_MIGRATED_REVID=102895524
diff --git a/WORKSPACE b/WORKSPACE
index 3486acd..897060c 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -95,3 +95,10 @@
sha256 = "aa76bb83c38b3f7495516eb08977fc9700c664d7a945ba3ac3c0004a6a8509f2",
build_file = "tools/build_defs/d/dmd.BUILD",
)
+
+new_git_repository(
+ name = "jsonnet",
+ remote = "https://github.com/google/jsonnet.git",
+ tag = "v0.8.0",
+ build_file = "tools/build_defs/jsonnet/jsonnet.BUILD",
+)
diff --git a/examples/jsonnet/BUILD b/examples/jsonnet/BUILD
new file mode 100644
index 0000000..3c829df
--- /dev/null
+++ b/examples/jsonnet/BUILD
@@ -0,0 +1,41 @@
+package(default_visibility = ["//visibility:public"])
+
+load("/tools/build_defs/jsonnet/jsonnet", "jsonnet_library", "jsonnet_to_json")
+
+jsonnet_library(
+ name = "workflow",
+ srcs = ["workflow.jsonnet"],
+)
+
+jsonnet_to_json(
+ name = "wordcount",
+ src = "wordcount.jsonnet",
+ outs = ["wordcount.json"],
+ deps = [":workflow"],
+)
+
+jsonnet_to_json(
+ name = "intersection",
+ src = "intersection.jsonnet",
+ outs = ["intersection.json"],
+ deps = [":workflow"],
+)
+
+jsonnet_library(
+ name = "shell-workflows-lib",
+ srcs = [
+ "intersection.jsonnet",
+ "wordcount.jsonnet",
+ ],
+ deps = [":workflow"],
+)
+
+jsonnet_to_json(
+ name = "shell-workflows",
+ src = "shell-workflows.jsonnet",
+ outs = [
+ "intersection-workflow.json",
+ "wordcount-workflow.json",
+ ],
+ deps = [":shell-workflows-lib"],
+)
diff --git a/examples/jsonnet/intersection.jsonnet b/examples/jsonnet/intersection.jsonnet
new file mode 100644
index 0000000..e0f2fd1
--- /dev/null
+++ b/examples/jsonnet/intersection.jsonnet
@@ -0,0 +1,60 @@
+// Copyright 2015 Google Inc. 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.
+
+local workflow = import "examples/jsonnet/workflow.jsonnet";
+
+// Workflow that performs an intersection of two files using shell commands.
+{
+ intersection: workflow.Workflow {
+ jobs: {
+ local input_file1 = "/tmp/list1",
+ local input_file2 = "/tmp/list2",
+ local sorted_file1 = "/tmp/list1_sorted",
+ local sorted_file2 = "/tmp/list2_sorted",
+ local intersection = "/tmp/intersection",
+
+ SortJob:: workflow.ShJob {
+ input_file:: "",
+ output_file:: "",
+ command: "sort %s > %s" % [self.input_file, self.output_file],
+ inputs: [self.input_file],
+ outputs: [self.output_file],
+ },
+
+ sort_file1: self.SortJob {
+ input_file:: input_file1,
+ output_file:: sorted_file1,
+ },
+
+ sort_file2: self.SortJob {
+ input_file:: input_file2,
+ output_file:: sorted_file2,
+ },
+
+ intersect: workflow.ShJob {
+ deps: [
+ ":sort_file1",
+ ":sort_file2",
+ ],
+ command: "comm -12 %s %s > %s" %
+ [sorted_file1, sorted_file2, intersection],
+ inputs: [
+ sorted_file1,
+ sorted_file2,
+ ],
+ outputs: [intersection],
+ },
+ }
+ }
+}
diff --git a/examples/jsonnet/shell-workflows.jsonnet b/examples/jsonnet/shell-workflows.jsonnet
new file mode 100644
index 0000000..d5e36a0
--- /dev/null
+++ b/examples/jsonnet/shell-workflows.jsonnet
@@ -0,0 +1,21 @@
+// Copyright 2015 Google Inc. 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.
+
+local wordcount = import "examples/jsonnet/wordcount.jsonnet";
+local intersection = import "examples/jsonnet/intersection.jsonnet";
+
+{
+ "wordcount-workflow.json": wordcount,
+ "intersection-workflow.json": intersection,
+}
diff --git a/examples/jsonnet/wordcount.jsonnet b/examples/jsonnet/wordcount.jsonnet
new file mode 100644
index 0000000..e816d44
--- /dev/null
+++ b/examples/jsonnet/wordcount.jsonnet
@@ -0,0 +1,59 @@
+// Copyright 2015 Google Inc. 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.
+
+local workflow = import "examples/jsonnet/workflow.jsonnet";
+
+// Workflow that performs a wordcount using shell commands.
+{
+ wordcount: workflow.Workflow {
+ retries: 12,
+ schedule: workflow.Schedule {
+ start_date: "2015-11-15",
+ start_time: "17:30",
+ repeat_frequency: 1,
+ repeat_type: "week",
+ },
+ jobs: {
+ local input_file = "/tmp/passage_test",
+ local tokens_file = "/tmp/tokens",
+ local sorted_tokens_file = "/tmp/sorted_tokens",
+ local counts_file = "/tmp/counts",
+
+ // Reads the input file and produces an output file with one word per
+ // line.
+ tokenize: workflow.ShJob {
+ command: "tr ' ' '\n' < %s > %s" % [input_file, tokens_file],
+ inputs: [input_file],
+ outputs: [tokens_file],
+ },
+
+ // Takes the tokens file and produces a file with the tokens sorted.
+ sort: workflow.ShJob {
+ deps: [":tokenize"],
+ command: "sort %s > %s" % [tokens_file, sorted_tokens_file],
+ inputs: [tokens_file],
+ outputs: [sorted_tokens_file],
+ },
+
+ // Takes the file containing sorted tokens and produces a file containing
+ // the counts for each word.
+ count: workflow.ShJob {
+ deps: [":sort"],
+ command: "uniq -c %s > %s" % [sorted_tokens_file, counts_file],
+ inputs: [sorted_tokens_file],
+ outputs: [counts_file],
+ },
+ }
+ }
+}
diff --git a/examples/jsonnet/workflow.jsonnet b/examples/jsonnet/workflow.jsonnet
new file mode 100644
index 0000000..bca2bd7
--- /dev/null
+++ b/examples/jsonnet/workflow.jsonnet
@@ -0,0 +1,46 @@
+// Copyright 2015 Google Inc. 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.
+
+// Configuration for a hypothetical workflow scheduling system.
+{
+ // Configuration for a workflow.
+ Workflow:: {
+ schedule: {},
+ retries: 5,
+ jobs: {},
+ },
+
+ // Scheduling configuration for a workflow.
+ Schedule:: {
+ start_date: "",
+ start_time: "",
+ repeat_frequency: 0,
+ repeat_type: "",
+ },
+
+ // Base configuration for a Job in a workflow.
+ Job:: {
+ type: "base",
+ deps: [],
+ inputs: [],
+ outputs: [],
+ },
+
+ // Configuration for a job that runs a shell command.
+ ShJob:: self.Job {
+ type: "sh",
+ command: "",
+ vars: {},
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/docgen/templates/be-header.vm b/src/main/java/com/google/devtools/build/docgen/templates/be-header.vm
index 97f5303..e10b1b5 100644
--- a/src/main/java/com/google/devtools/build/docgen/templates/be-header.vm
+++ b/src/main/java/com/google/devtools/build/docgen/templates/be-header.vm
@@ -137,26 +137,30 @@
<h4>Rules implemented as Skylark extensions</h4>
+<p>
The Bazel team provides a set of supported build rules written using the
<a href="/docs/skylark/index.html">Skylark</a> rules framework. These rules
should be explicitly <a href="#load">load</a>ed. They allow you to build the
following:
+</p>
<ul>
<li> <a href="https://github.com/bazelbuild/bazel/tree/master/tools/build_rules/closure">
- Closure libraries</a>
+ Closure libraries</a></li>
<li> <a href="https://github.com/bazelbuild/bazel/tree/master/tools/build_defs/docker">
- Docker images</a>
+ Docker images</a></li>
<li> <a href="https://github.com/bazelbuild/bazel/tree/master/tools/build_defs/groovy">
- Groovy projects</a>
+ Groovy projects</a></li>
<li> <a href="https://github.com/bazelbuild/bazel/tree/master/tools/build_rules/appengine">
- Java App Engine applications</a>
+ Java App Engine applications</a></li>
<li> <a href="https://github.com/bazelbuild/bazel/tree/master/tools/build_defs/d">
- D projects</a>
+ D projects</a></li>
<li> <a href="https://github.com/bazelbuild/bazel/tree/master/tools/build_rules/rust">
- Rust projects</a>
+ Rust projects</a></li>
+<li> <a href="https://github.com/bazelbuild/bazel/tree/master/tools/build_defs/jsonnet">
+ Jsonnet files</a></li>
<li> <a href="https://github.com/bazelbuild/bazel/tree/master/tools/build_defs/scala">
- Scala projects</a> - experimental
+ Scala projects</a> - experimental</li>
</ul>
<h2 id="common-definitions">Common definitions</h2>
diff --git a/tools/BUILD b/tools/BUILD
index a2df391..f370eb3 100644
--- a/tools/BUILD
+++ b/tools/BUILD
@@ -23,6 +23,7 @@
name = "package-srcs",
srcs = glob(["**"]) + [
"//tools/build_defs/d:srcs",
+ "//tools/build_defs/jsonnet:srcs",
"//tools/build_defs/docker:srcs",
"//tools/build_rules/appengine:srcs",
"//tools/build_rules/closure:srcs",
diff --git a/tools/build_defs/jsonnet/BUILD b/tools/build_defs/jsonnet/BUILD
new file mode 100644
index 0000000..7f38b97
--- /dev/null
+++ b/tools/build_defs/jsonnet/BUILD
@@ -0,0 +1,16 @@
+package(default_visibility = ["//visibility:public"])
+
+filegroup(
+ name = "srcs",
+ srcs = glob(["**"]),
+)
+
+filegroup(
+ name = "jsonnet",
+ srcs = ["@jsonnet//:jsonnet"],
+)
+
+filegroup(
+ name = "std",
+ srcs = ["@jsonnet//:std"],
+)
diff --git a/tools/build_defs/jsonnet/README.md b/tools/build_defs/jsonnet/README.md
new file mode 100644
index 0000000..6d40df7
--- /dev/null
+++ b/tools/build_defs/jsonnet/README.md
@@ -0,0 +1,310 @@
+# Jsonnet Rules
+
+## Rules
+
+* [`jsonnet_library`](#jsonnet_library)
+* [`jsonnet_to_json`](#jsonnet_to_json)
+
+## Overview
+
+These are build rules for working with [Jsonnet][jsonnet] files with Bazel.
+
+[jsonnet]: http://google.github.io/jsonnet/doc/
+
+## Setup
+
+To use the Jsonnet rules, simply copy the contents of `jsonnet.WORKSPACE` into
+your `WORKSPACE` file.
+
+<a name="#jsonnet_library"></a>
+## jsonnet_library
+
+```python
+jsonnet_library(name, srcs, deps, imports)
+```
+
+<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 <code>.jsonnet</code> files that comprises this Jsonnet
+ library.
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>deps</code></td>
+ <td>
+ <code>List of labels, optional</code>
+ <p>
+ List of targets that are required by the <code>srcs</code> Jsonnet
+ files.
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>imports</code></td>
+ <td>
+ <code>List of strings, optional</code>
+ <p>
+ List of import <code>-J</code> flags to be passed to the
+ <code>jsonnet</code> compiler.
+ </p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+### Example
+
+Suppose you have the following directory structure:
+
+```
+[workspace]/
+ WORKSPACE
+ configs/
+ BUILD
+ backend.jsonnet
+ frontend.jsonnet
+```
+
+You can use the `jsonnet_library` rule to build a collection of `.jsonnet`
+files that can be imported by other `.jsonnet` files as dependencies:
+
+`configs/BUILD`:
+
+```python
+load("/tools/build_defs/jsonnet/jsonnet", "jsonnet_library")
+
+jsonnet_library(
+ name = "configs",
+ srcs = [
+ "backend.jsonnet",
+ "frontend.jsonnet",
+ ],
+)
+```
+
+<a name="#jsonnet_to_json"></a>
+## jsonnet_to_json
+
+```python
+jsonnet_to_json(name, src, deps, outs, multiple_outputs, imports)
+```
+
+<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>
+ <p>
+ This name will be used as the name of the JSON file generated by this
+ rule.
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>src</code></td>
+ <td>
+ <code>Label, required</code>
+ <p>
+ The <code>.jsonnet</code> file to convert to JSON.
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>deps</code></td>
+ <td>
+ <code>List of labels, optional</code>
+ <p>
+ List of targets that are required by the <code>src</code> Jsonnet
+ file.
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>outs</code></td>
+ <td>
+ <code>List of Filenames, optional</code>
+ <p>
+ Names of the output .json files to be generated by this rule.
+ </p>
+ <p>
+ If you are generating only a single JSON file and are not using
+ jsonnet multiple output files, then this attribute should only
+ contain the file name of the JSON file you are generating.
+ </p>
+ <p>
+ If you are generating multiple JSON files using jsonnet multiple file
+ output (<code>jsonnet -m</code>), then list the file names of all the
+ JSON files to be generated. The file names specified here must match
+ the file names specified in your <code>src</code> Jsonnet file.
+ </p>
+ <p>
+ For the case where multiple file output is used but only for
+ generating one output file, set the <code>multiple_outputs</code>
+ attribute to 1 to explicitly enable the <code>-m</code> flag for
+ multiple file output.
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>multiple_outputs</code></td>
+ <td>
+ <code>bool, optional, default 0</code>
+ <p>
+ Set to 1 to explicitly enable multiple file output via the
+ <code>jsonnet -m</code> flag.
+ </p>
+ <p>
+ This is used for the case where multiple file output is used but only
+ for generating a single output file. For example:
+ </p>
+<pre>
+local foo = import "foo.jsonnet";
+
+{
+ "foo.json": foo,
+}
+</pre>
+ </p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>imports</code></td>
+ <td>
+ <code>List of strings, optional</code>
+ <p>
+ List of import <code>-J</code> flags to be passed to the
+ <code>jsonnet</code> compiler.
+ </p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+### Example
+
+Suppose you have the following directory structure:
+
+```
+[workspace]/
+ WORKSPACE
+ workflows/
+ BUILD
+ workflow.jsonnet
+ wordcount.jsonnet
+ intersection.jsonnet
+```
+
+Say that `workflow.jsonnet` is a base configuration library for a workflow
+scheduling system and `wordcount.jsonnet` and `intersection.jsonnet` both
+import `workflow.jsonnet` to define workflows for performing a wordcount and
+intersection of two files, respectively.
+
+First, create a `jsonnet_library` target with `workflow.jsonnet`:
+
+`workflows/BUILD`:
+
+```python
+load("/tools/build_defs/jsonnet/jsonnet", "jsonnet_library")
+
+jsonnet_library(
+ name = "workflow",
+ srcs = ["workflow.jsonnet"],
+)
+```
+
+To compile `wordcount.jsonnet` and `intersection.jsonnet` to JSON, define two
+`jsonnet_to_json` targets:
+
+```python
+jsonnet_to_json(
+ name = "wordcount",
+ src = "wordcount.jsonnet",
+ outs = ["wordcount.json"],
+ deps = [":workflow"],
+)
+
+jsonnet_to_json(
+ name = "intersection",
+ src = "intersection.jsonnet",
+ outs = ["intersection.json"],
+ deps = [":workflow"],
+)
+```
+
+### Example: Multiple output files
+
+To use Jsonnet's [multiple output files][multiple-output-files], suppose you
+add a file `shell-workflows.jsonnet` that imports `wordcount.jsonnet` and
+`intersection.jsonnet`:
+
+`workflows/shell-workflows.jsonnet`:
+
+```
+local wordcount = import "workflows/wordcount.jsonnet";
+local intersection = import "workflows/intersection.jsonnet";
+
+{
+ "wordcount-workflow.json": wordcount,
+ "intersection-workflow.json": intersection,
+}
+```
+
+To compile `shell-workflows.jsonnet` into the two JSON files,
+`wordcount-workflow.json` and `intersection-workflow.json`, first create a
+`jsonnet_library` target containing the two files that
+`shell-workflows.jsonnet` depends on:
+
+```python
+jsonnet_library(
+ name = "shell-workflows-lib",
+ srcs = [
+ "wordcount.jsonnet",
+ "intersection.jsonnet",
+ ],
+ deps = [":workflow"],
+)
+```
+
+Then, create a `jsonnet_to_json` target and set `outs` to the list of output
+files to indicate that multiple output JSON files are generated:
+
+```python
+jsonnet_to_json(
+ name = "shell-workflows",
+ src = "shell-workflows.jsonnet",
+ deps = [":shell-workflows-lib"],
+ outs = [
+ "wordcount-workflow.jsonnet",
+ "intersection-workflow.jsonnet",
+ ],
+)
+```
+
+[multiple-output-files]: http://google.github.io/jsonnet/doc/commandline.html
diff --git a/tools/build_defs/jsonnet/jsonnet.BUILD b/tools/build_defs/jsonnet/jsonnet.BUILD
new file mode 100644
index 0000000..4b7dca6
--- /dev/null
+++ b/tools/build_defs/jsonnet/jsonnet.BUILD
@@ -0,0 +1,80 @@
+package(default_visibility = ["//visibility:public"])
+
+filegroup(
+ name = "std",
+ srcs = ["std.jsonnet"],
+)
+
+genrule(
+ name = "gen-std-jsonnet-h",
+ srcs = ["std.jsonnet"],
+ outs = ["std.jsonnet.h"],
+ cmd = "((od -v -Anone -t u1 $< | tr \" \" \"\n\" | grep -v \"^$$\" " +
+ "| tr \"\n\" \",\" ) && echo \"0\") > $@; " +
+ "echo >> $@",
+)
+
+cc_library(
+ name = "jsonnet-common",
+ srcs = [
+ "lexer.cpp",
+ "parser.cpp",
+ "static_analysis.cpp",
+ "vm.cpp",
+ "std.jsonnet.h",
+ ],
+ hdrs = [
+ "lexer.h",
+ "parser.h",
+ "static_analysis.h",
+ "static_error.h",
+ "vm.h",
+ ],
+ linkopts = ["-lm"],
+ includes = ["."],
+)
+
+cc_library(
+ name = "libjsonnet",
+ srcs = ["libjsonnet.cpp"],
+ hdrs = ["libjsonnet.h"],
+ deps = [":jsonnet-common"],
+ includes = ["."],
+)
+
+cc_binary(
+ name = "jsonnet",
+ srcs = ["jsonnet.cpp"],
+ deps = [":libjsonnet"],
+ includes = ["."],
+)
+
+cc_binary(
+ name = "libjsonnet_test_snippet",
+ srcs = ["libjsonnet_test_snippet.c"],
+ deps = [":libjsonnet"],
+ includes = ["."],
+)
+
+cc_binary(
+ name = "libjsonnet_test_file",
+ srcs = ["libjsonnet_test_file.c"],
+ deps = [":libjsonnet"],
+ includes = ["."],
+)
+
+filegroup(
+ name = "object_jsonnet",
+ srcs = ["test_suite/object.jsonnet"],
+)
+
+sh_test(
+ name = "libjsonnet_test",
+ srcs = ["libjsonnet_test.sh"],
+ data = [
+ ":jsonnet",
+ ":libjsonnet_test_snippet",
+ ":libjsonnet_test_file",
+ ":object_jsonnet",
+ ],
+)
diff --git a/tools/build_defs/jsonnet/jsonnet.WORKSPACE b/tools/build_defs/jsonnet/jsonnet.WORKSPACE
new file mode 100644
index 0000000..e6da943
--- /dev/null
+++ b/tools/build_defs/jsonnet/jsonnet.WORKSPACE
@@ -0,0 +1,6 @@
+new_git_repository(
+ name = "jsonnet",
+ remote = "https://github.com/google/jsonnet.git",
+ tag = "v0.8.0",
+ build_file = "tools/build_defs/jsonnet/jsonnet.BUILD",
+)
diff --git a/tools/build_defs/jsonnet/jsonnet.bzl b/tools/build_defs/jsonnet/jsonnet.bzl
new file mode 100644
index 0000000..13a1ba5
--- /dev/null
+++ b/tools/build_defs/jsonnet/jsonnet.bzl
@@ -0,0 +1,139 @@
+# Copyright 2015 Google Inc. 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.
+
+"""Jsonnet rules for Bazel."""
+
+JSONNET_FILETYPE = FileType([".jsonnet"])
+
+def _setup_deps(deps):
+ """Collects source files and import flags of transitive dependencies.
+
+ Args:
+ deps: List of deps labels from ctx.attr.deps.
+
+ Returns:
+ Returns a struct containing the following fields:
+ transitive_sources: List of Files containing sources of transitive
+ dependencies
+ imports: List of Strings containing import flags set by transitive
+ dependency targets.
+ """
+ transitive_sources = set(order="compile")
+ imports = set()
+ for dep in deps:
+ transitive_sources += dep.transitive_jsonnet_files
+ imports += dep.imports
+
+ return struct(
+ transitive_sources = transitive_sources,
+ imports = imports)
+
+def _jsonnet_library_impl(ctx):
+ """Implementation of the jsonnet_library rule."""
+ depinfo = _setup_deps(ctx.attr.deps)
+ sources = depinfo.transitive_sources + ctx.files.srcs
+ imports = depinfo.imports + ctx.attr.imports
+ return struct(files = set(),
+ transitive_jsonnet_files = sources,
+ imports = imports)
+
+def _jsonnet_toolchain(ctx):
+ return struct(
+ jsonnet_path = ctx.file._jsonnet.path,
+ imports = ["-J %s" % ctx.file._std.dirname])
+
+def _jsonnet_to_json_impl(ctx):
+ """Implementation of the jsonnet_to_json rule."""
+ depinfo = _setup_deps(ctx.attr.deps)
+ toolchain = _jsonnet_toolchain(ctx)
+ command = (
+ [
+ "set -e;",
+ toolchain.jsonnet_path,
+ ] +
+ toolchain.imports +
+ ctx.attr.imports +
+ list(depinfo.imports) +
+ ["-J ."])
+
+ outputs = []
+ # If multiple_outputs is set to true, then jsonnet will be invoked with the
+ # -m flag for multiple outputs. Otherwise, jsonnet will write the resulting
+ # JSON to stdout, which is redirected into a single JSON output file.
+ if len(ctx.attr.outs) > 1 or ctx.attr.multiple_outputs:
+ output_json_files = [ctx.new_file(ctx.configuration.bin_dir, out.name)
+ for out in ctx.attr.outs]
+ outputs += output_json_files
+ command += ["-m", ctx.file.src.path]
+ # Currently, jsonnet -m creates the output files in the current working
+ # directory. Append mv commands to move the output files into their
+ # correct output directories.
+ # TODO(dzc): Remove this hack when jsonnet supports a flag for setting
+ # an output directory.
+ for json_file in output_json_files:
+ command += ["; mv %s %s" % (json_file.basename, json_file.path)]
+ else:
+ if len(ctx.attr.outs) > 1:
+ fail("Only one file can be specified in outs if multiple_outputs is " +
+ "not set.")
+
+ compiled_json = ctx.new_file(ctx.configuration.bin_dir,
+ ctx.attr.outs[0].name)
+ outputs += [compiled_json]
+ command += [ctx.file.src.path, "> %s" % compiled_json.path]
+
+ compile_inputs = (
+ [ctx.file.src, ctx.file._jsonnet, ctx.file._std] +
+ list(depinfo.transitive_sources))
+
+ ctx.action(
+ inputs = compile_inputs,
+ outputs = outputs,
+ mnemonic = "Jsonnet",
+ command = " ".join(command),
+ use_default_shell_env = True,
+ progress_message = "Compiling Jsonnet to JSON for " + ctx.label.name);
+
+_jsonnet_common_attrs = {
+ "deps": attr.label_list(providers = ["transitive_jsonnet_files"],
+ allow_files = False),
+ "imports": attr.string_list(),
+ "_jsonnet": attr.label(
+ default = Label("//tools/build_defs/jsonnet:jsonnet"),
+ executable = True,
+ single_file = True),
+ "_std": attr.label(default = Label("//tools/build_defs/jsonnet:std"),
+ single_file = True),
+}
+
+_jsonnet_library_attrs = {
+ "srcs": attr.label_list(allow_files = JSONNET_FILETYPE),
+}
+
+jsonnet_library = rule(
+ _jsonnet_library_impl,
+ attrs = _jsonnet_library_attrs + _jsonnet_common_attrs,
+)
+
+_jsonnet_to_json_attrs = {
+ "src": attr.label(allow_files = JSONNET_FILETYPE,
+ single_file = True),
+ "outs": attr.output_list(mandatory = True),
+ "multiple_outputs": attr.bool(),
+}
+
+jsonnet_to_json = rule(
+ _jsonnet_to_json_impl,
+ attrs = _jsonnet_to_json_attrs + _jsonnet_common_attrs,
+)