composite builds in gradle

In the lab today, I got a nice Gradle question. I’m answering it here on the blog so all the students can see it. (and anyone else who is curious).

The use case

We have a common library that this year (and all future year’s robots should use). However, this is the first year of competition with the library so it is likely we will need to make changes to it and rebuild at competition.

Constraint #1 – lack of wifi

For any professionals reading this wondering why we don’t use Jitpack, github or any other hosting – internet is “tricky” at competition.; It is common for there to not be any wifi in the pit and you aren’t allowed to make your own hotspot. So we need a solution that works without internet and easily lets us re-build on the same machines.

Constraint #2 – reuse

I really want the library (StuyLib) to stay in it’s own repository and not have the build file “polluted” by any changes. Why you ask? So it stays a library and not something we copy/paste from year to year.

The solution

Composite builds. Gradle has a nice system for composite builds that lets you refer to one build from another.

Directory structure

  • git clone https://github.com/StuyPulse/StuyLib
  • git clone https://github.com/StuyPulse/fantastic-spork (or any other robot)
  • That means StuyLib and fantastic-spork are in parallel directories

Updates to StuyLib

Yes, I know, I said I didn’t want updates. The only things I added were a group and version variable. That gives the artifact a proper name. (group id = com.stuypulse, artifact id = StuyLib, version = 1.0.0). StuyLib still doesn’t know it is part of a composite build.

plugins {
   id "java"
   id "edu.wpi.first.GradleRIO" version "2020.1.2"
}

// add the following two lines
group = 'com.stuypulse'
version = '1.0.0'

sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11

Updates to Robot

At end of settings.gradle, add this line:

includeBuild '../StuyLib'

Then in build.gradle, add a dependency on StuyLib

def ROBOT_MAIN_CLASS = "com.stuypulse.robot.Main"

// add a dependency
dependencies {
  implementation('com.stuypulse:StuyLib:1.0.0')
}

Testing

First, I tested that I could build each independently:

  1. cd StuyLib
  2. ./gradlew build
  3. cd ..
  4. cd fantastic-spork
  5. ./gradlew build

Then I added a class that used existing functionality in StuyLib to fantastic-spork

package jb;

import com.stuypulse.stuylib.util.*;

public class Jeanne {
  StopWatch s;
//  String str = StopWatch.TEST;
}

I re-ran the ./gradlew build in fantastic-spork and good. Then I added one line to StopWatch:

public static final String TEST = "test";

I uncommented the line in Jeanne.java. Then for the key part. I re-ran ./gradlew build in fantastic-spork and it worked. I was able to recompile fantastic-spork and have it see a change in StuyLib without having to rebuild StuyLib.

Plus this change to StuyLib only exists on my machine which proves it is being used.

FRC using VS Code and Eclipse together for WPILIb programming

I’ve tried using VS Code. I enjoy uisng it for things like JavaScript, Python and Markdown. With Java, I feel like I’m hitting my head against the wall. I’m too used to a “full powered IDE” so an editor makes me aware of what I rely on. (I tried IntelliJ as well and that felt productive easily.)

The nice thing is that 2019 FRC projects are “just” gradle projects. So there is no reason I can’t use both VS Code and Eclipse together! VS Code for creation a new project and deploying. Eclipse for virtually everything else.

Creating a project from VS Code

Just like when I was first trying VS Code, creating a WPILib project is easy. Just like the screensteps say!

  1. Click “W” icon in top right
  2. Choose template for a new project
  3. Choose Java
  4. Choose command based project (or whatever you prefer)
  5. Enter directory – this can be the same directory for all projects since they each get their own folder.
  6. Enter project name
  7. Enter team number
  8. Click generate project

Importing the Project in Eclipse

Since the project is just a Gradle project, you can import it into Eclipse

  • File > Import
  • Existing Gradle Project
  • Enter the root directory that the project is in. For example suppose your directory was “frc” and project name was “NewRobotProject”. Then the root directory would be “…/git/frc/NewRobotProject”. In other words, the directory with your build.gradle file.
  • Click Finish
  • Wait a minute or two. The bottom right will say “Synching Gradle project workspace”. It will show the percentage as the import occurs.

