Skip to content

Commit

Permalink
Default to non static library loading for JNI
Browse files Browse the repository at this point in the history
  • Loading branch information
ThadHouse committed Aug 2, 2024
1 parent caf424e commit becd63a
Show file tree
Hide file tree
Showing 34 changed files with 350 additions and 38 deletions.
17 changes: 15 additions & 2 deletions apriltag/src/main/java/edu/wpi/first/apriltag/jni/AprilTagJNI.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ public class AprilTagJNI {
static boolean libraryLoaded = false;

/** Sets whether JNI should be loaded in the static block. */
public static class Helper {
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
public static final class Helper {
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(false);

/**
* Returns true if the JNI should be loaded in the static block.
Expand Down Expand Up @@ -55,6 +55,19 @@ private Helper() {}
}
}

/**
* Force load the library.
*
* @throws IOException if library load failed
*/
public static synchronized void forceLoad() throws IOException {
if (libraryLoaded) {
return;
}
RuntimeLoader.loadLibrary("apriltagjni");
libraryLoaded = true;
}

/**
* Constructs an AprilTag detector engine.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// 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.apriltag;

import edu.wpi.first.apriltag.jni.AprilTagJNI;
import edu.wpi.first.util.WPIUtilJNI;

import java.io.IOException;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;

public final class AprilTagJniTestExtension implements BeforeAllCallback {
private static ExtensionContext getRoot(ExtensionContext context) {
return context.getParent().map(AprilTagJniTestExtension::getRoot).orElse(context);
}

@Override
public void beforeAll(ExtensionContext context) throws Exception {
getRoot(context)
.getStore(Namespace.GLOBAL)
.getOrComputeIfAbsent(
"April Tag Initialized",
key -> {
initializeNatives();
return true;
},
Boolean.class);
}

private void initializeNatives() {
try {
WPIUtilJNI.forceLoad();
AprilTagJNI.forceLoad();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
edu.wpi.first.apriltag.AprilTagJniTestExtension
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public class CameraServerJNI {
static boolean libraryLoaded = false;

/** Sets whether JNI should be loaded in the static block. */
public static class Helper {
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
public static final class Helper {
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(false);

/**
* Returns true if the JNI should be loaded in the static block.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public final class OpenCvLoader {

/** Sets whether JNI should be loaded in the static block. */
public static final class Helper {
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(false);

/**
* Returns true if the JNI should be loaded in the static block.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// 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.cscore;

import edu.wpi.first.util.WPIUtilJNI;

import java.io.IOException;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;

public final class CameraServerJniTestExtension implements BeforeAllCallback {
private static ExtensionContext getRoot(ExtensionContext context) {
return context.getParent().map(CameraServerJniTestExtension::getRoot).orElse(context);
}

@Override
public void beforeAll(ExtensionContext context) throws Exception {
getRoot(context)
.getStore(Namespace.GLOBAL)
.getOrComputeIfAbsent(
"CsCore Initialized",
key -> {
initializeNatives();
return true;
},
Boolean.class);
}

private void initializeNatives() {
try {
WPIUtilJNI.forceLoad();
CameraServerJNI.forceLoad();
OpenCvLoader.forceLoad();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
edu.wpi.first.cscore.CameraServerJniTestExtension
4 changes: 2 additions & 2 deletions hal/src/main/java/edu/wpi/first/hal/JNIWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ public class JNIWrapper {
static boolean libraryLoaded = false;

/** Sets whether JNI should be loaded in the static block. */
public static class Helper {
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
public static final class Helper {
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(false);

/**
* Returns true if the JNI should be loaded in the static block.
Expand Down
40 changes: 40 additions & 0 deletions hal/src/test/java/edu/wpi/first/hal/HalJniTestExtension.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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.hal;

import edu.wpi.first.util.WPIUtilJNI;

import java.io.IOException;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;

public final class HalJniTestExtension implements BeforeAllCallback {
private static ExtensionContext getRoot(ExtensionContext context) {
return context.getParent().map(HalJniTestExtension::getRoot).orElse(context);
}

@Override
public void beforeAll(ExtensionContext context) throws Exception {
getRoot(context)
.getStore(Namespace.GLOBAL)
.getOrComputeIfAbsent(
"HAL Initialized",
key -> {
initializeNatives();
return true;
},
Boolean.class);
}

private void initializeNatives() {
try {
WPIUtilJNI.forceLoad();
JNIWrapper.forceLoad();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
edu.wpi.first.hal.HalJniTestExtension
5 changes: 2 additions & 3 deletions ntcore/src/generate/main/java/NetworkTablesJNI.java.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ public final class NetworkTablesJNI {
static boolean libraryLoaded = false;

/** Sets whether JNI should be loaded in the static block. */
public static class Helper {
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(true);
public static final class Helper {
private static AtomicBoolean extractOnStaticLoad = new AtomicBoolean(false);

/**
* Returns true if the JNI should be loaded in the static block.
Expand Down Expand Up @@ -1088,4 +1088,3 @@ public final class NetworkTablesJNI {
/** Utility class. */
private NetworkTablesJNI() {}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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.networktables;

import edu.wpi.first.util.WPIUtilJNI;

import java.io.IOException;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;

public final class NetworkTablesJniTestExtension implements BeforeAllCallback {
private static ExtensionContext getRoot(ExtensionContext context) {
return context.getParent().map(NetworkTablesJniTestExtension::getRoot).orElse(context);
}

@Override
public void beforeAll(ExtensionContext context) throws Exception {
getRoot(context)
.getStore(Namespace.GLOBAL)
.getOrComputeIfAbsent(
"Ntcore Initialized",
key -> {
initializeNatives();
return true;
},
Boolean.class);
}

private void initializeNatives() {
try {
WPIUtilJNI.forceLoad();
NetworkTablesJNI.forceLoad();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
edu.wpi.first.networktables.NetworkTablesJniTestExtension
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

package edu.wpi.first.wpilibj2;

import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.RobotBase;
import edu.wpi.first.wpilibj.simulation.DriverStationSim;

import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
Expand All @@ -29,7 +30,8 @@ public void beforeAll(ExtensionContext context) {
}

private void initializeHardware() {
HAL.initialize(500, 0);
RobotBase.loadLibrariesAndInitializeHal();

DriverStationSim.setDsAttached(true);
DriverStationSim.setAutonomous(false);
DriverStationSim.setEnabled(true);
Expand Down
1 change: 1 addition & 0 deletions wpilibj/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ dependencies {
implementation project(':ntcore')
implementation project(':cscore')
implementation project(':cameraserver')
implementation project(':apriltag')
testImplementation 'org.mockito:mockito-core:4.1.0'
devImplementation sourceSets.main.output
}
Expand Down
40 changes: 39 additions & 1 deletion wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,24 @@

package edu.wpi.first.wpilibj;

import edu.wpi.first.apriltag.jni.AprilTagJNI;
import edu.wpi.first.cameraserver.CameraServerShared;
import edu.wpi.first.cameraserver.CameraServerSharedStore;
import edu.wpi.first.cscore.CameraServerJNI;
import edu.wpi.first.cscore.OpenCvLoader;
import edu.wpi.first.hal.FRCNetComm.tInstances;
import edu.wpi.first.hal.FRCNetComm.tResourceType;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.hal.HALUtil;
import edu.wpi.first.hal.JNIWrapper;
import edu.wpi.first.math.MathShared;
import edu.wpi.first.math.MathSharedStore;
import edu.wpi.first.math.MathUsageId;
import edu.wpi.first.math.jni.WPIMathJNI;
import edu.wpi.first.net.WPINetJNI;
import edu.wpi.first.networktables.MultiSubscriber;
import edu.wpi.first.networktables.NetworkTableInstance;
import edu.wpi.first.networktables.NetworkTablesJNI;
import edu.wpi.first.util.WPIUtilJNI;
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard;
Expand Down Expand Up @@ -390,14 +397,45 @@ public static void suppressExitWarning(boolean value) {
m_runMutex.unlock();
}

/**
* Loads base native libraries needed by WPILib in all robot projects.
*
* @throws IOException If any library was not found
*/
public static void loadBaseNativeLibraries() throws IOException {
WPIUtilJNI.forceLoad();
WPINetJNI.forceLoad();
WPIMathJNI.forceLoad();
JNIWrapper.forceLoad();
NetworkTablesJNI.forceLoad();
}

public static void setVisionNativeLibrariesStaticLoadBehavior(boolean loadOnStaticInitialization) {
CameraServerJNI.Helper.setExtractOnStaticLoad(true);
OpenCvLoader.Helper.setExtractOnStaticLoad(true);
AprilTagJNI.Helper.setExtractOnStaticLoad(true);
}

public static boolean loadLibrariesAndInitializeHal() {
try {
loadBaseNativeLibraries();
} catch (IOException e) {
throw new RuntimeException(e);
}

setVisionNativeLibrariesStaticLoadBehavior(true);

return HAL.initialize(500, 0);
}

/**
* Starting point for the applications.
*
* @param <T> Robot subclass.
* @param robotSupplier Function that returns an instance of the robot subclass.
*/
public static <T extends RobotBase> void startRobot(Supplier<T> robotSupplier) {
if (!HAL.initialize(500, 0)) {
if (!loadLibrariesAndInitializeHal()) {
throw new IllegalStateException("Failed to initialize. Terminating");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

package edu.wpi.first.wpilibj;

import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.simulation.DriverStationSim;

import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
Expand All @@ -29,7 +29,8 @@ public void beforeAll(ExtensionContext context) {
}

private void initializeHardware() {
HAL.initialize(500, 0);
RobotBase.loadLibrariesAndInitializeHal();

DriverStationSim.setDsAttached(true);
DriverStationSim.setAutonomous(false);
DriverStationSim.setEnabled(true);
Expand Down
3 changes: 3 additions & 0 deletions wpilibjExamples/networktables.json.bck
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[

]
Loading

0 comments on commit becd63a

Please sign in to comment.