Skip to content

Commit

Permalink
Move to maven JNI
Browse files Browse the repository at this point in the history
  • Loading branch information
mcm001 committed Dec 10, 2023
1 parent 203982c commit e2b8007
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 143 deletions.
14 changes: 8 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ allprojects {
mavenCentral()
mavenLocal()
maven { url = "https://maven.photonvision.org/repository/internal/" }
maven { url = "https://maven.photonvision.org/repository/snapshots/" }
}
wpilibRepositories.addAllReleaseRepositories(it)
wpilibRepositories.addAllDevelopmentRepositories(it)
Expand All @@ -30,13 +31,14 @@ ext {
isDev = pubVersion.startsWith("dev")

// A list, for legacy reasons, with only the current platform contained
String nativeName = wpilibTools.platformMapper.currentPlatform.platformName;
if (nativeName == "linuxx64") nativeName = "linuxx86-64";
if (nativeName == "winx64") nativeName = "windowsx86-64";
if (nativeName == "macx64") nativeName = "osxx86-64";
if (nativeName == "macarm64") nativeName = "osxarm64";
wpilibNativeName = wpilibTools.platformMapper.currentPlatform.platformName;
def nativeName = wpilibNativeName
if (wpilibNativeName == "linuxx64") nativeName = "linuxx86-64";
if (wpilibNativeName == "winx64") nativeName = "windowsx86-64";
if (wpilibNativeName == "macx64") nativeName = "osxx86-64";
if (wpilibNativeName == "macarm64") nativeName = "osxarm64";
jniPlatform = nativeName
println("Building for platform " + jniPlatform)
println("Building for platform " + jniPlatform + " wpilib: " + wpilibNativeName)
}

wpilibTools.deps.wpilibVersion = wpilibVersion
Expand Down
3 changes: 3 additions & 0 deletions photon-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ dependencies {
implementation wpilibTools.deps.wpilibJava("apriltag")

implementation "org.xerial:sqlite-jdbc:3.41.0.0"

implementation "org.photonvision:photon-mrcal-java:dev-Unknown"
implementation "org.photonvision:photon-mrcal-jni:dev-Unknown:" + wpilibNativeName;
}

