From 04d611a825bf3bd88c8fe57787dfbd4144cbbc48 Mon Sep 17 00:00:00 2001 From: Paul Adelsbach Date: Mon, 2 Feb 2026 09:11:37 -0800 Subject: [PATCH] Add make target to enable all patches, and corresponding CI workflow --- .github/workflows/jni-patched-ci.yml | 137 +++++++++++++++++++++++ Makefile | 24 +++- java.sh | 22 ++-- scripts/find-wolfssl-pr-patch-defines.sh | 18 +++ 4 files changed, 191 insertions(+), 10 deletions(-) create mode 100644 .github/workflows/jni-patched-ci.yml create mode 100755 scripts/find-wolfssl-pr-patch-defines.sh diff --git a/.github/workflows/jni-patched-ci.yml b/.github/workflows/jni-patched-ci.yml new file mode 100644 index 00000000..e3db340a --- /dev/null +++ b/.github/workflows/jni-patched-ci.yml @@ -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 diff --git a/Makefile b/Makefile index 022dded3..c233ec70 100644 --- a/Makefile +++ b/Makefile @@ -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) diff --git a/java.sh b/java.sh index 7ae60bbe..797089c7 100755 --- a/java.sh +++ b/java.sh @@ -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= - 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 @@ -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 @@ -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" ] @@ -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!' diff --git a/scripts/find-wolfssl-pr-patch-defines.sh b/scripts/find-wolfssl-pr-patch-defines.sh new file mode 100755 index 00000000..b3ef1af6 --- /dev/null +++ b/scripts/find-wolfssl-pr-patch-defines.sh @@ -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