1

Is there a way to export a variable in gradle, so that other projects that import the project as a dependency may access it?

For my particular case, I have an Android project that makes use of AppCompat. I currently have the AppCompat version as a variable in gradle.properties, but AppCompat has multiple components, and I only add the ones I need. For anyone else using my library and needing the other AppCompat components, it is best that they add it with the same version. As of now, they have to specify the version themselves and make sure it's the same. It would be better if they have a way of accessing the version I'm using as a variable so it is always in sync.

I'm hoping there is a better solution than to say host a raw gradle file on github that will add the variables as extensions, but as of now that seems like the most viable option.

Allan W
  • 2,791
  • 4
  • 23
  • 41
  • Conflict resolution seems like how it's handled now. AppCompat will complain if the versions differ, so I change it manually in my app. I don't think this happens for all dependencies, but if there's a way to make an error message for different versions, that would be interesting. BOM also seems like a viable solution. I didn't know about that, and I will see if there are any sample projects that use it. In the end, I'd simply like to offer an easier way of maintaining the same dependency versions as my library where possible, where only my own library's version code matters. – Allan W Jan 22 '18 at 00:19
  • added my comment as answer, since it seemed sufficient to you. – tkruse Jan 22 '18 at 01:07

2 Answers2

1

Theoretically what you ask is difficult, because gradle would need to resolve one dependency first to resolve another one, but gradle cannot know the correct order in advance. Your users could use a custom plugin or buildSrc code to fetch your jar/a pom before the main build process, extracting version numbers. But it would be messy.

There are three common approaches to solving the root problem:

  1. Users of your library can use Gradle resolution strategy failOnversionConflict() to fail if their version does not match yours
  2. You can provide a BOM (Bill of materials) with version numbers, though this may require additional gradle plugins or recent versions of gradle
  3. You can shade a library into your jar, that way your code always uses that version (not sure if that is viable in your case)

(Related issue for Maven)

tkruse
  • 10,222
  • 7
  • 53
  • 80
  • Upon second look, BOM doesn't seem to match what I want, as my versions are intended for dependencies related to but outside of my own dependencies. For example, if I have some jackson libraries, and someone else wants to use other jackson libraries, the version should be the same, but I won't be able to list out every possible dependency in my BOM. Can you elaborate on "shading" a library into my jar? – Allan W Jan 22 '18 at 02:07
  • shading is a beast of its own. In a nutshell you extract class files from a jar, change their package declaration on the bytecode, and add the result to your jar. If it is just jackson, consider using the jackson BOM: https://github.com/FasterXML/jackson-bom – tkruse Jan 22 '18 at 02:50
  • I've accepted your answer as it has given me more insight on what is possible with gradle. In the end, I decided that making a plugin collecting the variables was the best approach. Having a BOM works well when it's a base library and should always be updated. However, as mine holds a bunch of other libraries, I think it may go out of sync quickly if I had a BOM with the newest updates and a user decided to revert to an older build. – Allan W Jan 22 '18 at 06:07
0

I ended up deciding that making a gradle plugin was the best solution.

I personally deploy my library through jitpack, where every commit, tag, or snapshot can be used as a version. It is therefore important that I can have users easily update all their dependencies by just changing my library's version number, as opposed to having to change every included dependency as well.

The plugin and its description can be found here

In essence, it bundles up the version codes and adds them as extensions. Putting it under buildSrc allows it to be automatically included in the project itself, so there are no duplicate version codes. Having them as variables allows it to be updated automatically, while giving developers the flexibility of where to use it, and whether they want to use it at all.

Every set of versions is also tied to the library's version, so updating and reverting is seamless

Allan W
  • 2,791
  • 4
  • 23
  • 41