001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package org.wpilib.util.runtime; 006 007import java.io.IOException; 008 009/** Loads a native library at runtime. */ 010public final class RuntimeLoader { 011 /** 012 * Returns platform name. 013 * 014 * @return The current platform name. 015 * @throws IllegalStateException Thrown if the operating system is unknown. 016 */ 017 public static String getPlatformName() { 018 String arch = System.getProperty("os.arch"); 019 020 boolean intel64 = "amd64".equals(arch) || "x86_64".equals(arch); 021 boolean arm64 = "aarch64".equals(arch) || "arm64".equals(arch); 022 023 if (intel64) { 024 arch = "x86_64"; 025 } else if (arm64) { 026 arch = "arm64"; 027 } else { 028 throw new IllegalStateException("Unsupported architecture: " + arch); 029 } 030 031 String osName = System.getProperty("os.name"); 032 033 if (osName.startsWith("Windows")) { 034 osName = "windows"; 035 } else if (osName.startsWith("Mac")) { 036 osName = "osx"; 037 arch = "universal"; 038 } else if (osName.startsWith("Linux")) { 039 osName = "linux"; 040 } else { 041 throw new IllegalStateException("Unsupported operating system: " + osName); 042 } 043 044 return osName + "-" + arch; 045 } 046 047 /** 048 * Returns a load error message given the information in the provided UnsatisfiedLinkError. 049 * 050 * @param libraryName the name of the library that failed to load. 051 * @param ule UnsatisfiedLinkError object. 052 * @return A load error message. 053 */ 054 private static String getLoadErrorMessage(String libraryName, UnsatisfiedLinkError ule) { 055 String jvmLocation = ProcessHandle.current().info().command().orElse("Unknown"); 056 StringBuilder msg = new StringBuilder(512); 057 msg.append(libraryName) 058 .append(" could not be loaded from path.\n" + "\tattempted to load for platform ") 059 .append(getPlatformName()) 060 .append("\nLast Load Error: \n") 061 .append(ule.getMessage()) 062 .append('\n') 063 .append(String.format("JVM Location: %s\n", jvmLocation)); 064 if (System.getProperty("os.name").startsWith("Windows")) { 065 msg.append( 066 "A common cause of this error is using a JVM with an incorrect MSVC runtime.\n" 067 + "Ensure you are using the WPILib JVM (The current running JVM is listed above)\n" 068 + "See https://wpilib.org/jvmruntime for more information\n"); 069 } 070 return msg.toString(); 071 } 072 073 /** 074 * Loads a native library. 075 * 076 * @param libraryName the name of the library to load. 077 * @throws IOException if the library fails to load 078 */ 079 public static void loadLibrary(String libraryName) throws IOException { 080 try { 081 System.loadLibrary(libraryName); 082 } catch (UnsatisfiedLinkError ule) { 083 throw new IOException(getLoadErrorMessage(libraryName, ule)); 084 } 085 } 086 087 private RuntimeLoader() { 088 throw new IllegalStateException("This class shouldn't be instantiated"); 089 } 090}