From e5e1a1a4d162dbf9094633bc7af7ed7ee742fd97 Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Thu, 20 Oct 2016 23:54:04 -0700 Subject: [PATCH] Moved version generation to the WPILib versioning plugin. (#277) * Moved version generation to the WPILib versioning plugin. This also moves ntcore and wpilib to the latest available version. * Fixed description string. * Gave full path for ignored files. --- .gitignore | 2 + build.gradle | 25 +--- cppSettings.gradle | 127 ++++++++++++++---- simulation/JavaGazebo/build.gradle | 2 +- simulation/SimDS/build.gradle | 18 +-- simulation/build.gradle | 3 +- wpilibc/athena.gradle | 11 +- wpilibc/athena/src/RobotBase.cpp | 3 +- wpilibc/build.gradle | 42 ++++++ wpilibc/shared/include/WPILibVersion.h | 13 ++ wpilibc/simulation.gradle | 2 +- wpilibj/athena.gradle | 27 ++-- wpilibj/build.gradle | 54 +++++++- wpilibj/simulation.gradle | 4 +- .../java/edu/wpi/first/wpilibj/RobotBase.java | 3 +- wpilibjIntegrationTests/build.gradle | 17 +-- 16 files changed, 258 insertions(+), 95 deletions(-) create mode 100644 wpilibc/shared/include/WPILibVersion.h diff --git a/.gitignore b/.gitignore index aa31f31b69..f2440c0adb 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ dependency-reduced-pom.xml /wpilibj/src/athena/cpp/nivision/*.java /wpilibj/src/athena/cpp/nivision/nivision_funcs.txt /wpilibj/src/athena/cpp/nivision/imaqdx_funcs.txt +/wpilibj/src/shared/java/edu/wpi/first/wpilibj/util/WPILibVersion.java +/wpilibc/shared/src/WPILibVersion.cpp doxygen.log # Created by the jenkins test script diff --git a/build.gradle b/build.gradle index 05215c9259..644d5a5559 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,6 @@ -buildscript { - repositories { - maven { - url "https://plugins.gradle.org/m2/" - } - } - - dependencies { - classpath 'net.ltgt.gradle:gradle-errorprone-plugin:0.0.8' - } +plugins { + id 'net.ltgt.errorprone' version '0.0.8' + id 'edu.wpi.first.wpilib.versioning.WPILibVersioningPlugin' version '1.1' } def enableSimulation = hasProperty('enableSimulation') @@ -16,9 +9,6 @@ if (!hasProperty('repo')) { ext.repo = 'development' } -def repoBaseUrl = "http://first.wpi.edu/FRC/roborio/maven/${repo}" -def publishUrl = "${System.getProperty('user.home')}/releases/maven/${repo}" - ext.simulationInstallDir = "$rootDir/build/install/simulation" allprojects { @@ -27,12 +17,6 @@ allprojects { repositories { mavenCentral() - maven { - url publishUrl - } - maven { - url repoBaseUrl - } } } @@ -54,10 +38,9 @@ subprojects { options.addStringOption('Xdoclint:none', '-quiet') } } - ext.setupWpilibRepo = { publishing -> publishing.repositories.maven { - url = "${System.getProperty('user.home')}/releases/maven/${repo}" + url = WPILibVersion.mavenLocalUrl } } } diff --git a/cppSettings.gradle b/cppSettings.gradle index de082a3155..573d90ab76 100644 --- a/cppSettings.gradle +++ b/cppSettings.gradle @@ -19,19 +19,53 @@ niLibraryTree.each { lib -> } } -def armNtDependency = - project.dependencies.create("edu.wpi.first.wpilib.networktables.cpp:NetworkTables:3.0.0-SNAPSHOT:arm@zip") -def armConfig = project.configurations.detachedConfiguration(armNtDependency) -armConfig.setTransitive(false) -def armNetTables = armConfig.files[0].canonicalFile +task downloadArmNetworkTables() { + description = 'Downloads the C++ ARM NetworkTables maven dependency.' + group = 'WPILib' + def depFolder = "$buildDir/dependencies" + def ntZip = file("$depFolder/ntcore-arm.zip") + outputs.file(ntZip) + def armNetTables + + doFirst { + def armNtDependency = project.dependencies.create('edu.wpi.first.wpilib.networktables.cpp:NetworkTables:+:arm@zip') + def armConfig = project.configurations.detachedConfiguration(armNtDependency) + armConfig.setTransitive(false) + armNetTables = armConfig.files[0].canonicalFile + } + + doLast { + copy { + from armNetTables + rename 'NetworkTables(.+)', 'ntcore-arm.zip' + into depFolder + } + } +} -def desktopNetTables if (project.hasProperty('makeSim')) { - def desktopNtDependency = - project.dependencies.create("edu.wpi.first.wpilib.networktables.cpp:NetworkTables:3.0.0-SNAPSHOT:desktop@zip") - def desktopConfig = project.configurations.detachedConfiguration(desktopNtDependency) - desktopConfig.setTransitive(false) - desktopNetTables = desktopConfig.files[0].canonicalFile + task downloadDesktopNetworkTables() { + description = 'Downloads the C++ Desktop NetworkTables maven dependency.' + group = 'WPILib' + def depFolder = "$buildDir/dependencies" + def ntZip = file("$depFolder/ntcore-desk.zip") + outputs.file(ntZip) + def desktopNetTables + doFirst { + def desktopNtDependency = project.dependencies.create("edu.wpi.first.wpilib.networktables.cpp:NetworkTables:+:desktop@zip") + def desktopConfig = project.configurations.detachedConfiguration(desktopNtDependency) + desktopConfig.setTransitive(false) + desktopNetTables = desktopConfig.files[0].canonicalFile + } + + doLast { + copy { + from desktopNetTables + rename 'NetworkTables(.+)', 'ntcore-desk.zip' + into depFolder + } + } + } } def netTablesUnzipLocation = "$buildDir/networktables" @@ -40,26 +74,64 @@ def netTablesUnzipLocation = "$buildDir/networktables" task unzipNetworkTables(type: Copy) { description = 'Unzips the networktables maven dependency so that the include files and libraries can be used' group = 'WPILib' + dependsOn downloadArmNetworkTables + if (project.hasProperty('makeSim')) { - from zipTree(desktopNetTables) + dependsOn downloadDesktopNetworkTables + from zipTree(downloadDesktopNetworkTables.outputs.files.singleFile) } - from zipTree(armNetTables) + from zipTree(downloadArmNetworkTables.outputs.files.singleFile) into netTablesUnzipLocation } -def armWpiUtilDependency = - project.dependencies.create("edu.wpi.first.wpilib:wpiutil:1.0.0-SNAPSHOT:arm@zip") -def armWpiUtilConfig = project.configurations.detachedConfiguration(armWpiUtilDependency) -armWpiUtilConfig.setTransitive(false) -def armWpiUtil = armWpiUtilConfig.files[0].canonicalFile +task downloadArmWpiUtil() { + description = 'Downloads the C++ ARM wpiutil maven dependency.' + group = 'WPILib' + def depFolder = "$buildDir/dependencies" + def utilZip = file("$depFolder/wpiutil-arm.zip") + outputs.file(utilZip) + def armWpiUtil + + doFirst { + def armWpiUtilDependency = project.dependencies.create("edu.wpi.first.wpilib:wpiutil:+:arm@zip") + def armWpiUtilConfig = project.configurations.detachedConfiguration(armWpiUtilDependency) + armWpiUtilConfig.setTransitive(false) + armWpiUtil = armWpiUtilConfig.files[0].canonicalFile + } + + doLast { + copy { + from armWpiUtil + rename 'wpiutil(.+)', 'wpiutil-arm.zip' + into depFolder + } + } +} -def desktopWpiUtil if (project.hasProperty('makeSim')) { - def desktopWpiUtilDependency = - project.dependencies.create("edu.wpi.first.wpilib:wpiutil:1.0.0-SNAPSHOT:desktop@zip") - def desktopWpiUtilConfig = project.configurations.detachedConfiguration(desktopWpiUtilDependency) - desktopWpiUtilConfig.setTransitive(false) - desktopWpiUtil = desktopWpiUtilConfig.files[0].canonicalFile + task downloadDesktopWpiUtil() { + description = 'Downloads the C++ Desktop wpiutil maven dependency.' + group = 'WPILib' + def depFolder = "$buildDir/dependencies" + def wpiutilZip = file("$depFolder/wpiutil-desk.zip") + outputs.file(wpiutilZip) + def wpiUtil + + doFirst { + def desktopWpiUtilDependency = project.dependencies.create("edu.wpi.first.wpilib:wpiutil:+:desktop@zip") + def desktopWpiUtilConfig = project.configurations.detachedConfiguration(desktopWpiUtilDependency) + desktopWpiUtilConfig.setTransitive(false) + wpiUtil = desktopWpiUtilConfig.files[0].canonicalFile + } + + doLast { + copy { + from wpiUtil + rename 'wpiutil(.+)', 'wpiutil-desk.zip' + into depFolder + } + } + } } def wpiUtilUnzipLocation = "$buildDir/wpiutil" @@ -68,10 +140,13 @@ def wpiUtilUnzipLocation = "$buildDir/wpiutil" task unzipWpiUtil(type: Copy) { description = 'Unzips the wpiutil maven dependency so that the include files and libraries can be used' group = 'WPILib' + dependsOn downloadArmWpiUtil + if (project.hasProperty('makeSim')) { - from zipTree(desktopWpiUtil) + dependsOn downloadDesktopWpiUtil + from zipTree(downloadDesktopWpiUtil.outputs.files.singleFile) } - from zipTree(armWpiUtil) + from zipTree(downloadArmWpiUtil.outputs.files.singleFile) into wpiUtilUnzipLocation } diff --git a/simulation/JavaGazebo/build.gradle b/simulation/JavaGazebo/build.gradle index 9b77dc0365..38ac9f3b84 100644 --- a/simulation/JavaGazebo/build.gradle +++ b/simulation/JavaGazebo/build.gradle @@ -7,7 +7,7 @@ publishing { artifact jar groupId 'org.gazebosim' artifactId 'JavaGazebo' - version '0.1.0-SNAPSHOT' + version WPILibVersion.version } } setupWpilibRepo(it) diff --git a/simulation/SimDS/build.gradle b/simulation/SimDS/build.gradle index 541d4f5765..14ade5df78 100644 --- a/simulation/SimDS/build.gradle +++ b/simulation/SimDS/build.gradle @@ -1,14 +1,8 @@ -apply plugin: 'java' -apply plugin: 'application' -apply plugin: 'com.github.johnrengelman.shadow' -apply plugin: 'maven-publish' - -// Adds the dependency for the shadow plugin, which creates an uberjar with all dependencies -buildscript { - repositories { jcenter() } - dependencies { - classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3' - } +plugins { + id 'java' + id 'application' + id 'com.github.johnrengelman.shadow' version '1.2.3' + id 'maven-publish' } publishing { @@ -26,7 +20,7 @@ publishing { } groupId 'edu.wpi.first.wpilibj.simulation' artifactId 'SimDS' - version '0.1.0-SNAPSHOT' + version WPILibVersion.version } } setupWpilibRepo(it) diff --git a/simulation/build.gradle b/simulation/build.gradle index 4da5451b5b..e96b764cba 100644 --- a/simulation/build.gradle +++ b/simulation/build.gradle @@ -7,10 +7,9 @@ publishing { artifact zip groupId 'edu.wpi.first.wpilib.simulation' artifactId 'simulation' - version '1.0.0' + version WPILibVersion.version } } - setupWpilibRepo(it) } diff --git a/wpilibc/athena.gradle b/wpilibc/athena.gradle index d6bc0d9f4d..5efad08409 100644 --- a/wpilibc/athena.gradle +++ b/wpilibc/athena.gradle @@ -115,9 +115,16 @@ project(':hal').tasks.whenTaskAdded { task -> } } +// Add the generate version file task as a dependency +tasks.whenTaskAdded { task -> + if (task.name.toLowerCase().startsWith('compilewpilib')) { + task.dependsOn generateCppVersion + } +} + if (checkDoxygen()) { - def ntSourcesDependency = project.dependencies.create('edu.wpi.first.wpilib.networktables.cpp:NetworkTables:3.0.0-SNAPSHOT:sources@zip') + def ntSourcesDependency = project.dependencies.create('edu.wpi.first.wpilib.networktables.cpp:NetworkTables:+:sources@zip') def ntSourcesConfig = project.configurations.detachedConfiguration(ntSourcesDependency) ntSourcesDependency.setTransitive(false) def ntSources = ntSourcesConfig.singleFile @@ -185,7 +192,7 @@ publishing { groupId 'edu.wpi.first.wpilib.cmake' artifactId 'cpp-root' - version '1.0.0' + version WPILibVersion.version } } diff --git a/wpilibc/athena/src/RobotBase.cpp b/wpilibc/athena/src/RobotBase.cpp index 5dcc42e2bf..a75777245a 100644 --- a/wpilibc/athena/src/RobotBase.cpp +++ b/wpilibc/athena/src/RobotBase.cpp @@ -15,6 +15,7 @@ #include "Internal/HardwareHLReporting.h" #include "RobotState.h" #include "Utility.h" +#include "WPILibVersion.h" #include "networktables/NetworkTable.h" /** @@ -39,7 +40,7 @@ RobotBase::RobotBase() : m_ds(DriverStation::GetInstance()) { file = std::fopen("/tmp/frc_versions/FRC_Lib_Version.ini", "w"); if (file != nullptr) { - std::fputs("v2017.1.0-beta-1", file); + std::fputs(WPILibVersion, file); std::fclose(file); } } diff --git a/wpilibc/build.gradle b/wpilibc/build.gradle index fd29972fb6..9fa2fa3928 100644 --- a/wpilibc/build.gradle +++ b/wpilibc/build.gradle @@ -10,6 +10,48 @@ ext.shared = 'shared' ext.athena = 'athena' ext.simulation = 'sim' +def versionClass = """ +/* + * Autogenerated file! Do not manually edit this file. This version is regenerated + * any time the publish task is run, or when this file is deleted. + */ + +const char* WPILibVersion = "${WPILibVersion.version}"; +""".trim() + +def wpilibVersionFile = file('shared/src/WPILibVersion.cpp') + +def willPublish = false +gradle.taskGraph.addTaskExecutionGraphListener { graph -> + willPublish = graph.hasTask(publish) +} + +task generateCppVersion() { + description = 'Generates the wpilib version class' + group = 'WPILib' + + // We follow a simple set of checks to determine whether we should generate a new version file: + // 1. If the release type is not development, we generate a new verison file + // 2. If there is no generated version number, we generate a new version file + // 3. If there is a generated build number, and the release type is development, then we will + // only generate if the publish task is run. + doLast { + if (!WPILibVersion.releaseType.toString().equalsIgnoreCase('official') && !willPublish && wpilibVersionFile.exists()) { + return + } + println "Writing version ${WPILibVersion.version} to $wpilibVersionFile" + + if (wpilibVersionFile.exists()) { + wpilibVersionFile.delete() + } + wpilibVersionFile.write(versionClass) + } +} + +clean { + delete wpilibVersionFile +} + // Attempts to execute the doxygen command. If there is no exception, doxygen exists, so return true. If there's // an IOException, it doesn't exist, so return false ext.checkDoxygen = { diff --git a/wpilibc/shared/include/WPILibVersion.h b/wpilibc/shared/include/WPILibVersion.h new file mode 100644 index 0000000000..f68ff96c87 --- /dev/null +++ b/wpilibc/shared/include/WPILibVersion.h @@ -0,0 +1,13 @@ +/*----------------------------------------------------------------------------*/ +/* Copyright (c) FIRST 2008-2016. All Rights Reserved. */ +/* Open Source Software - may be modified and shared by FRC teams. The code */ +/* must be accompanied by the FIRST BSD license file in the root directory of */ +/* the project. */ +/*----------------------------------------------------------------------------*/ +#pragma once + +/* + * The corresponding WPILibVersion.cpp file is autogenerated by the build system. If it does not exist, make sure that you + * run a build. + */ +extern const char* WPILibVersion; diff --git a/wpilibc/simulation.gradle b/wpilibc/simulation.gradle index 45d85873fa..fffda15f14 100644 --- a/wpilibc/simulation.gradle +++ b/wpilibc/simulation.gradle @@ -54,7 +54,7 @@ task gz_msgs(type: Exec, dependsOn: cmake) { } } -task wpilibcSim(type: Exec, dependsOn: ['cmake', ':unzipNetworkTables', ':unzipWpiUtil']) { +task wpilibcSim(type: Exec, dependsOn: ['cmake', ':unzipNetworkTables', ':unzipWpiUtil', 'generateCppVersion']) { description = 'build WPILib C++ for simulation with cmake' group = 'WPILib Simulation' workingDir '../build' diff --git a/wpilibj/athena.gradle b/wpilibj/athena.gradle index ea0222aa92..e99692705f 100644 --- a/wpilibj/athena.gradle +++ b/wpilibj/athena.gradle @@ -10,8 +10,8 @@ sourceSets { dependencies { athenaCompile sourceSets.shared.output - athenaCompile 'edu.wpi.first.wpilib.networktables.java:NetworkTables:3.0.0-SNAPSHOT:arm' - athenaRuntime 'edu.wpi.first.wpilib.networktables.java:NetworkTables:3.0.0-SNAPSHOT:arm' + athenaCompile 'edu.wpi.first.wpilib.networktables.java:NetworkTables:+:arm' + athenaRuntime 'edu.wpi.first.wpilib.networktables.java:NetworkTables:+:arm' } // Configuration for the HAL bindings @@ -61,7 +61,7 @@ publishing { groupId 'edu.wpi.first.wpilibj' artifactId 'wpilibJavaFinal' - version '0.1.0-SNAPSHOT' + version WPILibVersion.version } } @@ -111,18 +111,21 @@ task wpilibjSources(type: Jar, dependsOn: classes) { from sourceSets.shared.allJava } -def ntSourcesDependency = - project.dependencies.create('edu.wpi.first.wpilib.networktables.java:NetworkTables:3.0.0-SNAPSHOT:sources@jar') -def ntSourcesConfig = project.configurations.detachedConfiguration(ntSourcesDependency) -ntSourcesDependency.setTransitive(false) -def ntSources = ntSourcesConfig.singleFile - task unzipJavaNtSources(type: Copy) { description = 'Unzips the java networktables sources for doc creation' group = 'WPILib' - from zipTree(ntSources) - exclude 'META-INF/*' - into ntSourceDir + doFirst { + def ntSourcesDependency = + project.dependencies.create('edu.wpi.first.wpilib.networktables.java:NetworkTables:+:sources@jar') + def ntSourcesConfig = project.configurations.detachedConfiguration(ntSourcesDependency) + ntSourcesDependency.setTransitive(false) + def ntSources = ntSourcesConfig.singleFile + } + doLast { + from zipTree(ntSources) + exclude 'META-INF/*' + into ntSourceDir + } } task javadoc(type: Javadoc, overwrite: true) { diff --git a/wpilibj/build.gradle b/wpilibj/build.gradle index 1b3854a9fb..0257129d10 100644 --- a/wpilibj/build.gradle +++ b/wpilibj/build.gradle @@ -6,16 +6,64 @@ configurations.errorprone { resolutionStrategy.force 'com.google.errorprone:error_prone_core:2.0.9' } +def versionClass = """ +package edu.wpi.first.wpilibj.util; + +/* + * Autogenerated file! Do not manually edit this file. This version is regenerated + * any time the publish task is run, or when this file is deleted. + */ + +public final class WPILibVersion { + public static final String Version = "${WPILibVersion.version}"; +} +""".trim() + +def wpilibVersionFile = file('src/shared/java/edu/wpi/first/wpilibj/util/WPILibVersion.java') + +def willPublish = false +gradle.taskGraph.addTaskExecutionGraphListener { graph -> + willPublish = graph.hasTask(publish) +} + +task generateJavaVersion() { + description = 'Generates the wpilib version class.' + group = 'WPILib' + + // We follow a simple set of checks to determine whether we should generate a new version file: + // 1. If the release type is not development, we generate a new verison file + // 2. If there is no generated version number, we generate a new version file + // 3. If there is a generated build number, and the release type is development, then we will + // only generate if the publish task is run. + doLast { + if (!WPILibVersion.releaseType.toString().equalsIgnoreCase('official') && !willPublish && wpilibVersionFile.exists()) { + return + } + println "Writing version ${WPILibVersion.version} to $wpilibVersionFile" + + if (wpilibVersionFile.exists()) { + wpilibVersionFile.delete() + } + wpilibVersionFile.write(versionClass) + } +} + +clean { + delete wpilibVersionFile +} + sourceSets { shared } +compileSharedJava.dependsOn generateJavaVersion + dependencies { - sharedCompile 'edu.wpi.first.wpilib.networktables.java:NetworkTables:3.0.0-SNAPSHOT:arm' - sharedRuntime 'edu.wpi.first.wpilib.networktables.java:NetworkTables:3.0.0-SNAPSHOT:arm' + sharedCompile 'edu.wpi.first.wpilib.networktables.java:NetworkTables:+:arm' + sharedRuntime 'edu.wpi.first.wpilib.networktables.java:NetworkTables:+:arm' testCompile 'org.hamcrest:hamcrest-all:1.3' testCompile 'junit:junit:4.12' - testCompile 'edu.wpi.first.wpilib.networktables.java:NetworkTables:3.0.0-SNAPSHOT:desktop' + testCompile 'edu.wpi.first.wpilib.networktables.java:NetworkTables:+:desktop' testCompile 'com.google.guava:guava:19.0' testCompile sourceSets.shared.output } diff --git a/wpilibj/simulation.gradle b/wpilibj/simulation.gradle index 56f84ae03d..8a87bf4801 100644 --- a/wpilibj/simulation.gradle +++ b/wpilibj/simulation.gradle @@ -5,8 +5,8 @@ sourceSets { dependencies { simCompile sourceSets.shared.output simCompile project(':simulation:JavaGazebo') - simCompile 'edu.wpi.first.wpilib.networktables.java:NetworkTables:3.0.0-SNAPSHOT:desktop' - simRuntime "edu.wpi.first.wpilib.networktables.java:NetworkTables:3.0.0-SNAPSHOT:desktop" + simCompile 'edu.wpi.first.wpilib.networktables.java:NetworkTables:+:desktop' + simRuntime "edu.wpi.first.wpilib.networktables.java:NetworkTables:+:desktop" } task wpilibjSimJar(type: Jar, dependsOn: simClasses) { diff --git a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/RobotBase.java b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/RobotBase.java index ce6a87ed50..d2f1317ff0 100644 --- a/wpilibj/src/athena/java/edu/wpi/first/wpilibj/RobotBase.java +++ b/wpilibj/src/athena/java/edu/wpi/first/wpilibj/RobotBase.java @@ -21,6 +21,7 @@ import edu.wpi.first.wpilibj.hal.HAL; import edu.wpi.first.wpilibj.internal.HardwareHLUsageReporting; import edu.wpi.first.wpilibj.internal.HardwareTimer; import edu.wpi.first.wpilibj.networktables.NetworkTable; +import edu.wpi.first.wpilibj.util.WPILibVersion; /** * Implement a Robot Program framework. The RobotBase class is intended to be subclassed by a user @@ -215,7 +216,7 @@ public abstract class RobotBase { file.createNewFile(); try (FileOutputStream output = new FileOutputStream(file)) { - output.write("v2017.1.0-beta-1".getBytes()); + output.write(WPILibVersion.Version.getBytes()); } } catch (IOException ex) { diff --git a/wpilibjIntegrationTests/build.gradle b/wpilibjIntegrationTests/build.gradle index 5b0f904370..88c27bf589 100644 --- a/wpilibjIntegrationTests/build.gradle +++ b/wpilibjIntegrationTests/build.gradle @@ -1,6 +1,8 @@ -apply plugin: 'java' -apply plugin: 'application' -apply plugin: 'com.github.johnrengelman.shadow' +plugins { + id 'java' + id 'application' + id 'com.github.johnrengelman.shadow' version '1.2.3' +} apply plugin: 'net.ltgt.errorprone' configurations.errorprone { @@ -11,19 +13,12 @@ evaluationDependsOn(':wpilibj') mainClassName = 'edu.wpi.first.wpilibj.test.AntJunitLanucher' -buildscript { - repositories { jcenter() } - dependencies { - classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3' - } -} - def wpilibj = project(':wpilibj') dependencies { compile wpilibj compile files(wpilibj.sourceSets.test.output.classesDir) - compile 'edu.wpi.first.wpilib.networktables.java:NetworkTables:3.0.0-SNAPSHOT:arm' + compile 'edu.wpi.first.wpilib.networktables.java:NetworkTables:+:arm' compile 'junit:junit:4.11' compile 'com.googlecode.junit-toolbox:junit-toolbox:2.0' compile 'org.apache.ant:ant:1.9.4'