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
137 changes: 137 additions & 0 deletions .github/workflows/jni-patched-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
name: Patched JNI CI

# This workflow attempts to build and test the wolfSSL JNI library with all
# available wolfSSL PR patches applied, eg WOLFSSL_PR*_PATCH_APPLIED defines.
# It currently only supports a single PR patch at a time, using the highest PR
# number found in the defines.

on:
push:
branches: [ 'master', 'main', 'release/**' ]
pull_request:
branches: [ 'master' ]

jobs:
resolve_wolfssl_ref:
runs-on: ubuntu-latest
outputs:
should_run: ${{ steps.resolve.outputs.should_run }}
wolfssl_repo: ${{ steps.resolve.outputs.wolfssl_repo }}
wolfssl_ref: ${{ steps.resolve.outputs.wolfssl_ref }}
pr_number: ${{ steps.resolve.outputs.pr_number }}
steps:
- uses: actions/checkout@v4

- name: Resolve wolfSSL ref from patch defines
id: resolve
run: |
set -euo pipefail

# Find WOLFSSL_PR*_PATCH_APPLIED defines in wolfssl source.
defines="$(./scripts/find-wolfssl-pr-patch-defines.sh)"
if [ -z "$defines" ]; then
echo "::warning::No WOLFSSL_PR*_PATCH_APPLIED defines found; skipping patched CI."
echo "should_run=false" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "Found patch defines:"
printf "%s\n" "$defines"

# Find the highest PR number from the defines.
pr_number="$(printf "%s\n" "$defines" | sed -E 's/^WOLFSSL_PR([0-9]+)_PATCH_APPLIED$/\1/' | sort -n | tail -1)"
if [ -z "$pr_number" ]; then
echo "::warning::Failed to derive PR number from patch defines; skipping patched CI."
echo "should_run=false" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "Highest PR number from defines: $pr_number"

# Check PR status via GitHub API.
pr_json="$(curl -fsSL "https://api.github.com/repos/wolfSSL/wolfssl/pulls/$pr_number" || true)"
if [ -z "$pr_json" ]; then
echo "::warning::Unable to fetch PR #$pr_number from GitHub API; skipping patched CI."
echo "should_run=false" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "Fetched PR #$pr_number info from GitHub API."

state="$(printf "%s" "$pr_json" | jq -r '.state // empty')"
merged_at="$(printf "%s" "$pr_json" | jq -r '.merged_at // empty')"
head_repo="$(printf "%s" "$pr_json" | jq -r '.head.repo.full_name // empty')"
head_ref="$(printf "%s" "$pr_json" | jq -r '.head.ref // empty')"

if [ -n "$merged_at" ]; then
echo "PR #$pr_number is merged; using wolfSSL master branch."
echo "should_run=true" >> "$GITHUB_OUTPUT"
echo "wolfssl_repo=wolfSSL/wolfssl" >> "$GITHUB_OUTPUT"
echo "wolfssl_ref=master" >> "$GITHUB_OUTPUT"
echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT"
exit 0
fi

if [ "$state" = "open" ] && [ -n "$head_repo" ] && [ -n "$head_ref" ]; then
echo "should_run=true" >> "$GITHUB_OUTPUT"
echo "wolfssl_repo=$head_repo" >> "$GITHUB_OUTPUT"
echo "wolfssl_ref=$head_ref" >> "$GITHUB_OUTPUT"
echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT"
echo "PR #$pr_number is open; using branch $head_ref from repo $head_repo."
exit 0
fi

echo "::warning::PR #$pr_number is not merged or has no accessible branch; skipping patched CI."
echo "should_run=false" >> "$GITHUB_OUTPUT"

patched_jni_build:
needs: resolve_wolfssl_ref
if: needs.resolve_wolfssl_ref.outputs.should_run == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Cache JUnit dependencies
uses: actions/cache@v4
id: cache-junit
with:
path: junit
key: junit-jars-v1

- name: Download junit-4.13.2.jar
if: steps.cache-junit.outputs.cache-hit != 'true'
run: curl -fsSL -o "$GITHUB_WORKSPACE/junit/junit-4.13.2.jar" https://repo1.maven.org/maven2/junit/junit/4.13.2/junit-4.13.2.jar
- name: Download hamcrest-all-1.3.jar
if: steps.cache-junit.outputs.cache-hit != 'true'
run: curl -fsSL -o "$GITHUB_WORKSPACE/junit/hamcrest-all-1.3.jar" https://repo1.maven.org/maven2/org/hamcrest/hamcrest-all/1.3/hamcrest-all-1.3.jar

- name: Build native wolfSSL
uses: wolfSSL/actions-build-autotools-project@v1
with:
repository: ${{ needs.resolve_wolfssl_ref.outputs.wolfssl_repo }}
ref: ${{ needs.resolve_wolfssl_ref.outputs.wolfssl_ref }}
path: wolfssl
configure: --enable-jni
check: false
install: true

- name: Setup java
uses: actions/setup-java@v4
with:
distribution: zulu
java-version: '21'

