Best Practices for Libraries in FRC Gradle

I’m wondering if there’s a suggested pattern for using libraries in FRC Java builds. (I’m still trying to figure my way around Gradle and large Java projects.) Specifically, I’m talking about team-internal libraries that are kept separate from the year’s robot code. While playing around, I’ve gotten two different methods to work:

  1. Include libraries in the code repo as git submodules, and build the whole thing as a Gradle multi-project build;
  2. Build the libraries separately, push the .jar files to a Maven repo (Artifactory, in my case), and add that to the Gradle repositories.

Both seem to work. Without wishing to start a vi-vs-emacs-style holy war, is one of these methods clearly superior for including team libraries? Or, is the best way some other thing that I haven’t mentioned?

Please don’t use submodules. They’re really hard to understand and harder to get right. I would suggest using GitHub Packages or JitPack to host your libraries on a Maven server.

5 Likes

We prefer to use the second approach as it doesn’t make sense for the library to be a Gradle subproject of the robot code project.

Furthermore, with the subproject structure, your library won’t compile standalone since you cannot specify the version of a Gradle plugin (we want to use GradleRIO in the library) in a subproject.

Our library is published on JitPack, so it’s really easy to add this as a dependency in our robot code.

2 Likes

We’ve done variations of both of these on 5499. While i wouldnt say either is clearly superior, I’ve found the maven repository route to be better for our purposes. It leaves your repositories much cleaner and it’s easier to change between library versions. We’ve found that organizing git submodules to be a big pain some of the time. The most annoying part of the maven route was setting up our own maven repository server, which you can completely avoid with jitpack (or similar solutions).

We also had our CI script automatically push the jar of each library to our maven repository when a pull request was merged into master in their respective git repositories.

1 Like

We switched to having our library as a submodule this offseason so we can easily make changes on the fly at competition. During season we hosted our library using jitpack, and there were multiple instances when we had to edit the library at comp, meaning I had to take a spare laptop, run outside of the convention hall where the regional was at to the lobby where there was wifi, and make the changes there. Not very fun, I’ll take the added complexity of submodules.

1 Like

When I was on a team we would just copy and paste the code we wanted from the previous year’s repo to the freshly created one. We were able to do this because weren’t ever going to use the code for more than one robot configuration. This prevented any git submodules issues or needing to jump around repos to fix bugs. The pros weren’t worth the process inefficiencies because we were only working on one thing at a time.

Relevant XKCD: xkcd: Automation

5 Likes

What we do is having a repository holding the library code/“robot template” code in a GitHub repository, and each year we fork it and start developing the code for this year’s robot.

But this thread made me think that using GitHub Packages will be very suited in our case.

1 Like

You can get around this by making the changes in your library and publishing to maven local with a new version number. Then you can simply change the version number in your robot code project (assuming you have mavenLocal() in your repositories {...}) and it will work.

It’s much easier to share code if you have a separate library repo because all they have to do is add the dependency and now they have access.

2 Likes

Completely agree. That wasn’t one of my team’s requirements though— which guided our decision.

We are currently doing the good old copy-paste method. Currently, we are only working on 1 robot, and have “frozen” our other for use in demos. So this works out great. Also allows team members to add / modify features in their own git branches while working. Every month or so, we just clear our dedicated repo for the library, and copy whatever the current “master” is back into the repo. Basically just an archive.

I am thinking about automating this in some way, but keep getting distracted by other projects

Keep in mind that at competition, you don’t want someone else’s library to randomly update and inject a bug into your code. Also keep in mind that there is almost never (appropriate) internet at a FRC venue.

If you want to segment your own code into (e.g.) robot code, display code, and common code, then check out gradle project structures. These are managed as a single github repository, but with a folder structure. This allows, for example, JavaFX libraries to be completely isolated from robot code.

Check out the build.gradle files here, and note the gradle.properties / settings.gradle files.

If we wanted to take our common code folder and make it a shareable library, we could edit the build.gradle file in the common/ folder to incorporate JitPack. The rest of the robot code would not be shared as a lilbrary.

At least with the case of maven dependencies, they will not “randomly” update, as the desired version of the library must be incremented manually. If you do move to a newer version, you can always go back with little amount of effort. The same goes for git submodules (although its more of a pain).

This can definitely be an issue. This past season, we solved this by having our library code more or less frozen before competition. But If a bug was found in the library repository, we would fix the bug and publish the small update to the maven local repository (the maven repo that exists locally on your device). We then updated the build file in the robot code to use that version from maven local. The updates would are pushed to git and through CI after the competition. This method worked very well for us the couple of times we needed to use it. The downside with this is that it’s hard to use maven local if you have more than 1 programmer working on robot code at a time (we never did), as the updates won’t be synced between devices. It may be too complicated for the purposes of some teams though.

1 Like

Would someone be kind enough to post how to make a library using Github Packages because right now I am stuck at authenticating with Github Package Repository so I don’t know if I should just switch to JitPack or what.

We attempted to look at GitHub packages for wpilib, and it really was a pain and not what we expected. It requires authentication both to publish and to consume, which is a bit of a pain to set up. Something like JitPack works much better for those purposes.

2 Likes

How exactly does one push to mavenLocal?

On another note, should library dependencies be declared as api or implementation? What’s the better practice? As I understand, the difference is the transitivity of the dependency.

git clone --recursive

Submodules are good if you are rapidly developing your library or modifying the source of another. (You can make commits in your copy and simply push them). This forgoes the latency of the internet and having to deal with school firewalls.

Of course, once you are done, you should generally use jitpack or some other hosting service because submodules can go awry if you do them wrong.

I mean like awry in the history of awries.

Even more awry than the git source code:

I believe ./gradlew publishToMavenLocal was the command that we used. Keep in mind that you need the maven-publish Gradle plugin for this.

You are correct in that the difference between api and implementation is in transitiveness. In our library, we use api because we want the robot code to be able to directly access our library’s dependencies.

As I said,

They’re really hard to understand and harder to get right.

But if you get them right, you can use them for faster development. And I didn’t say you need to use them. Being able to not have to wait for jitpack to build each and every time I compile to test changes to a library makes me feel like
“gods of speed have blessed [me] with unworldly powers” – paraphrasing git documentation.

If you have a library that does not need to be changed often, then by all means. But if you do, I’m just saying that git submodules do have a use. Not all schools have good wifi lol. And why go around the world to get to Walmart when you can just take the next block? Yes, it is generally better to us jitpack forstable and mostly finished packages. But if you’re developing, use submodules, it allows rapid changes to code and saves a lot more time. And once you’re done, you can do the jitpack route.

Your complete aversion to git submodules is like saying Calculus or Boolean Algebra is hard to get right so you shouldn’t use them. You just need some practice. And you don’t need to whip out the integral or l’hopital for every math problem. Or reach for the Karnaugh maps…

1 Like