Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
204 changes: 204 additions & 0 deletions .github/workflows/native-builds.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
name: Native build matrix

on:
pull_request:
branches: [ main ]
workflow_call:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: native-builds-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
native:
name: ${{ matrix.classifier }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- classifier: linux-glibc-x86_64
family: linux
runner: ubuntu-22.04
task: compileNativeForLinuxGlibcX8664
directory: linux-glibc-x86_64
library: libdatachannel-java.so
platform: amd64
libc: glibc
- classifier: linux-glibc-aarch64
family: linux
runner: ubuntu-22.04-arm
task: compileNativeForLinuxGlibcAarch64
directory: linux-glibc-aarch64
library: libdatachannel-java.so
platform: arm64
libc: glibc
- classifier: linux-musl-x86_64
family: linux
runner: ubuntu-latest
task: compileNativeForLinuxMuslX8664
directory: linux-musl-x86_64
library: libdatachannel-java.so
platform: amd64
libc: musl
runtime: alpine:3.22
- classifier: linux-musl-aarch64
family: linux
runner: ubuntu-24.04-arm
task: compileNativeForLinuxMuslAarch64
directory: linux-musl-aarch64
library: libdatachannel-java.so
platform: arm64
libc: musl
runtime: alpine:3.22
- classifier: windows-x86_64
family: windows
runner: windows-2022
msystem: MINGW64
package-prefix: mingw-w64-x86_64
compiler: gcc
task: compileNativeForWindowsX8664
directory: windows-x86_64
library: libdatachannel-java.dll
- classifier: windows-aarch64
family: windows
runner: windows-11-arm
msystem: CLANGARM64
package-prefix: mingw-w64-clang-aarch64
compiler: clang
task: compileNativeForWindowsAarch64
directory: windows-aarch64
library: libdatachannel-java.dll
- classifier: macos-arm64
family: macos
runner: macos-26
task: compileNativeForHost
directory: host
library: libdatachannel-java.dylib
- classifier: macos-x86_64
family: macos
runner: macos-15-intel
task: compileNativeForHost
directory: host
library: libdatachannel-java.dylib
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- uses: actions/setup-java@v5
with:
java-version: '17'
distribution: ${{ matrix.classifier == 'windows-aarch64' && 'microsoft' || 'temurin' }}
- uses: gradle/actions/setup-gradle@v5
- name: Install glibc build dependencies
if: matrix.libc == 'glibc'
run: |
sudo apt-get update
sudo apt-get install -y gcc-12 g++-12 libssl-dev
echo "CC=gcc-12" >> "$GITHUB_ENV"
echo "CXX=g++-12" >> "$GITHUB_ENV"
- uses: msys2/setup-msys2@v2
if: matrix.family == 'windows'
with:
msystem: ${{ matrix.msystem }}
path-type: inherit
update: true
install: >-
${{ matrix.package-prefix }}-${{ matrix.compiler }}
${{ matrix.package-prefix }}-cmake
${{ matrix.package-prefix }}-ninja
${{ matrix.package-prefix }}-openssl
${{ matrix.package-prefix }}-winpthreads
- name: Install macOS build dependencies
if: matrix.family == 'macos'
env:
HOMEBREW_NO_AUTO_UPDATE: '1'
HOMEBREW_NO_INSTALL_CLEANUP: '1'
run: |
brew uninstall --ignore-dependencies cmake || true
brew install cmake
pipx install conan || brew install conan
cmake --version
conan --version
- name: Build release native
if: matrix.family != 'windows'
env:
CLASSIFIER: ${{ matrix.classifier }}
TASK: ${{ matrix.task }}
run: |
./gradlew "$TASK" --max-workers=2 --no-configuration-cache \
-Plibdatachannel.targets="$CLASSIFIER" \
-Plibdatachannel.build-release-binaries=true
- name: Build Windows native
if: matrix.family == 'windows'
shell: msys2 {0}
env:
CLASSIFIER: ${{ matrix.classifier }}
TASK: ${{ matrix.task }}
run: |
export JAVA_HOME="$(cygpath -u "$JAVA_HOME")"
export MSYS2_BASH="$(cygpath -w /usr/bin/bash)"
./gradlew "$TASK" --max-workers=2 --no-configuration-cache \
-Plibdatachannel.targets="$CLASSIFIER" \
-Plibdatachannel.build-release-binaries=true
- name: Package bundle for runtime checks
shell: bash
env:
CLASSIFIER: ${{ matrix.classifier }}
NATIVE: build/dockcross/${{ matrix.directory }}/native/${{ matrix.library }}
run: |
if command -v cygpath >/dev/null; then
export JAVA_HOME="$(cygpath -u "$JAVA_HOME")"
fi
./gradlew prepareNativeSmoke --max-workers=2 --no-configuration-cache \
-Plibdatachannel.targets="$CLASSIFIER" \
"-Plibdatachannel.$CLASSIFIER.prebuilt-path=$NATIVE"
- name: Load Windows bundle without toolchain DLLs on PATH
if: matrix.family == 'windows'
shell: pwsh
env:
CLASSIFIER: ${{ matrix.classifier }}
run: |
$env:PATH = "$env:JAVA_HOME\bin;$env:SystemRoot\System32;$env:SystemRoot"
foreach ($mode in @("lazy", "eager")) {
& "$env:JAVA_HOME\bin\java.exe" -Xcheck:jni -cp "build/native-smoke/*;build/native-smoke/classes" `
tel.schich.libdatachannel.NativeLibrarySmoke $env:CLASSIFIER $mode
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
}
- name: Load bundle in the host JVM
if: matrix.family == 'macos' || matrix.libc == 'glibc'
env:
CLASSIFIER: ${{ matrix.classifier }}
run: |
for mode in lazy eager; do
java -Xcheck:jni -cp "build/native-smoke/*:build/native-smoke/classes" \
tel.schich.libdatachannel.NativeLibrarySmoke "$CLASSIFIER" "$mode"
done
- name: Load musl bundle in an Alpine JVM
if: matrix.libc == 'musl'
env:
CLASSIFIER: ${{ matrix.classifier }}
PLATFORM: linux/${{ matrix.platform }}
RUNTIME: ${{ matrix.runtime }}
run: |
docker run --rm --platform "$PLATFORM" -v "$PWD:/work:ro" -w /work \
-e CLASSIFIER "$RUNTIME" sh -ec '
apk add --no-cache openjdk17-jre-headless libstdc++ libssl3
for mode in lazy eager; do
java -Xcheck:jni -cp "build/native-smoke/*:build/native-smoke/classes" \
tel.schich.libdatachannel.NativeLibrarySmoke "$CLASSIFIER" "$mode"
done
'
- uses: actions/upload-artifact@v6
with:
name: libdatachannel-${{ matrix.classifier }}
path: build/dockcross/${{ matrix.directory }}/native/${{ matrix.library }}
retention-days: 30
if-no-files-found: error
113 changes: 9 additions & 104 deletions .github/workflows/publish-opencollab.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,113 +13,16 @@ permissions:
contents: read

env:
# linux and windows are cross compiled on the publishing job, macOS is built on its own runners
TARGETS: linux-x86_64,linux-aarch64,windows-x86_64,windows-aarch64,macos-arm64,macos-x86_64
# Linux builds and JVM smoke tests cover both libc implementations.
TARGETS: linux-glibc-x86_64,linux-glibc-aarch64,linux-musl-x86_64,linux-musl-aarch64,windows-x86_64,windows-aarch64,macos-arm64,macos-x86_64

jobs:
build-macos:
name: Build macOS Native Libraries
strategy:
matrix:
include:
- os: macos-26 # Apple Silicon runner
classifier: macos-arm64
- os: macos-15-intel # Intel runner
classifier: macos-x86_64
runs-on: ${{ matrix.os }}
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-tags: 'true'
fetch-depth: '0'
submodules: recursive

- name: Set up JDK 17
uses: actions/setup-java@v5
with:
java-version: '17'
distribution: 'temurin'
cache: gradle

- name: Install dependencies
env:
HOMEBREW_NO_AUTO_UPDATE: '1'
HOMEBREW_NO_INSTALL_CLEANUP: '1'
run: |
brew uninstall --ignore-dependencies cmake || true
brew install cmake
pipx install conan || brew install conan
cmake --version
conan --version

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v5

- name: Build native library for host
run: ./gradlew compileNativeForHost -Plibdatachannel.build-release-binaries=true

- name: Upload artifacts
uses: actions/upload-artifact@v6
with:
name: libdatachannel-${{ matrix.classifier }}
path: |
build/dockcross/host/native/libdatachannel-java.dylib
retention-days: 30
if-no-files-found: error

build-cross:
name: Cross Compile Native Libraries
strategy:
matrix:
include:
- classifier: linux-x86_64
task: compileNativeForLinuxX8664
library: libdatachannel-java.so
- classifier: linux-aarch64
task: compileNativeForLinuxAarch64
library: libdatachannel-java.so
- classifier: windows-x86_64
task: compileNativeForWindowsX8664
library: libdatachannel-java.dll
- classifier: windows-aarch64
task: compileNativeForWindowsAarch64
library: libdatachannel-java.dll
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-tags: 'true'
fetch-depth: '0'
submodules: recursive

- name: Set up JDK 17
uses: actions/setup-java@v5
with:
java-version: '17'
distribution: 'temurin'
cache: gradle

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v5

- name: Build native library
run: |
./gradlew ${{ matrix.task }} \
-Plibdatachannel.build-release-binaries=true \
-Plibdatachannel.targets=${{ matrix.classifier }}

- name: Upload artifacts
uses: actions/upload-artifact@v6
with:
name: libdatachannel-${{ matrix.classifier }}
path: build/dockcross/${{ matrix.classifier }}/native/${{ matrix.library }}
retention-days: 30
if-no-files-found: error
build-natives:
uses: ./.github/workflows/native-builds.yml

publish:
name: Publish to OpenCollab
needs: [ build-macos, build-cross ]
needs: [ build-natives ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
Expand Down Expand Up @@ -148,8 +51,10 @@ jobs:
run: |
./gradlew --no-configuration-cache openCollabDeploy \
-Plibdatachannel.targets="$TARGETS" \
-Plibdatachannel.linux-x86_64.prebuilt-path=artifacts/libdatachannel-linux-x86_64/libdatachannel-java.so \
-Plibdatachannel.linux-aarch64.prebuilt-path=artifacts/libdatachannel-linux-aarch64/libdatachannel-java.so \
-Plibdatachannel.linux-glibc-x86_64.prebuilt-path=artifacts/libdatachannel-linux-glibc-x86_64/libdatachannel-java.so \
-Plibdatachannel.linux-glibc-aarch64.prebuilt-path=artifacts/libdatachannel-linux-glibc-aarch64/libdatachannel-java.so \
-Plibdatachannel.linux-musl-x86_64.prebuilt-path=artifacts/libdatachannel-linux-musl-x86_64/libdatachannel-java.so \
-Plibdatachannel.linux-musl-aarch64.prebuilt-path=artifacts/libdatachannel-linux-musl-aarch64/libdatachannel-java.so \
-Plibdatachannel.windows-x86_64.prebuilt-path=artifacts/libdatachannel-windows-x86_64/libdatachannel-java.dll \
-Plibdatachannel.windows-aarch64.prebuilt-path=artifacts/libdatachannel-windows-aarch64/libdatachannel-java.dll \
-Plibdatachannel.macos-arm64.prebuilt-path=artifacts/libdatachannel-macos-arm64/libdatachannel-java.dylib \
Expand Down
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,37 @@ implementation("dev.opencollab:libdatachannel-java:0.24.1.1")
Additionally, pull the architecture-specific native components using their the architecture-specific classifier.

Alternatively, use the `libdatachannel-java-arch-detect` module, which includes common architectures and has
code to detect which one to apply.
code to detect which one to apply, including the libc loaded by a Linux JVM.

Linux classifiers are `linux-glibc-x86_64`, `linux-glibc-aarch64`,
`linux-musl-x86_64`, and `linux-musl-aarch64`. Alpine uses the musl variants.
These replace the ambiguous `linux-x86_64` and `linux-aarch64` classifiers;
update explicit classifier dependencies when upgrading. Other platforms keep
`windows-x86_64`, `windows-aarch64`, `macos-x86_64`, and `macos-arm64`.

Linux requires OpenSSL 3 and the target distribution's C++ runtime (on Alpine,
`apk add libssl3 libstdc++`). Installing `gcompat` is unnecessary. The bundle
selects libc from `/proc/self/maps`; if procfs is unavailable, explicitly set
`-Dlibdatachannel.libc=glibc` or `-Dlibdatachannel.libc=musl` to match the JVM.

Build one Linux native with, for example:

```sh
./gradlew compileNativeForLinuxMuslAarch64 \
-Plibdatachannel.targets=linux-musl-aarch64 \
-Plibdatachannel.build-release-binaries=true
```

The CI matrix builds all eight Linux, Windows, and macOS targets concurrently
on matching x86_64 or ARM64 runners. Only musl uses a container (Alpine 3.22);
glibc builds use GCC 12 and OpenSSL from Ubuntu 22.04, Windows builds use native
MSYS2 MINGW64/CLANGARM64 with static OpenSSL, and macOS builds use the host
toolchain. Install the corresponding build dependencies for local builds.

Every job checks lazy and eager loading of the packaged bundle in a matching
JVM. Windows checks exclude toolchain DLLs from PATH. Publishing waits for every
matrix job to pass. Docker is required only for the musl targets; local builds
of those targets need a matching host architecture or Docker/QEMU emulation.

### Offerer example

Expand Down
Loading
Loading