diff --git a/build.gradle b/build.gradle index 3b32c0b25..658945de3 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,5 @@ +import edu.wpi.first.toolchain.* + plugins { id "com.diffplug.spotless" version "6.22.0" id "edu.wpi.first.NativeUtils" version "2024.6.1" apply false @@ -96,3 +98,7 @@ spotless { wrapper { gradleVersion '8.4' } + +ext.getCurrentArch = { + return NativePlatforms.desktop +} diff --git a/photon-core/build.gradle b/photon-core/build.gradle index 862fdd0fc..8ccde803a 100644 --- a/photon-core/build.gradle +++ b/photon-core/build.gradle @@ -1,7 +1,31 @@ +plugins { + id 'edu.wpi.first.WpilibTools' version '1.3.0' +} + import java.nio.file.Path apply from: "${rootDir}/shared/common.gradle" +wpilibTools.deps.wpilibVersion = wpi.versions.wpilibVersion.get() + +def nativeConfigName = 'wpilibNatives' +def nativeConfig = configurations.create(nativeConfigName) + +def nativeTasks = wpilibTools.createExtractionTasks { + configurationName = nativeConfigName +} + +nativeTasks.addToSourceSetResources(sourceSets.main) + +nativeConfig.dependencies.add wpilibTools.deps.wpilib("wpimath") +nativeConfig.dependencies.add wpilibTools.deps.wpilib("wpinet") +nativeConfig.dependencies.add wpilibTools.deps.wpilib("wpiutil") +nativeConfig.dependencies.add wpilibTools.deps.wpilib("ntcore") +nativeConfig.dependencies.add wpilibTools.deps.wpilib("cscore") +nativeConfig.dependencies.add wpilibTools.deps.wpilib("apriltag") +nativeConfig.dependencies.add wpilibTools.deps.wpilib("hal") +nativeConfig.dependencies.add wpilibTools.deps.wpilibOpenCv("frc" + wpi.frcYear.get(), wpi.versions.opencvVersion.get()) + dependencies { // JOGL stuff (currently we only distribute for aarch64, which is Pi 4) implementation "org.jogamp.gluegen:gluegen-rt:$joglVersion" diff --git a/photon-lib/build.gradle b/photon-lib/build.gradle index 0a42bf54b..9e76b6cce 100644 --- a/photon-lib/build.gradle +++ b/photon-lib/build.gradle @@ -1,9 +1,3 @@ -plugins { - id 'edu.wpi.first.WpilibTools' version '1.3.0' -} - -apply plugin: "edu.wpi.first.NativeUtils" - import java.nio.file.Path ext { @@ -13,9 +7,125 @@ ext { generatedHeaders = "src/generate/native/include" } -apply from: "${rootDir}/shared/javacpp/setupBuild.gradle" +apply plugin: 'cpp' +apply plugin: 'google-test-test-suite' +apply plugin: 'edu.wpi.first.NativeUtils' + +apply from: "${rootDir}/shared/config.gradle" +apply from: "${rootDir}/shared/javacommon.gradle" + apply from: "${rootDir}/versioningHelper.gradle" +nativeUtils { + exportsConfigs { + "${nativeName}" {} + } +} + +model { + components { + "${nativeName}"(NativeLibrarySpec) { + sources { + cpp { + source { + srcDirs 'src/main/native/cpp', "$buildDir/generated/source/proto/main/cpp" + include '**/*.cpp', '**/*.cc' + } + exportedHeaders { + srcDirs 'src/main/native/include', "$buildDir/generated/source/proto/main/cpp" + if (project.hasProperty('generatedHeaders')) { + srcDir generatedHeaders + } + include "**/*.h" + } + } + } + + binaries.all { + it.tasks.withType(CppCompile) { + it.dependsOn generateProto + } + if(project.hasProperty('includePhotonTargeting')) { + lib project: ':photon-targeting', library: 'photontargeting', linkage: 'shared' + } + } + + nativeUtils.useRequiredLibrary(it, "wpilib_shared") + nativeUtils.useRequiredLibrary(it, "apriltag_shared") + nativeUtils.useRequiredLibrary(it, "opencv_shared") + } + } + testSuites { + "${nativeName}Test"(GoogleTestTestSuiteSpec) { + for(NativeComponentSpec c : $.components) { + if (c.name == nativeName) { + testing c + break + } + } + sources { + cpp { + source { + srcDirs 'src/test/native/cpp' + include '**/*.cpp' + } + exportedHeaders { + srcDirs 'src/test/native/include', "$buildDir/generated/source/proto/main/cpp" + } + } + } + + binaries.all { + it.tasks.withType(CppCompile) { + it.dependsOn generateProto + } + if(project.hasProperty('includePhotonTargeting')) { + lib project: ':photon-targeting', library: 'photontargeting', linkage: 'shared' + } + } + + nativeUtils.useRequiredLibrary(it, "cscore_shared") + nativeUtils.useRequiredLibrary(it, "cameraserver_shared") + nativeUtils.useRequiredLibrary(it, "wpilib_executable_shared") + nativeUtils.useRequiredLibrary(it, "googletest_static") + nativeUtils.useRequiredLibrary(it, "apriltag_shared") + nativeUtils.useRequiredLibrary(it, "opencv_shared") + } + } + + tasks { + def c = $.testSuites + project.tasks.create('runCpp', Exec) { + description = "Run the photon-lib executable" + def found = false + def systemArch = getCurrentArch() + c.each { + if (it in GoogleTestTestSuiteSpec && it.name == "${nativeName}Test") { + it.binaries.each { + if (!found) { + def arch = it.targetPlatform.name + if (arch == systemArch) { + dependsOn it.tasks.install + commandLine it.tasks.install.runScriptFile.get().asFile.toString() + def filePath = it.tasks.install.installDirectory.get().toString() + File.separatorChar + 'lib' + test.dependsOn it.tasks.install + test.systemProperty 'java.library.path', filePath + test.environment 'LD_LIBRARY_PATH', filePath + test.environment 'DYLD_LIBRARY_PATH', filePath + test.workingDir filePath + + found = true + } + } + } + } + } + } + } +} + +apply from: "${rootDir}/shared/javacpp/publish.gradle" + // Include the version file in the distributed sources cppHeadersZip { from('src/generate/native/include') { diff --git a/photon-lib/src/test/java/org/photonvision/OpenCVTest.java b/photon-lib/src/test/java/org/photonvision/OpenCVTest.java index 52b61f573..2849c8455 100644 --- a/photon-lib/src/test/java/org/photonvision/OpenCVTest.java +++ b/photon-lib/src/test/java/org/photonvision/OpenCVTest.java @@ -26,31 +26,23 @@ package org.photonvision; import static org.junit.jupiter.api.Assertions.*; -import edu.wpi.first.apriltag.jni.AprilTagJNI; import edu.wpi.first.cscore.CameraServerCvJNI; -import edu.wpi.first.cscore.CameraServerJNI; -import edu.wpi.first.hal.JNIWrapper; import edu.wpi.first.math.MathUtil; import edu.wpi.first.math.geometry.Pose3d; import edu.wpi.first.math.geometry.Rotation2d; import edu.wpi.first.math.geometry.Rotation3d; import edu.wpi.first.math.geometry.Transform3d; import edu.wpi.first.math.geometry.Translation3d; -import edu.wpi.first.net.WPINetJNI; import edu.wpi.first.networktables.NetworkTableInstance; -import edu.wpi.first.networktables.NetworkTablesJNI; -import edu.wpi.first.util.CombinedRuntimeLoader; -import edu.wpi.first.util.WPIUtilJNI; +import java.io.IOException; import java.util.List; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import org.opencv.core.Core; import org.photonvision.estimation.CameraTargetRelation; import org.photonvision.estimation.OpenCVHelp; import org.photonvision.estimation.RotTrlTransform3d; import org.photonvision.estimation.TargetModel; import org.photonvision.simulation.SimCameraProperties; -import org.photonvision.simulation.VisionSystemSim; import org.photonvision.simulation.VisionTargetSim; public class OpenCVTest { @@ -84,28 +76,8 @@ public class OpenCVTest { private static final SimCameraProperties prop = new SimCameraProperties(); @BeforeAll - public static void setUp() { - JNIWrapper.Helper.setExtractOnStaticLoad(false); - WPIUtilJNI.Helper.setExtractOnStaticLoad(false); - NetworkTablesJNI.Helper.setExtractOnStaticLoad(false); - WPINetJNI.Helper.setExtractOnStaticLoad(false); - CameraServerJNI.Helper.setExtractOnStaticLoad(false); - CameraServerCvJNI.Helper.setExtractOnStaticLoad(false); - AprilTagJNI.Helper.setExtractOnStaticLoad(false); - - try { - CombinedRuntimeLoader.loadLibraries( - VisionSystemSim.class, - "wpiutiljni", - "ntcorejni", - "wpinetjni", - "wpiHaljni", - Core.NATIVE_LIBRARY_NAME, - "cscorejni", - "apriltagjni"); - } catch (Exception e) { - e.printStackTrace(); - } + public static void setUp() throws IOException { + CameraServerCvJNI.forceLoad(); // NT live for debug purposes NetworkTableInstance.getDefault().startServer(); diff --git a/photon-lib/src/test/java/org/photonvision/PhotonPoseEstimatorTest.java b/photon-lib/src/test/java/org/photonvision/PhotonPoseEstimatorTest.java index 4eaffa0fe..81842dcc4 100644 --- a/photon-lib/src/test/java/org/photonvision/PhotonPoseEstimatorTest.java +++ b/photon-lib/src/test/java/org/photonvision/PhotonPoseEstimatorTest.java @@ -30,17 +30,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import edu.wpi.first.apriltag.AprilTag; import edu.wpi.first.apriltag.AprilTagFieldLayout; -import edu.wpi.first.hal.JNIWrapper; import edu.wpi.first.math.geometry.Pose3d; import edu.wpi.first.math.geometry.Rotation3d; import edu.wpi.first.math.geometry.Transform3d; import edu.wpi.first.math.geometry.Translation3d; import edu.wpi.first.math.util.Units; -import edu.wpi.first.net.WPINetJNI; -import edu.wpi.first.networktables.NetworkTablesJNI; -import edu.wpi.first.util.CombinedRuntimeLoader; -import edu.wpi.first.util.WPIUtilJNI; -import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -56,19 +50,6 @@ class PhotonPoseEstimatorTest { @BeforeAll public static void init() { - JNIWrapper.Helper.setExtractOnStaticLoad(false); - WPIUtilJNI.Helper.setExtractOnStaticLoad(false); - NetworkTablesJNI.Helper.setExtractOnStaticLoad(false); - WPINetJNI.Helper.setExtractOnStaticLoad(false); - - try { - CombinedRuntimeLoader.loadLibraries( - PhotonPoseEstimatorTest.class, "wpiutiljni", "ntcorejni", "wpinetjni", "wpiHaljni"); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - List tagList = new ArrayList<>(2); tagList.add(new AprilTag(0, new Pose3d(3, 3, 3, new Rotation3d()))); tagList.add(new AprilTag(1, new Pose3d(5, 5, 5, new Rotation3d()))); diff --git a/photon-lib/src/test/java/org/photonvision/VisionSystemSimTest.java b/photon-lib/src/test/java/org/photonvision/VisionSystemSimTest.java index c668621fd..e0ffce7ab 100644 --- a/photon-lib/src/test/java/org/photonvision/VisionSystemSimTest.java +++ b/photon-lib/src/test/java/org/photonvision/VisionSystemSimTest.java @@ -30,10 +30,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import edu.wpi.first.apriltag.AprilTag; import edu.wpi.first.apriltag.AprilTagFieldLayout; -import edu.wpi.first.apriltag.jni.AprilTagJNI; -import edu.wpi.first.cscore.CameraServerCvJNI; -import edu.wpi.first.cscore.CameraServerJNI; -import edu.wpi.first.hal.JNIWrapper; import edu.wpi.first.math.geometry.Pose2d; import edu.wpi.first.math.geometry.Pose3d; import edu.wpi.first.math.geometry.Rotation2d; @@ -42,11 +38,7 @@ import edu.wpi.first.math.geometry.Transform3d; import edu.wpi.first.math.geometry.Translation2d; import edu.wpi.first.math.geometry.Translation3d; import edu.wpi.first.math.util.Units; -import edu.wpi.first.net.WPINetJNI; import edu.wpi.first.networktables.NetworkTableInstance; -import edu.wpi.first.networktables.NetworkTablesJNI; -import edu.wpi.first.util.CombinedRuntimeLoader; -import edu.wpi.first.util.WPIUtilJNI; import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; @@ -58,7 +50,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; -import org.opencv.core.Core; import org.photonvision.estimation.TargetModel; import org.photonvision.estimation.VisionEstimation; import org.photonvision.simulation.PhotonCameraSim; @@ -85,28 +76,6 @@ class VisionSystemSimTest { @BeforeAll public static void setUp() { - JNIWrapper.Helper.setExtractOnStaticLoad(false); - WPIUtilJNI.Helper.setExtractOnStaticLoad(false); - NetworkTablesJNI.Helper.setExtractOnStaticLoad(false); - WPINetJNI.Helper.setExtractOnStaticLoad(false); - CameraServerJNI.Helper.setExtractOnStaticLoad(false); - CameraServerCvJNI.Helper.setExtractOnStaticLoad(false); - AprilTagJNI.Helper.setExtractOnStaticLoad(false); - - try { - CombinedRuntimeLoader.loadLibraries( - VisionSystemSim.class, - "wpiutiljni", - "ntcorejni", - "wpinetjni", - "wpiHaljni", - Core.NATIVE_LIBRARY_NAME, - "cscorejni", - "apriltagjni"); - } catch (Exception e) { - e.printStackTrace(); - } - // NT live for debug purposes NetworkTableInstance.getDefault().startServer(); diff --git a/photon-lib/src/test/java/org/photonvision/estimation/ApriltagWorkbenchTest.java b/photon-lib/src/test/java/org/photonvision/estimation/ApriltagWorkbenchTest.java index fa70467c5..1c0750d82 100644 --- a/photon-lib/src/test/java/org/photonvision/estimation/ApriltagWorkbenchTest.java +++ b/photon-lib/src/test/java/org/photonvision/estimation/ApriltagWorkbenchTest.java @@ -26,14 +26,8 @@ package org.photonvision.estimation; import edu.wpi.first.apriltag.AprilTagFieldLayout; import edu.wpi.first.apriltag.AprilTagFields; -import edu.wpi.first.cscore.CameraServerCvJNI; -import edu.wpi.first.hal.JNIWrapper; import edu.wpi.first.math.geometry.Transform3d; -import edu.wpi.first.net.WPINetJNI; import edu.wpi.first.networktables.NetworkTableInstance; -import edu.wpi.first.networktables.NetworkTablesJNI; -import edu.wpi.first.util.CombinedRuntimeLoader; -import edu.wpi.first.util.WPIUtilJNI; import edu.wpi.first.wpilibj.smartdashboard.Field2d; import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import java.io.IOException; @@ -44,25 +38,6 @@ import org.photonvision.PhotonPoseEstimator; public class ApriltagWorkbenchTest { @BeforeAll public static void setUp() { - JNIWrapper.Helper.setExtractOnStaticLoad(false); - WPIUtilJNI.Helper.setExtractOnStaticLoad(false); - NetworkTablesJNI.Helper.setExtractOnStaticLoad(false); - WPINetJNI.Helper.setExtractOnStaticLoad(false); - CameraServerCvJNI.Helper.setExtractOnStaticLoad(false); - - try { - CombinedRuntimeLoader.loadLibraries( - ApriltagWorkbenchTest.class, - "wpiutiljni", - "ntcorejni", - "wpinetjni", - "wpiHaljni", - "cscorejnicvstatic"); - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - // No version check for testing PhotonCamera.setVersionCheckEnabled(false); } diff --git a/photon-targeting/build.gradle b/photon-targeting/build.gradle index 4238e951e..4424bf398 100644 --- a/photon-targeting/build.gradle +++ b/photon-targeting/build.gradle @@ -1,9 +1,122 @@ -plugins { - id 'edu.wpi.first.WpilibTools' version '1.3.0' -} - ext { nativeName = "photontargeting" } -apply from: "${rootDir}/shared/javacpp/setupBuild.gradle" +apply plugin: 'cpp' +apply plugin: 'google-test-test-suite' +apply plugin: 'edu.wpi.first.NativeUtils' + +apply from: "${rootDir}/shared/config.gradle" +apply from: "${rootDir}/shared/javacommon.gradle" + +apply from: "${rootDir}/versioningHelper.gradle" + +nativeUtils { + exportsConfigs { + "${nativeName}" {} + } +} + +model { + components { + "${nativeName}"(NativeLibrarySpec) { + sources { + cpp { + source { + srcDirs 'src/main/native/cpp', "$buildDir/generated/source/proto/main/cpp" + include '**/*.cpp', '**/*.cc' + } + exportedHeaders { + srcDirs 'src/main/native/include', "$buildDir/generated/source/proto/main/cpp" + if (project.hasProperty('generatedHeaders')) { + srcDir generatedHeaders + } + include "**/*.h" + } + } + } + + binaries.all { + it.tasks.withType(CppCompile) { + it.dependsOn generateProto + } + if(project.hasProperty('includePhotonTargeting')) { + lib project: ':photon-targeting', library: 'photontargeting', linkage: 'shared' + } + } + + nativeUtils.useRequiredLibrary(it, "wpilib_shared") + nativeUtils.useRequiredLibrary(it, "apriltag_shared") + nativeUtils.useRequiredLibrary(it, "opencv_shared") + } + } + testSuites { + "${nativeName}Test"(GoogleTestTestSuiteSpec) { + for(NativeComponentSpec c : $.components) { + if (c.name == nativeName) { + testing c + break + } + } + sources { + cpp { + source { + srcDirs 'src/test/native/cpp' + include '**/*.cpp' + } + exportedHeaders { + srcDirs 'src/test/native/include', "$buildDir/generated/source/proto/main/cpp" + } + } + } + + binaries.all { + it.tasks.withType(CppCompile) { + it.dependsOn generateProto + } + if(project.hasProperty('includePhotonTargeting')) { + lib project: ':photon-targeting', library: 'photontargeting', linkage: 'shared' + } + } + + nativeUtils.useRequiredLibrary(it, "cscore_shared") + nativeUtils.useRequiredLibrary(it, "cameraserver_shared") + nativeUtils.useRequiredLibrary(it, "wpilib_executable_shared") + nativeUtils.useRequiredLibrary(it, "googletest_static") + nativeUtils.useRequiredLibrary(it, "apriltag_shared") + nativeUtils.useRequiredLibrary(it, "opencv_shared") + } + } + + tasks { + def c = $.testSuites + project.tasks.create('runCpp', Exec) { + description = "Run the photon-lib executable" + def found = false + def systemArch = getCurrentArch() + c.each { + if (it in GoogleTestTestSuiteSpec && it.name == "${nativeName}Test") { + it.binaries.each { + if (!found) { + def arch = it.targetPlatform.name + if (arch == systemArch) { + dependsOn it.tasks.install + commandLine it.tasks.install.runScriptFile.get().asFile.toString() + def filePath = it.tasks.install.installDirectory.get().toString() + File.separatorChar + 'lib' + test.dependsOn it.tasks.install + test.systemProperty 'java.library.path', filePath + test.environment 'LD_LIBRARY_PATH', filePath + test.environment 'DYLD_LIBRARY_PATH', filePath + test.workingDir filePath + + found = true + } + } + } + } + } + } + } +} + +apply from: "${rootDir}/shared/javacpp/publish.gradle"