Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jvm_import_external #5068

Closed
wants to merge 3 commits into from
Closed

Conversation

natansil
Copy link
Contributor

This PR copies "upstream" a change made to java_import_external inrules_scala (see PR)

This change was originally proposed by @dslomov here (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

…rt_external macro inin order to allow for other jvm languages to utilize the 'import_external' functionality
@zaaraameera2014
Copy link

Google bot

@zaaraameera2014
Copy link

zaaraameera2014 commented Apr 22, 2018 via email

@natansil
Copy link
Contributor Author

@jart I would appreciate your review as well :)

@ittaiz
Copy link
Member

ittaiz commented Apr 23, 2018

cc @simontoens about the maven_import we discussed

@ittaiz
Copy link
Member

ittaiz commented Apr 23, 2018

cc bazel-discuss thread also #4876

jart
jart previously requested changes Apr 26, 2018
Copy link
Contributor

@jart jart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAICT this change would cause us to migrate our Java repository definitions to use template metaprogramming in our Java WORKSPACE definitions, e.g.:

java_import_external = jvm_import_external("java_import(name = '%{name}', ...)", extra_attrs = {})

What is the use case for this?

cc: @ronshapiro from Java Core Library Teams

See also Bazel Maven Config Generator which includes a java_import_external Best Practices Guide that explains why this file was designed the way it was.

It's verbose, but I determined it needed to be that way, because so many one-off changes needed to be made to the generated configs, particularly for things like annotation processing libraries. These cannot be inferred from Maven POM metadata.

@ittaiz
Copy link
Member

ittaiz commented Apr 26, 2018 via email

@ittaiz
Copy link
Member

ittaiz commented Apr 30, 2018

@dslomov I think we need your help here.
This change was strongly encouraged by you.

@jin
Copy link
Member

jin commented Apr 30, 2018

This looks like it's just a drop in replacement for existing java_import_external calls?

@ittaiz
Copy link
Member

ittaiz commented Apr 30, 2018 via email

@iirina
Copy link
Contributor

iirina commented May 2, 2018

@dslomov PTAL

@jart
Copy link
Contributor

jart commented May 4, 2018

@jart I’m not sure I understand the problem. The user API did not change, right? What is it that you’d like to change?

I can't easily verify that is the case because this change rewrites the whole file. java.bzl is a high risk file to modify, because projects using it can't pin the version of @bazel_tools, so breaking changes would break historical revisions, even if the user migrates to the new API. I'd recommend developing this new functionality in a different file. In that case, you can do anything you want, and I would have zero concerns.

@natansil
Copy link
Contributor Author

natansil commented May 6, 2018

@jart I've taken out the jvm_import_external definition to jvm.bzl.
If you compare jvm.bzl to the original java.bzl you will find there are only minor changes.

IIUC, you're suggesting to write a macro for java with a different name and keep the original java.bzl as well, but I think this would lead to 85% code duplication.

Also the API hasn't changed at all (in terms of attributes of java_import_external)

@dslomov
Copy link
Contributor

dslomov commented May 6, 2018

I generally like this idea. @jart, what is the nature of your objection? Looks like java_import_external user-facing API does not change, there is full backward compatibility for java_import_external.
Do we have tests for java_import_external? This should validate that it stays backward compatible now and in the future.

@dslomov
Copy link
Contributor

dslomov commented May 11, 2018

ping @jart

@jart
Copy link
Contributor

jart commented May 11, 2018

I took a closer look at the code. Is there a design doc for this? The main change that seems to be happening here is it'll accept Maven coordinate triplet strings.

I recommend using java_import_external with verbatim URLs. We need to be able to grep URLs (see GitHub BigQuery dataset) in order to offer high availability mirroring via mirror.bazel.build. Folks who do things like https://%s or maven:abbreviation:v1 will miss out on those reliability and performance benefits. Yes it makes your WORKSPACE file ugly, but it's worth it.

@jin
Copy link
Member

jin commented May 12, 2018

The main change that seems to be happening here is it'll accept Maven coordinate triplet strings.

@jart I think the main change here is abstracting the *_import rule generation away from the user interface (macro). With jvm_import_external, anyone can write a custom *_import rule and create an externalized version of it with jvm_import_external.rule_name. For one, I can create android_import_external easily by creating a macro that wraps jvm_import_external with aar_import.

@ittaiz
Copy link
Member

ittaiz commented May 12, 2018 via email

@jart
Copy link
Contributor

jart commented May 12, 2018

I think the main change here is abstracting the *_import rule generation away from the user interface (macro).

@jin I understand; I agree; I would ask if we've considered generalizing to all build rules, rather than just JVM? I would support Skylark automatically defining a foo_external for all foo. I consider repository rules like java_import_external and filegroup_external (see also NodeJS, DefinitelyTyped) to be simple one-off solutions. I want one to become infinity. I'm less excited about the integers between.

  1. Why are you the one making the tradeoff? Why not allow users to choose?

@ittaiz I'm very interested in hearing more of what you have to say.

@ittaiz
Copy link
Member

ittaiz commented May 12, 2018 via email

@jart
Copy link
Contributor

jart commented May 15, 2018

It's only worthwhile to go to the trouble of defining redundant URLs explicitly when you're a public project that wants its build definitions to be as universally reliable / performant as possible. For example, any Skylark rule that uses repository_ctx.download (e.g. java_import_external) will respect the http_proxy environment variable. That grants private entities the flexibility to use their own private storage / retrieval infrastructure when inheriting public definitions. This is also the case if you write a macro wrapper that fills in URLs for convenience.

@ittaiz
Copy link
Member

ittaiz commented May 15, 2018 via email

@jart
Copy link
Contributor

jart commented May 15, 2018

