diff --git a/WORKSPACE b/WORKSPACE index 602b2ed4297..c58480b60d5 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -15,7 +15,7 @@ rules_jvm_external_deps() load("@rules_jvm_external//:defs.bzl", "maven_install") maven_artifacts = [ - "org.ejml:ejml-simple:0.43.1", + "org.ejml:ejml-one:0.43.1", "com.fasterxml.jackson.core:jackson-annotations:2.15.2", "com.fasterxml.jackson.core:jackson-core:2.15.2", "com.fasterxml.jackson.core:jackson-databind:2.15.2", diff --git a/apriltag/build.gradle b/apriltag/build.gradle index ffdf094ede0..ad911db169e 100644 --- a/apriltag/build.gradle +++ b/apriltag/build.gradle @@ -48,6 +48,9 @@ dependencies { implementation project(':wpimath') } +apply from: "${rootDir}/shared/java/wpimath-module-patches.gradle" +apply from: "${rootDir}/shared/java/opencv-module-patches.gradle" + sourceSets { main { resources { diff --git a/apriltag/src/main/java/module-info.java b/apriltag/src/main/java/module-info.java new file mode 100644 index 00000000000..363d25c9e5e --- /dev/null +++ b/apriltag/src/main/java/module-info.java @@ -0,0 +1,14 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +open module wpilib.apriltag { + requires transitive wpilib.opencv; + requires wpilib.math; + requires wpilib.util; + requires com.fasterxml.jackson.annotation; + requires com.fasterxml.jackson.databind; + + exports edu.wpi.first.apriltag; + exports edu.wpi.first.apriltag.jni; +} diff --git a/build.gradle b/build.gradle index 8a51182b787..c7a5eb03dad 100644 --- a/build.gradle +++ b/build.gradle @@ -21,6 +21,7 @@ plugins { id 'com.github.johnrengelman.shadow' version '8.1.1' apply false id 'com.diffplug.spotless' version '6.20.0' apply false id 'com.github.spotbugs' version '6.0.2' apply false + id 'org.javamodularity.moduleplugin' version '1.8.15' apply false } wpilibVersioning.buildServerMode = project.hasProperty('buildServer') @@ -29,8 +30,10 @@ wpilibVersioning.releaseMode = project.hasProperty('releaseMode') allprojects { repositories { maven { - url = 'https://frcmaven.wpi.edu/artifactory/ex-mvn' - } + url = 'https://frcmaven.wpi.edu/artifactory/ex-mvn' + } + // For testing local EJML uberjar builds + mavenLocal() } if (project.hasProperty('releaseMode')) { wpilibRepositories.addAllReleaseRepositories(it) diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 5c555c1c53a..3bf3f960be5 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -10,4 +10,6 @@ repositories { } dependencies { implementation "edu.wpi.first:native-utils:2025.7.1" + implementation("org.gradlex:extra-java-module-info:1.9") + implementation("org.gradlex:java-module-testing:1.5") } diff --git a/cameraserver/build.gradle b/cameraserver/build.gradle index 92925c65646..69a477460e2 100644 --- a/cameraserver/build.gradle +++ b/cameraserver/build.gradle @@ -8,6 +8,7 @@ evaluationDependsOn(':cscore') evaluationDependsOn(':hal') apply from: "${rootDir}/shared/javacpp/setupBuild.gradle" +apply from: "${rootDir}/shared/java/opencv-module-patches.gradle" dependencies { implementation project(':wpiutil') diff --git a/cameraserver/src/main/java/module-info.java b/cameraserver/src/main/java/module-info.java new file mode 100644 index 00000000000..f956002f08f --- /dev/null +++ b/cameraserver/src/main/java/module-info.java @@ -0,0 +1,18 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +/** + * The WPILib cameraserver module. This defines APIs for streaming cameras from the robot for use by + * dashboards and coprocessors, and for running OpenCV pipelines (though note that the roboRIO is + * too slow to run any but the most simple pipelines at a reasonable speed). + */ +open module wpilib.cameraserver { + requires transitive wpilib.cscore; + requires transitive wpilib.ntcore; + requires wpilib.opencv; + requires wpilib.util; + + exports edu.wpi.first.cameraserver; + exports edu.wpi.first.vision; +} diff --git a/cscore/build.gradle b/cscore/build.gradle index 5b2299548d7..db1e962ed92 100644 --- a/cscore/build.gradle +++ b/cscore/build.gradle @@ -14,6 +14,7 @@ if (OperatingSystem.current().isMacOsX()) { } apply from: "${rootDir}/shared/jni/setupBuild.gradle" +apply from: "${rootDir}/shared/java/opencv-module-patches.gradle" model { components { diff --git a/cscore/src/main/java/module-info.java b/cscore/src/main/java/module-info.java new file mode 100644 index 00000000000..3f446d59666 --- /dev/null +++ b/cscore/src/main/java/module-info.java @@ -0,0 +1,15 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +/** + * The WPILib cscore module. This defines APIs for connecting to and reading images from cameras + * connected to the robot and for configuring those cameras. + */ +open module wpilib.cscore { + requires transitive wpilib.opencv; + requires wpilib.util; + + exports edu.wpi.first.cscore; + exports edu.wpi.first.cscore.raw; +} diff --git a/epilogue-processor/build.gradle b/epilogue-processor/build.gradle index 6a67ca3e8aa..d1cda4a89b6 100644 --- a/epilogue-processor/build.gradle +++ b/epilogue-processor/build.gradle @@ -8,6 +8,7 @@ ext { } apply from: "${rootDir}/shared/java/javacommon.gradle" +//apply from: "${rootDir}/shared/java/opencv-module-patches.gradle" dependencies { implementation(project(':epilogue-runtime')) @@ -15,3 +16,9 @@ dependencies { testImplementation 'com.google.testing.compile:compile-testing:+' } + +test { + moduleOptions { + runOnClasspath = true + } +} diff --git a/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/AnnotationProcessor.java b/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/AnnotationProcessor.java index 22f0e894595..b5bac917ba7 100644 --- a/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/AnnotationProcessor.java +++ b/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/AnnotationProcessor.java @@ -66,6 +66,7 @@ public boolean process(Set annotations, RoundEnvironment }); roundEnv.getRootElements().stream() + .filter(e -> e instanceof TypeElement) .filter( e -> processingEnv diff --git a/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/EpilogueGenerator.java b/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/EpilogueGenerator.java index 24520f5647b..b6463dcb556 100644 --- a/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/EpilogueGenerator.java +++ b/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/EpilogueGenerator.java @@ -46,15 +46,17 @@ public void writeEpilogueFile( List loggerClassNames, Collection mainRobotClasses) { try { var centralStore = - m_processingEnv.getFiler().createSourceFile("edu.wpi.first.epilogue.Epilogue"); + m_processingEnv.getFiler().createSourceFile("edu.wpi.first.epilogue.generated.Epilogue"); try (var out = new PrintWriter(centralStore.openOutputStream())) { - out.println("package edu.wpi.first.epilogue;"); + out.println("package edu.wpi.first.epilogue.generated;"); out.println(); out.println("import static edu.wpi.first.units.Units.Seconds;"); out.println(); + out.println("import edu.wpi.first.epilogue.Logged;"); + out.println("import edu.wpi.first.epilogue.EpilogueConfiguration;"); out.println("import edu.wpi.first.hal.FRCNetComm;"); out.println("import edu.wpi.first.hal.HAL;"); out.println(); diff --git a/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/LoggerGenerator.java b/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/LoggerGenerator.java index 15fa2104dcd..951e7137b6e 100644 --- a/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/LoggerGenerator.java +++ b/epilogue-processor/src/main/java/edu/wpi/first/epilogue/processor/LoggerGenerator.java @@ -190,7 +190,7 @@ private void writeLoggerFile( } out.println("import edu.wpi.first.epilogue.Logged;"); - out.println("import edu.wpi.first.epilogue.Epilogue;"); + out.println("import edu.wpi.first.epilogue.generated.Epilogue;"); out.println("import edu.wpi.first.epilogue.logging.ClassSpecificLogger;"); out.println("import edu.wpi.first.epilogue.logging.EpilogueBackend;"); if (requiresVarHandles) { diff --git a/epilogue-processor/src/main/java/module-info.java b/epilogue-processor/src/main/java/module-info.java new file mode 100644 index 00000000000..8014979cb1a --- /dev/null +++ b/epilogue-processor/src/main/java/module-info.java @@ -0,0 +1,14 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +import javax.annotation.processing.Processor; + +open module wpilib.epilogue.processor { + requires java.compiler; + requires jdk.compiler; + requires wpilib.epilogue; + + provides Processor with + edu.wpi.first.epilogue.processor.AnnotationProcessor; +} diff --git a/epilogue-processor/src/test/java/edu/wpi/first/epilogue/processor/AnnotationProcessorTest.java b/epilogue-processor/src/test/java/edu/wpi/first/epilogue/processor/AnnotationProcessorTest.java index cdfb99e0824..9068abeb0e5 100644 --- a/epilogue-processor/src/test/java/edu/wpi/first/epilogue/processor/AnnotationProcessorTest.java +++ b/epilogue-processor/src/test/java/edu/wpi/first/epilogue/processor/AnnotationProcessorTest.java @@ -38,7 +38,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -77,7 +77,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -116,7 +116,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; import java.lang.invoke.MethodHandles; @@ -167,7 +167,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; import java.lang.invoke.MethodHandles; @@ -220,7 +220,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -268,7 +268,7 @@ enum E { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -312,7 +312,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -359,7 +359,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -404,7 +404,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -449,7 +449,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -496,7 +496,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -543,7 +543,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -593,7 +593,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -642,7 +642,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -692,7 +692,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -751,7 +751,7 @@ static class Structable implements StructSerializable { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -802,7 +802,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -852,7 +852,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -983,7 +983,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -1035,7 +1035,7 @@ public class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -1122,7 +1122,7 @@ public class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -1185,7 +1185,7 @@ class Example { // Deliberately nonstatic package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -1231,7 +1231,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -1271,7 +1271,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -1324,7 +1324,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -1376,7 +1376,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; import java.lang.invoke.MethodHandles; @@ -1426,21 +1426,21 @@ void customLogger() { record Point(int x, int y) {} - @CustomLoggerFor(Point.class) - class CustomPointLogger extends ClassSpecificLogger { - public CustomPointLogger() { - super(Point.class); - } - - @Override - public void update(EpilogueBackend backend, Point point) { - // Implementation is irrelevant - } - } - @Logged - class Example { + public class Example { Point point; + + @CustomLoggerFor(Point.class) + public static class CustomPointLogger extends ClassSpecificLogger { + public CustomPointLogger() { + super(Point.class); + } + + @Override + public void update(EpilogueBackend backend, Point point) { + // Implementation is irrelevant + } + } } """; @@ -1449,7 +1449,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -1481,21 +1481,21 @@ void customGenericLogger() { import edu.wpi.first.math.Num; import edu.wpi.first.math.Vector; - @CustomLoggerFor(Vector.class) - class VectorLogger extends ClassSpecificLogger> { - public VectorLogger() { - super((Class) Vector.class); - } - - @Override - public void update(EpilogueBackend backend, Vector object) { - // Implementation is irrelevant - } - } - @Logged - class Example { + public class Example { Vector vec; + + @CustomLoggerFor(Vector.class) + public static class VectorLogger extends ClassSpecificLogger> { + public VectorLogger() { + super((Class) Vector.class); + } + + @Override + public void update(EpilogueBackend backend, Vector object) { + // Implementation is irrelevant + } + } } """; @@ -1504,7 +1504,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -1612,7 +1612,7 @@ record Example(double x, double y) { } package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -1700,7 +1700,7 @@ class Example { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; @@ -1752,7 +1752,7 @@ public double optedOut() { package edu.wpi.first.epilogue; import edu.wpi.first.epilogue.Logged; - import edu.wpi.first.epilogue.Epilogue; + import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.epilogue.logging.ClassSpecificLogger; import edu.wpi.first.epilogue.logging.EpilogueBackend; diff --git a/epilogue-processor/src/test/java/edu/wpi/first/epilogue/processor/EpilogueGeneratorTest.java b/epilogue-processor/src/test/java/edu/wpi/first/epilogue/processor/EpilogueGeneratorTest.java index 1e9806d3a20..f6c1af2bcec 100644 --- a/epilogue-processor/src/test/java/edu/wpi/first/epilogue/processor/EpilogueGeneratorTest.java +++ b/epilogue-processor/src/test/java/edu/wpi/first/epilogue/processor/EpilogueGeneratorTest.java @@ -23,16 +23,18 @@ void noFields() { package edu.wpi.first.epilogue; @Logged - class Example { + public class Example { } """; String expected = """ - package edu.wpi.first.epilogue; + package edu.wpi.first.epilogue.generated; import static edu.wpi.first.units.Units.Seconds; + import edu.wpi.first.epilogue.Logged; + import edu.wpi.first.epilogue.EpilogueConfiguration; import edu.wpi.first.hal.FRCNetComm; import edu.wpi.first.hal.HAL; @@ -78,7 +80,7 @@ void robotBase() { package edu.wpi.first.epilogue; @Logged - class Example extends edu.wpi.first.wpilibj.RobotBase { + public class Example extends edu.wpi.first.wpilibj.RobotBase { @Override public void startCompetition() {} @Override @@ -88,10 +90,12 @@ public void endCompetition() {} String expected = """ - package edu.wpi.first.epilogue; + package edu.wpi.first.epilogue.generated; import static edu.wpi.first.units.Units.Seconds; + import edu.wpi.first.epilogue.Logged; + import edu.wpi.first.epilogue.EpilogueConfiguration; import edu.wpi.first.hal.FRCNetComm; import edu.wpi.first.hal.HAL; @@ -136,16 +140,18 @@ void timedRobot() { package edu.wpi.first.epilogue; @Logged - class Example extends edu.wpi.first.wpilibj.TimedRobot { + public class Example extends edu.wpi.first.wpilibj.TimedRobot { } """; String expected = """ - package edu.wpi.first.epilogue; + package edu.wpi.first.epilogue.generated; import static edu.wpi.first.units.Units.Seconds; + import edu.wpi.first.epilogue.Logged; + import edu.wpi.first.epilogue.EpilogueConfiguration; import edu.wpi.first.hal.FRCNetComm; import edu.wpi.first.hal.HAL; @@ -219,7 +225,9 @@ public static void bind(edu.wpi.first.epilogue.Example robot) { void multipleRobots() { String source = """ - package edu.wpi.first.epilogue; + package edu.wpi.first.epilogue.generated; + + import edu.wpi.first.epilogue.Logged; @Logged class AlphaBot extends edu.wpi.first.wpilibj.TimedRobot { } @@ -230,15 +238,17 @@ class BetaBot extends edu.wpi.first.wpilibj.TimedRobot { } String expected = """ - package edu.wpi.first.epilogue; + package edu.wpi.first.epilogue.generated; import static edu.wpi.first.units.Units.Seconds; + import edu.wpi.first.epilogue.Logged; + import edu.wpi.first.epilogue.EpilogueConfiguration; import edu.wpi.first.hal.FRCNetComm; import edu.wpi.first.hal.HAL; - import edu.wpi.first.epilogue.AlphaBotLogger; - import edu.wpi.first.epilogue.BetaBotLogger; + import edu.wpi.first.epilogue.generated.AlphaBotLogger; + import edu.wpi.first.epilogue.generated.BetaBotLogger; public final class Epilogue { static { @@ -273,7 +283,7 @@ public static boolean shouldLog(Logged.Importance importance) { * new values. Alternatively, {@code bind()} can be used to update at an offset from * the main robot loop. */ - public static void update(edu.wpi.first.epilogue.AlphaBot robot) { + public static void update(edu.wpi.first.epilogue.generated.AlphaBot robot) { long start = System.nanoTime(); alphaBotLogger.tryUpdate(config.backend.getNested(config.root), robot, config.errorHandler); config.backend.log(\"Epilogue/Stats/Last Run\", (System.nanoTime() - start) / 1e6); @@ -287,7 +297,7 @@ public static void update(edu.wpi.first.epilogue.AlphaBot robot) { * directly from sensors will be slightly different from data used in the main robot * loop. */ - public static void bind(edu.wpi.first.epilogue.AlphaBot robot) { + public static void bind(edu.wpi.first.epilogue.generated.AlphaBot robot) { if (config.loggingPeriod == null) { config.loggingPeriod = Seconds.of(robot.getPeriod()); } @@ -305,7 +315,7 @@ public static void bind(edu.wpi.first.epilogue.AlphaBot robot) { * new values. Alternatively, {@code bind()} can be used to update at an offset from * the main robot loop. */ - public static void update(edu.wpi.first.epilogue.BetaBot robot) { + public static void update(edu.wpi.first.epilogue.generated.BetaBot robot) { long start = System.nanoTime(); betaBotLogger.tryUpdate(config.backend.getNested(config.root), robot, config.errorHandler); config.backend.log(\"Epilogue/Stats/Last Run\", (System.nanoTime() - start) / 1e6); @@ -319,7 +329,7 @@ public static void update(edu.wpi.first.epilogue.BetaBot robot) { * directly from sensors will be slightly different from data used in the main robot * loop. */ - public static void bind(edu.wpi.first.epilogue.BetaBot robot) { + public static void bind(edu.wpi.first.epilogue.generated.BetaBot robot) { if (config.loggingPeriod == null) { config.loggingPeriod = Seconds.of(robot.getPeriod()); } @@ -349,33 +359,35 @@ class A {} class B extends A {} class C extends A {} - @CustomLoggerFor({A.class, B.class, C.class}) - class CustomLogger extends ClassSpecificLogger { - public CustomLogger() { super(A.class); } - - @Override - public void update(EpilogueBackend backend, A object) {} // implementation is irrelevant - } - @Logged - class Example { + public class Example { A a_b_or_c; B b; C c; + + @CustomLoggerFor({A.class, B.class, C.class}) + public static class CustomLogger extends ClassSpecificLogger { + public CustomLogger() { super(A.class); } + + @Override + public void update(EpilogueBackend backend, A object) {} // implementation is irrelevant + } } """; String expected = """ - package edu.wpi.first.epilogue; + package edu.wpi.first.epilogue.generated; import static edu.wpi.first.units.Units.Seconds; + import edu.wpi.first.epilogue.Logged; + import edu.wpi.first.epilogue.EpilogueConfiguration; import edu.wpi.first.hal.FRCNetComm; import edu.wpi.first.hal.HAL; import edu.wpi.first.epilogue.ExampleLogger; - import edu.wpi.first.epilogue.CustomLogger; + import edu.wpi.first.epilogue.Example.CustomLogger; public final class Epilogue { static { @@ -416,7 +428,9 @@ private void assertGeneratedEpilogueContents( javac() .withOptions(kJavaVersionOptions) .withProcessors(new AnnotationProcessor()) - .compile(JavaFileObjects.forSourceString("", loggedClassContent)); + .compile( + JavaFileObjects.forSourceString( + "edu.wpi.first.epilogue.Example", loggedClassContent)); assertThat(compilation).succeededWithoutWarnings(); var generatedFiles = compilation.generatedSourceFiles(); diff --git a/epilogue-runtime/src/main/java/module-info.java b/epilogue-runtime/src/main/java/module-info.java new file mode 100644 index 00000000000..0b87e21df57 --- /dev/null +++ b/epilogue-runtime/src/main/java/module-info.java @@ -0,0 +1,12 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +open module wpilib.epilogue { + requires wpilib.ntcore; + requires wpilib.units; + requires wpilib.util; + + exports edu.wpi.first.epilogue; + exports edu.wpi.first.epilogue.logging; +} diff --git a/fieldImages/src/main/java/module-info.java b/fieldImages/src/main/java/module-info.java new file mode 100644 index 00000000000..934e96f37c8 --- /dev/null +++ b/fieldImages/src/main/java/module-info.java @@ -0,0 +1,9 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +open module wpilib.fieldimages { + requires com.fasterxml.jackson.databind; + + exports edu.wpi.first.fields; +} diff --git a/hal/src/main/java/module-info.java b/hal/src/main/java/module-info.java new file mode 100644 index 00000000000..4f7074e3b3d --- /dev/null +++ b/hal/src/main/java/module-info.java @@ -0,0 +1,18 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +/** + * The WPILib HAL module. This defines APIs for interacting with hardware through the native C++ + * layer and JNI bindings. Most robot programs don't need to use this directly and should use the + * {@code wpilib} module instead. + */ +open module wpilib.hal { + requires wpilib.util; + + exports edu.wpi.first.hal; + exports edu.wpi.first.hal.can; + exports edu.wpi.first.hal.communication; + exports edu.wpi.first.hal.simulation; + exports edu.wpi.first.hal.util; +} diff --git a/ntcore/src/main/java/module-info.java b/ntcore/src/main/java/module-info.java new file mode 100644 index 00000000000..71248542d7c --- /dev/null +++ b/ntcore/src/main/java/module-info.java @@ -0,0 +1,13 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +/** + * The WPILib networking module. This defines APIs for sending and receiving data over the robot + * network for communication with coprocessors and the driver station. + */ +open module wpilib.ntcore { + requires wpilib.util; + + exports edu.wpi.first.networktables; +} diff --git a/romiVendordep/build.gradle b/romiVendordep/build.gradle index b891c4de406..44b09cb5494 100644 --- a/romiVendordep/build.gradle +++ b/romiVendordep/build.gradle @@ -23,6 +23,8 @@ dependencies { implementation project(":wpilibj") } +apply from: "${rootDir}/shared/java/wpimath-module-patches.gradle" + nativeUtils.exportsConfigs { // Main library is just default empty. This will export everything romiVendordep { diff --git a/romiVendordep/src/main/java/module-info.java b/romiVendordep/src/main/java/module-info.java new file mode 100644 index 00000000000..70658622462 --- /dev/null +++ b/romiVendordep/src/main/java/module-info.java @@ -0,0 +1,10 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +open module wpilib.romi { + requires transitive wpilib; + requires wpilib.hal; + + exports edu.wpi.first.wpilibj.romi; +} diff --git a/shared/java/javacommon.gradle b/shared/java/javacommon.gradle index 7802818b483..c9efe218260 100644 --- a/shared/java/javacommon.gradle +++ b/shared/java/javacommon.gradle @@ -1,6 +1,11 @@ apply plugin: 'maven-publish' apply plugin: 'java-library' apply plugin: 'jacoco' +if (project.name != 'epilogue-processor') { + println("Applying extra-java-module-info to project ${project.name}") + apply plugin: 'org.gradlex.extra-java-module-info' +} +apply plugin: 'org.javamodularity.moduleplugin' def baseArtifactId = project.baseId def artifactGroupId = project.groupId @@ -114,6 +119,15 @@ tasks.withType(JavaCompile).configureEach { "-Xlint:-serial", // ignore unclaimed annotation warning from annotation processing "-Xlint:-processing", + "-Xlint:-preview", + // ignore modules requiring automatic library modules + "-Xlint:-requires-automatic", + "-Xlint:-requires-transitive-automatic", + "-Xlint:-exports", + // Java modules warn about exposing classes without an explicitly declared constructor + "-Xlint:-missing-explicit-ctor", + // Java modules warn about module names with trailing digits + "-Xlint:-module" ] } diff --git a/shared/java/javastyle.gradle b/shared/java/javastyle.gradle index e2b713e7e6f..33c2b56fa4e 100644 --- a/shared/java/javastyle.gradle +++ b/shared/java/javastyle.gradle @@ -10,6 +10,13 @@ checkstyle { config = resources.text.fromFile(new File(configDirectory.get().getAsFile(), "checkstyle.xml")) } +tasks.withType(Checkstyle) { + // Checkstyle falls over if module-info files are included in the check scope + // The suppressions file does not appear to work for this, so we need to configure the task + // itself + exclude("**/module-info.java") +} + apply plugin: 'pmd' pmd { diff --git a/shared/java/opencv-module-patches.gradle b/shared/java/opencv-module-patches.gradle new file mode 100644 index 00000000000..6e1ea749446 --- /dev/null +++ b/shared/java/opencv-module-patches.gradle @@ -0,0 +1,9 @@ +// Patch legacy non-modularized dependencies to have module info +extraJavaModuleInfo { + module('edu.wpi.first.thirdparty.frc2024.opencv:opencv-java', 'wpilib.opencv') { + exportAllPackages() + } + module('edu.wpi.first.thirdparty.frc2025.opencv:opencv-java', 'wpilib.opencv') { + exportAllPackages() + } +} diff --git a/shared/java/wpimath-module-patches.gradle b/shared/java/wpimath-module-patches.gradle new file mode 100644 index 00000000000..976136370f3 --- /dev/null +++ b/shared/java/wpimath-module-patches.gradle @@ -0,0 +1,34 @@ +// Patch legacy non-modularized dependencies to have module info +extraJavaModuleInfo { + module('org.ejml:ejml-core', 'ejml.core') { + exportAllPackages() + } + module('org.ejml:ejml-simple', 'ejml.simple') { + exportAllPackages() + requiresTransitive('ejml.core') + } + module('org.ejml:ejml-fsparse', 'ejml.fsparse') { + exportAllPackages() + requiresTransitive('ejml.core') + } + module('org.ejml:ejml-dsparse', 'ejml.dsparse') { + exportAllPackages() + requiresTransitive('ejml.core') + } + module('org.ejml:ejml-fdense', 'ejml.fdense') { + exportAllPackages() + requiresTransitive('ejml.core') + } + module('org.ejml:ejml-ddense', 'ejml.ddense') { + exportAllPackages() + requiresTransitive('ejml.core') + } + module('org.ejml:ejml-cdense', 'ejml.cdense') { + exportAllPackages() + requiresTransitive('ejml.core') + } + module('org.ejml:ejml-zdense', 'ejml.zdense') { + exportAllPackages() + requiresTransitive('ejml.core') + } +} diff --git a/wpilibNewCommands/build.gradle b/wpilibNewCommands/build.gradle index 884c18b65cb..02ee1924260 100644 --- a/wpilibNewCommands/build.gradle +++ b/wpilibNewCommands/build.gradle @@ -24,6 +24,9 @@ dependencies { testImplementation 'org.mockito:mockito-core:4.1.0' } +apply from: "${rootDir}/shared/java/wpimath-module-patches.gradle" +apply from: "${rootDir}/shared/java/opencv-module-patches.gradle" + sourceSets.main.java.srcDir "${projectDir}/src/generated/main/java" nativeUtils.exportsConfigs { diff --git a/wpilibNewCommands/src/main/java/module-info.java b/wpilibNewCommands/src/main/java/module-info.java new file mode 100644 index 00000000000..4377159d065 --- /dev/null +++ b/wpilibNewCommands/src/main/java/module-info.java @@ -0,0 +1,14 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +open module wpilib.commands2 { + requires wpilib.units; + requires wpilib; + requires wpilib.hal; + requires wpilib.ntcore; + + exports edu.wpi.first.wpilibj2.command; + exports edu.wpi.first.wpilibj2.command.button; + exports edu.wpi.first.wpilibj2.command.sysid; +} diff --git a/wpilibj/build.gradle b/wpilibj/build.gradle index d397f934801..6e4eacc36df 100644 --- a/wpilibj/build.gradle +++ b/wpilibj/build.gradle @@ -74,6 +74,9 @@ dependencies { devImplementation sourceSets.main.output } +apply from: "${rootDir}/shared/java/opencv-module-patches.gradle" +apply from: "${rootDir}/shared/java/wpimath-module-patches.gradle" + apply plugin: 'cpp' apply plugin: 'edu.wpi.first.NativeUtils' apply plugin: ExtraTasks @@ -168,6 +171,9 @@ test { outputs.upToDateWhen {false} showStandardStreams = true } + moduleOptions { + runOnClasspath = true + } } apply from: "${rootDir}/shared/javaDesktopTestTask.gradle" diff --git a/wpilibj/src/main/java/module-info.java b/wpilibj/src/main/java/module-info.java new file mode 100644 index 00000000000..0f540fab63c --- /dev/null +++ b/wpilibj/src/main/java/module-info.java @@ -0,0 +1,30 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +/** + * The core WPILib module. This defines APIs for interacting with robot sensors and actuators, + * dashboard applications, and high-level program control frameworks. + */ +open module wpilib { + requires transitive wpilib.math; + requires transitive wpilib.units; + requires transitive wpilib.util; + requires wpilib.hal; + requires wpilib.ntcore; + requires wpilib.cscore; + requires wpilib.cameraserver; + + exports edu.wpi.first.wpilibj; + exports edu.wpi.first.wpilibj.counter; + exports edu.wpi.first.wpilibj.drive; + exports edu.wpi.first.wpilibj.event; + exports edu.wpi.first.wpilibj.internal; + exports edu.wpi.first.wpilibj.livewindow; + exports edu.wpi.first.wpilibj.motorcontrol; + exports edu.wpi.first.wpilibj.shuffleboard; + exports edu.wpi.first.wpilibj.simulation; + exports edu.wpi.first.wpilibj.smartdashboard; + exports edu.wpi.first.wpilibj.sysid; + exports edu.wpi.first.wpilibj.util; +} diff --git a/wpilibj/src/test/java/edu/wpi/first/math/util/ColorTest.java b/wpilibj/src/test/java/edu/wpi/first/math/util/ColorTest.java deleted file mode 100644 index 668531427dd..00000000000 --- a/wpilibj/src/test/java/edu/wpi/first/math/util/ColorTest.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -package edu.wpi.first.math.util; - -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.params.provider.Arguments.arguments; - -import edu.wpi.first.wpilibj.util.Color; -import java.util.stream.Stream; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -class ColorTest { - private static final double kEpsilon = 1e-3; - - void assertColorMatches(double red, double green, double blue, Color color) { - assertAll( - () -> assertEquals(red, color.red, kEpsilon), - () -> assertEquals(green, color.green, kEpsilon), - () -> assertEquals(blue, color.blue, kEpsilon)); - } - - @ParameterizedTest - @MethodSource("staticColorProvider") - void staticColorTest(double red, double green, double blue, Color color) { - assertColorMatches(red, green, blue, color); - } - - @ParameterizedTest - @MethodSource("staticColorProvider") - void colorEqualsTest(double red, double green, double blue, Color color) { - assertEquals(color, new Color(red, green, blue)); - } - - static Stream staticColorProvider() { - return Stream.of( - arguments(0.0823529412, 0.376470589, 0.7411764706, Color.kDenim), - arguments(0.0, 0.4, 0.7019607844, Color.kFirstBlue), - arguments(0.9294117648, 0.1098039216, 0.1411764706, Color.kFirstRed)); - } -} diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/util/ColorTest.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/util/ColorTest.java index 76901c2f403..bf33f650b96 100644 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/util/ColorTest.java +++ b/wpilibj/src/test/java/edu/wpi/first/wpilibj/util/ColorTest.java @@ -123,4 +123,32 @@ private static Stream hsvToRgbProvider() { arguments(120, 255, 128, 0, 0, 128) // Navy ); } + + void assertColorMatches(double red, double green, double blue, Color color) { + double epsilon = 1e-3; + + assertAll( + () -> assertEquals(red, color.red, epsilon), + () -> assertEquals(green, color.green, epsilon), + () -> assertEquals(blue, color.blue, epsilon)); + } + + @ParameterizedTest + @MethodSource("staticColorProvider") + void staticColorTest(double red, double green, double blue, Color color) { + assertColorMatches(red, green, blue, color); + } + + @ParameterizedTest + @MethodSource("staticColorProvider") + void colorEqualsTest(double red, double green, double blue, Color color) { + assertEquals(color, new Color(red, green, blue)); + } + + static Stream staticColorProvider() { + return Stream.of( + arguments(0.0823529412, 0.376470589, 0.7411764706, Color.kDenim), + arguments(0.0, 0.4, 0.7019607844, Color.kFirstBlue), + arguments(0.9294117648, 0.1098039216, 0.1411764706, Color.kFirstRed)); + } } diff --git a/wpilibjExamples/build.gradle b/wpilibjExamples/build.gradle index 115b2539650..f0f8a6f7b1d 100644 --- a/wpilibjExamples/build.gradle +++ b/wpilibjExamples/build.gradle @@ -2,6 +2,8 @@ import edu.wpi.first.toolchain.NativePlatforms apply plugin: 'java' apply plugin: 'jacoco' +apply plugin: 'org.gradlex.extra-java-module-info' +apply plugin: 'org.javamodularity.moduleplugin' ext { useJava = true @@ -10,6 +12,7 @@ ext { } apply from: "${rootDir}/shared/opencv.gradle" +apply from: "${rootDir}/shared/java/opencv-module-patches.gradle" dependencies { implementation project(':wpilibj') diff --git a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/Robot.java b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/Robot.java index 463e1d6f3c8..53dc177b69c 100644 --- a/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/Robot.java +++ b/wpilibjExamples/src/main/java/edu/wpi/first/wpilibj/examples/rapidreactcommandbot/Robot.java @@ -4,8 +4,8 @@ package edu.wpi.first.wpilibj.examples.rapidreactcommandbot; -import edu.wpi.first.epilogue.Epilogue; import edu.wpi.first.epilogue.Logged; +import edu.wpi.first.epilogue.generated.Epilogue; import edu.wpi.first.wpilibj.DataLogManager; import edu.wpi.first.wpilibj.TimedRobot; import edu.wpi.first.wpilibj2.command.Command; diff --git a/wpilibjExamples/src/main/java/module-info.java b/wpilibjExamples/src/main/java/module-info.java new file mode 100644 index 00000000000..77ab98ad0a8 --- /dev/null +++ b/wpilibjExamples/src/main/java/module-info.java @@ -0,0 +1,11 @@ +open module wpilib.examples { + requires wpilib.apriltag; + requires wpilib.cameraserver; + requires wpilib.commands2; + requires wpilib.cscore; + requires wpilib.epilogue; + requires wpilib.hal; + requires wpilib.ntcore; + requires wpilib.romi; + requires wpilib.xrp; +} diff --git a/wpimath/build.gradle b/wpimath/build.gradle index 9cb07b416ef..d090260216b 100644 --- a/wpimath/build.gradle +++ b/wpimath/build.gradle @@ -83,13 +83,15 @@ nativeUtils.exportsConfigs { dependencies { api project(":wpiunits") - api "org.ejml:ejml-simple:0.43.1" + api "org.ejml:ejml-one:0.43.1" api "com.fasterxml.jackson.core:jackson-annotations:2.15.2" api "com.fasterxml.jackson.core:jackson-core:2.15.2" api "com.fasterxml.jackson.core:jackson-databind:2.15.2" api "us.hebi.quickbuf:quickbuf-runtime:1.3.3" } +apply from: "${rootDir}/shared/java/wpimath-module-patches.gradle" + sourceSets.main.java.srcDir "${projectDir}/src/generated/main/java" sourceSets.main.resources.srcDir "${projectDir}/src/main/proto" diff --git a/wpimath/src/main/java/module-info.java b/wpimath/src/main/java/module-info.java new file mode 100644 index 00000000000..76db6720065 --- /dev/null +++ b/wpimath/src/main/java/module-info.java @@ -0,0 +1,48 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +/** + * The WPILib math module. This defines APIs for geometry, kinematics, odometry, path planning, + * control algorithms, and physics simulators for simple mechanisms. + */ +open module wpilib.math { + requires com.fasterxml.jackson.annotation; + requires transitive ejml.all; + requires us.hebi.quickbuf.runtime; + requires transitive wpilib.units; + requires wpilib.util; + + exports edu.wpi.first.math; + exports edu.wpi.first.math.controller; + exports edu.wpi.first.math.controller.proto; + exports edu.wpi.first.math.controller.struct; + exports edu.wpi.first.math.estimator; + exports edu.wpi.first.math.filter; + exports edu.wpi.first.math.geometry; + exports edu.wpi.first.math.geometry.proto; + exports edu.wpi.first.math.geometry.struct; + exports edu.wpi.first.math.interpolation; + exports edu.wpi.first.math.jni; // Probably unnecessary + exports edu.wpi.first.math.kinematics; + exports edu.wpi.first.math.kinematics.proto; + exports edu.wpi.first.math.kinematics.struct; + exports edu.wpi.first.math.optimization; + exports edu.wpi.first.math.path; + exports edu.wpi.first.math.proto; + exports edu.wpi.first.math.spline; + exports edu.wpi.first.math.spline.proto; + exports edu.wpi.first.math.spline.struct; + exports edu.wpi.first.math.struct; + exports edu.wpi.first.math.system; + exports edu.wpi.first.math.system.plant; + exports edu.wpi.first.math.system.plant.proto; + exports edu.wpi.first.math.system.plant.struct; + exports edu.wpi.first.math.system.proto; + exports edu.wpi.first.math.system.struct; + exports edu.wpi.first.math.trajectory; + exports edu.wpi.first.math.trajectory.constraint; + exports edu.wpi.first.math.trajectory.proto; + exports edu.wpi.first.math.util; + exports edu.wpi.first.math.numbers; +} diff --git a/wpinet/src/main/java/module-info.java b/wpinet/src/main/java/module-info.java new file mode 100644 index 00000000000..d14f7dafc73 --- /dev/null +++ b/wpinet/src/main/java/module-info.java @@ -0,0 +1,9 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +open module wpilib.net { + requires wpilib.util; + + exports edu.wpi.first.net; +} diff --git a/wpiunits/src/main/java/module-info.java b/wpiunits/src/main/java/module-info.java new file mode 100644 index 00000000000..a466b80ee30 --- /dev/null +++ b/wpiunits/src/main/java/module-info.java @@ -0,0 +1,13 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +/** + * The WPILib units module. This defines APIs for type-safe unit definitions and math operations. + */ +open module wpilib.units { + exports edu.wpi.first.units; + exports edu.wpi.first.units.collections; + exports edu.wpi.first.units.measure; + exports edu.wpi.first.units.mutable; +} diff --git a/wpiutil/src/main/java/module-info.java b/wpiutil/src/main/java/module-info.java new file mode 100644 index 00000000000..7f8c67b112e --- /dev/null +++ b/wpiutil/src/main/java/module-info.java @@ -0,0 +1,23 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +/** + * The WPILib utility module. This defines miscellaneous APIs for concurrency, data logging, lambda + * functions, binary serialization and deserialization, native library interactions, and error + * reporting. + */ +@SuppressWarnings("requires-transitive-automatic") +open module wpilib.util { + requires com.fasterxml.jackson.databind; + requires transitive us.hebi.quickbuf.runtime; + + exports edu.wpi.first.util; + exports edu.wpi.first.util.cleanup; + exports edu.wpi.first.util.concurrent; + exports edu.wpi.first.util.datalog; + exports edu.wpi.first.util.function; + exports edu.wpi.first.util.protobuf; + exports edu.wpi.first.util.sendable; + exports edu.wpi.first.util.struct; +} diff --git a/xrpVendordep/build.gradle b/xrpVendordep/build.gradle index 21278f55dee..1649cbc21e2 100644 --- a/xrpVendordep/build.gradle +++ b/xrpVendordep/build.gradle @@ -23,6 +23,8 @@ dependencies { implementation project(":wpilibj") } +apply from: "${rootDir}/shared/java/wpimath-module-patches.gradle" + nativeUtils.exportsConfigs { // Main library is just default empty. This will export everything xrpVendordep { diff --git a/xrpVendordep/src/main/java/module-info.java b/xrpVendordep/src/main/java/module-info.java new file mode 100644 index 00000000000..562f7fd4ba7 --- /dev/null +++ b/xrpVendordep/src/main/java/module-info.java @@ -0,0 +1,10 @@ +// Copyright (c) FIRST and other WPILib contributors. +// Open Source Software; you can modify and/or share it under the terms of +// the WPILib BSD license file in the root directory of this project. + +open module wpilib.xrp { + requires transitive wpilib; + requires wpilib.hal; + + exports edu.wpi.first.wpilibj.xrp; +}