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 edu.wpi.first.util;
006
007import java.io.File;
008
009/**
010 * A utility class for detecting and providing platform-specific such as OS and CPU architecture.
011 */
012public final class RuntimeDetector {
013  private static String filePrefix;
014  private static String fileExtension;
015  private static String filePath;
016
017  private static synchronized void computePlatform() {
018    if (fileExtension != null && filePath != null && filePrefix != null) {
019      return;
020    }
021
022    boolean intel32 = is32BitIntel();
023    boolean intel64 = is64BitIntel();
024    boolean arm64 = isArm64();
025
026    if (isWindows()) {
027      filePrefix = "";
028      fileExtension = ".dll";
029      if (intel32) {
030        filePath = "/windows/x86/";
031      } else {
032        filePath = "/windows/x86-64/";
033      }
034    } else if (isMac()) {
035      filePrefix = "lib";
036      fileExtension = ".dylib";
037      filePath = "/osx/universal/";
038    } else if (isLinux()) {
039      filePrefix = "lib";
040      fileExtension = ".so";
041      if (intel32) {
042        filePath = "/linux/x86/";
043      } else if (intel64) {
044        filePath = "/linux/x86-64/";
045      } else if (isAthena()) {
046        filePath = "/linux/athena/";
047      } else if (isArm32()) {
048        filePath = "/linux/arm32/";
049      } else if (arm64) {
050        filePath = "/linux/arm64/";
051      } else {
052        filePath = "/linux/nativearm/";
053      }
054    } else {
055      throw new IllegalStateException("Failed to determine OS");
056    }
057  }
058
059  /**
060   * Get the file prefix for the current system.
061   *
062   * @return The file prefix.
063   */
064  public static synchronized String getFilePrefix() {
065    computePlatform();
066
067    return filePrefix;
068  }
069
070  /**
071   * Get the file extension for the current system.
072   *
073   * @return The file extension.
074   */
075  public static synchronized String getFileExtension() {
076    computePlatform();
077
078    return fileExtension;
079  }
080
081  /**
082   * Get the platform path for the current system.
083   *
084   * @return The platform path.
085   */
086  public static synchronized String getPlatformPath() {
087    computePlatform();
088
089    return filePath;
090  }
091
092  /**
093   * Get the path to the requested resource.
094   *
095   * @param libName Library name.
096   * @return The path to the requested resource.
097   */
098  public static synchronized String getLibraryResource(String libName) {
099    computePlatform();
100
101    return filePath + filePrefix + libName + fileExtension;
102  }
103
104  /**
105   * Get the path to the hash to the requested resource.
106   *
107   * @param libName Library name.
108   * @return The path to the hash to the requested resource.
109   */
110  public static synchronized String getHashLibraryResource(String libName) {
111    computePlatform();
112
113    return filePath + libName + ".hash";
114  }
115
116  /**
117   * Check if hardware platform is Athena.
118   *
119   * @return True if hardware platform is Athena.
120   */
121  public static boolean isAthena() {
122    File runRobotFile = new File("/usr/local/frc/bin/frcRunRobot.sh");
123    return runRobotFile.exists();
124  }
125
126  /**
127   * Check if OS is Arm32.
128   *
129   * @return True if OS is Arm32.
130   */
131  public static boolean isArm32() {
132    String arch = System.getProperty("os.arch");
133    return "arm".equals(arch) || "arm32".equals(arch);
134  }
135
136  /**
137   * Check if architecture is Arm64.
138   *
139   * @return if architecture is Arm64.
140   */
141  public static boolean isArm64() {
142    String arch = System.getProperty("os.arch");
143    return "aarch64".equals(arch) || "arm64".equals(arch);
144  }
145
146  /**
147   * Check if OS is Linux.
148   *
149   * @return if OS is Linux.
150   */
151  public static boolean isLinux() {
152    return System.getProperty("os.name").startsWith("Linux");
153  }
154
155  /**
156   * Check if OS is Windows.
157   *
158   * @return if OS is Windows.
159   */
160  public static boolean isWindows() {
161    return System.getProperty("os.name").startsWith("Windows");
162  }
163
164  /**
165   * Check if OS is Mac.
166   *
167   * @return if OS is Mac.
168   */
169  public static boolean isMac() {
170    return System.getProperty("os.name").startsWith("Mac");
171  }
172
173  /**
174   * Check if OS is 32bit Intel.
175   *
176   * @return if OS is 32bit Intel.
177   */
178  public static boolean is32BitIntel() {
179    String arch = System.getProperty("os.arch");
180    return "x86".equals(arch) || "i386".equals(arch);
181  }
182
183  /**
184   * Check if OS is 64bit Intel.
185   *
186   * @return if OS is 64bit Intel.
187   */
188  public static boolean is64BitIntel() {
189    String arch = System.getProperty("os.arch");
190    return "amd64".equals(arch) || "x86_64".equals(arch);
191  }
192
193  private RuntimeDetector() {}
194}