- name: Set JUNIT_HOME
run: |
echo "JUNIT_HOME=$GITHUB_WORKSPACE/junit" >> "$GITHUB_ENV"

- name: Set LD_LIBRARY_PATH
run: |
echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$GITHUB_WORKSPACE/build-dir/lib" >> "$GITHUB_ENV"

- name: Build and test JNI library with all patches
run: |
make all-patched PREFIX=$GITHUB_WORKSPACE/build-dir
make check

- name: Show logs on failure
if: failure() || cancelled()
run: |
cat build/reports/*.txt
24 changes: 23 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,32 @@ endif

all: build

build:
build: java.sh build.xml
./java.sh $(INSTALL_DIR)
ant

check: build
ant test

clean:
ant clean cleanjni

# Enable all WOLFSSL_PR*_PATCH_APPLIED defines when building JNI.
# Requires latest/recent wolfssl source with patches applied. This is not
# detected automatically.
all-patched:
@defines="$$(./scripts/find-wolfssl-pr-patch-defines.sh)"; \
if [ -z "$$defines" ]; then \
echo "warning: no WOLFSSL_PR*_PATCH_APPLIED defines found; skipping all-patched"; \
exit 0; \
fi; \
cflags=""; \
for define in $$defines; do \
cflags="$$cflags -D$$define"; \
done; \
CFLAGS="$$cflags" ./java.sh $(INSTALL_DIR); \
ant

install:
$(INSTALL) -d $(INSTALL_DIR)/$(LIBDIR)
$(INSTALL) lib/libwolfssljni.so $(INSTALL_DIR)/$(LIBDIR)
Expand Down
22 changes: 13 additions & 9 deletions java.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,31 +29,34 @@
#
# java.sh /usr/local wolfssljsse

# Fail on any errors
set -euo pipefail

OS=`uname`
ARCH=`uname -m`

if [ -z "$1" ]; then
if [ -z "${1-}" ]; then
# default install location is /usr/local
WOLFSSL_INSTALL_DIR="/usr/local"
else
# use custom wolfSSL install location
# should match directory set at wolfSSL ./configure --prefix=<DIR>
WOLFSSL_INSTALL_DIR=$1
WOLFSSL_INSTALL_DIR="$1"
fi

if [ -z "$2" ]; then
if [ -z "${2-}" ]; then
# default wolfSSL library name is libwolfssl
WOLFSSL_LIBNAME="wolfssl"
else
# use custom wolfSSL library name
# should match wolfsslSUFFIX as set using ./configure --with-libsuffix
WOLFSSL_LIBNAME=$2
WOLFSSL_LIBNAME="$2"
fi

echo "Compiling Native JNI library:"
echo " WOLFSSL_INSTALL_DIR = $WOLFSSL_INSTALL_DIR"

if [ -z "$JAVA_HOME" ]; then
if [ -z "${JAVA_HOME:-}" ]; then
# if JAVA_HOME not set, detect based on platform/OS
echo " JAVA_HOME empty, trying to detect"
else
Expand All @@ -62,11 +65,14 @@ else
javaHome="$JAVA_HOME"
fi

fpic=""
CFLAGS="${CFLAGS:-}"

# set up Java include and library paths for OS X and Linux
# NOTE: you may need to modify these if your platform uses different locations
if [ "$OS" == "Darwin" ] ; then
echo " Detected Darwin/OSX host OS"
if [ -z $javaHome ]; then
if [ -z "${javaHome:-}" ]; then
# this is broken since Big Sur, set JAVA_HOME environment var instead
# OSX JAVA_HOME is typically similar to:
# /Library/Java/JavaVirtualMachines/jdk1.8.0_261.jdk/Contents/Home
Expand All @@ -77,7 +83,7 @@ if [ "$OS" == "Darwin" ] ; then
jniLibName="libwolfssljni.dylib"
elif [ "$OS" == "Linux" ] ; then
echo " Detected Linux host OS"
if [ -z $javaHome ]; then
if [ -z "${javaHome:-}" ]; then
javaHome=`echo $(dirname $(dirname $(readlink -f $(which java))))`
fi
if [ ! -d "$javaHome/include" ]
Expand All @@ -89,8 +95,6 @@ elif [ "$OS" == "Linux" ] ; then
jniLibName="libwolfssljni.so"
if [ "$ARCH" == "x86_64" ] || [ "$ARCH" == "aarch64" ]; then
fpic="-fPIC"
else
fpic=""
fi
else
echo 'Unknown host OS!'
Expand Down
18 changes: 18 additions & 0 deletions scripts/find-wolfssl-pr-patch-defines.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env bash

# This script searches the wolfssl repository for any defined
# WOLFSSL_PR*_PATCH_APPLIED macros and lists them in sorted order.

set -euo pipefail

repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"

matches="$(grep -R -h -o -E 'WOLFSSL_PR[0-9]+_PATCH_APPLIED' \
--exclude-dir=.git \
--exclude-dir=build \
"$repo_root" || true)"
if [ -z "$matches" ]; then
exit 0
fi

printf "%s\n" "$matches" | sort -u
Loading