By we you're referring to rules_scala, correct? Is rules_scala blocked by this change? If so, why?

@dslomov
Copy link
Contributor

dslomov commented May 15, 2018

@jart I think @ittaiz has argumented the point behind this change rather well. I do support the trade-off argument; it is important for the rules to be able to refer to maven coordinates as opposed to just urls, so that Bazel and Maven can interoperate.

@dslomov
Copy link
Contributor

dslomov commented May 15, 2018

@jin I understand; I agree; I would ask if we've considered generalizing to all build rules, rather than just JVM? I would support Skylark automatically defining a foo_external for all foo. I consider repository rules like java_import_external and filegroup_external (see also NodeJS, DefinitelyTyped) to be simple one-off solutions. I want one to become infinity. I'm less excited about the integers between.

I am not sure "I want one to become infinity. I'm less excited about the integers between." is a good reason to block this PR. We should first explore the "integers between" before we generalize.

@jart jart dismissed their stale review May 15, 2018 06:59

Unblocking review

@ittaiz
Copy link
Member

ittaiz commented May 15, 2018 via email

@jart
Copy link
Contributor

jart commented May 15, 2018

@ittaiz I sometimes use stash.sh to cache HTTP downloads, since it's easier than Squid, and cheaper than Artifactory. I was under the impression Bazel supported this, but just noticed 86a28b0 which unsets http_proxy in blaze.cc to workaround a gRPC issue. Is this something that'd be helpful to you and your employer? Because that support could easily be added back via a flag.

@ittaiz
Copy link
Member

ittaiz commented May 16, 2018 via email

@jart
Copy link
Contributor

jart commented May 16, 2018

Mandate? Please note I work TensorBoard, not Bazel. You can do anything you want.

Having a caching HTTP proxy like stash.sh is useful because you'll hit a point where GitHub starts sending HTTP/1.1 429 TOO MANY REQUESTS responses, or goes slow, or has an outage, or your policymakers are concerned about confidentiality. URL caching is zero config, language agnostic, and doesn't cost $30k/year like certain enterprise artifact management solutions. If that script saves your company money, send me a postcard.

@ronshapiro
Copy link
Contributor

ronshapiro commented May 16, 2018

The current form of this PR doesn't handle android rules/aars. I imagine that we could, and probably should handle that, otherwise we raise the risk for another fork.

To go back to @jart's desire for infinity rules, one thing that may make this more concrete is a rule like so:

download_file(
  name = "foo.jar",
  urls = [
    # list of url strings
  ],
  sha256 = "abcdefgh",
  licenses = [], 
)

That seems to be the minimum necessary to use repository_ctx.download. That file doesn't do a whole lot, but it does mean that I can now write the java_import, scala_import, aar_import directly on top of that.

(maybe that's the same as native.http_file, but with licenses?)

Once we take out the downloading, it seems that most of what is in this PR is a bit of feature creep. Inserting a load statement, extra build file content, and more. Perhaps having people write their own build file templates would actually be clearer and stop us from adding even more attributes to this in the future.

@jin
Copy link
Member

jin commented May 16, 2018

The current form of this PR doesn't handle android rules/aars. I imagine that we could, and probably should handle that, otherwise we raise the risk for another fork.

Yes, I plan to upstream the aar_import_external parts of https://github.com/bazelbuild/gmaven_rules/blob/master/import_external.bzl into Bazel once this PR is resolved and merged.

@jart
Copy link
Contributor

jart commented May 16, 2018

@ronshapiro That's how we did things before 2017, when we'd define a folder in //third_party/java/... to java_library(name = "foo", exports = ["@foo//jar"], deps = ["//third_party/java/bar"]) because maven_jar doesn't have deps. The main concern is not having a canonical label across repositories. For example, is it @args4j//jar or @io_bazel_rules_closure//third_party/java/args4j or @domain_registry//third_party/java/args4j? Arching towards canonical labels isn't a strict requirement, but it does make things a lot simpler / elegant plus avoids bind() soup if folks can agree on names.

@ronshapiro
Copy link
Contributor

That seems like two separate issues. java_import_external and maven_jar download the file to different locations, but the actual rule for them both defines @foo//jar.

@dslomov
Copy link
Contributor

dslomov commented May 17, 2018

To @ronshapiro's point.
We already have an API for Bazel downloader: it is repositiory_ctx.download.
Your proposal suggests exposing this as a repository rule and then then writing macros to refer to its results - I am not sure in which way this is better. That pollutes the workspace with multiple "hidden" repositories, not directly usable by workspace users. Implementation details of rules should be hidden within their implementation.

On the other hand, parameterizing underlying build file definitions is a large part of this PR. I have trouble interpreting this statement:

Once we take out the downloading, it seems that most of what is in this PR is a bit of feature creep. Inserting a load statement, extra build file content, and more. Perhaps having people write their own build file templates would actually be clearer and stop us from adding even more attributes to this in the future.

This PR is about making BUILD files generated by jvm_import_external configurable. How is that a "feature creep"? The alternative is full duplication of all code (url generation, passing through attributes and so on) in all repository rules that implement similar functionality.

@bazel-io bazel-io closed this in 45c2dce May 29, 2018
@ronshapiro
Copy link
Contributor

What's the plan for Android support? Is this going to be further factored to handle that? Are there any other formats besides .jar and .aar that are worth supporting (ear? war? I don't know if anyone actually uses those).

The parts that deal with neverlink seem like feature creep to me. That, to me, seems like something that should be done separately from the repository configuration. Visibility can help with that. It's a style question, so people can reasonably disagree.

@ittaiz
Copy link
Member

ittaiz commented Jun 3, 2018 via email

@jin
Copy link
Member

jin commented Jun 3, 2018

@ronshapiro Here's the prototype PR: #5319

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants