org.forstdb.util.Environment Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of forstjni Show documentation
Show all versions of forstjni Show documentation
ForSt fat jar with modifications specific for Apache Flink that contains .so files for linux32 and linux64 (glibc and musl-libc), jnilib files
for Mac OSX, and a .dll for Windows x64.
// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
package org.forstdb.util;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
public class Environment {
@SuppressWarnings("FieldMayBeFinal")
private static String OS = System.getProperty("os.name").toLowerCase(Locale.getDefault());
@SuppressWarnings("FieldMayBeFinal")
private static String ARCH = System.getProperty("os.arch").toLowerCase(Locale.getDefault());
@SuppressWarnings("FieldMayBeFinal")
private static String MUSL_ENVIRONMENT = System.getenv("ROCKSDB_MUSL_LIBC");
private static final String LIBC_MUSL_PREFIX = "libc.musl";
private static final String SPARCV9 = "sparcv9";
/**
* Will be lazily initialised by {@link #isMuslLibc()} instead of the previous static
* initialisation. The lazy initialisation prevents Windows from reporting suspicious behaviour of
* the JVM attempting IO on Unix paths.
*/
private static Boolean MUSL_LIBC = null;
public static boolean isAarch64() {
return ARCH.contains("aarch64");
}
public static boolean isPowerPC() {
return ARCH.contains("ppc");
}
public static boolean isS390x() {
return ARCH.contains("s390x");
}
public static boolean isRiscv64() {
return ARCH.contains("riscv64");
}
public static boolean isWindows() {
return (OS.contains("win"));
}
public static boolean isFreeBSD() {
return (OS.contains("freebsd"));
}
public static boolean isMac() {
return (OS.contains("mac"));
}
public static boolean isAix() {
return OS.contains("aix");
}
public static boolean isUnix() {
return OS.contains("nix") ||
OS.contains("nux");
}
/**
* Determine if the environment has a musl libc.
*
* @return true if the environment has a musl libc, false otherwise.
*/
public static boolean isMuslLibc() {
if (MUSL_LIBC == null) {
MUSL_LIBC = initIsMuslLibc();
}
return MUSL_LIBC;
}
/**
* Determine if the environment has a musl libc.
*
* The initialisation counterpart of {@link #isMuslLibc()}.
*
* Intentionally package-private for testing.
*
* @return true if the environment has a musl libc, false otherwise.
*/
@SuppressWarnings("PMD.EmptyCatchBlock")
static boolean initIsMuslLibc() {
// consider explicit user setting from environment first
if ("true".equalsIgnoreCase(MUSL_ENVIRONMENT)) {
return true;
}
if ("false".equalsIgnoreCase(MUSL_ENVIRONMENT)) {
return false;
}
// check if ldd indicates a muslc lib
try {
final Process p =
new ProcessBuilder("/usr/bin/env", "sh", "-c", "ldd /usr/bin/env | grep -q musl").start();
if (p.waitFor() == 0) {
return true;
}
} catch (final IOException | InterruptedException e) {
// do nothing, and move on to the next check
}
final File lib = new File("/lib");
if (lib.exists() && lib.isDirectory() && lib.canRead()) {
// attempt the most likely musl libc name first
final String possibleMuslcLibName;
if (isPowerPC()) {
possibleMuslcLibName = "libc.musl-ppc64le.so.1";
} else if (isAarch64()) {
possibleMuslcLibName = "libc.musl-aarch64.so.1";
} else if (isS390x()) {
possibleMuslcLibName = "libc.musl-s390x.so.1";
} else {
possibleMuslcLibName = "libc.musl-x86_64.so.1";
}
final File possibleMuslcLib = new File(lib, possibleMuslcLibName);
if (possibleMuslcLib.exists() && possibleMuslcLib.canRead()) {
return true;
}
// fallback to scanning for a musl libc
final File[] libFiles = lib.listFiles();
if (libFiles == null) {
return false;
}
for (final File f : libFiles) {
if (f.getName().startsWith(LIBC_MUSL_PREFIX)) {
return true;
}
}
}
return false;
}
public static boolean isSolaris() {
return OS.contains("sunos");
}
public static boolean isOpenBSD() {
return (OS.contains("openbsd"));
}
public static boolean is64Bit() {
if (ARCH.contains(SPARCV9)) {
return true;
}
return (ARCH.indexOf("64") > 0);
}
public static String getSharedLibraryName(final String name) {
return name + "jni";
}
public static String getSharedLibraryFileName(final String name) {
return appendLibOsSuffix("lib" + getSharedLibraryName(name), true);
}
/**
* Get the name of the libc implementation
*
* @return the name of the implementation,
* or null if the default for that platform (e.g. glibc on Linux).
*/
public static /* @Nullable */ String getLibcName() {
if (isMuslLibc()) {
return "musl";
} else {
return null;
}
}
private static String getLibcPostfix() {
final String libcName = getLibcName();
if (libcName == null) {
return "";
}
return "-" + libcName;
}
public static String getJniLibraryName(final String name) {
if (isUnix()) {
final String arch = is64Bit() ? "64" : "32";
if (isPowerPC() || isAarch64() || isRiscv64()) {
return String.format("%sjni-linux-%s%s", name, ARCH, getLibcPostfix());
} else if (isS390x()) {
return String.format("%sjni-linux-%s", name, ARCH);
} else {
return String.format("%sjni-linux%s%s", name, arch, getLibcPostfix());
}
} else if (isMac()) {
if (is64Bit()) {
final String arch;
if (isAarch64()) {
arch = "arm64";
} else {
arch = "x86_64";
}
return String.format("%sjni-osx-%s", name, arch);
} else {
return String.format("%sjni-osx", name);
}
} else if (isFreeBSD()) {
return String.format("%sjni-freebsd%s", name, is64Bit() ? "64" : "32");
} else if (isAix() && is64Bit()) {
return String.format("%sjni-aix64", name);
} else if (isSolaris()) {
final String arch = is64Bit() ? "64" : "32";
return String.format("%sjni-solaris%s", name, arch);
} else if (isWindows() && is64Bit()) {
return String.format("%sjni-win64", name);
} else if (isOpenBSD()) {
return String.format("%sjni-openbsd%s", name, is64Bit() ? "64" : "32");
}
throw new UnsupportedOperationException(String.format("Cannot determine JNI library name for ARCH='%s' OS='%s' name='%s'", ARCH, OS, name));
}
public static /*@Nullable*/ String getFallbackJniLibraryName(final String name) {
if (isMac() && is64Bit()) {
return String.format("%sjni-osx", name);
}
return null;
}
public static String getJniLibraryFileName(final String name) {
return appendLibOsSuffix("lib" + getJniLibraryName(name), false);
}
public static /*@Nullable*/ String getFallbackJniLibraryFileName(final String name) {
final String fallbackJniLibraryName = getFallbackJniLibraryName(name);
if (fallbackJniLibraryName == null) {
return null;
}
return appendLibOsSuffix("lib" + fallbackJniLibraryName, false);
}
private static String appendLibOsSuffix(final String libraryFileName, final boolean shared) {
if (isUnix() || isAix() || isSolaris() || isFreeBSD() || isOpenBSD()) {
return libraryFileName + ".so";
} else if (isMac()) {
return libraryFileName + (shared ? ".dylib" : ".jnilib");
} else if (isWindows()) {
return libraryFileName + ".dll";
}
throw new UnsupportedOperationException();
}
public static String getJniLibraryExtension() {
if (isWindows()) {
return ".dll";
}
return (isMac()) ? ".jnilib" : ".so";
}
}