Editing in Multiple IDEs/Editors

At this point, you have a normal Eclipse project.   All the features and keyboard shortcuts from Eclipse are there. For example, open a command and click on the super class name (Command.) Press F3 and it takes you right to the source code. Eclipse knows where it is because Gradle told it.

If you edit in multiple tools, you just need to know how to refresh from disk in each one.

In Eclipse, right click the project and choose refresh. (Or click F5)

In VS Code,mouse over the project name and choose the circle refresh arrow.

Deploying the Project from VS Code

Since the VS Code and Eclipse projects are pointing at the same directory, you only have one project. This means you can simply:

  1. Click “W” icon in top right
  2. Choose “Deploy Robot Code” from the menu

 

five hours of real coding in Visual Studio Code

I tried to code for real in Visual Studio Code for the first time. This means not just dealing with my first impressions, but actually trying to get something done. I spent five hours coding today. The project I was working on uses Maven, Selenium and JUnit 5.

I tried to *only* use VS Code for the five hours of coding I did today. Learning any new tool is frustrating. I didn’t complete the development task I wanted to. But I made a decent amount of progress. And more importantly, I have a better understanding of the VS Code environment.

What I re-learned

I learned these when I was playing last time. But this time, I used them a bunch.

  • Shift Command/Windows P – Lets you type in the name of what you want to do. Useful when you don’t know the keyboard shortcuts or location of anything! I used it a lot for organize imports!
  • F12 – drill down into a class

What I learned for the first time

  • F2 – renames a method
  • The left explorer view has a “Maven Projects” section. This provides a visual way to run Maven clean/install/etc. it also provides a visual way to run effective pom. Or at least it did until I disabled the Maven integration. See the “challenges” section for why.

What I liked

  • Running a junit test is easy. Click “run test” over the class name or method name. This causes the test to run and a green (or red) status to appear in the bottom left line with how it went.
  • A green check or red x also appears next to each test method which you can click to see the test result details.
  • Extract to method is easy. Just highlight the code and click the lightbulb.
  • The git integration is good. It is clear on how to pull/push/commit/stash
  • Typing code was relatively easy.

“Challenges”

  • F2 does not rename a class completely. It does rename the “public class” line. But it doesn’t rename the file. There was a github issue logged about this in August. It was closed because it was going to be resolved “soon”, but still seems to be a problem.
  • JUnit 5 tests in classes that end with *IT.java run normally but report as if they were skipped. This means integration is partial. If you open the test class, the green check or red x are correct. And the test explorer recognizes integration tests as tests. But the bottom bar status and test report show as skipped. I had to temporarily rename my test to *Test.java and name it back before committing for this to be usable. I reported this as an issue in the vscode-java-test project
  • There doesn’t appear to be an easy way to make the editor (the part where you type code) full screen. You can choose the command “Maximize editor group and hide sidebar”, but the problems/terminal/etc group is still at the bottom along with some visual clutter on the right. This means you actually have to drag stuff around. In Eclipse, you just double click the “title” and get full screen. More importantly, in Eclipse you double click again to get your original view back. This was requested back in 2016 so I doubt it will be added.
  • Printing something in JUnit doesn’t play well with the Maven integration. Seriously, even if you remember to switch the output tab to “test output”, nothing gets output. I quickly learned that I wasn’t the only one with this problem. It was also logged as a defect this month and sounds like it is being worked on. In the meantime, I disabled the Maven plugin. This isn’t terribly inconvenient because of the Terminal tab. I can still run a Maven build right from my editor.
  • You have to create packages and classes “manually.” This is annoying from deeply nested packages. It is also annoying to have to type the package declaration when creating a new class. This is because VS Code has the concept of folders/files vs packages/classes

What I had to fall back to Eclipse for

There were two tasks where I decided to use Eclipse rather than VS Code:

  1. I needed to paste a very long string. Eclipse adds the line breaks and string concatenation to make this elegant. VS Code does not. I could have spent 15 minutes doing it by hand, but I let Eclipse do it for me.
  2. Eclipse is really good at showing all the differences visually between two Strings in an assertion. (See #1 for my long string.) I could have read the text assertion to see the differences. But again, Eclipse is just so good at this.