task writeCurrentVersionJava {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
@SuppressWarnings("unused")
public enum Platform {
// WPILib Supported (JNI)
WINDOWS_64("Windows x64", "winx86-64", false, OSType.WINDOWS, true),
LINUX_32("Linux x86", "linuxx86-64", false, OSType.LINUX, true),
LINUX_64("Linux x64", "linuxx86-64", false, OSType.LINUX, true),
WINDOWS_64("Windows x64", "winx64", false, OSType.WINDOWS, true),
LINUX_32("Linux x86", "linuxx64", false, OSType.LINUX, true),
LINUX_64("Linux x64", "linuxx64", false, OSType.LINUX, true),
LINUX_RASPBIAN32(
"Linux Raspbian 32-bit",
"linuxarm32",
Expand All @@ -51,7 +51,7 @@ public enum Platform {
LINUX_ARM64("Linux ARM64", "linuxarm64", false, OSType.LINUX, true), // ODROID C2, N2

// Completely unsupported
WINDOWS_32("Windows x86", "windowsx86-64", false, OSType.WINDOWS, false),
WINDOWS_32("Windows x86", "windowsx64", false, OSType.WINDOWS, false),
MACOS("Mac OS", "osxuniversal", false, OSType.MACOS, false),
UNKNOWN("Unsupported Platform", "", false, OSType.UNKNOWN, false);

Expand Down Expand Up @@ -233,4 +233,9 @@ private static boolean fileHasText(String filename, String text) {
return false;
}
}

public static boolean isWindows() {
var p = getCurrentPlatform();
return (p == WINDOWS_32 || p == WINDOWS_64);
}
}
70 changes: 40 additions & 30 deletions photon-core/src/main/java/org/photonvision/jni/PhotonJniCommon.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

import org.photonvision.common.hardware.Platform;
import org.photonvision.common.logging.LogGroup;
import org.photonvision.common.logging.Logger;
Expand All @@ -32,44 +34,52 @@ public abstract class PhotonJniCommon {
static boolean libraryLoaded = false;
protected static Logger logger = null;

protected static synchronized void forceLoad(Class<?> clazz, String libraryName) throws IOException {
if (libraryLoaded) return;
if (logger == null) logger = new Logger(clazz, LogGroup.Camera);

try {
protected static synchronized void forceLoad(Class<?> clazz, List<String> libraries) throws IOException {
if (libraryLoaded)
return;
if (logger == null)
logger = new Logger(clazz, LogGroup.Camera);

// We always extract the shared object (we could hash each so, but that's a lot of work)
var arch_name = Platform.getNativeLibraryFolderName();
var nativeLibName = System.mapLibraryName(libraryName);
var in = clazz.getResourceAsStream("/nativelibraries/" + arch_name + "/" + nativeLibName);

if (in == null) {
libraryLoaded = false;
return;
}
for (var libraryName : libraries) {
try {
// We always extract the shared object (we could hash each so, but that's a lot of work)
var arch_name = Platform.getNativeLibraryFolderName();
var nativeLibName = System.mapLibraryName(libraryName);
var in = clazz.getResourceAsStream("/nativelibraries/" + arch_name + "/" + nativeLibName);

File temp = File.createTempFile(nativeLibName, "");
FileOutputStream fos = new FileOutputStream(temp);
if (in == null) {
libraryLoaded = false;
return;
}

int read = -1;
byte[] buffer = new byte[1024];
while((read = in.read(buffer)) != -1) {
fos.write(buffer, 0, read);
}
fos.close();
in.close();
// It's important that we don't mangle the names of these files on Windows at least
File temp = new File(System.getProperty("java.io.tmpdir"), nativeLibName);
FileOutputStream fos = new FileOutputStream(temp);

System.load(temp.getAbsolutePath());
int read = -1;
byte[] buffer = new byte[1024];
while ((read = in.read(buffer)) != -1) {
fos.write(buffer, 0, read);
}
fos.close();
in.close();

libraryLoaded = true;
logger.info("Successfully loaded shared object");
System.load(temp.getAbsolutePath());

logger.info("Successfully loaded shared object " + temp.getName());

} catch (UnsatisfiedLinkError e) {
logger.error("Couldn't load shared object", e);
e.printStackTrace();
logger.error(System.getProperty("java.library.path"));
} catch (UnsatisfiedLinkError e) {
logger.error("Couldn't load shared object " + libraryName, e);
e.printStackTrace();
// logger.error(System.getProperty("java.library.path"));
break;
}
}
libraryLoaded = true;
}

protected static synchronized void forceLoad(Class<?> clazz, String libraryName) throws IOException {
forceLoad(clazz, List.of(libraryName));
}

public static boolean isWorking() {
Expand Down
43 changes: 43 additions & 0 deletions photon-core/src/main/java/org/photonvision/mrcal/MrCal.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (C) Photon Vision.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package org.photonvision.mrcal;

import java.io.IOException;
import java.util.List;

import org.photonvision.common.hardware.Platform;
import org.photonvision.common.util.TestUtils;
import org.photonvision.jni.PhotonJniCommon;

public class MrCal extends PhotonJniCommon {

public static synchronized void forceLoad() throws IOException {
// Force load opencv
TestUtils.loadLibraries();

// Library naming is dumb and has "lib" appended for Windows when it ought not to
if (Platform.isWindows()) {
// Order is correct to match dependencies of libraries
forceLoad(MrCal.class, List.of("libamd", "libcamd", "libcolamd", "libccolamd", "openblas", "libgcc_s_seh-1", "libgfortran-5", "liblapack", "libcholmod", "mrcal_jni"));
}
}

public static void main(String[] args) throws IOException, InterruptedException {
MrCal.forceLoad();
}
}
102 changes: 0 additions & 102 deletions photon-core/src/main/java/org/photonvision/mrcal/MrCalJNI.java

This file was deleted.

Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,15 @@
public class MrCalTest {
@BeforeAll
static public void load() {
assertDoesNotThrow(MrCalJNI::forceLoad);
assertDoesNotThrow(MrCal::forceLoad);
assertDoesNotThrow(TestUtils::loadLibraries);
}

@Test
public void smokeTest() {

}

@Test
public void calibrateSquares640x480_pi() {
// Pi3 and V1.3 camera
Expand Down

0 comments on commit e2b8007

Please sign in to comment.