Add shared library for musl-libc (#3143)

Summary:
Add the jni library for musl-libc, specifically for incorporating into Alpine based docker images. The classifier is `musl64`.

I have signed the CLA electronically.
Pull Request resolved: https://github.com/facebook/rocksdb/pull/3143

Differential Revision: D18719372

fbshipit-source-id: 6189d149310b6436d6def7d808566b0234b23313
This commit is contained in:
Patrick Double 2019-11-26 16:51:26 -08:00 committed by Facebook Github Bot
parent d9314a9214
commit 8ae149eba1
9 changed files with 282 additions and 29 deletions

View File

@ -1731,12 +1731,23 @@ else
ARCH := $(shell getconf LONG_BIT) ARCH := $(shell getconf LONG_BIT)
endif endif
ifneq (,$(filter ppc% arm64 aarch64 sparc64, $(MACHINE))) ifeq ($(shell ldd /usr/bin/env 2>/dev/null | grep -q musl; echo $$?),0)
ROCKSDBJNILIB = librocksdbjni-linux-$(MACHINE).so JNI_LIBC = musl
else # GNU LibC (or glibc) is so pervasive we can assume it is the default
ROCKSDBJNILIB = librocksdbjni-linux$(ARCH).so # else
# JNI_LIBC = glibc
endif endif
ROCKSDB_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-linux$(ARCH).jar
ifneq ($(origin JNI_LIBC), undefined)
JNI_LIBC_POSTFIX = -$(JNI_LIBC)
endif
ifneq (,$(filter ppc% arm64 aarch64 sparc64, $(MACHINE)))
ROCKSDBJNILIB = librocksdbjni-linux-$(MACHINE)$(JNI_LIBC_POSTFIX).so
else
ROCKSDBJNILIB = librocksdbjni-linux$(ARCH)$(JNI_LIBC_POSTFIX).so
endif
ROCKSDB_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-linux$(ARCH)$(JNI_LIBC_POSTFIX).jar
ROCKSDB_JAR_ALL = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH).jar ROCKSDB_JAR_ALL = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH).jar
ROCKSDB_JAVADOCS_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-javadoc.jar ROCKSDB_JAVADOCS_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-javadoc.jar
ROCKSDB_SOURCES_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-sources.jar ROCKSDB_SOURCES_JAR = rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-sources.jar
@ -1910,12 +1921,12 @@ rocksdbjavastatic: $(java_static_all_libobjects)
cd java/src/main/java;jar -cf ../../../target/$(ROCKSDB_SOURCES_JAR) org cd java/src/main/java;jar -cf ../../../target/$(ROCKSDB_SOURCES_JAR) org
rocksdbjavastaticrelease: rocksdbjavastatic rocksdbjavastaticrelease: rocksdbjavastatic
cd java/crossbuild && vagrant destroy -f && vagrant up linux32 && vagrant halt linux32 && vagrant up linux64 && vagrant halt linux64 cd java/crossbuild && (vagrant destroy -f || true) && vagrant up linux32 && vagrant halt linux32 && vagrant up linux64 && vagrant halt linux64 && vagrant up linux64-musl && vagrant halt linux64-musl
cd java;jar -cf target/$(ROCKSDB_JAR_ALL) HISTORY*.md cd java;jar -cf target/$(ROCKSDB_JAR_ALL) HISTORY*.md
cd java/target;jar -uf $(ROCKSDB_JAR_ALL) librocksdbjni-*.so librocksdbjni-*.jnilib cd java/target;jar -uf $(ROCKSDB_JAR_ALL) librocksdbjni-*.so librocksdbjni-*.jnilib
cd java/target/classes;jar -uf ../$(ROCKSDB_JAR_ALL) org/rocksdb/*.class org/rocksdb/util/*.class cd java/target/classes;jar -uf ../$(ROCKSDB_JAR_ALL) org/rocksdb/*.class org/rocksdb/util/*.class
rocksdbjavastaticreleasedocker: rocksdbjavastatic rocksdbjavastaticdockerx86 rocksdbjavastaticdockerx86_64 rocksdbjavastaticreleasedocker: rocksdbjavastatic rocksdbjavastaticdockerx86 rocksdbjavastaticdockerx86_64 rocksdbjavastaticdockerx86musl rocksdbjavastaticdockerx86_64musl
cd java;jar -cf target/$(ROCKSDB_JAR_ALL) HISTORY*.md cd java;jar -cf target/$(ROCKSDB_JAR_ALL) HISTORY*.md
cd java/target;jar -uf $(ROCKSDB_JAR_ALL) librocksdbjni-*.so librocksdbjni-*.jnilib cd java/target;jar -uf $(ROCKSDB_JAR_ALL) librocksdbjni-*.so librocksdbjni-*.jnilib
cd java/target/classes;jar -uf ../$(ROCKSDB_JAR_ALL) org/rocksdb/*.class org/rocksdb/util/*.class cd java/target/classes;jar -uf ../$(ROCKSDB_JAR_ALL) org/rocksdb/*.class org/rocksdb/util/*.class
@ -1936,6 +1947,22 @@ rocksdbjavastaticdockerarm64v8:
mkdir -p java/target mkdir -p java/target
docker run --rm --name rocksdb_linux_arm64v8-be --attach stdin --attach stdout --attach stderr --volume `pwd`:/rocksdb-host:ro --volume /rocksdb-local-build --volume `pwd`/java/target:/rocksdb-java-target --env DEBUG_LEVEL=$(DEBUG_LEVEL) evolvedbinary/rocksjava:centos7_arm64v8-be /rocksdb-host/java/crossbuild/docker-build-linux-centos.sh docker run --rm --name rocksdb_linux_arm64v8-be --attach stdin --attach stdout --attach stderr --volume `pwd`:/rocksdb-host:ro --volume /rocksdb-local-build --volume `pwd`/java/target:/rocksdb-java-target --env DEBUG_LEVEL=$(DEBUG_LEVEL) evolvedbinary/rocksjava:centos7_arm64v8-be /rocksdb-host/java/crossbuild/docker-build-linux-centos.sh
rocksdbjavastaticdockerx86musl:
mkdir -p java/target
docker run --rm --name rocksdb_linux_x86-musl-be --attach stdin --attach stdout --attach stderr --volume `pwd`:/rocksdb-host:ro --volume /rocksdb-local-build --volume `pwd`/java/target:/rocksdb-java-target --env DEBUG_LEVEL=$(DEBUG_LEVEL) evolvedbinary/rocksjava:alpine3_x86-be /rocksdb-host/java/crossbuild/docker-build-linux-centos.sh
rocksdbjavastaticdockerx86_64musl:
mkdir -p java/target
docker run --rm --name rocksdb_linux_x64-musl-be --attach stdin --attach stdout --attach stderr --volume `pwd`:/rocksdb-host:ro --volume /rocksdb-local-build --volume `pwd`/java/target:/rocksdb-java-target --env DEBUG_LEVEL=$(DEBUG_LEVEL) evolvedbinary/rocksjava:alpine3_x64-be /rocksdb-host/java/crossbuild/docker-build-linux-centos.sh
rocksdbjavastaticdockerppc64lemusl:
mkdir -p java/target
docker run --rm --name rocksdb_linux_ppc64le-musl-be --attach stdin --attach stdout --attach stderr --volume `pwd`:/rocksdb-host:ro --volume /rocksdb-local-build --volume `pwd`/java/target:/rocksdb-java-target --env DEBUG_LEVEL=$(DEBUG_LEVEL) evolvedbinary/rocksjava:alpine3_ppc64le-be /rocksdb-host/java/crossbuild/docker-build-linux-centos.sh
rocksdbjavastaticdockerarm64v8musl:
mkdir -p java/target
docker run --rm --name rocksdb_linux_arm64v8-musl-be --attach stdin --attach stdout --attach stderr --volume `pwd`:/rocksdb-host:ro --volume /rocksdb-local-build --volume `pwd`/java/target:/rocksdb-java-target --env DEBUG_LEVEL=$(DEBUG_LEVEL) evolvedbinary/rocksjava:alpine3_arm64v8-be /rocksdb-host/java/crossbuild/docker-build-linux-centos.sh
rocksdbjavastaticpublish: rocksdbjavastaticrelease rocksdbjavastaticpublishcentral rocksdbjavastaticpublish: rocksdbjavastaticrelease rocksdbjavastaticpublishcentral
rocksdbjavastaticpublishdocker: rocksdbjavastaticreleasedocker rocksdbjavastaticpublishcentral rocksdbjavastaticpublishdocker: rocksdbjavastaticreleasedocker rocksdbjavastaticpublishcentral
@ -1945,6 +1972,8 @@ rocksdbjavastaticpublishcentral:
mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-sources.jar -Dclassifier=sources mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-sources.jar -Dclassifier=sources
mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-linux64.jar -Dclassifier=linux64 mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-linux64.jar -Dclassifier=linux64
mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-linux32.jar -Dclassifier=linux32 mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-linux32.jar -Dclassifier=linux32
mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-linux64-musl.jar -Dclassifier=linux64-musl
mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-linux32-musl.jar -Dclassifier=linux32-musl
mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-osx.jar -Dclassifier=osx mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-osx.jar -Dclassifier=osx
mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-win64.jar -Dclassifier=win64 mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH)-win64.jar -Dclassifier=win64
mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH).jar mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile=java/rocksjni.pom -Dfile=java/target/rocksdbjni-$(ROCKSDB_MAJOR).$(ROCKSDB_MINOR).$(ROCKSDB_PATCH).jar

View File

@ -4,28 +4,33 @@ RocksDB can be built as a single self contained cross-platform JAR. The cross-pl
Building a cross-platform JAR requires: Building a cross-platform JAR requires:
* [Vagrant](https://www.vagrantup.com/) * [Docker](https://www.docker.com/docker-community)
* [Virtualbox](https://www.virtualbox.org/)
* A Mac OSX machine that can compile RocksDB. * A Mac OSX machine that can compile RocksDB.
* Java 7 set as JAVA_HOME. * Java 7 set as JAVA_HOME.
Once you have these items, run this make command from RocksDB's root source directory: Once you have these items, run this make command from RocksDB's root source directory:
make jclean clean rocksdbjavastaticrelease make jclean clean rocksdbjavastaticreleasedocker
This command will build RocksDB natively on OSX, and will then spin up two Vagrant Virtualbox Ubuntu images to build RocksDB for both 32-bit and 64-bit Linux. This command will build RocksDB natively on OSX, and will then spin up docker containers to build RocksDB for 32-bit and 64-bit Linux with glibc, and 32-bit and 64-bit Linux with musl libc.
You can find all native binaries and JARs in the java/target directory upon completion: You can find all native binaries and JARs in the java/target directory upon completion:
librocksdbjni-linux32.so librocksdbjni-linux32.so
librocksdbjni-linux64.so librocksdbjni-linux64.so
librocksdbjni-linux64-musl.so
librocksdbjni-linux32-musl.so
librocksdbjni-osx.jnilib librocksdbjni-osx.jnilib
rocksdbjni-3.5.0-javadoc.jar rocksdbjni-x.y.z-javadoc.jar
rocksdbjni-3.5.0-linux32.jar rocksdbjni-x.y.z-linux32.jar
rocksdbjni-3.5.0-linux64.jar rocksdbjni-x.y.z-linux64.jar
rocksdbjni-3.5.0-osx.jar rocksdbjni-x.y.z-linux64-musl.jar
rocksdbjni-3.5.0-sources.jar rocksdbjni-x.y.z-linux32-musl.jar
rocksdbjni-3.5.0.jar rocksdbjni-x.y.z-osx.jar
rocksdbjni-x.y.z-sources.jar
rocksdbjni-x.y.z.jar
Where x.y.z is the built version number of RocksDB.
## Maven publication ## Maven publication

View File

@ -8,10 +8,28 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.define "linux32" do |linux32| config.vm.define "linux32" do |linux32|
linux32.vm.box = "bento/centos-6.10-i386" linux32.vm.box = "bento/centos-6.10-i386"
linux32.vm.provision :shell, path: "build-linux-centos.sh"
end end
config.vm.define "linux64" do |linux64| config.vm.define "linux64" do |linux64|
linux64.vm.box = "bento/centos-6.10" linux64.vm.box = "bento/centos-6.10"
linux64.vm.provision :shell, path: "build-linux-centos.sh"
end
config.vm.define "linux32-musl" do |musl32|
musl32.vm.box = "alpine/alpine32"
musl32.vm.box_version = "3.6.0"
musl32.vm.provision :shell, path: "build-linux-alpine.sh"
end
config.vm.define "linux64-musl" do |musl64|
musl64.vm.box = "generic/alpine36"
## Should use the alpine/alpine64 box, but this issue needs to be fixed first - https://github.com/hashicorp/vagrant/issues/11218
# musl64.vm.box = "alpine/alpine64"
# musl64.vm.box_version = "3.6.0"
musl64.vm.provision :shell, path: "build-linux-alpine.sh"
end end
config.vm.provider "virtualbox" do |v| config.vm.provider "virtualbox" do |v|
@ -20,7 +38,13 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
v.customize ["modifyvm", :id, "--nictype1", "virtio" ] v.customize ["modifyvm", :id, "--nictype1", "virtio" ]
end end
config.vm.provision :shell, path: "build-linux-centos.sh" if Vagrant.has_plugin?("vagrant-cachier")
config.cache.scope = :box
end
if Vagrant.has_plugin?("vagrant-vbguest")
config.vbguest.no_install = true
end
config.vm.synced_folder "../target", "/rocksdb-build" config.vm.synced_folder "../target", "/rocksdb-build"
config.vm.synced_folder "../..", "/rocksdb", type: "rsync" config.vm.synced_folder "../..", "/rocksdb", type: "rsync"
config.vm.boot_timeout = 1200 config.vm.boot_timeout = 1200

View File

@ -0,0 +1,70 @@
#!/usr/bin/env bash
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
set -e
# update Alpine with latest versions
echo '@edge http://nl.alpinelinux.org/alpine/edge/main' >> /etc/apk/repositories
echo '@community http://nl.alpinelinux.org/alpine/edge/community' >> /etc/apk/repositories
apk update
apk upgrade
# install CA certificates
apk add ca-certificates
# install build tools
apk add \
build-base \
coreutils \
file \
git \
perl \
automake \
autoconf \
cmake
# install tool dependencies for building RocksDB static library
apk add \
curl \
bash \
wget \
tar \
openssl
# install RocksDB dependencies
apk add \
snappy snappy-dev \
zlib zlib-dev \
bzip2 bzip2-dev \
lz4 lz4-dev \
zstd zstd-dev \
linux-headers \
jemalloc jemalloc-dev
# install OpenJDK7
apk add openjdk7 \
&& apk add java-cacerts \
&& rm /usr/lib/jvm/java-1.7-openjdk/jre/lib/security/cacerts \
&& ln -s /etc/ssl/certs/java/cacerts /usr/lib/jvm/java-1.7-openjdk/jre/lib/security/cacerts
# cleanup
rm -rf /var/cache/apk/*
# puts javac in the PATH
export JAVA_HOME=/usr/lib/jvm/java-1.7-openjdk
export PATH=/usr/lib/jvm/java-1.7-openjdk/bin:$PATH
# gflags from source
cd /tmp &&\
git clone -b v2.0 --single-branch https://github.com/gflags/gflags.git &&\
cd gflags &&\
./configure --prefix=/usr && make && make install &&\
rm -rf /tmp/*
# build rocksdb
cd /rocksdb
make jclean clean
PORTABLE=1 make -j8 rocksdbjavastatic
cp /rocksdb/java/target/librocksdbjni-* /rocksdb-build
cp /rocksdb/java/target/rocksdbjni-* /rocksdb-build

View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
set -e
#set -x
# just in-case this is run outside Docker
mkdir -p /rocksdb-local-build
rm -rf /rocksdb-local-build/*
cp -r /rocksdb-host/* /rocksdb-local-build
cd /rocksdb-local-build
make clean-not-downloaded
PORTABLE=1 make rocksdbjavastatic
cp java/target/librocksdbjni-linux*.so java/target/rocksdbjni-*-linux*.jar /rocksdb-java-target

View File

@ -10,7 +10,7 @@
<artifactId>rocksdbjni</artifactId> <artifactId>rocksdbjni</artifactId>
<!-- Version will be automatically replaced --> <!-- Version will be automatically replaced -->
<version>-</version> <version>-</version>
<description>RocksDB fat jar that contains .so files for linux32 and linux64, jnilib files <description>RocksDB fat jar that contains .so files for linux32 and linux64 (glibc and musl-libc), jnilib files
for Mac OSX, and a .dll for Windows x64. for Mac OSX, and a .dll for Windows x64.
</description> </description>
<licenses> <licenses>

View File

@ -1,9 +1,22 @@
// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
package org.rocksdb.util; package org.rocksdb.util;
import java.io.File;
import java.io.IOException;
public class Environment { public class Environment {
private static String OS = System.getProperty("os.name").toLowerCase(); private static String OS = System.getProperty("os.name").toLowerCase();
private static String ARCH = System.getProperty("os.arch").toLowerCase(); private static String ARCH = System.getProperty("os.arch").toLowerCase();
private static boolean MUSL_LIBC;
static {
try {
final Process p = new ProcessBuilder("/usr/bin/env", "sh", "-c", "ldd /usr/bin/env | grep -q musl").start();
MUSL_LIBC = p.waitFor() == 0;
} catch (final IOException | InterruptedException e) {
MUSL_LIBC = false;
}
}
public static boolean isAarch64() { public static boolean isAarch64() {
return ARCH.contains("aarch64"); return ARCH.contains("aarch64");
@ -38,6 +51,10 @@ public class Environment {
OS.contains("nux"); OS.contains("nux");
} }
public static boolean isMuslLibc() {
return MUSL_LIBC;
}
public static boolean isSolaris() { public static boolean isSolaris() {
return OS.contains("sunos"); return OS.contains("sunos");
} }
@ -61,15 +78,37 @@ public class Environment {
return appendLibOsSuffix("lib" + getSharedLibraryName(name), true); 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) { public static String getJniLibraryName(final String name) {
if (isUnix()) { if (isUnix()) {
final String arch = is64Bit() ? "64" : "32"; final String arch = is64Bit() ? "64" : "32";
if (isPowerPC() || isAarch64()) { if (isPowerPC() || isAarch64()) {
return String.format("%sjni-linux-%s", name, ARCH); return String.format("%sjni-linux-%s%s", name, ARCH, getLibcPostfix());
} else if (isS390x()) { } else if (isS390x()) {
return String.format("%sjni-linux%s", name, ARCH); return String.format("%sjni-linux%s", name, ARCH);
} else { } else {
return String.format("%sjni-linux%s", name, arch); return String.format("%sjni-linux%s%s", name, arch, getLibcPostfix());
} }
} else if (isMac()) { } else if (isMac()) {
return String.format("%sjni-osx", name); return String.format("%sjni-osx", name);

View File

@ -16,14 +16,17 @@ import static org.assertj.core.api.Assertions.assertThat;
public class EnvironmentTest { public class EnvironmentTest {
private final static String ARCH_FIELD_NAME = "ARCH"; private final static String ARCH_FIELD_NAME = "ARCH";
private final static String OS_FIELD_NAME = "OS"; private final static String OS_FIELD_NAME = "OS";
private final static String MUSL_LIBC_FIELD_NAME = "MUSL_LIBC";
private static String INITIAL_OS; private static String INITIAL_OS;
private static String INITIAL_ARCH; private static String INITIAL_ARCH;
private static boolean INITIAL_MUSL_LIBC;
@BeforeClass @BeforeClass
public static void saveState() { public static void saveState() {
INITIAL_ARCH = getEnvironmentClassField(ARCH_FIELD_NAME); INITIAL_ARCH = getEnvironmentClassField(ARCH_FIELD_NAME);
INITIAL_OS = getEnvironmentClassField(OS_FIELD_NAME); INITIAL_OS = getEnvironmentClassField(OS_FIELD_NAME);
INITIAL_MUSL_LIBC = getEnvironmentClassField(MUSL_LIBC_FIELD_NAME);
} }
@Test @Test
@ -53,6 +56,7 @@ public class EnvironmentTest {
@Test @Test
public void nix32() { public void nix32() {
// Linux // Linux
setEnvironmentClassField(MUSL_LIBC_FIELD_NAME, false);
setEnvironmentClassFields("Linux", "32"); setEnvironmentClassFields("Linux", "32");
assertThat(Environment.isWindows()).isFalse(); assertThat(Environment.isWindows()).isFalse();
assertThat(Environment.getJniLibraryExtension()). assertThat(Environment.getJniLibraryExtension()).
@ -61,7 +65,17 @@ public class EnvironmentTest {
isEqualTo("librocksdbjni-linux32.so"); isEqualTo("librocksdbjni-linux32.so");
assertThat(Environment.getSharedLibraryFileName("rocksdb")). assertThat(Environment.getSharedLibraryFileName("rocksdb")).
isEqualTo("librocksdbjni.so"); isEqualTo("librocksdbjni.so");
// Linux musl-libc (Alpine)
setEnvironmentClassField(MUSL_LIBC_FIELD_NAME, true);
assertThat(Environment.isWindows()).isFalse();
assertThat(Environment.getJniLibraryExtension()).
isEqualTo(".so");
assertThat(Environment.getJniLibraryFileName("rocksdb")).
isEqualTo("librocksdbjni-linux32-musl.so");
assertThat(Environment.getSharedLibraryFileName("rocksdb")).
isEqualTo("librocksdbjni.so");
// UNIX // UNIX
setEnvironmentClassField(MUSL_LIBC_FIELD_NAME, false);
setEnvironmentClassFields("Unix", "32"); setEnvironmentClassFields("Unix", "32");
assertThat(Environment.isWindows()).isFalse(); assertThat(Environment.isWindows()).isFalse();
assertThat(Environment.getJniLibraryExtension()). assertThat(Environment.getJniLibraryExtension()).
@ -84,6 +98,7 @@ public class EnvironmentTest {
@Test @Test
public void nix64() { public void nix64() {
setEnvironmentClassField(MUSL_LIBC_FIELD_NAME, false);
setEnvironmentClassFields("Linux", "x64"); setEnvironmentClassFields("Linux", "x64");
assertThat(Environment.isWindows()).isFalse(); assertThat(Environment.isWindows()).isFalse();
assertThat(Environment.getJniLibraryExtension()). assertThat(Environment.getJniLibraryExtension()).
@ -92,7 +107,17 @@ public class EnvironmentTest {
isEqualTo("librocksdbjni-linux64.so"); isEqualTo("librocksdbjni-linux64.so");
assertThat(Environment.getSharedLibraryFileName("rocksdb")). assertThat(Environment.getSharedLibraryFileName("rocksdb")).
isEqualTo("librocksdbjni.so"); isEqualTo("librocksdbjni.so");
// Linux musl-libc (Alpine)
setEnvironmentClassField(MUSL_LIBC_FIELD_NAME, true);
assertThat(Environment.isWindows()).isFalse();
assertThat(Environment.getJniLibraryExtension()).
isEqualTo(".so");
assertThat(Environment.getJniLibraryFileName("rocksdb")).
isEqualTo("librocksdbjni-linux64-musl.so");
assertThat(Environment.getSharedLibraryFileName("rocksdb")).
isEqualTo("librocksdbjni.so");
// UNIX // UNIX
setEnvironmentClassField(MUSL_LIBC_FIELD_NAME, false);
setEnvironmentClassFields("Unix", "x64"); setEnvironmentClassFields("Unix", "x64");
assertThat(Environment.isWindows()).isFalse(); assertThat(Environment.isWindows()).isFalse();
assertThat(Environment.getJniLibraryExtension()). assertThat(Environment.getJniLibraryExtension()).
@ -130,8 +155,37 @@ public class EnvironmentTest {
isEqualTo("librocksdbjni.dll"); isEqualTo("librocksdbjni.dll");
} }
@Test
public void ppc64le() {
setEnvironmentClassField(MUSL_LIBC_FIELD_NAME, false);
setEnvironmentClassFields("Linux", "ppc64le");
assertThat(Environment.isUnix()).isTrue();
assertThat(Environment.isPowerPC()).isTrue();
assertThat(Environment.is64Bit()).isTrue();
assertThat(Environment.getJniLibraryExtension()).isEqualTo(".so");
assertThat(Environment.getSharedLibraryName("rocksdb")).isEqualTo("rocksdbjni");
assertThat(Environment.getJniLibraryName("rocksdb")).isEqualTo("rocksdbjni-linux-ppc64le");
assertThat(Environment.getJniLibraryFileName("rocksdb"))
.isEqualTo("librocksdbjni-linux-ppc64le.so");
assertThat(Environment.getSharedLibraryFileName("rocksdb")).isEqualTo("librocksdbjni.so");
// Linux musl-libc (Alpine)
setEnvironmentClassField(MUSL_LIBC_FIELD_NAME, true);
setEnvironmentClassFields("Linux", "ppc64le");
assertThat(Environment.isUnix()).isTrue();
assertThat(Environment.isPowerPC()).isTrue();
assertThat(Environment.is64Bit()).isTrue();
assertThat(Environment.getJniLibraryExtension()).isEqualTo(".so");
assertThat(Environment.getSharedLibraryName("rocksdb")).isEqualTo("rocksdbjni");
assertThat(Environment.getJniLibraryName("rocksdb")).isEqualTo("rocksdbjni-linux-ppc64le-musl");
assertThat(Environment.getJniLibraryFileName("rocksdb"))
.isEqualTo("librocksdbjni-linux-ppc64le-musl.so");
assertThat(Environment.getSharedLibraryFileName("rocksdb")).isEqualTo("librocksdbjni.so");
setEnvironmentClassField(MUSL_LIBC_FIELD_NAME, false);
}
@Test @Test
public void aarch64() { public void aarch64() {
setEnvironmentClassField(MUSL_LIBC_FIELD_NAME, false);
setEnvironmentClassFields("Linux", "aarch64"); setEnvironmentClassFields("Linux", "aarch64");
assertThat(Environment.isUnix()).isTrue(); assertThat(Environment.isUnix()).isTrue();
assertThat(Environment.isAarch64()).isTrue(); assertThat(Environment.isAarch64()).isTrue();
@ -142,6 +196,19 @@ public class EnvironmentTest {
assertThat(Environment.getJniLibraryFileName("rocksdb")) assertThat(Environment.getJniLibraryFileName("rocksdb"))
.isEqualTo("librocksdbjni-linux-aarch64.so"); .isEqualTo("librocksdbjni-linux-aarch64.so");
assertThat(Environment.getSharedLibraryFileName("rocksdb")).isEqualTo("librocksdbjni.so"); assertThat(Environment.getSharedLibraryFileName("rocksdb")).isEqualTo("librocksdbjni.so");
// Linux musl-libc (Alpine)
setEnvironmentClassField(MUSL_LIBC_FIELD_NAME, true);
setEnvironmentClassFields("Linux", "aarch64");
assertThat(Environment.isUnix()).isTrue();
assertThat(Environment.isAarch64()).isTrue();
assertThat(Environment.is64Bit()).isTrue();
assertThat(Environment.getJniLibraryExtension()).isEqualTo(".so");
assertThat(Environment.getSharedLibraryName("rocksdb")).isEqualTo("rocksdbjni");
assertThat(Environment.getJniLibraryName("rocksdb")).isEqualTo("rocksdbjni-linux-aarch64-musl");
assertThat(Environment.getJniLibraryFileName("rocksdb"))
.isEqualTo("librocksdbjni-linux-aarch64-musl.so");
assertThat(Environment.getSharedLibraryFileName("rocksdb")).isEqualTo("librocksdbjni.so");
setEnvironmentClassField(MUSL_LIBC_FIELD_NAME, false);
} }
private void setEnvironmentClassFields(String osName, private void setEnvironmentClassFields(String osName,
@ -154,9 +221,10 @@ public class EnvironmentTest {
public static void restoreState() { public static void restoreState() {
setEnvironmentClassField(OS_FIELD_NAME, INITIAL_OS); setEnvironmentClassField(OS_FIELD_NAME, INITIAL_OS);
setEnvironmentClassField(ARCH_FIELD_NAME, INITIAL_ARCH); setEnvironmentClassField(ARCH_FIELD_NAME, INITIAL_ARCH);
setEnvironmentClassField(MUSL_LIBC_FIELD_NAME, INITIAL_MUSL_LIBC);
} }
private static String getEnvironmentClassField(String fieldName) { private static <T> T getEnvironmentClassField(String fieldName) {
final Field field; final Field field;
try { try {
field = Environment.class.getDeclaredField(fieldName); field = Environment.class.getDeclaredField(fieldName);
@ -164,13 +232,13 @@ public class EnvironmentTest {
final Field modifiersField = Field.class.getDeclaredField("modifiers"); final Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true); modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
return (String)field.get(null); return (T)field.get(null);
} catch (NoSuchFieldException | IllegalAccessException e) { } catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
private static void setEnvironmentClassField(String fieldName, String value) { private static void setEnvironmentClassField(String fieldName, Object value) {
final Field field; final Field field;
try { try {
field = Environment.class.getDeclaredField(fieldName); field = Environment.class.getDeclaredField(fieldName);