diff --git a/native/README.md b/native/README.md index 327edfdc7..81e4e3b6c 100644 --- a/native/README.md +++ b/native/README.md @@ -18,13 +18,11 @@ CommonCrypto library. - macOS aarch64 ("Apple Silicon") For Linux platforms, we provide two versions of the native library: one built against OpenSSL 1.1.x and one built against OpenSSL 3.x.x. -All native libraries are built on various versions of Ubuntu: +All native libraries are built on various versions of Ubuntu and Alpine: - Ubuntu 20.04 for OpenSSL 1.1.x support and for compression - Ubuntu 22.04 for OpenSSL 3.x.x support - -Currently, we do not provide native libraries for distributions based on musl libc, like Alpine Linux. You might be able to use `apk add libc6-compat` to fake it, but this is not officially supported. -In the future we may provide a musl libc build. +- Alpine 3.18 for OpenSSL 3.x.x support and compression (musl libc users only) ## Building diff --git a/native/build-support/alpine.Dockerfile b/native/build-support/alpine.Dockerfile new file mode 100644 index 000000000..c67cd822d --- /dev/null +++ b/native/build-support/alpine.Dockerfile @@ -0,0 +1,9 @@ + +FROM amazoncorretto:17.0.12-alpine3.18 + +# Install required dependencies +RUN apk add --no-cache bash alpine-sdk cmake openssl-dev openssl + +# Create a non-root user +RUN adduser -D user +USER user \ No newline at end of file diff --git a/native/build-support/build-all-linux-natives.sh b/native/build-support/build-all-linux-natives.sh index 32397f591..0e182da69 100755 --- a/native/build-support/build-all-linux-natives.sh +++ b/native/build-support/build-all-linux-natives.sh @@ -6,7 +6,8 @@ set -e cd "$(dirname "$0")/.." || exit 1 ARCHS=(x86_64 aarch64) -BASE_DOCKERFILE_VARIANTS=(ubuntu-focal ubuntu-jammy) +BASE_DOCKERFILE_VARIANTS=(ubuntu-focal ubuntu-jammy alpine) +COMPRESSION_VARIANTS=(ubuntu-focal alpine) for variant in "${BASE_DOCKERFILE_VARIANTS[@]}"; do docker_platforms="" @@ -25,8 +26,8 @@ for arch in "${ARCHS[@]}"; do docker run --rm -v "$(pwd)":/app --platform linux/${arch} velocity-native-build:$variant /bin/bash -c "cd /app && ./build-support/compile-linux-crypto.sh" done - # Use only the oldest variant for the compression library - variant=${BASE_DOCKERFILE_VARIANTS[0]} - echo "Building native compression for $arch on $variant..." - docker run --rm -v "$(pwd)":/app --platform linux/${arch} velocity-native-build:$variant /bin/bash -c "cd /app && ./build-support/compile-linux-compress.sh" + for variant in "${COMPRESSION_VARIANTS[@]}"; do + echo "Building native compression for $arch on $variant..." + docker run --rm -v "$(pwd)":/app --platform linux/${arch} velocity-native-build:$variant /bin/bash -c "cd /app && ./build-support/compile-linux-compress.sh" + done done \ No newline at end of file diff --git a/native/build-support/compile-linux-compress.sh b/native/build-support/compile-linux-compress.sh index b03ca37cf..2222c4a31 100755 --- a/native/build-support/compile-linux-compress.sh +++ b/native/build-support/compile-linux-compress.sh @@ -16,8 +16,14 @@ cd libdeflate || exit rm -rf build && cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -B build && cmake --build build --target libdeflate_static cd .. +# Determine if we are on musl libc or glibc +suffix="" +if ldd --version 2>&1 | grep -q musl; then + suffix="-musl" +fi + CFLAGS="-O2 -I$JAVA_HOME/include/ -I$JAVA_HOME/include/linux/ -fPIC -shared -Wl,-z,noexecstack -Wall -Werror -fomit-frame-pointer" ARCH=$(uname -m) mkdir -p src/main/resources/linux_$ARCH $CC $CFLAGS -Ilibdeflate src/main/c/jni_util.c src/main/c/jni_zlib_deflate.c src/main/c/jni_zlib_inflate.c \ - libdeflate/build/libdeflate.a -o src/main/resources/linux_$ARCH/velocity-compress.so \ No newline at end of file + libdeflate/build/libdeflate.a -o src/main/resources/linux_$ARCH/velocity-compress$suffix.so \ No newline at end of file diff --git a/native/build-support/compile-linux-crypto.sh b/native/build-support/compile-linux-crypto.sh index 221656647..d29a96918 100755 --- a/native/build-support/compile-linux-crypto.sh +++ b/native/build-support/compile-linux-crypto.sh @@ -20,9 +20,11 @@ if [ ! "$CC" ]; then export CC=gcc fi -output_file="velocity-cipher.so" -if [ -n "$OPENSSL_VERSION" ]; then - output_file="velocity-cipher-ossl${OPENSSL_VERSION}.so" +# Determine if we are on musl libc or glibc +suffix="" +if ldd --version 2>&1 | grep -q musl; then + suffix="-musl" + filename=$(echo "$filename" | sed "s/\.so/$suffix.so/") fi CFLAGS="-O2 -I$JAVA_HOME/include/ -I$JAVA_HOME/include/linux/ -fPIC -shared -Wl,-z,noexecstack -Wall -Werror -fomit-frame-pointer" diff --git a/native/src/main/java/com/velocitypowered/natives/util/NativeConstraints.java b/native/src/main/java/com/velocitypowered/natives/util/NativeConstraints.java index 04e5faff0..852a1f062 100644 --- a/native/src/main/java/com/velocitypowered/natives/util/NativeConstraints.java +++ b/native/src/main/java/com/velocitypowered/natives/util/NativeConstraints.java @@ -19,6 +19,7 @@ package com.velocitypowered.natives.util; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import java.nio.charset.StandardCharsets; import java.util.function.BooleanSupplier; /** @@ -29,6 +30,8 @@ public class NativeConstraints { private static final boolean IS_AMD64; private static final boolean IS_AARCH64; private static final boolean CAN_GET_MEMORYADDRESS; + private static final boolean IS_LINUX; + private static final boolean IS_MUSL_LIBC; static { ByteBuf test = Unpooled.directBuffer(); @@ -41,17 +44,44 @@ public class NativeConstraints { String osArch = System.getProperty("os.arch", ""); IS_AMD64 = osArch.equals("amd64") || osArch.equals("x86_64"); IS_AARCH64 = osArch.equals("aarch64") || osArch.equals("arm64"); + + IS_LINUX = System.getProperty("os.name", "").equalsIgnoreCase("Linux"); + + // Determine if we're using musl libc by invoking `ldd --version`. + if (IS_LINUX) { + boolean isMusl; + try { + Process process = new ProcessBuilder("ldd", "--version") + .redirectErrorStream(true) + .start(); + process.waitFor(); + try (var reader = process.getInputStream()) { + byte[] outputRaw = reader.readAllBytes(); + String output = new String(outputRaw, StandardCharsets.UTF_8); + isMusl = output.contains("musl"); + } + } catch (Exception e) { + isMusl = false; + } + IS_MUSL_LIBC = isMusl; + } else { + IS_MUSL_LIBC = false; + } } static final BooleanSupplier NATIVE_BASE = () -> NATIVES_ENABLED && CAN_GET_MEMORYADDRESS; static final BooleanSupplier LINUX_X86_64 = () -> NATIVE_BASE.getAsBoolean() - && System.getProperty("os.name", "").equalsIgnoreCase("Linux") - && IS_AMD64; + && IS_LINUX && IS_AMD64 && !IS_MUSL_LIBC; + + static final BooleanSupplier LINUX_X86_64_MUSL = () -> NATIVE_BASE.getAsBoolean() + && IS_LINUX && IS_AMD64 && IS_MUSL_LIBC; static final BooleanSupplier LINUX_AARCH64 = () -> NATIVE_BASE.getAsBoolean() - && System.getProperty("os.name", "").equalsIgnoreCase("Linux") - && IS_AARCH64; + && IS_LINUX && IS_AARCH64 && !IS_MUSL_LIBC; + + static final BooleanSupplier LINUX_AARCH64_MUSL = () -> NATIVE_BASE.getAsBoolean() + && IS_LINUX && IS_AARCH64 && IS_MUSL_LIBC; static final BooleanSupplier MACOS_AARCH64 = () -> NATIVE_BASE.getAsBoolean() && System.getProperty("os.name", "").equalsIgnoreCase("Mac OS X") diff --git a/native/src/main/java/com/velocitypowered/natives/util/Natives.java b/native/src/main/java/com/velocitypowered/natives/util/Natives.java index 1c1e26cea..8c99fe51a 100644 --- a/native/src/main/java/com/velocitypowered/natives/util/Natives.java +++ b/native/src/main/java/com/velocitypowered/natives/util/Natives.java @@ -83,11 +83,21 @@ public class Natives { new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_X86_64, copyAndLoadNative("/linux_x86_64/velocity-compress.so"), "libdeflate (Linux x86_64)", - LibdeflateVelocityCompressor.FACTORY), // compiled with Debian 10 + LibdeflateVelocityCompressor.FACTORY), // compiled with Ubuntu 20.04 + new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_X86_64_MUSL, + copyAndLoadNative("/linux_x86_64/velocity-compress-musl.so"), + "libdeflate (Linux x86_64, musl)", + LibdeflateVelocityCompressor.FACTORY), // compiled with Alpine 3.18 + new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_AARCH64, copyAndLoadNative("/linux_aarch64/velocity-compress.so"), "libdeflate (Linux aarch64)", - LibdeflateVelocityCompressor.FACTORY), // compiled with Fedora 36 + LibdeflateVelocityCompressor.FACTORY), // compiled with Ubuntu 20.04 + new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_AARCH64_MUSL, + copyAndLoadNative("/linux_aarch64/velocity-compress-musl.so"), + "libdeflate (Linux aarch64, musl)", + LibdeflateVelocityCompressor.FACTORY), // compiled with Alpine 3.18 + new NativeCodeLoader.Variant<>(NativeConstraints.MACOS_AARCH64, copyAndLoadNative("/macos_arm64/velocity-compress.dylib"), "libdeflate (macOS ARM64 / Apple Silicon)", @@ -108,6 +118,9 @@ public class Natives { new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_X86_64, copyAndLoadNative("/linux_x86_64/velocity-cipher-ossl11x.so"), // Ubuntu 20.04 "OpenSSL 1.1.x (Linux x86_64)", NativeVelocityCipher.FACTORY), + new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_X86_64_MUSL, + copyAndLoadNative("/linux_x86_64/velocity-cipher-ossl30x-musl.so"), // Alpine 3.18 + "OpenSSL 3.x.x (Linux x86_64, musl)", NativeVelocityCipher.FACTORY), new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_AARCH64, copyAndLoadNative("/linux_aarch64/velocity-cipher.so"), @@ -118,6 +131,9 @@ public class Natives { new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_AARCH64, copyAndLoadNative("/linux_aarch64/velocity-cipher-ossl11x.so"), "OpenSSL 1.1.x (Linux aarch64)", NativeVelocityCipher.FACTORY), // Ubuntu 20.04 + new NativeCodeLoader.Variant<>(NativeConstraints.LINUX_AARCH64_MUSL, + copyAndLoadNative("/linux_aarch64/velocity-cipher-ossl30x-musl.so"), + "OpenSSL 1.1.x (Linux aarch64, musl)", NativeVelocityCipher.FACTORY), // Alpine 3.18 new NativeCodeLoader.Variant<>(NativeConstraints.MACOS_AARCH64, copyAndLoadNative("/macos_arm64/velocity-cipher.dylib"), diff --git a/native/src/main/resources/linux_aarch64/velocity-cipher-ossl30x-musl.so b/native/src/main/resources/linux_aarch64/velocity-cipher-ossl30x-musl.so new file mode 100755 index 000000000..1c6b876a6 Binary files /dev/null and b/native/src/main/resources/linux_aarch64/velocity-cipher-ossl30x-musl.so differ diff --git a/native/src/main/resources/linux_aarch64/velocity-compress-musl.so b/native/src/main/resources/linux_aarch64/velocity-compress-musl.so new file mode 100755 index 000000000..28137308c Binary files /dev/null and b/native/src/main/resources/linux_aarch64/velocity-compress-musl.so differ diff --git a/native/src/main/resources/linux_x86_64/velocity-cipher-ossl30x-musl.so b/native/src/main/resources/linux_x86_64/velocity-cipher-ossl30x-musl.so new file mode 100755 index 000000000..56f2fe3c7 Binary files /dev/null and b/native/src/main/resources/linux_x86_64/velocity-cipher-ossl30x-musl.so differ diff --git a/native/src/main/resources/linux_x86_64/velocity-compress-musl.so b/native/src/main/resources/linux_x86_64/velocity-compress-musl.so new file mode 100755 index 000000000..57a25fea8 Binary files /dev/null and b/native/src/main/resources/linux_x86_64/velocity-compress-musl.so differ