aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar natans <natans@wix.com>2018-05-29 08:23:41 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-05-29 08:24:52 -0700
commit45c2dce449eb7d4b0934471c3d8a8bd3bc635f31 (patch)
tree588eafba4a6d06f16996aa27f0a09e12b9e63ab1
parent73d33107fb06fd85efecdf2fc735e9e654aabbd0 (diff)
Generaliaze java_import_external to jvm_import_external
This PR copies "upstream" a change made to java_import_external in`rules_scala` (see [PR](https://github.com/bazelbuild/rules_scala/pull/473)) This change was originally proposed by @dslomov [here](https://github.com/bazelbuild/bazel/issues/3528) (search for 'jvm_import_external') java_import_external was changed to `jvm_import_external` 'template like' rule + `java_import_external` macro in order to allow for other jvm languages (e.g. scala and kotlin) to utilize the 'import_external' functionality without copying the boiler plate again and again. This has already been used in `rules_scala` with the introduction of `scala_import_external` and `scala_maven_import_external` In addition to the `import rule name`, `jvm_import_external` can also be called with custom attributes needed by the underlying import rules, as well as a custom load statement. `java_import_external` is used as a macro in rules_scala to make sure it's still functioning properly after the change. `jvm_maven_import_external` exposes maven artifact terminology. This will also allow to create a `maven_import_external` macro that will delegate to `jvm_maven_import_external` with a `maven_import` rule which will have `MavenCoordinates` Provider as discussed [here](https://github.com/bazelbuild/bazel/issues/4654) Closes #5068. PiperOrigin-RevId: 198398621
-rw-r--r--tools/build_defs/repo/java.bzl116
-rw-r--r--tools/build_defs/repo/jvm.bzl185
2 files changed, 193 insertions, 108 deletions
diff --git a/tools/build_defs/repo/java.bzl b/tools/build_defs/repo/java.bzl
index 559cc77a04..9803658204 100644
--- a/tools/build_defs/repo/java.bzl
+++ b/tools/build_defs/repo/java.bzl
@@ -169,111 +169,11 @@ will be loaded into a runtime environment where certain dependencies can be
reasonably expected to already be provided.
"""
-_HEADER = "# DO NOT EDIT: generated by java_import_external()"
-
-_PASS_PROPS = (
- "neverlink",
- "testonly_",
- "visibility",
- "exports",
- "runtime_deps",
- "deps",
- "tags",
-)
-
-def _java_import_external(repository_ctx):
- """Implementation of `java_import_external` rule."""
- if (repository_ctx.attr.generated_linkable_rule_name and
- not repository_ctx.attr.neverlink):
- fail("Only use generated_linkable_rule_name if neverlink is set")
- name = repository_ctx.attr.generated_rule_name or repository_ctx.name
- urls = repository_ctx.attr.jar_urls
- sha = repository_ctx.attr.jar_sha256
- path = repository_ctx.name + ".jar"
- for url in urls:
- if url.endswith(".jar"):
- path = url[url.rindex("/") + 1:]
- break
- srcurls = repository_ctx.attr.srcjar_urls
- srcsha = repository_ctx.attr.srcjar_sha256
- srcpath = repository_ctx.name + "-src.jar" if srcurls else ""
- for url in srcurls:
- if url.endswith(".jar"):
- srcpath = url[url.rindex("/") + 1:].replace("-sources.jar", "-src.jar")
- break
- lines = [_HEADER, ""]
- if repository_ctx.attr.default_visibility:
- lines.append("package(default_visibility = %s)" % (
- repository_ctx.attr.default_visibility))
- lines.append("")
- lines.append("licenses(%s)" % repr(repository_ctx.attr.licenses))
- lines.append("")
- lines.extend(_make_java_import(
- name, path, srcpath, repository_ctx.attr, _PASS_PROPS))
- if (repository_ctx.attr.neverlink and
- repository_ctx.attr.generated_linkable_rule_name):
- lines.extend(_make_java_import(
- repository_ctx.attr.generated_linkable_rule_name,
- path,
- srcpath,
- repository_ctx.attr,
- [p for p in _PASS_PROPS if p != "neverlink"]))
- extra = repository_ctx.attr.extra_build_file_content
- if extra:
- lines.append(extra)
- if not extra.endswith("\n"):
- lines.append("")
- repository_ctx.download(urls, path, sha)
- if srcurls:
- repository_ctx.download(srcurls, srcpath, srcsha)
- repository_ctx.file("BUILD", "\n".join(lines))
- repository_ctx.file("jar/BUILD", "\n".join([
- _HEADER,
- "",
- "package(default_visibility = %r)" % (
- repository_ctx.attr.visibility or
- repository_ctx.attr.default_visibility),
- "",
- "alias(",
- " name = \"jar\",",
- " actual = \"@%s\"," % repository_ctx.name,
- ")",
- "",
- ]))
-
-def _make_java_import(name, path, srcpath, attrs, props):
- lines = [
- "java_import(",
- " name = %s," % repr(name),
- " jars = [%s]," % repr(path),
- ]
- if srcpath:
- lines.append(" srcjar = %s," % repr(srcpath))
- for prop in props:
- value = getattr(attrs, prop, None)
- if value:
- if prop.endswith("_"):
- prop = prop[:-1]
- lines.append(" %s = %s," % (prop, repr(value)))
- lines.append(")")
- lines.append("")
- return lines
-
-java_import_external = repository_rule(
- implementation=_java_import_external,
- attrs={
- "licenses": attr.string_list(mandatory=True, allow_empty=False),
- "jar_urls": attr.string_list(mandatory=True, allow_empty=False),
- "jar_sha256": attr.string(mandatory=True),
- "srcjar_urls": attr.string_list(),
- "srcjar_sha256": attr.string(),
- "deps": attr.string_list(),
- "runtime_deps": attr.string_list(),
- "testonly_": attr.bool(),
- "exports": attr.string_list(),
- "neverlink": attr.bool(),
- "generated_rule_name": attr.string(),
- "generated_linkable_rule_name": attr.string(),
- "default_visibility": attr.string_list(default=["//visibility:public"]),
- "extra_build_file_content": attr.string(),
- })
+load("@bazel_tools//tools/build_defs/repo:jvm.bzl", "jvm_import_external")
+
+def java_import_external(jar_sha256, **kwargs):
+ jvm_import_external(
+ rule_name = "java_import",
+ jar_sha256 = jar_sha256,
+ **kwargs
+ )
diff --git a/tools/build_defs/repo/jvm.bzl b/tools/build_defs/repo/jvm.bzl
new file mode 100644
index 0000000000..f0d80ffe3e
--- /dev/null
+++ b/tools/build_defs/repo/jvm.bzl
@@ -0,0 +1,185 @@
+# Copyright 2018 The Bazel Authors. 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.
+
+"""
+'jvm_import_external' offers additional functionality above what maven_jar has to offer.
+In addition to downloading the jars, it allows to define this jar's dependencies.
+thus it enables the explicit definition of the entire transitive dependency graph.
+
+The rule achieves this by writing 'import' build rules in BUILD files next to the downloaded jars.
+The name of the underlying 'import' rule needs to be specified.
+An optional 'load' statement can also be provided, along with any other relevant custom attribute.
+These import rules must have the following attributes:
+- "jars"
+- "deps"
+- "runtime_deps"
+- "exports"
+
+the following macros are defined below that utilize jvm_import_external:
+
+- jvm_maven_import_external - offers a 'maven' like api for identifying jars using 'artifact' format
+- java_import_external - uses `java_import` as the underlying build rule
+"""
+
+_HEADER = "# DO NOT EDIT: generated by jvm_import_external()"
+_PASS_PROPS = (
+ "neverlink",
+ "testonly_",
+ "visibility",
+ "exports",
+ "runtime_deps",
+ "deps",
+ "tags",
+)
+
+def _jvm_import_external(repository_ctx):
+ """Implementation of `java_import_external` rule."""
+ if (repository_ctx.attr.generated_linkable_rule_name and
+ not repository_ctx.attr.neverlink):
+ fail("Only use generated_linkable_rule_name if neverlink is set")
+ name = repository_ctx.attr.generated_rule_name or repository_ctx.name
+ urls = repository_ctx.attr.jar_urls
+ sha = repository_ctx.attr.jar_sha256
+ path = repository_ctx.name + ".jar"
+ for url in urls:
+ if url.endswith(".jar"):
+ path = url[url.rindex("/") + 1:]
+ break
+ srcurls = repository_ctx.attr.srcjar_urls
+ srcsha = repository_ctx.attr.srcjar_sha256
+ srcpath = repository_ctx.name + "-src.jar" if srcurls else ""
+ for url in srcurls:
+ if url.endswith(".jar"):
+ srcpath = url[url.rindex("/") + 1:].replace("-sources.jar", "-src.jar")
+ break
+ lines = [_HEADER, ""]
+ if repository_ctx.attr.rule_load:
+ lines.append(repository_ctx.attr.rule_load)
+ lines.append("")
+ if repository_ctx.attr.default_visibility:
+ lines.append("package(default_visibility = %s)" % (
+ repository_ctx.attr.default_visibility))
+ lines.append("")
+ lines.append("licenses(%s)" % repr(repository_ctx.attr.licenses))
+ lines.append("")
+ lines.extend(_serialize_given_rule_import(
+ repository_ctx.attr.rule_name, name, path, srcpath, repository_ctx.attr, _PASS_PROPS, repository_ctx.attr.additional_rule_attrs))
+ if (repository_ctx.attr.neverlink and
+ repository_ctx.attr.generated_linkable_rule_name):
+ lines.extend(_serialize_given_rule_import(
+ repository_ctx.attr.rule_name,
+ repository_ctx.attr.generated_linkable_rule_name,
+ path,
+ srcpath,
+ repository_ctx.attr,
+ [p for p in _PASS_PROPS if p != "neverlink"],
+ repository_ctx.attr.additional_rule_attrs))
+ extra = repository_ctx.attr.extra_build_file_content
+ if extra:
+ lines.append(extra)
+ if not extra.endswith("\n"):
+ lines.append("")
+ repository_ctx.download(urls, path, sha)
+ if srcurls:
+ repository_ctx.download(srcurls, srcpath, srcsha)
+ repository_ctx.file("BUILD", "\n".join(lines))
+ repository_ctx.file("jar/BUILD", "\n".join([
+ _HEADER,
+ "",
+ "package(default_visibility = %r)" % (
+ repository_ctx.attr.visibility or
+ repository_ctx.attr.default_visibility),
+ "",
+ "alias(",
+ " name = \"jar\",",
+ " actual = \"@%s\"," % repository_ctx.name,
+ ")",
+ "",
+ ]))
+
+def _convert_to_url(artifact, server_urls):
+ parts = artifact.split(":")
+ group_id_part = parts[0].replace(".","/")
+ artifact_id = parts[1]
+ version = parts[2]
+ packaging = "jar"
+ classifier_part = ""
+ if len(parts) == 4:
+ packaging = parts[2]
+ version = parts[3]
+ elif len(parts) == 5:
+ packaging = parts[2]
+ classifier_part = "-"+parts[3]
+ version = parts[4]
+
+ final_name = artifact_id + "-" + version + classifier_part + "." + packaging
+ url_suffix = group_id_part+"/"+artifact_id + "/" + version + "/" + final_name
+ urls = []
+ for server_url in server_urls:
+ urls.append(_concat_with_needed_slash(server_url, url_suffix))
+ return urls
+
+def _concat_with_needed_slash(server_url, url_suffix):
+ if server_url.endswith("/"):
+ return server_url + url_suffix
+ else:
+ return server_url + "/" + url_suffix
+
+def _serialize_given_rule_import(rule_name, name, path, srcpath, attrs, props, additional_rule_attrs):
+ lines = [
+ "%s(" % rule_name,
+ " name = %s," % repr(name),
+ " jars = [%s]," % repr(path),
+ ]
+ if srcpath:
+ lines.append(" srcjar = %s," % repr(srcpath))
+ for prop in props:
+ value = getattr(attrs, prop, None)
+ if value:
+ if prop.endswith("_"):
+ prop = prop[:-1]
+ lines.append(" %s = %s," % (prop, repr(value)))
+ for attr_key in additional_rule_attrs:
+ lines.append(" %s = %s," % (attr_key, additional_rule_attrs[attr_key]))
+ lines.append(")")
+ lines.append("")
+ return lines
+
+jvm_import_external = repository_rule(
+ implementation=_jvm_import_external,
+ attrs={
+ "rule_name": attr.string(mandatory=True),
+ "licenses": attr.string_list(mandatory=True, allow_empty=False),
+ "jar_urls": attr.string_list(mandatory=True, allow_empty=False),
+ "jar_sha256": attr.string(),
+ "rule_load": attr.string(),
+ "additional_rule_attrs": attr.string_dict(),
+ "srcjar_urls": attr.string_list(),
+ "srcjar_sha256": attr.string(),
+ "deps": attr.string_list(),
+ "runtime_deps": attr.string_list(),
+ "testonly_": attr.bool(),
+ "exports": attr.string_list(),
+ "neverlink": attr.bool(),
+ "generated_rule_name": attr.string(),
+ "generated_linkable_rule_name": attr.string(),
+ "default_visibility": attr.string_list(default=["//visibility:public"]),
+ "extra_build_file_content": attr.string(),
+ })
+
+def jvm_maven_import_external(artifact, server_urls, **kwargs):
+ jvm_import_external(
+ jar_urls = _convert_to_url(artifact, server_urls),
+ **kwargs
+ ) \ No newline at end of file