From a72f84b70d8e4fc17b751ec1add2dbf1c9d6969e Mon Sep 17 00:00:00 2001 From: oh-dan Date: Wed, 10 Sep 2025 08:45:09 +1200 Subject: [PATCH 1/5] update tooling --- .mvn/wrapper/maven-wrapper.jar | Bin 47774 -> 0 bytes .mvn/wrapper/maven-wrapper.properties | 20 +- .sdkmanrc | 4 + mvnw | 422 ++++++++++++-------------- mvnw.cmd | 310 +++++++++---------- 5 files changed, 370 insertions(+), 386 deletions(-) delete mode 100644 .mvn/wrapper/maven-wrapper.jar create mode 100644 .sdkmanrc diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar deleted file mode 100644 index 41c70a7e0b7da7ecbbcf53b62aacdf8bc81e10b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47774 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 Be7*nx diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index 0061e75..12fbe1e 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1 +1,19 @@ -distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip \ No newline at end of file +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip diff --git a/.sdkmanrc b/.sdkmanrc new file mode 100644 index 0000000..3b3f7c5 --- /dev/null +++ b/.sdkmanrc @@ -0,0 +1,4 @@ +# Enable auto-env through the sdkman_auto_env config +# Add key=value pairs of SDKs to use below +java=17.0.16-zulu +maven=3.9.11 \ No newline at end of file diff --git a/mvnw b/mvnw index 8dfad2c..19529dd 100755 --- a/mvnw +++ b/mvnw @@ -19,267 +19,241 @@ # ---------------------------------------------------------------------------- # ---------------------------------------------------------------------------- -# Maven2 Start Up Batch script -# -# Required ENV vars: -# ------------------ -# JAVA_HOME - location of a JDK home dir +# Apache Maven Wrapper startup batch script, version 3.3.2 # # Optional ENV vars # ----------------- -# M2_HOME - location of maven2's installed home dir -# MAVEN_OPTS - parameters passed to the Java VM when running Maven -# e.g. to debug Maven itself, use -# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output # ---------------------------------------------------------------------------- -if [ -z "$MAVEN_SKIP_RC" ] ; then - - if [ -f /etc/mavenrc ] ; then - . /etc/mavenrc - fi +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x - if [ -f "$HOME/.mavenrc" ] ; then - . "$HOME/.mavenrc" - fi +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac -fi +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" -# OS specific support. $var _must_ be set to either true or false. -cygwin=false; -darwin=false; -mingw=false -case "`uname`" in - CYGWIN*) cygwin=true ;; - MINGW*) mingw=true;; - Darwin*) darwin=true - # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home - # See https://developer.apple.com/library/mac/qa/qa1170/_index.html - if [ -z "$JAVA_HOME" ]; then - if [ -x "/usr/libexec/java_home" ]; then - export JAVA_HOME="`/usr/libexec/java_home`" - else - export JAVA_HOME="/Library/Java/Home" + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 fi fi - ;; -esac + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : -if [ -z "$JAVA_HOME" ] ; then - if [ -r /etc/gentoo-release ] ; then - JAVA_HOME=`java-config --jre-home` + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi fi -fi - -if [ -z "$M2_HOME" ] ; then - ## resolve links - $0 may be a link to maven's home - PRG="$0" +} - # need this for relative symlinks - while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG="`dirname "$PRG"`/$link" - fi +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" done + printf %x\\n $h +} - saveddir=`pwd` +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } - M2_HOME=`dirname "$PRG"`/.. +die() { + printf %s\\n "$1" >&2 + exit 1 +} - # make it fully qualified - M2_HOME=`cd "$M2_HOME" && pwd` +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} - cd "$saveddir" - # echo Using m2 at $M2_HOME -fi +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" -# For Cygwin, ensure paths are in UNIX format before anything is touched -if $cygwin ; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --unix "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --unix "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --unix "$CLASSPATH"` -fi +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac -# For Mingw, ensure paths are in UNIX format before anything is touched -if $mingw ; then - [ -n "$M2_HOME" ] && - M2_HOME="`(cd "$M2_HOME"; pwd)`" - [ -n "$JAVA_HOME" ] && - JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" -fi +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" -if [ -z "$JAVA_HOME" ]; then - javaExecutable="`which javac`" - if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then - # readlink(1) is not available as standard on Solaris 10. - readLink=`which readlink` - if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then - if $darwin ; then - javaHome="`dirname \"$javaExecutable\"`" - javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" - else - javaExecutable="`readlink -f \"$javaExecutable\"`" - fi - javaHome="`dirname \"$javaExecutable\"`" - javaHome=`expr "$javaHome" : '\(.*\)/bin'` - JAVA_HOME="$javaHome" - export JAVA_HOME - fi - fi -fi +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} -if [ -z "$JAVACMD" ] ; then - if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - else - JAVACMD="`which java`" - fi +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" fi -if [ ! -x "$JAVACMD" ] ; then - echo "Error: JAVA_HOME is not defined correctly." >&2 - echo " We cannot execute $JAVACMD" >&2 - exit 1 -fi +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac -if [ -z "$JAVA_HOME" ] ; then - echo "Warning: JAVA_HOME environment variable is not set." +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" fi -CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher +mkdir -p -- "${MAVEN_HOME%/*}" -# traverses directory structure from process work directory to filesystem root -# first directory with .mvn subdirectory is considered project base directory -find_maven_basedir() { +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - if [ -z "$1" ] - then - echo "Path not specified to find_maven_basedir" - return 1 - fi +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi - basedir="$1" - wdir="$1" - while [ "$wdir" != '/' ] ; do - if [ -d "$wdir"/.mvn ] ; then - basedir=$wdir - break - fi - # workaround for JBEAP-8937 (on Solaris 10/Sparc) - if [ -d "${wdir}" ]; then - wdir=`cd "$wdir/.."; pwd` - fi - # end of workaround - done - echo "${basedir}" -} +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v -# concatenates all lines of a file -concat_lines() { - if [ -f "$1" ]; then - echo "$(tr -s '\n' ' ' < "$1")" - fi -} +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac -BASE_DIR=`find_maven_basedir "$(pwd)"` -if [ -z "$BASE_DIR" ]; then - exit 1; +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" fi -########################################################################################## -# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -# This allows using the maven wrapper in projects that prohibit checking in binary data. -########################################################################################## -if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found .mvn/wrapper/maven-wrapper.jar" +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then + distributionSha256Result=true fi -else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." - fi - jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" - while IFS="=" read key value; do - case "$key" in (wrapperUrl) jarUrl="$value"; break ;; - esac - done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" - if [ "$MVNW_VERBOSE" = true ]; then - echo "Downloading from: $jarUrl" - fi - wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" - - if command -v wget > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found wget ... using wget" - fi - wget "$jarUrl" -O "$wrapperJarPath" - elif command -v curl > /dev/null; then - if [ "$MVNW_VERBOSE" = true ]; then - echo "Found curl ... using curl" - fi - curl -o "$wrapperJarPath" "$jarUrl" - else - if [ "$MVNW_VERBOSE" = true ]; then - echo "Falling back to using Java to download" - fi - javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" - if [ -e "$javaClass" ]; then - if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Compiling MavenWrapperDownloader.java ..." - fi - # Compiling the Java class - ("$JAVA_HOME/bin/javac" "$javaClass") - fi - if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then - # Running the downloader - if [ "$MVNW_VERBOSE" = true ]; then - echo " - Running MavenWrapperDownloader.java ..." - fi - ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") - fi - fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi fi -########################################################################################## -# End of extension -########################################################################################## - -export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} -if [ "$MVNW_VERBOSE" = true ]; then - echo $MAVEN_PROJECTBASEDIR -fi -MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" -# For Cygwin, switch paths to Windows format before running java -if $cygwin; then - [ -n "$M2_HOME" ] && - M2_HOME=`cygpath --path --windows "$M2_HOME"` - [ -n "$JAVA_HOME" ] && - JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` - [ -n "$CLASSPATH" ] && - CLASSPATH=`cygpath --path --windows "$CLASSPATH"` - [ -n "$MAVEN_PROJECTBASEDIR" ] && - MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" fi +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" -WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -exec "$JAVACMD" \ - $MAVEN_OPTS \ - -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ - "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ - ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" +clean || : +exec_maven "$@" diff --git a/mvnw.cmd b/mvnw.cmd index e5cfb0a..b150b91 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -1,161 +1,149 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM set title of command window -title %0 -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" -set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" -FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO ( - IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B -) - -@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central -@REM This allows using the maven wrapper in projects that prohibit checking in binary data. -if exist %WRAPPER_JAR% ( - echo Found %WRAPPER_JAR% -) else ( - echo Couldn't find %WRAPPER_JAR%, downloading it ... - echo Downloading from: %DOWNLOAD_URL% - powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" - echo Finished downloading %WRAPPER_JAR% -) -@REM End of extension - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.2 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' +$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" +if ($env:MAVEN_USER_HOME) { + $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" +} +$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" From 14a3689bdc3b549560219e8fe7bc18fc75b53d09 Mon Sep 17 00:00:00 2001 From: oh-dan Date: Wed, 10 Sep 2025 08:48:25 +1200 Subject: [PATCH 2/5] add support for building current arch native lib locally including aarch64 --- modules/agent/compile_darwin.sh | 8 - modules/agent/compile_linux.sh | 8 - modules/agent/compile_win32.bat | 16 - modules/agent/pom.xml | 456 ++++++++++++------ .../main/resources/darwin_x86_32/libfaketime | Bin 9244 -> 0 bytes .../main/resources/darwin_x86_64/libfaketime | Bin 9244 -> 0 bytes .../main/resources/linux_x86_32/libfaketime | Bin 12798 -> 0 bytes .../main/resources/linux_x86_64/libfaketime | Bin 12798 -> 0 bytes .../main/resources/win32_x86_32/faketime.dll | Bin 9728 -> 0 bytes .../main/resources/win32_x86_64/faketime.dll | Bin 12800 -> 0 bytes .../agent/src/main/scripts/compile_darwin.sh | 26 + .../agent/src/main/scripts/compile_linux.sh | 61 +++ .../agent/src/main/scripts/compile_win32.bat | 31 ++ modules/api/pom.xml | 24 +- modules/junit/pom.xml | 48 +- modules/maven-plugin/pom.xml | 162 ++++--- .../java/io/github/faketime/FakeTimeMojo.java | 176 ++++--- .../src/main/java/io/github/faketime/Os.java | 102 ++-- pom.xml | 277 ++++++----- 19 files changed, 844 insertions(+), 551 deletions(-) delete mode 100755 modules/agent/compile_darwin.sh delete mode 100755 modules/agent/compile_linux.sh delete mode 100644 modules/agent/compile_win32.bat delete mode 100755 modules/agent/src/main/resources/darwin_x86_32/libfaketime delete mode 100755 modules/agent/src/main/resources/darwin_x86_64/libfaketime delete mode 100755 modules/agent/src/main/resources/linux_x86_32/libfaketime delete mode 100755 modules/agent/src/main/resources/linux_x86_64/libfaketime delete mode 100644 modules/agent/src/main/resources/win32_x86_32/faketime.dll delete mode 100644 modules/agent/src/main/resources/win32_x86_64/faketime.dll create mode 100755 modules/agent/src/main/scripts/compile_darwin.sh create mode 100755 modules/agent/src/main/scripts/compile_linux.sh create mode 100644 modules/agent/src/main/scripts/compile_win32.bat diff --git a/modules/agent/compile_darwin.sh b/modules/agent/compile_darwin.sh deleted file mode 100755 index 845ff2c..0000000 --- a/modules/agent/compile_darwin.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -gcc -O2 -fPIC -pthread -c -I $JAVA_HOME/include -I $JAVA_HOME/include/darwin src/main/c/agent.c -gcc -shared -o src/main/resources/darwin_x86_32/libfaketime agent.o -lc -rm agent.o - -gcc -O2 -fPIC -pthread -D_LP64=1 -c -I $JAVA_HOME/include -I $JAVA_HOME/include/darwin src/main/c/agent.c -gcc -shared -o src/main/resources/darwin_x86_64/libfaketime agent.o -lc -rm agent.o diff --git a/modules/agent/compile_linux.sh b/modules/agent/compile_linux.sh deleted file mode 100755 index 2a0c1ba..0000000 --- a/modules/agent/compile_linux.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -gcc -O2 -fPIC -pthread -c -I $JAVA_HOME/include -I $JAVA_HOME/include/linux src/main/c/agent.c -gcc -z defs -static-libgcc -shared -o src/main/resources/linux_x86_32/libfaketime agent.o -lc -rm agent.o - -gcc -O2 -fPIC -pthread -D_LP64=1 -c -I $JAVA_HOME/include -I $JAVA_HOME/include/linux src/main/c/agent.c -gcc -z defs -static-libgcc -shared -o src/main/resources/linux_x86_64/libfaketime agent.o -lc -rm agent.o diff --git a/modules/agent/compile_win32.bat b/modules/agent/compile_win32.bat deleted file mode 100644 index e721b78..0000000 --- a/modules/agent/compile_win32.bat +++ /dev/null @@ -1,16 +0,0 @@ -set VC_BIN=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin -set PATH=%VC_BIN%;%PATH% - -call "%VC_BIN%\vcvars32.bat" -cl /O1 /MD /D _STATIC_CPPLIB /c /I"%JAVA_HOME%\include" /I"%JAVA_HOME%\include\win32" src\main\c\agent.c -link /dll /opt:REF /out:src\main\resources\win32_x86_32\faketime.dll agent.obj -del agent.obj -del src\main\resources\win32_x86_32\faketime.exp -del src\main\resources\win32_x86_32\faketime.lib - -call "%VC_BIN%\amd64\vcvars64.bat" -cl /O1 /MD /D _STATIC_CPPLIB /c /I"%JAVA_HOME%\include" /I"%JAVA_HOME%\include\win32" src\main\c\agent.c -link /dll /opt:REF /out:src\main\resources\win32_x86_64\faketime.dll agent.obj -del agent.obj -del src\main\resources\win32_x86_64\faketime.exp -del src\main\resources\win32_x86_64\faketime.lib diff --git a/modules/agent/pom.xml b/modules/agent/pom.xml index 551e86b..54a8554 100644 --- a/modules/agent/pom.xml +++ b/modules/agent/pom.xml @@ -1,160 +1,318 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - FakeTime Native Agent - faketime-agent - jar - 0-SNAPSHOT + + io.github.faketime-java + faketime-parent + 0.9.0-SNAPSHOT + ../../pom.xml + - io.github.faketime-java - faketime-parent - 0-SNAPSHOT - ../../pom.xml - + faketime-agent + FakeTime Native Agent + pom - - - compile-agents - - - - org.codehaus.mojo - exec-maven-plugin - 1.5.0 - - - compile-agents - compile - - exec - - - ./${compile.script} - - - - - - - + + + + + org.codehaus.mojo + exec-maven-plugin + 3.5.1 + + + org.apache.maven.plugins + maven-jar-plugin + 3.4.2 + + + + - - darwin - - - mac - - - - compile_darwin.sh - - + + + + darwin + + + mac + + + + + + org.codehaus.mojo + exec-maven-plugin + + + compile-native-darwin + compile + + exec + + + ${project.basedir}/src/main/scripts/compile_darwin.sh + + + + - - linux - - - unix - Linux - - - - compile_linux.sh - - + + org.apache.maven.plugins + maven-jar-plugin + + + darwin_x86_64 + package + + jar + + + mac_x86_64 + ${project.build.directory}/native/darwin_x86_64 + + + + darwin_aarch64 + package + + jar + + + mac_aarch64 + ${project.build.directory}/native/darwin_aarch64 + + + + + + + - - windows - - - windows - - - - compile_win32.bat - - - + + + linux + + + unix + Linux + + + + + + org.codehaus.mojo + exec-maven-plugin + + + compile-native-linux + compile + + exec + + + ${project.basedir}/src/main/scripts/compile_linux.sh + + + + - - - - org.apache.maven.plugins - maven-jar-plugin - 3.0.2 - - - darwin_x86_32 - package - - jar - - - mac32 - ${project.build.outputDirectory}/darwin_x86_32 - - - - darwin_x86_64 - package - - jar - - - mac64 - ${project.build.outputDirectory}/darwin_x86_64 - - - - linux_x86_32 - package - - jar - - - linux32 - ${project.build.outputDirectory}/linux_x86_32 - - - - linux_x86_64 - package - - jar - - - linux64 - ${project.build.outputDirectory}/linux_x86_64 - - - - win32_x86_32 - package - - jar - - - windows32 - ${project.build.outputDirectory}/win32_x86_32 - - - - win32_x86_64 - package - - jar - - - windows64 - ${project.build.outputDirectory}/win32_x86_64 - - - - - - - \ No newline at end of file + + org.apache.maven.plugins + maven-jar-plugin + + + linux_x86_32 + package + + jar + + + linux_x86_32 + ${project.build.directory}/native/linux_x86_32 + + + + linux_x86_64 + package + + jar + + + linux_x86_64 + ${project.build.directory}/native/linux_x86_64 + + + + + + + + + + + linux-arm64 + + + unix + Linux + aarch64 + + + + + + org.codehaus.mojo + exec-maven-plugin + + + compile-native-linux-arm64 + compile + + exec + + + ${project.basedir}/src/main/scripts/compile_linux.sh + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + native-jar-linux_aarch64 + package + + jar + + + linux_aarch64 + ${project.build.directory}/native/linux_aarch64 + + + + + + + + + + + linux-arm64-cross + + + linux.arm64.cross + true + + + + + + org.codehaus.mojo + exec-maven-plugin + + + compile-linux-aarch64-cross + compile + + exec + + + ${project.basedir}/src/main/scripts/compile_linux.sh + + true + aarch64-linux-gnu-gcc + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + native-jar-linux_aarch64-cross + package + + jar + + + linux_aarch64 + ${project.build.directory}/native/linux_aarch64 + + + + + + + + + + + windows + + + windows + + + + + + org.codehaus.mojo + exec-maven-plugin + + + compile-native-windows + compile + + exec + + + ${project.basedir}/src/main/scripts/compile_win32.bat + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + win32_x86_32 + package + + jar + + + windows_x86_32 + ${project.build.directory}/native/win32_x86_32 + + + + win32_x86_64 + package + + jar + + + windows_x86_64 + ${project.build.directory}/native/win32_x86_64 + + + + + + + + + diff --git a/modules/agent/src/main/resources/darwin_x86_32/libfaketime b/modules/agent/src/main/resources/darwin_x86_32/libfaketime deleted file mode 100755 index f4e81bb4cf83a3e9075f8cd389aa70b16f3dc863..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9244 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 diff --git a/modules/agent/src/main/resources/darwin_x86_64/libfaketime b/modules/agent/src/main/resources/darwin_x86_64/libfaketime deleted file mode 100755 index 50031b8103f212248e08fbebeb7f6b8d12485ed6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9244 zcmeHNZ){W76~7L+1WHJtL(5bUhQb!ADUP>+Lc3^rH0hq{3r&@fqP6M6v7gBU|4Hp< zN~Wo#3YPlhx$`DX+DH1KYPCOFr3r~G;6?!u`i)raxtc= zy`6h|IjQu+W}Bx896A})@J5rWYG{WI8re{;FGtLPb+vX+_)>dle=cPs#i*(#jnqK0 zKq}Ywb8-Z*#_ky5aH9aVLLd1|VCz!{waAc`;CQLOd7-bFb2CPGjTrN8fqlWGkHcgJfaR63D{X#pQDD#isT)j_!r}0ro-Tn=4L>~wT4r+!T)ga0?F*edd0}o>q<686_$C#kiW8;J9 zKLbuRMr$74$k+qu&p|;q47eZTZZrbQ2esvBtHc;xMR)`9#8(avf`BA5UpIn7}~=Qj-Fs8S}PjKlC3r0yod<8m^YP7knhxbhLeUCZQj`& z8U_X?z?acT?>_iNvRegCe*Q0Ek8FM*JuUS~d!*i;Zohe3HvcJSmdM#{?MR2!-QqXT z09P_^%&T4Ij66D7 z`;7Fg)Gs|Jsr`~QUB987m98(Fsi}eiZ=>dl40ux*@D|80V4S)V1KzRiK4(u9jOg@T zo44bJWL<vl+v;q;3+bEB-BroDVCN2*Gup~?ce;?fJ2SiOY&sP=r`##x)b~Eyf(j-+ZJYS)y-YkJBrBA8!9=6)zm(U{a4b{~zrBan)*#P{t8CXy$Qk#n zQyI5QD~~o**?#hy7fZHO1dDQqX|pPs6Jkq+K}JpvQb(&_clNZ{Qp5H{c}}h?Cic@G zv2D82*NnaM4nyAFPiG1_v1Z2jDN)!@5WZ{Y#IK)j{Fh~suX?_HXFV%*i(H+GIPF-CpXWegewJU2Bv!kZA ze`3LTB#(a7)MZZk&ENXX3--BGC>I3E%6X8Zqj}>2yU-9dtm@0p{s^67YA1Yo95nSu zN2%b%;fPYap_u=$18g6W>35A#X6-|;C4K(I@5sUPD9$awe0dyQ@{U!;D!(-;kDhMu z@A$*_KKZZ}=g$e*q%$a*SIpE|Qk~tCe~XSI=fpTcoBPx?a`HVS&!6d7T8pqX&7Z#$ z;rb07jMqy~w`_ijMR(&13n%=qcvm-$PRY6-L~5XQ=C5Y5kPU%P{)AvLF?DsJ)J3sq+5+(@WKCOlu>+xlUOi@LiC7@wjq1sux37z=*d2()iB$?6 zNF|LZ1X`EaTbL*VXG^j0x7; zOrBsM5*Y{t4<;95C!H}3kJZUQVz?kU6d2GWx}j@}%FbPmhSdO6 z2kS)dK~La8qon_SuiHhxkLkIV+AqX!NgAW@@yzQ6FO3+RTFRC*fEVBXHOKB_u8pk5 znz}0@VmqBT$XN z|8)dbZ*1%#16Q}J^a?zrB@#pIsplJV?RXg$;xF0N0las{OYxBz+#qpq<=FF$Tw>t6 zS|ZMXdVq#sNa%(}SQ9Y3{x;%~2v80#6}J*@T$iwIbc4iRam8cow2NQk?8e2%A&t$t zB)a5LpNuK-K!|)REtp-w?~svdIFYanNv+NBwT@z74hg}2T`U~JYww6}< zB0k=1#Ihr+WrDIk>! zZDFE0xpJ;m)aN24M$`8!GMX$aNi`l@P%of~f>DcWAG^=qOGVqz*-(Y8v|vlB2`vz* k;31Lk;bD}QZfDF$4EwRI4>NV1g8NFQ9yk;=bROXU0J!%}>;M1& diff --git a/modules/agent/src/main/resources/linux_x86_32/libfaketime b/modules/agent/src/main/resources/linux_x86_32/libfaketime deleted file mode 100755 index 0e1af4ba5b9a6d5bfb7afcdad302288bd294c98f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12798 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 O8tvF=J7BoD=6?X+%ky~v diff --git a/modules/agent/src/main/resources/linux_x86_64/libfaketime b/modules/agent/src/main/resources/linux_x86_64/libfaketime deleted file mode 100755 index 0e1af4ba5b9a6d5bfb7afcdad302288bd294c98f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12798 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 O8tvF=J7BoD=6?X+%ky~v diff --git a/modules/agent/src/main/resources/win32_x86_32/faketime.dll b/modules/agent/src/main/resources/win32_x86_32/faketime.dll deleted file mode 100644 index dd56ff625328f6b62b1a55d7425c922e9d577395..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9728 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 macOS x86_64" +$CC $CFLAGS "${INCLUDES[@]}" -c -arch x86_64 src/main/c/agent.c -o agent_x86_64.o +$CC -dynamiclib -arch x86_64 agent_x86_64.o -lc -o "$OUT_X86/libfaketime.dylib" +rm -f agent_x86_64.o + +echo "==> macOS arm64" +$CC $CFLAGS "${INCLUDES[@]}" -c -arch arm64 src/main/c/agent.c -o agent_arm64.o +$CC -dynamiclib -arch arm64 agent_arm64.o -lc -o "$OUT_ARM/libfaketime.dylib" +rm -f agent_arm64.o + +echo "done." diff --git a/modules/agent/src/main/scripts/compile_linux.sh b/modules/agent/src/main/scripts/compile_linux.sh new file mode 100755 index 0000000..bae8209 --- /dev/null +++ b/modules/agent/src/main/scripts/compile_linux.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Build JNI .so for Linux. +# - On x86_64 host: builds x86_32 and x86_64. +# - On aarch64 host: builds aarch64. +# - Cross mode: if LINUX_AARCH64_CROSS=true, build aarch64 on x86 using aarch64-linux-gnu-gcc. + +CC="${CC:-gcc}" +CFLAGS_COMMON="-O2 -fPIC -pthread" +INCLUDES=(-I "$JAVA_HOME/include" -I "$JAVA_HOME/include/linux") + +# ---------- Cross-compile path for linux aarch64 ---------- +if [[ "${LINUX_AARCH64_CROSS:-}" == "true" ]]; then + OUTARM="target/native/linux_aarch64" + mkdir -p "$OUTARM" + : "${CC:=aarch64-linux-gnu-gcc}" + echo "==> Linux aarch64 (cross; CC=$CC)" + $CC $CFLAGS_COMMON -D_LP64=1 "${INCLUDES[@]}" -c src/main/c/agent.c -o agent_aarch64.o + $CC -shared -Wl,-z,defs -static-libgcc agent_aarch64.o -lc -o "$OUTARM/libfaketime.so" + rm -f agent_aarch64.o + echo "done (cross)." + exit 0 +fi +# ---------------------------------------------------------- + +ARCH="$(uname -m || true)" + +if [[ "${ARCH}" == "x86_64" ]]; then + OUT32="target/native/linux_x86_32" + OUT64="target/native/linux_x86_64" + mkdir -p "$OUT32" "$OUT64" + + echo "==> Linux x86_32" + if ! echo 'int main(){}' | $CC -m32 -x c - -o /dev/null >/dev/null 2>&1; then + echo "WARNING: 32-bit toolchain not available; skipping linux_x86_32." >&2 + else + $CC -m32 $CFLAGS_COMMON "${INCLUDES[@]}" -c src/main/c/agent.c -o agent_x86_32.o + $CC -m32 -shared -Wl,-z,defs -static-libgcc agent_x86_32.o -lc -o "$OUT32/libfaketime.so" + rm -f agent_x86_32.o + fi + + echo "==> Linux x86_64" + $CC -m64 $CFLAGS_COMMON -D_LP64=1 "${INCLUDES[@]}" -c src/main/c/agent.c -o agent_x86_64.o + $CC -m64 -shared -Wl,-z,defs -static-libgcc agent_x86_64.o -lc -o "$OUT64/libfaketime.so" + rm -f agent_x86_64.o + +elif [[ "${ARCH}" == "aarch64" ]]; then + OUTARM="target/native/linux_aarch64" + mkdir -p "$OUTARM" + + echo "==> Linux aarch64 (native)" + $CC $CFLAGS_COMMON -D_LP64=1 "${INCLUDES[@]}" -c src/main/c/agent.c -o agent_aarch64.o + $CC -shared -Wl,-z,defs -static-libgcc agent_aarch64.o -lc -o "$OUTARM/libfaketime.so" + rm -f agent_aarch64.o +else + echo "ERROR: Unsupported Linux host arch '${ARCH}'. Supported: x86_64, aarch64." >&2 + exit 1 +fi + +echo "done." diff --git a/modules/agent/src/main/scripts/compile_win32.bat b/modules/agent/src/main/scripts/compile_win32.bat new file mode 100644 index 0000000..c29fd4b --- /dev/null +++ b/modules/agent/src/main/scripts/compile_win32.bat @@ -0,0 +1,31 @@ +@echo off +REM Build JNI DLLs for Windows (x86 and x64) using MinGW (gcc). +REM Outputs go to target\native\win32_\ + +setlocal enabledelayedexpansion + +if "%JAVA_HOME%"=="" ( + echo ERROR: JAVA_HOME must be set + exit /b 1 +) + +set CC32=%CC32% +if "%CC32%"=="" set CC32=gcc +set CC64=%CC64% +if "%CC64%"=="" set CC64=x86_64-w64-mingw32-gcc + +set INCLUDES=-I "%JAVA_HOME%\include" -I "%JAVA_HOME%\include\win32" + +set OUT32=target\native\win32_x86_32 +set OUT64=target\native\win32_x86_64 + +if not exist "%OUT32%" mkdir "%OUT32%" +if not exist "%OUT64%" mkdir "%OUT64%" + +echo ==> Windows x86 (32-bit) +%CC32% -m32 -O2 -shared -static-libgcc -Wl,--add-stdcall-alias -o "%OUT32%\faketime.dll" -D_JNI_IMPLEMENTATION_ %INCLUDES% src\main\c\agent.c + +echo ==> Windows x86_64 +%CC64% -O2 -shared -static-libgcc -Wl,--add-stdcall-alias -o "%OUT64%\faketime.dll" -D_JNI_IMPLEMENTATION_ %INCLUDES% src\main\c\agent.c + +echo done. diff --git a/modules/api/pom.xml b/modules/api/pom.xml index ded76ce..ed71bea 100644 --- a/modules/api/pom.xml +++ b/modules/api/pom.xml @@ -2,17 +2,17 @@ - 4.0.0 + 4.0.0 - FakeTime API - faketime-api - jar - 0-SNAPSHOT + + io.github.faketime-java + faketime-parent + 0.9.0-SNAPSHOT + ../../pom.xml + - - io.github.faketime-java - faketime-parent - 0-SNAPSHOT - ../../pom.xml - - \ No newline at end of file + FakeTime API + faketime-api + jar + + diff --git a/modules/junit/pom.xml b/modules/junit/pom.xml index 3c87662..6f53c05 100644 --- a/modules/junit/pom.xml +++ b/modules/junit/pom.xml @@ -2,33 +2,27 @@ - 4.0.0 + 4.0.0 - FakeTime JUnit API - faketime-junit - jar - 0-SNAPSHOT + + io.github.faketime-java + faketime-parent + 0.9.0-SNAPSHOT + ../../pom.xml + - - io.github.faketime-java - faketime-parent - 0-SNAPSHOT - ../../pom.xml - + FakeTime JUnit API + faketime-junit + jar - - - io.github.faketime-java - faketime-api - 0-SNAPSHOT - compile - - - - junit - junit - 4.12 - compile - - - \ No newline at end of file + + + io.github.faketime-java + faketime-api + + + junit + junit + + + diff --git a/modules/maven-plugin/pom.xml b/modules/maven-plugin/pom.xml index 1c06e22..5e0aadc 100644 --- a/modules/maven-plugin/pom.xml +++ b/modules/maven-plugin/pom.xml @@ -2,74 +2,106 @@ - 4.0.0 + 4.0.0 - FakeTime Maven Plugin - faketime-maven-plugin - maven-plugin - 0-SNAPSHOT + + io.github.faketime-java + faketime-parent + 0.9.0-SNAPSHOT + ../../pom.xml + - - io.github.faketime-java - faketime-parent - 0-SNAPSHOT - ../../pom.xml - + FakeTime Maven Plugin + faketime-maven-plugin + maven-plugin - - - org.apache.maven - maven-core - 3.6.0 - provided - + + + org.apache.maven + maven-artifact + ${maven.version} + provided + + + org.apache.maven + maven-core + ${maven.version} + provided + + + org.apache.maven + maven-model + ${maven.version} + provided + + + org.apache.maven + maven-plugin-api + ${maven.version} + provided + + + org.apache.maven.plugin-tools + maven-plugin-annotations + ${maven.version} + provided + - - org.apache.maven.plugin-tools - maven-plugin-annotations - 3.6.0 - provided - + + org.apache.maven.shared + maven-artifact-transfer + 0.13.1 + compile + - - org.apache.maven.shared - maven-artifact-transfer - 0.10.0 - compile - + + org.codehaus.plexus + plexus-archiver + 4.10.0 + compile + + - - org.codehaus.plexus - plexus-archiver - 3.7.0 - compile - - - - - - - maven-plugin-plugin - 3.6.0 - - faketime - true - - - - mojo-descriptor - - descriptor - - - - help-goal - - helpmojo - - - - - - - \ No newline at end of file + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + org.apache.maven.plugin-tools + maven-plugin-annotations + ${maven.version} + + + + + + maven-plugin-plugin + ${maven.version} + + faketime + true + + + + mojo-descriptor + + descriptor + + + + help-goal + + helpmojo + + + + + + + + 3.9.0 + + diff --git a/modules/maven-plugin/src/main/java/io/github/faketime/FakeTimeMojo.java b/modules/maven-plugin/src/main/java/io/github/faketime/FakeTimeMojo.java index 254f610..fdad22a 100644 --- a/modules/maven-plugin/src/main/java/io/github/faketime/FakeTimeMojo.java +++ b/modules/maven-plugin/src/main/java/io/github/faketime/FakeTimeMojo.java @@ -1,15 +1,5 @@ package io.github.faketime; -import static org.apache.maven.plugins.annotations.LifecyclePhase.VALIDATE; -import static org.codehaus.plexus.util.Os.OS_ARCH; -import static org.codehaus.plexus.util.Os.OS_NAME; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; -import java.util.stream.Stream; - import org.apache.maven.artifact.Artifact; import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.AbstractMojo; @@ -27,102 +17,110 @@ import org.codehaus.plexus.components.io.fileselectors.FileSelector; import org.codehaus.plexus.components.io.fileselectors.IncludeExcludeFileSelector; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; +import java.util.stream.Stream; + +import static org.apache.maven.plugins.annotations.LifecyclePhase.VALIDATE; +import static org.codehaus.plexus.util.Os.OS_ARCH; +import static org.codehaus.plexus.util.Os.OS_NAME; + /** * @threadSafe */ -@Mojo(name="prepare", defaultPhase = VALIDATE) +@Mojo(name = "prepare", defaultPhase = VALIDATE) public class FakeTimeMojo extends AbstractMojo { - private static final String GROUP_ID = "io.github.faketime-java"; - private static final String ARTIFACT_ID = "faketime-maven-plugin"; - private static final String AGENT_ARTIFACT_ID = "faketime-agent"; + private static final String GROUP_ID = "io.github.faketime-java"; + private static final String ARTIFACT_ID = "faketime-maven-plugin"; + private static final String AGENT_ARTIFACT_ID = "faketime-agent"; - private static final String ARG_LINE_PROPERTY_NAME = "faketime.argLine"; + private static final String ARG_LINE_PROPERTY_NAME = "faketime.argLine"; - @Component - private ArtifactResolver artifactResolver; + @Component + private ArtifactResolver artifactResolver; - @Component - private ArchiverManager archiverManager; + @Component + private ArchiverManager archiverManager; - @Parameter(defaultValue = "${session}", readonly = true) - private MavenSession session; + @Parameter(defaultValue = "${session}", readonly = true) + private MavenSession session; - @Override - public void execute() throws MojoFailureException { - if (getOs() == null || Os.getBitness() == null) { - getLog().warn(String.format("!!! %s %s is not supported by FakeTime !!!", OS_NAME, OS_ARCH)); - return; + @Override + public void execute() throws MojoFailureException { + if (getOs() == null || Os.getArch() == null) { + getLog().warn(String.format("!!! %s %s is not supported by FakeTime !!!", OS_NAME, OS_ARCH)); + return; + } + + unpackAgent(); + setArgLineProperty(); } - unpackAgent(); - setArgLineProperty(); - } + private void unpackAgent() { + try { + Artifact artifact = artifactResolver.resolveArtifact(session.getProjectBuildingRequest(), getAgentArtifactCoordinate()).getArtifact(); - private void unpackAgent() { - try { - Artifact artifact = artifactResolver.resolveArtifact(session.getProjectBuildingRequest(), getAgentArtifactCoordinate()).getArtifact(); + getTargetDirectory().mkdirs(); - getTargetDirectory().mkdirs(); + UnArchiver unArchiver = archiverManager.getUnArchiver(artifact.getType()); + unArchiver.setSourceFile(artifact.getFile()); + unArchiver.setDestDirectory(getTargetDirectory()); + unArchiver.setFileSelectors(getAgentBinaryFileSelector()); + unArchiver.extract(); + } catch (ArtifactResolverException | NoSuchArchiverException e) { + throw new RuntimeException(e); + } + } - UnArchiver unArchiver = archiverManager.getUnArchiver(artifact.getType()); - unArchiver.setSourceFile(artifact.getFile()); - unArchiver.setDestDirectory(getTargetDirectory()); - unArchiver.setFileSelectors(getAgentBinaryFileSelector()); - unArchiver.extract(); + private void setArgLineProperty() { + session.getCurrentProject().getProperties().setProperty(ARG_LINE_PROPERTY_NAME, getAgentJvmArguments()); } - catch (ArtifactResolverException | NoSuchArchiverException e) { - throw new RuntimeException(e); + + private ArtifactCoordinate getAgentArtifactCoordinate() { + DefaultArtifactCoordinate coordinate = new DefaultArtifactCoordinate(); + coordinate.setGroupId(GROUP_ID); + coordinate.setArtifactId(AGENT_ARTIFACT_ID); + coordinate.setVersion(getPluginVersion()); + coordinate.setClassifier(String.format("%s_%s", getOs().getClassifierName(), Os.getArch())); + return coordinate; } - } - - private void setArgLineProperty() { - session.getCurrentProject().getProperties().setProperty(ARG_LINE_PROPERTY_NAME, getAgentJvmArguments()); - } - - private ArtifactCoordinate getAgentArtifactCoordinate() { - DefaultArtifactCoordinate coordinate = new DefaultArtifactCoordinate(); - coordinate.setGroupId(GROUP_ID); - coordinate.setArtifactId(AGENT_ARTIFACT_ID); - coordinate.setVersion(getPluginVersion()); - coordinate.setClassifier(getOs().getClassifierName() + Os.getBitness()); - return coordinate; - } - - private File getTargetDirectory() { - return new File(session.getCurrentProject().getBuild().getDirectory()); - } - - private FileSelector[] getAgentBinaryFileSelector() { - IncludeExcludeFileSelector fileSelector = new IncludeExcludeFileSelector(); - fileSelector.setIncludes(new String[] { getOs().getAgentBinaryName() }); - return new IncludeExcludeFileSelector[] { fileSelector }; - } - - private String getPluginVersion() { - try { - try (InputStream is = getClass().getResourceAsStream("/META-INF/maven/" + GROUP_ID + "/" + ARTIFACT_ID + "/pom.properties")) { - Properties properties = new Properties(); - properties.load(is); - return properties.getProperty("version"); - } + + private File getTargetDirectory() { + return new File(session.getCurrentProject().getBuild().getDirectory()); } - catch (IOException e) { - throw new RuntimeException(e); + + private FileSelector[] getAgentBinaryFileSelector() { + IncludeExcludeFileSelector fileSelector = new IncludeExcludeFileSelector(); + fileSelector.setIncludes(new String[]{getOs().getAgentBinaryName()}); + return new IncludeExcludeFileSelector[]{fileSelector}; + } + + private String getPluginVersion() { + try { + try (InputStream is = getClass().getResourceAsStream("/META-INF/maven/" + GROUP_ID + "/" + ARTIFACT_ID + "/pom.properties")) { + Properties properties = new Properties(); + properties.load(is); + return properties.getProperty("version"); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private String getAgentJvmArguments() { + return String.join(" ", + "-agentpath:" + new File(getTargetDirectory(), getOs().getAgentBinaryName()).getAbsolutePath(), + "-XX:+UnlockDiagnosticVMOptions", + "-XX:DisableIntrinsic=_currentTimeMillis", + "-XX:CompileCommand=quiet", + "-XX:CompileCommand=exclude,java/lang/System.currentTimeMillis", + "-XX:CompileCommand=exclude,jdk/internal/misc/VM.getNanoTimeAdjustment"); + } + + private Os getOs() { + return Stream.of(Os.values()).filter(Os::isCurrent).findFirst().orElse(null); } - } - - private String getAgentJvmArguments() { - return String.join(" ", - "-agentpath:" + new File(getTargetDirectory(), getOs().getAgentBinaryName()).getAbsolutePath(), - "-XX:+UnlockDiagnosticVMOptions", - "-XX:DisableIntrinsic=_currentTimeMillis", - "-XX:CompileCommand=quiet", - "-XX:CompileCommand=exclude,java/lang/System.currentTimeMillis", - "-XX:CompileCommand=exclude,jdk/internal/misc/VM.getNanoTimeAdjustment"); - } - - private Os getOs() { - return Stream.of(Os.values()).filter(Os::isCurrent).findFirst().orElse(null); - } } diff --git a/modules/maven-plugin/src/main/java/io/github/faketime/Os.java b/modules/maven-plugin/src/main/java/io/github/faketime/Os.java index e91e3c2..09daa45 100644 --- a/modules/maven-plugin/src/main/java/io/github/faketime/Os.java +++ b/modules/maven-plugin/src/main/java/io/github/faketime/Os.java @@ -1,63 +1,67 @@ package io.github.faketime; +import java.util.List; + import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.codehaus.plexus.util.Os.OS_ARCH; import static org.codehaus.plexus.util.Os.OS_NAME; -import java.util.List; - public enum Os { - WINDOWS("windows", "windows", "faketime.dll"), - LINUX("linux", "linux", "libfaketime"), - MAC(asList("mac", "osx"), "mac", "libfaketime"); - - private final List names; - private final String classifierName; - private final String agentBinaryName; - - Os(List names, String classifierName, String agentBinaryName) { - this.names = names; - this.classifierName = classifierName; - this.agentBinaryName = agentBinaryName; - } - - Os(String name, String classifierName, String agentBinaryName) { - this(singletonList(name), classifierName, agentBinaryName); - } - - public static String getBitness() { - switch (OS_ARCH.replace("_", "")) { - case "x8664": - case "amd64": - case "ia32e": - case "em64t": - case "x64": - return "64"; - case "x8632": - case "x86": - case "i386": - case "i486": - case "i586": - case "i686": - case "ia32": - case "x32": - return "32"; - default: - return null; + WINDOWS("windows", "windows", "faketime.dll"), + LINUX("linux", "linux", "libfaketime"), + MAC(asList("mac", "osx"), "mac", "libfaketime.dylib"); + + private final List names; + private final String classifierName; + private final String agentBinaryName; + + Os(List names, String classifierName, String agentBinaryName) { + this.names = names; + this.classifierName = classifierName; + this.agentBinaryName = agentBinaryName; } - } - public String getClassifierName() { - return classifierName; - } + Os(String name, String classifierName, String agentBinaryName) { + this(singletonList(name), classifierName, agentBinaryName); + } - public String getAgentBinaryName() { - return agentBinaryName; - } + public static String getArch() { + switch (OS_ARCH.replace("_", "")) { + case "arm64": + return "arm64"; + case "aarch64": + return "aarch64"; + case "x8664": + case "amd64": + case "ia32e": + case "em64t": + case "x64": + return "x86_64"; + case "x8632": + case "x86": + case "i386": + case "i486": + case "i586": + case "i686": + case "ia32": + case "x32": + return "x86_32"; + default: + return null; + } + } + + public String getClassifierName() { + return classifierName; + } - public boolean isCurrent() { - return names.stream().anyMatch(OS_NAME::contains); - } + public String getAgentBinaryName() { + return agentBinaryName; + } + + public boolean isCurrent() { + return names.stream().anyMatch(OS_NAME::contains); + } } diff --git a/pom.xml b/pom.xml index e94dd80..76d91dd 100644 --- a/pom.xml +++ b/pom.xml @@ -2,143 +2,164 @@ - 4.0.0 + 4.0.0 - FakeTime Parent POM - io.github.faketime-java - faketime-parent - pom - 0-SNAPSHOT + FakeTime Parent POM + io.github.faketime-java + faketime-parent + pom + 0.9.0-SNAPSHOT - - FakeTime uses a native Java agent to replace System.currentTimeMillis() implementation with the one you can control using system properties - - https://github.com/faketime-java/faketime - - - MIT - http://opensource.org/licenses/MIT - - - - - mihhail-lapushkin - Mihhail Lapushkin - mihhail.lapushkin@gmail.com - - - - scm:git:https://github.com/faketime-java/faketime.git - scm:git:git@github.com:faketime-java/faketime.git + + FakeTime uses a native Java agent to replace System.currentTimeMillis() implementation with the one you can control using system properties + https://github.com/faketime-java/faketime - HEAD - + + + MIT + http://opensource.org/licenses/MIT + + + + + mihhail-lapushkin + Mihhail Lapushkin + mihhail.lapushkin@gmail.com + + + + scm:git:https://github.com/faketime-java/faketime.git + scm:git:git@github.com:faketime-java/faketime.git + https://github.com/faketime-java/faketime + HEAD + - - UTF-8 - UTF-8 - + + UTF-8 + UTF-8 + - - modules/agent - modules/api - modules/junit - modules/maven-plugin - + + modules/agent + modules/api + modules/junit + modules/maven-plugin + - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.0 - - 1.8 - 1.8 - - -Xlint:all - - - + + + + io.github.faketime-java + faketime-api + ${project.version} + + + junit + junit + 4.12 + + + - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.8 - true - - ossrh - https://oss.sonatype.org/ - true - - - - + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.14.0 + + 8 + + -Xlint:all + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + - - - with-e2e-tests - - e2e-tests - - + + + with-e2e-tests + + e2e-tests + + - - release - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.6 - - - sign-artifacts - verify - - sign - - - - + + release + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.2.8 + + + sign-artifacts + verify + + sign + + + + - - org.apache.maven.plugins - maven-source-plugin - 3.0.1 - - - attach-sources - - jar-no-fork - - - - + + org.apache.maven.plugins + maven-source-plugin + 3.3.1 + + + attach-sources + + jar-no-fork + + + + - - org.apache.maven.plugins - maven-javadoc-plugin - 3.0.0 - - - attach-javadocs - - jar - - - - - - - threadSafe - X - - - - - - - - + + org.apache.maven.plugins + maven-javadoc-plugin + 3.11.2 + + + attach-javadocs + + jar + + + + + + + threadSafe + X + + + + + + + + From 34e9fa839019ccf2bdc60e964f4fa86cdcd4a9ec Mon Sep 17 00:00:00 2001 From: oh-dan Date: Wed, 10 Sep 2025 08:49:44 +1200 Subject: [PATCH 3/5] add github actions to build native libraries for supported os/arch --- .../workflows/branch-build-and-publish.yml | 350 ++++++++++++++++++ .../workflows/main-publish-pom-version.yml | 331 +++++++++++++++++ 2 files changed, 681 insertions(+) create mode 100644 .github/workflows/branch-build-and-publish.yml create mode 100644 .github/workflows/main-publish-pom-version.yml diff --git a/.github/workflows/branch-build-and-publish.yml b/.github/workflows/branch-build-and-publish.yml new file mode 100644 index 0000000..1af4312 --- /dev/null +++ b/.github/workflows/branch-build-and-publish.yml @@ -0,0 +1,350 @@ +name: Branch — Build & Publish (reactor + agent natives) + +on: + push: + branches-ignore: [ main, master ] + pull_request: + +permissions: + contents: read + packages: write + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + GITHUB_PACKAGES_URL: https://maven.pkg.github.com/${{ github.repository }} + JAVA_VERSION: "21" + JAVA_DISTRIBUTION: "temurin" + +jobs: + prepare: + name: Prepare version + runs-on: ubuntu-latest + outputs: + new_version: ${{ steps.vars.outputs.new_version }} + steps: + - uses: actions/checkout@v4.1.1 + - uses: actions/setup-java@v4.0.0 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: maven + - id: vars + run: | + SHORT_SHA=$(git rev-parse --short=8 HEAD) + BASE_VER=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' \ + --non-recursive org.codehaus.mojo:exec-maven-plugin:3.5.1:exec) + if [[ "$BASE_VER" != *-SNAPSHOT ]]; then + echo "Branch workflow skipped: version '$BASE_VER' is not a SNAPSHOT" + exit 0 + fi + # Replace -SNAPSHOT with -SHORT_SHA-RUN_ATTEMPT + #NEW_VER="${BASE_VER%-SNAPSHOT}-${SHORT_SHA}-${GITHUB_RUN_ATTEMPT}" + NEW_VER="${BASE_VER%-SNAPSHOT}-${SHORT_SHA}" + echo "new_version=${NEW_VER}" >> $GITHUB_OUTPUT + echo "Using ${NEW_VER}" + + macos: + name: macOS (x86_64 + arm64) + runs-on: macos-14 + needs: prepare + steps: + - uses: actions/checkout@v4.1.1 + - uses: actions/setup-java@v4.0.0 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: maven + - name: Make scripts executable + run: | + if git ls-files | grep -E "src/main/scripts/.*\\.sh$" | head -1; then + git ls-files | grep -E "src/main/scripts/.*\\.sh$" | xargs chmod +x + else + echo "No shell scripts found to make executable" + fi + - name: Set version + run: mvn -q -DnewVersion="${{ needs.prepare.outputs.new_version }}" -DgenerateBackupPoms=false versions:set + - name: Build packages + run: mvn -B -DskipTests -pl modules/agent package + - name: Upload native jars + uses: actions/upload-artifact@v4.3.1 + with: + name: native-macos + path: "**/target/*-mac_*.jar" + + linux-x: + name: Linux (x86_32 + x86_64 + aarch64 cross) + runs-on: ubuntu-22.04 + needs: prepare + steps: + - uses: actions/checkout@v4.1.1 + - uses: actions/setup-java@v4.0.0 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: maven + - name: Install cross-compilation tools + run: | + set -euo pipefail + sudo dpkg --add-architecture i386 + sudo apt-get update + + # Install 32-bit support step by step + echo "Installing 32-bit development libraries..." + sudo apt-get install -y libc6-dev:i386 || echo "Could not install libc6-dev:i386" + + echo "Installing multilib GCC..." + sudo apt-get install -y gcc-multilib g++-multilib || { + echo "multilib installation failed, trying alternative approach" + # Alternative: install 32-bit libraries manually + sudo apt-get install -y libc6-dev-i386 lib32gcc-s1 lib32stdc++6 + } + + # Install ARM64 cross-compilation tools + echo "Installing ARM64 cross-compilation tools..." + if ! sudo apt-get install -y crossbuild-essential-arm64; then + echo "Fallback: Installing explicit aarch64 packages" + sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu + fi + + # Verify installations + echo "=== Verifying toolchains ===" + echo "32-bit GCC test:" + if echo 'int main(){}' | gcc -m32 -x c - -o /dev/null 2>/dev/null; then + echo "✓ 32-bit compilation works" + gcc -m32 --version | head -1 + else + echo "✗ 32-bit compilation failed" + fi + + echo "ARM64 GCC test:" + aarch64-linux-gnu-gcc --version | head -1 || { echo "ARM64 cross-compiler not available"; exit 1; } + + - name: Make scripts executable + run: | + if git ls-files | grep -E "src/main/scripts/.*\\.sh$" | head -1; then + git ls-files | grep -E "src/main/scripts/.*\\.sh$" | xargs chmod +x + else + echo "No shell scripts found to make executable" + fi + - name: Set version + run: mvn -q -DnewVersion="${{ needs.prepare.outputs.new_version }}" -DgenerateBackupPoms=false versions:set + - name: Build x86 packages + run: mvn -B -DskipTests -pl modules/agent package + - name: Build ARM64 package (cross-compilation) + run: mvn -B -DskipTests -pl modules/agent -Dlinux.arm64.cross=true package + - name: Upload native jars + uses: actions/upload-artifact@v4.3.1 + with: + name: native-linux + path: | + **/target/*-linux_x86_*.jar + **/target/*-linux_aarch64.jar + + windows-x86: + name: Windows (x86 + x64) + runs-on: windows-latest + needs: prepare + steps: + - uses: actions/checkout@v4.1.1 + - uses: actions/setup-java@v4.0.0 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: maven + - name: Install MinGW (32/64) + shell: powershell + run: | + choco install mingw --yes --no-progress + echo "C:\\ProgramData\\chocolatey\\lib\\mingw\\tools\\install\\mingw64\\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + echo "C:\\ProgramData\\chocolatey\\lib\\mingw\\tools\\install\\mingw32\\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + - name: Set version + shell: bash + run: mvn -q -DnewVersion="${{ needs.prepare.outputs.new_version }}" -DgenerateBackupPoms=false versions:set + - name: Build packages + shell: bash + run: mvn -B -DskipTests -pl modules/agent package + - name: Upload native jars + uses: actions/upload-artifact@v4.3.1 + with: + name: native-windows-x86 + path: "**/target/*-windows_x86_*.jar" + + deploy-reactor: + name: Deploy non-agent modules + needs: [prepare, macos, linux-x, windows-x86] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4.1.1 + - uses: actions/setup-java@v4.0.0 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: maven + - name: Setup Maven settings for GitHub Packages + run: | + mkdir -p $HOME/.m2 + cat > $HOME/.m2/settings.xml <<'XML' + + + + github + ${env.GITHUB_ACTOR} + ${env.GITHUB_TOKEN} + + + + XML + - name: Set version + run: mvn -q -DnewVersion="${{ needs.prepare.outputs.new_version }}" -DgenerateBackupPoms=false versions:set + - name: Deploy all non-agent modules + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + mvn -B -DskipTests -pl '!modules/agent' -DaltDeploymentRepository=github::${{ env.GITHUB_PACKAGES_URL }} deploy + + publish-agent-classifiers: + name: Publish agent POM + native classifiers + needs: [prepare, macos, linux-x, windows-x86, deploy-reactor] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4.1.1 + - uses: actions/setup-java@v4.0.0 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: maven + - name: Setup Maven settings for GitHub Packages + run: | + mkdir -p $HOME/.m2 + cat > $HOME/.m2/settings.xml <<'XML' + + + + github + ${env.GITHUB_ACTOR} + ${env.GITHUB_TOKEN} + + + + XML + - uses: actions/download-artifact@v4.1.1 + with: + path: dist + - name: Set version for agent module + run: | + mvn -q -DnewVersion="${{ needs.prepare.outputs.new_version }}" -DgenerateBackupPoms=false versions:set + - name: Deploy agent POM + classifier jars + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + V="${{ needs.prepare.outputs.new_version }}" + + if [ ! -d "modules/agent" ]; then + echo "Error: modules/agent directory not found" + exit 1 + fi + + pushd modules/agent >/dev/null + G=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.groupId}' --non-recursive org.codehaus.mojo:exec-maven-plugin:3.5.1:exec) + A=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.artifactId}' --non-recursive org.codehaus.mojo:exec-maven-plugin:3.5.1:exec) + + if [ ! -f "pom.xml" ]; then + echo "Error: pom.xml not found in modules/agent" + exit 1 + fi + + # Create a dummy main JAR + echo "Creating dummy main JAR" + mkdir -p target + echo "# This is a dummy JAR - native libraries are provided as classifiers" > target/README.txt + jar cf "target/${A}-${V}.jar" -C target README.txt + + # Copy all classifier JARs to target and build deployment parameters + echo "Copying classifier JARs to target directory" + CLASSIFIER_JARS=$(find ../../dist -type f \( -name "*-mac_*.jar" -o -name "*-linux_*.jar" -o -name "*-windows_*.jar" \) | grep "$A-") + + FILES="" + CLASSIFIERS="" + TYPES="" + + if [ -n "$CLASSIFIER_JARS" ]; then + echo "Found classifier JARs:" + echo "$CLASSIFIER_JARS" + + for J in $CLASSIFIER_JARS; do + if [ -n "$J" ] && [ -f "$J" ]; then + BN=$(basename "$J") + # Extract classifier from filename: artifact-version-classifier.jar + NAME_NO_JAR=${BN%.jar} + CLASSIFIER="${NAME_NO_JAR#${A}-${V}-}" + + if [ -z "$CLASSIFIER" ] || [ "$CLASSIFIER" = "$NAME_NO_JAR" ]; then + echo "Warning: Could not extract classifier from $BN, skipping" + continue + fi + + # Copy to target directory + cp "$J" "target/${BN}" + echo "Copied $BN with classifier: $CLASSIFIER" + + # Build comma-separated parameter lists + if [ -z "$FILES" ]; then + FILES="target/${BN}" + CLASSIFIERS="$CLASSIFIER" + TYPES="jar" + else + FILES="${FILES},target/${BN}" + CLASSIFIERS="${CLASSIFIERS},${CLASSIFIER}" + TYPES="${TYPES},jar" + fi + fi + done + fi + + # Deploy main JAR with POM and all classifiers in a single command + if [ -n "$FILES" ]; then + echo "Deploying ${G}:${A}:${V} with classifiers: $CLASSIFIERS" + mvn -B -q deploy:deploy-file \ + -DrepositoryId=github -Durl="${{ env.GITHUB_PACKAGES_URL }}" \ + -DgroupId="$G" -DartifactId="$A" -Dversion="$V" \ + -Dpackaging=jar \ + -Dfile="target/${A}-${V}.jar" \ + -DpomFile=pom.xml \ + -Dfiles="$FILES" \ + -Dclassifiers="$CLASSIFIERS" \ + -Dtypes="$TYPES" + else + echo "No classifier JARs found, deploying only main JAR and POM" + mvn -B -q deploy:deploy-file \ + -DrepositoryId=github -Durl="${{ env.GITHUB_PACKAGES_URL }}" \ + -DgroupId="$G" -DartifactId="$A" -Dversion="$V" \ + -Dpackaging=jar \ + -Dfile="target/${A}-${V}.jar" \ + -DpomFile=pom.xml + fi + + popd >/dev/null + - name: Create distribution bundle + run: | + mkdir -p dist/bundle + find dist -type f -name "*.jar" -exec cp -t dist/bundle {} + 2>/dev/null || echo "No JARs found to bundle" + if [ -d "dist/bundle" ] && [ "$(ls -A dist/bundle)" ]; then + (cd dist && zip -r faketime-native-${{ needs.prepare.outputs.new_version }}-${{ github.sha }}.zip bundle) + else + echo "No files to bundle, creating empty archive" + (cd dist && zip faketime-native-${{ needs.prepare.outputs.new_version }}-${{ github.sha }}.zip -T) + fi + - uses: actions/upload-artifact@v4.3.1 + with: + name: faketime-native-${{ needs.prepare.outputs.new_version }}-${{ github.sha }} + path: dist/faketime-native-${{ needs.prepare.outputs.new_version }}-${{ github.sha }}.zip diff --git a/.github/workflows/main-publish-pom-version.yml b/.github/workflows/main-publish-pom-version.yml new file mode 100644 index 0000000..f5c634f --- /dev/null +++ b/.github/workflows/main-publish-pom-version.yml @@ -0,0 +1,331 @@ +name: Main — build & publish POM version (SNAPSHOT/RELEASE) + +on: + push: + branches: [ main, master ] + +permissions: + contents: read + packages: write + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + GITHUB_PACKAGES_URL: https://maven.pkg.github.com/${{ github.repository }} + JAVA_VERSION: "21" + JAVA_DISTRIBUTION: "temurin" + +jobs: + prepare: + name: Prepare POM version + runs-on: ubuntu-latest + outputs: + version: ${{ steps.vars.outputs.version }} + steps: + - uses: actions/checkout@v4.1.1 + - uses: actions/setup-java@v4.0.0 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: maven + - id: vars + name: Read version from POM + run: | + VER=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive org.codehaus.mojo:exec-maven-plugin:3.5.1:exec) + echo "version=${VER}" >> $GITHUB_OUTPUT + echo "Publishing version ${VER}" + + macos: + name: macOS (x86_64 + arm64) + runs-on: macos-14 + needs: prepare + steps: + - uses: actions/checkout@v4.1.1 + - uses: actions/setup-java@v4.0.0 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: maven + - name: Make scripts executable + run: | + if git ls-files | grep -E "src/main/scripts/.*\\.sh$" | head -1; then + git ls-files | grep -E "src/main/scripts/.*\\.sh$" | xargs chmod +x + else + echo "No shell scripts found to make executable" + fi + - name: Build packages + run: mvn -B -DskipTests -pl modules/agent package + - name: Upload native jars + uses: actions/upload-artifact@v4.3.1 + with: + name: native-macos + path: "**/target/*-mac_*.jar" + + linux-x: + name: Linux (x86_32 + x86_64 + aarch64 cross) + runs-on: ubuntu-22.04 + needs: prepare + steps: + - uses: actions/checkout@v4.1.1 + - uses: actions/setup-java@v4.0.0 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: maven + - name: Install cross-compilation tools + run: | + set -euo pipefail + sudo dpkg --add-architecture i386 + sudo apt-get update + + # Install 32-bit support step by step + echo "Installing 32-bit development libraries..." + sudo apt-get install -y libc6-dev:i386 || echo "Could not install libc6-dev:i386" + + echo "Installing multilib GCC..." + sudo apt-get install -y gcc-multilib g++-multilib || { + echo "multilib installation failed, trying alternative approach" + # Alternative: install 32-bit libraries manually + sudo apt-get install -y libc6-dev-i386 lib32gcc-s1 lib32stdc++6 + } + + # Install ARM64 cross-compilation tools + echo "Installing ARM64 cross-compilation tools..." + if ! sudo apt-get install -y crossbuild-essential-arm64; then + echo "Fallback: Installing explicit aarch64 packages" + sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu + fi + + # Verify installations + echo "=== Verifying toolchains ===" + echo "32-bit GCC test:" + if echo 'int main(){}' | gcc -m32 -x c - -o /dev/null 2>/dev/null; then + echo "✓ 32-bit compilation works" + gcc -m32 --version | head -1 + else + echo "✗ 32-bit compilation failed" + fi + + echo "ARM64 GCC test:" + aarch64-linux-gnu-gcc --version | head -1 || { echo "ARM64 cross-compiler not available"; exit 1; } + + - name: Make scripts executable + run: | + if git ls-files | grep -E "src/main/scripts/.*\\.sh$" | head -1; then + git ls-files | grep -E "src/main/scripts/.*\\.sh$" | xargs chmod +x + else + echo "No shell scripts found to make executable" + fi + - name: Build x86 packages + run: mvn -B -DskipTests -pl modules/agent package + - name: Build ARM64 package (cross-compilation) + run: mvn -B -DskipTests -pl modules/agent -Dlinux.arm64.cross=true package + - name: Upload native jars + uses: actions/upload-artifact@v4.3.1 + with: + name: native-linux + path: | + **/target/*-linux_x86_*.jar + **/target/*-linux_aarch64.jar + + windows-x86: + name: Windows (x86 + x64) + runs-on: windows-latest + needs: prepare + steps: + - uses: actions/checkout@v4.1.1 + - uses: actions/setup-java@v4.0.0 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: maven + - name: Install MinGW (32/64) + shell: powershell + run: | + choco install mingw --yes --no-progress + echo "C:\\ProgramData\\chocolatey\\lib\\mingw\\tools\\install\\mingw64\\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + echo "C:\\ProgramData\\chocolatey\\lib\\mingw\\tools\\install\\mingw32\\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + - name: Build packages + shell: bash + run: mvn -B -DskipTests -pl modules/agent package + - name: Upload native jars + uses: actions/upload-artifact@v4.3.1 + with: + name: native-windows-x86 + path: "**/target/*-windows_x86_*.jar" + + deploy-reactor: + name: Deploy non-agent modules + needs: [prepare, macos, linux-x, windows-x86] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4.1.1 + - uses: actions/setup-java@v4.0.0 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: maven + - name: Setup Maven settings for GitHub Packages + run: | + mkdir -p $HOME/.m2 + cat > $HOME/.m2/settings.xml <<'XML' + + + + github + ${env.GITHUB_ACTOR} + ${env.GITHUB_TOKEN} + + + + XML + - name: Ensure reactor version (no-op if already same) + run: mvn -q -DnewVersion="${{ needs.prepare.outputs.version }}" -DgenerateBackupPoms=false versions:set + - name: Deploy all non-agent modules + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + mvn -B -DskipTests -pl '!modules/agent' -DaltDeploymentRepository=github::${{ env.GITHUB_PACKAGES_URL }} deploy + + publish-agent-classifiers: + name: Publish agent POM + native classifiers + needs: [prepare, macos, linux-x, windows-x86, deploy-reactor] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4.1.1 + - uses: actions/setup-java@v4.0.0 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: maven + - name: Setup Maven settings for GitHub Packages + run: | + mkdir -p $HOME/.m2 + cat > $HOME/.m2/settings.xml <<'XML' + + + + github + ${env.GITHUB_ACTOR} + ${env.GITHUB_TOKEN} + + + + XML + - uses: actions/download-artifact@v4.1.1 + with: + path: dist + - name: Deploy agent POM + classifier jars + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + V="${{ needs.prepare.outputs.version }}" + + if [ ! -d "modules/agent" ]; then + echo "Error: modules/agent directory not found" + exit 1 + fi + + pushd modules/agent >/dev/null + G=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.groupId}' --non-recursive org.codehaus.mojo:exec-maven-plugin:3.5.1:exec) + A=$(mvn -q -Dexec.executable=echo -Dexec.args='${project.artifactId}' --non-recursive org.codehaus.mojo:exec-maven-plugin:3.5.1:exec) + + if [ ! -f "pom.xml" ]; then + echo "Error: pom.xml not found in modules/agent" + exit 1 + fi + + # Create a dummy main JAR + echo "Creating dummy main JAR" + mkdir -p target + echo "# This is a dummy JAR - native libraries are provided as classifiers" > target/README.txt + jar cf "target/${A}-${V}.jar" -C target README.txt + + # Copy all classifier JARs to target and build deployment parameters + echo "Copying classifier JARs to target directory" + CLASSIFIER_JARS=$(find ../../dist -type f \( -name "*-mac_*.jar" -o -name "*-linux_*.jar" -o -name "*-windows_*.jar" \) | grep "$A-") + + FILES="" + CLASSIFIERS="" + TYPES="" + + if [ -n "$CLASSIFIER_JARS" ]; then + echo "Found classifier JARs:" + echo "$CLASSIFIER_JARS" + + for J in $CLASSIFIER_JARS; do + if [ -n "$J" ] && [ -f "$J" ]; then + BN=$(basename "$J") + # Extract classifier from filename: artifact-version-classifier.jar + NAME_NO_JAR=${BN%.jar} + CLASSIFIER="${NAME_NO_JAR#${A}-${V}-}" + + if [ -z "$CLASSIFIER" ] || [ "$CLASSIFIER" = "$NAME_NO_JAR" ]; then + echo "Warning: Could not extract classifier from $BN, skipping" + continue + fi + + # Copy to target directory + cp "$J" "target/${BN}" + echo "Copied $BN with classifier: $CLASSIFIER" + + # Build comma-separated parameter lists + if [ -z "$FILES" ]; then + FILES="target/${BN}" + CLASSIFIERS="$CLASSIFIER" + TYPES="jar" + else + FILES="${FILES},target/${BN}" + CLASSIFIERS="${CLASSIFIERS},${CLASSIFIER}" + TYPES="${TYPES},jar" + fi + fi + done + fi + + # Deploy main JAR with POM and all classifiers in a single command + if [ -n "$FILES" ]; then + echo "Deploying ${G}:${A}:${V} with classifiers: $CLASSIFIERS" + mvn -B -q deploy:deploy-file \ + -DrepositoryId=github -Durl="${{ env.GITHUB_PACKAGES_URL }}" \ + -DgroupId="$G" -DartifactId="$A" -Dversion="$V" \ + -Dpackaging=jar \ + -Dfile="target/${A}-${V}.jar" \ + -DpomFile=pom.xml \ + -Dfiles="$FILES" \ + -Dclassifiers="$CLASSIFIERS" \ + -Dtypes="$TYPES" + else + echo "No classifier JARs found, deploying only main JAR and POM" + mvn -B -q deploy:deploy-file \ + -DrepositoryId=github -Durl="${{ env.GITHUB_PACKAGES_URL }}" \ + -DgroupId="$G" -DartifactId="$A" -Dversion="$V" \ + -Dpackaging=jar \ + -Dfile="target/${A}-${V}.jar" \ + -DpomFile=pom.xml + fi + + popd >/dev/null + - name: Create distribution bundle + run: | + mkdir -p dist/bundle + find dist -type f -name "*.jar" -exec cp -t dist/bundle {} + 2>/dev/null || echo "No JARs found to bundle" + if [ -d "dist/bundle" ] && [ "$(ls -A dist/bundle)" ]; then + (cd dist && zip -r faketime-native-${{ needs.prepare.outputs.version }}-${{ github.sha }}.zip bundle) + else + echo "No files to bundle, creating empty archive" + (cd dist && zip faketime-native-${{ needs.prepare.outputs.version }}-${{ github.sha }}.zip -T) + fi + - uses: actions/upload-artifact@v4.3.1 + with: + name: faketime-native-${{ needs.prepare.outputs.version }}-${{ github.sha }} + path: dist/faketime-native-${{ needs.prepare.outputs.version }}-${{ github.sha }}.zip From bf59c62fd2f32899adf6cf84e36fb7cdf0c062f8 Mon Sep 17 00:00:00 2001 From: oh-dan Date: Fri, 12 Dec 2025 08:08:24 +1300 Subject: [PATCH 4/5] ChatGPT improved workflows --- .../workflows/branch-build-and-publish.yml | 34 +++++++++++++++++-- .../workflows/main-publish-pom-version.yml | 25 ++++++++++++-- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/.github/workflows/branch-build-and-publish.yml b/.github/workflows/branch-build-and-publish.yml index 1af4312..df4e783 100644 --- a/.github/workflows/branch-build-and-publish.yml +++ b/.github/workflows/branch-build-and-publish.yml @@ -38,6 +38,7 @@ jobs: --non-recursive org.codehaus.mojo:exec-maven-plugin:3.5.1:exec) if [[ "$BASE_VER" != *-SNAPSHOT ]]; then echo "Branch workflow skipped: version '$BASE_VER' is not a SNAPSHOT" + echo "new_version=" >> $GITHUB_OUTPUT exit 0 fi # Replace -SNAPSHOT with -SHORT_SHA-RUN_ATTEMPT @@ -46,10 +47,30 @@ jobs: echo "new_version=${NEW_VER}" >> $GITHUB_OUTPUT echo "Using ${NEW_VER}" + tests: + name: Tests + runs-on: ubuntu-latest + needs: prepare + if: ${{ needs.prepare.outputs.new_version != '' }} + steps: + - uses: actions/checkout@v4.1.1 + - uses: actions/setup-java@v4.0.0 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: maven + - name: Set version + run: mvn -q -DnewVersion="${{ needs.prepare.outputs.new_version }}" -DgenerateBackupPoms=false versions:set + - name: Run reactor tests + run: | + mvn -B -pl '!modules/agent' test + mvn -B -pl modules/agent -DskipNativeBuild=true test + macos: name: macOS (x86_64 + arm64) runs-on: macos-14 needs: prepare + if: ${{ needs.prepare.outputs.new_version != '' }} steps: - uses: actions/checkout@v4.1.1 - uses: actions/setup-java@v4.0.0 @@ -78,6 +99,7 @@ jobs: name: Linux (x86_32 + x86_64 + aarch64 cross) runs-on: ubuntu-22.04 needs: prepare + if: ${{ needs.prepare.outputs.new_version != '' }} steps: - uses: actions/checkout@v4.1.1 - uses: actions/setup-java@v4.0.0 @@ -147,6 +169,7 @@ jobs: name: Windows (x86 + x64) runs-on: windows-latest needs: prepare + if: ${{ needs.prepare.outputs.new_version != '' }} steps: - uses: actions/checkout@v4.1.1 - uses: actions/setup-java@v4.0.0 @@ -174,7 +197,8 @@ jobs: deploy-reactor: name: Deploy non-agent modules - needs: [prepare, macos, linux-x, windows-x86] + needs: [prepare, tests, macos, linux-x, windows-x86] + if: ${{ github.event_name == 'push' && needs.prepare.outputs.new_version != '' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4.1.1 @@ -210,7 +234,8 @@ jobs: publish-agent-classifiers: name: Publish agent POM + native classifiers - needs: [prepare, macos, linux-x, windows-x86, deploy-reactor] + needs: [prepare, tests, macos, linux-x, windows-x86, deploy-reactor] + if: ${{ github.event_name == 'push' && needs.prepare.outputs.new_version != '' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4.1.1 @@ -277,6 +302,11 @@ jobs: CLASSIFIERS="" TYPES="" + if [ -z "$CLASSIFIER_JARS" ]; then + echo "Error: no classifier JARs found to publish" + exit 1 + fi + if [ -n "$CLASSIFIER_JARS" ]; then echo "Found classifier JARs:" echo "$CLASSIFIER_JARS" diff --git a/.github/workflows/main-publish-pom-version.yml b/.github/workflows/main-publish-pom-version.yml index f5c634f..53dbaec 100644 --- a/.github/workflows/main-publish-pom-version.yml +++ b/.github/workflows/main-publish-pom-version.yml @@ -37,6 +37,22 @@ jobs: echo "version=${VER}" >> $GITHUB_OUTPUT echo "Publishing version ${VER}" + tests: + name: Tests + runs-on: ubuntu-latest + needs: prepare + steps: + - uses: actions/checkout@v4.1.1 + - uses: actions/setup-java@v4.0.0 + with: + distribution: ${{ env.JAVA_DISTRIBUTION }} + java-version: ${{ env.JAVA_VERSION }} + cache: maven + - name: Run reactor tests + run: | + mvn -B -pl '!modules/agent' test + mvn -B -pl modules/agent -DskipNativeBuild=true test + macos: name: macOS (x86_64 + arm64) runs-on: macos-14 @@ -158,7 +174,7 @@ jobs: deploy-reactor: name: Deploy non-agent modules - needs: [prepare, macos, linux-x, windows-x86] + needs: [prepare, tests, macos, linux-x, windows-x86] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4.1.1 @@ -194,7 +210,7 @@ jobs: publish-agent-classifiers: name: Publish agent POM + native classifiers - needs: [prepare, macos, linux-x, windows-x86, deploy-reactor] + needs: [prepare, tests, macos, linux-x, windows-x86, deploy-reactor] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4.1.1 @@ -258,6 +274,11 @@ jobs: CLASSIFIERS="" TYPES="" + if [ -z "$CLASSIFIER_JARS" ]; then + echo "Error: no classifier JARs found to publish" + exit 1 + fi + if [ -n "$CLASSIFIER_JARS" ]; then echo "Found classifier JARs:" echo "$CLASSIFIER_JARS" From e98f4e9b938ef5c32dbc6cd39cf85b1384dd9592 Mon Sep 17 00:00:00 2001 From: oh-dan Date: Fri, 12 Dec 2025 08:18:06 +1300 Subject: [PATCH 5/5] update action versions and configure dependabot --- .github/dependabot.yml | 9 + .../workflows/branch-build-and-publish.yml | 38 +-- .../workflows/main-publish-pom-version.yml | 38 +-- BUILD.md | 83 +++++++ e2e-tests/pom.xml | 233 +++++++++--------- pom.xml | 5 + 6 files changed, 250 insertions(+), 156 deletions(-) create mode 100644 .github/dependabot.yml create mode 100644 BUILD.md diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..58bd4ac --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,9 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + commit-message: + prefix: "chore" + include: "scope" diff --git a/.github/workflows/branch-build-and-publish.yml b/.github/workflows/branch-build-and-publish.yml index df4e783..11dfe37 100644 --- a/.github/workflows/branch-build-and-publish.yml +++ b/.github/workflows/branch-build-and-publish.yml @@ -25,8 +25,8 @@ jobs: outputs: new_version: ${{ steps.vars.outputs.new_version }} steps: - - uses: actions/checkout@v4.1.1 - - uses: actions/setup-java@v4.0.0 + - uses: actions/checkout@v4.1.7 + - uses: actions/setup-java@v4.2.1 with: distribution: ${{ env.JAVA_DISTRIBUTION }} java-version: ${{ env.JAVA_VERSION }} @@ -53,8 +53,8 @@ jobs: needs: prepare if: ${{ needs.prepare.outputs.new_version != '' }} steps: - - uses: actions/checkout@v4.1.1 - - uses: actions/setup-java@v4.0.0 + - uses: actions/checkout@v4.1.7 + - uses: actions/setup-java@v4.2.1 with: distribution: ${{ env.JAVA_DISTRIBUTION }} java-version: ${{ env.JAVA_VERSION }} @@ -72,8 +72,8 @@ jobs: needs: prepare if: ${{ needs.prepare.outputs.new_version != '' }} steps: - - uses: actions/checkout@v4.1.1 - - uses: actions/setup-java@v4.0.0 + - uses: actions/checkout@v4.1.7 + - uses: actions/setup-java@v4.2.1 with: distribution: ${{ env.JAVA_DISTRIBUTION }} java-version: ${{ env.JAVA_VERSION }} @@ -90,7 +90,7 @@ jobs: - name: Build packages run: mvn -B -DskipTests -pl modules/agent package - name: Upload native jars - uses: actions/upload-artifact@v4.3.1 + uses: actions/upload-artifact@v4.3.3 with: name: native-macos path: "**/target/*-mac_*.jar" @@ -101,8 +101,8 @@ jobs: needs: prepare if: ${{ needs.prepare.outputs.new_version != '' }} steps: - - uses: actions/checkout@v4.1.1 - - uses: actions/setup-java@v4.0.0 + - uses: actions/checkout@v4.1.7 + - uses: actions/setup-java@v4.2.1 with: distribution: ${{ env.JAVA_DISTRIBUTION }} java-version: ${{ env.JAVA_VERSION }} @@ -158,7 +158,7 @@ jobs: - name: Build ARM64 package (cross-compilation) run: mvn -B -DskipTests -pl modules/agent -Dlinux.arm64.cross=true package - name: Upload native jars - uses: actions/upload-artifact@v4.3.1 + uses: actions/upload-artifact@v4.3.3 with: name: native-linux path: | @@ -171,8 +171,8 @@ jobs: needs: prepare if: ${{ needs.prepare.outputs.new_version != '' }} steps: - - uses: actions/checkout@v4.1.1 - - uses: actions/setup-java@v4.0.0 + - uses: actions/checkout@v4.1.7 + - uses: actions/setup-java@v4.2.1 with: distribution: ${{ env.JAVA_DISTRIBUTION }} java-version: ${{ env.JAVA_VERSION }} @@ -190,7 +190,7 @@ jobs: shell: bash run: mvn -B -DskipTests -pl modules/agent package - name: Upload native jars - uses: actions/upload-artifact@v4.3.1 + uses: actions/upload-artifact@v4.3.3 with: name: native-windows-x86 path: "**/target/*-windows_x86_*.jar" @@ -201,8 +201,8 @@ jobs: if: ${{ github.event_name == 'push' && needs.prepare.outputs.new_version != '' }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.1 - - uses: actions/setup-java@v4.0.0 + - uses: actions/checkout@v4.1.7 + - uses: actions/setup-java@v4.2.1 with: distribution: ${{ env.JAVA_DISTRIBUTION }} java-version: ${{ env.JAVA_VERSION }} @@ -238,8 +238,8 @@ jobs: if: ${{ github.event_name == 'push' && needs.prepare.outputs.new_version != '' }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.1 - - uses: actions/setup-java@v4.0.0 + - uses: actions/checkout@v4.1.7 + - uses: actions/setup-java@v4.2.1 with: distribution: ${{ env.JAVA_DISTRIBUTION }} java-version: ${{ env.JAVA_VERSION }} @@ -261,7 +261,7 @@ jobs: XML - - uses: actions/download-artifact@v4.1.1 + - uses: actions/download-artifact@v4.1.7 with: path: dist - name: Set version for agent module @@ -374,7 +374,7 @@ jobs: echo "No files to bundle, creating empty archive" (cd dist && zip faketime-native-${{ needs.prepare.outputs.new_version }}-${{ github.sha }}.zip -T) fi - - uses: actions/upload-artifact@v4.3.1 + - uses: actions/upload-artifact@v4.3.3 with: name: faketime-native-${{ needs.prepare.outputs.new_version }}-${{ github.sha }} path: dist/faketime-native-${{ needs.prepare.outputs.new_version }}-${{ github.sha }}.zip diff --git a/.github/workflows/main-publish-pom-version.yml b/.github/workflows/main-publish-pom-version.yml index 53dbaec..79f0350 100644 --- a/.github/workflows/main-publish-pom-version.yml +++ b/.github/workflows/main-publish-pom-version.yml @@ -24,8 +24,8 @@ jobs: outputs: version: ${{ steps.vars.outputs.version }} steps: - - uses: actions/checkout@v4.1.1 - - uses: actions/setup-java@v4.0.0 + - uses: actions/checkout@v4.1.7 + - uses: actions/setup-java@v4.2.1 with: distribution: ${{ env.JAVA_DISTRIBUTION }} java-version: ${{ env.JAVA_VERSION }} @@ -42,8 +42,8 @@ jobs: runs-on: ubuntu-latest needs: prepare steps: - - uses: actions/checkout@v4.1.1 - - uses: actions/setup-java@v4.0.0 + - uses: actions/checkout@v4.1.7 + - uses: actions/setup-java@v4.2.1 with: distribution: ${{ env.JAVA_DISTRIBUTION }} java-version: ${{ env.JAVA_VERSION }} @@ -58,8 +58,8 @@ jobs: runs-on: macos-14 needs: prepare steps: - - uses: actions/checkout@v4.1.1 - - uses: actions/setup-java@v4.0.0 + - uses: actions/checkout@v4.1.7 + - uses: actions/setup-java@v4.2.1 with: distribution: ${{ env.JAVA_DISTRIBUTION }} java-version: ${{ env.JAVA_VERSION }} @@ -74,7 +74,7 @@ jobs: - name: Build packages run: mvn -B -DskipTests -pl modules/agent package - name: Upload native jars - uses: actions/upload-artifact@v4.3.1 + uses: actions/upload-artifact@v4.3.3 with: name: native-macos path: "**/target/*-mac_*.jar" @@ -84,8 +84,8 @@ jobs: runs-on: ubuntu-22.04 needs: prepare steps: - - uses: actions/checkout@v4.1.1 - - uses: actions/setup-java@v4.0.0 + - uses: actions/checkout@v4.1.7 + - uses: actions/setup-java@v4.2.1 with: distribution: ${{ env.JAVA_DISTRIBUTION }} java-version: ${{ env.JAVA_VERSION }} @@ -139,7 +139,7 @@ jobs: - name: Build ARM64 package (cross-compilation) run: mvn -B -DskipTests -pl modules/agent -Dlinux.arm64.cross=true package - name: Upload native jars - uses: actions/upload-artifact@v4.3.1 + uses: actions/upload-artifact@v4.3.3 with: name: native-linux path: | @@ -151,8 +151,8 @@ jobs: runs-on: windows-latest needs: prepare steps: - - uses: actions/checkout@v4.1.1 - - uses: actions/setup-java@v4.0.0 + - uses: actions/checkout@v4.1.7 + - uses: actions/setup-java@v4.2.1 with: distribution: ${{ env.JAVA_DISTRIBUTION }} java-version: ${{ env.JAVA_VERSION }} @@ -167,7 +167,7 @@ jobs: shell: bash run: mvn -B -DskipTests -pl modules/agent package - name: Upload native jars - uses: actions/upload-artifact@v4.3.1 + uses: actions/upload-artifact@v4.3.3 with: name: native-windows-x86 path: "**/target/*-windows_x86_*.jar" @@ -177,8 +177,8 @@ jobs: needs: [prepare, tests, macos, linux-x, windows-x86] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.1 - - uses: actions/setup-java@v4.0.0 + - uses: actions/checkout@v4.1.7 + - uses: actions/setup-java@v4.2.1 with: distribution: ${{ env.JAVA_DISTRIBUTION }} java-version: ${{ env.JAVA_VERSION }} @@ -213,8 +213,8 @@ jobs: needs: [prepare, tests, macos, linux-x, windows-x86, deploy-reactor] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.1 - - uses: actions/setup-java@v4.0.0 + - uses: actions/checkout@v4.1.7 + - uses: actions/setup-java@v4.2.1 with: distribution: ${{ env.JAVA_DISTRIBUTION }} java-version: ${{ env.JAVA_VERSION }} @@ -236,7 +236,7 @@ jobs: XML - - uses: actions/download-artifact@v4.1.1 + - uses: actions/download-artifact@v4.1.7 with: path: dist - name: Deploy agent POM + classifier jars @@ -346,7 +346,7 @@ jobs: echo "No files to bundle, creating empty archive" (cd dist && zip faketime-native-${{ needs.prepare.outputs.version }}-${{ github.sha }}.zip -T) fi - - uses: actions/upload-artifact@v4.3.1 + - uses: actions/upload-artifact@v4.3.3 with: name: faketime-native-${{ needs.prepare.outputs.version }}-${{ github.sha }} path: dist/faketime-native-${{ needs.prepare.outputs.version }}-${{ github.sha }}.zip diff --git a/BUILD.md b/BUILD.md new file mode 100644 index 0000000..28ad4b9 --- /dev/null +++ b/BUILD.md @@ -0,0 +1,83 @@ +# Build Guide — faketime-java + +This project builds platform-specific JNI native libraries packaged as classifier JARs under the `faketime-agent` module. + +## Supported Platforms + +The CI matrix builds and publishes the following classifiers: + +- **macOS** + - `mac_x86_64` + - `mac_aarch64` + +- **Linux** + - `linux_x86_32` + - `linux_x86_64` + - `linux_aarch64` (native if running on ARM64, or cross-compiled using `aarch64-linux-gnu-gcc` on x86_64) + +- **Windows** + - `windows_x86_32` + - `windows_x86_64` + +## Windows ARM64 + +- Not built on GitHub-hosted runners: Ubuntu’s `mingw-w64` only supports x86 and x64 targets. +- The old `windows-arm64-cross` profile has been **removed** to avoid confusion. +- To support Windows ARM64: + - Provide a **self-hosted Windows ARM64 runner** (e.g. Surface Pro X, Windows Dev Kit 2023). + - Add a `` to `modules/agent/pom.xml` with activation `aarch64`. + - Update `compile_win32.bat` or create `compile_win_arm64.bat` using MSVC or a custom MinGW-w64 ARM64 toolchain. + - Add a workflow job with `runs-on: [self-hosted, Windows, ARM64]`. + +## Local Build + +Make sure `JAVA_HOME` is set to a JDK (Java 21 recommended). + +### macOS (x86_64 + arm64) +```bash +cd modules/agent +mvn -DskipTests package +``` + +### Linux x86_64 host +Install multilib toolchain for 32-bit: +```bash +sudo apt-get update +sudo apt-get install -y build-essential gcc-multilib g++-multilib +cd modules/agent +mvn -DskipTests package +``` + +### Linux ARM64 host +```bash +cd modules/agent +mvn -DskipTests package +``` + +### Linux ARM64 cross on x86_64 host +```bash +sudo apt-get update +sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu +cd modules/agent +mvn -DskipTests -Dlinux.arm64.cross=true package +``` + +### Windows (x86 + x64) +Install MinGW via Chocolatey: +```powershell +choco install mingw --yes +cd modules/agent +mvn -DskipTests package +``` + +## CI Workflows + +- **Branch builds** (`branch-snapshot-hash.yml`): + - Computes a snapshot version with commit hash suffix. + - Builds/publishes all classifiers. + +- **Main builds** (`main-publish-pom-version.yml`): + - Uses the POM version (snapshot or release). + - Builds/publishes all classifiers. + +Artifacts are published to GitHub Packages and uploaded as workflow artifacts for download. diff --git a/e2e-tests/pom.xml b/e2e-tests/pom.xml index 0d77a97..9586817 100644 --- a/e2e-tests/pom.xml +++ b/e2e-tests/pom.xml @@ -2,131 +2,128 @@ - 4.0.0 + 4.0.0 - FakeTime E2E Tests - faketime-e2e-tests - jar - 0-SNAPSHOT - - - io.github.faketime-java - faketime-parent - 0-SNAPSHOT - ../pom.xml - - - - libfaketime - - - - - faketimeBinary - - - windows - - - - faketime.dll - - - - - - - io.github.faketime-java - faketime-junit - 0-SNAPSHOT - test - + + io.github.faketime-java + faketime-parent + 0.9.0-SNAPSHOT + ../pom.xml + - - junit - junit - 4.12 - test - + FakeTime E2E Tests + faketime-e2e-tests + jar - - org.assertj - assertj-core - 3.11.1 - test - - + + + + libfaketime + - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.22.1 + + + faketimeBinary + + + windows + + + + + faketime.dll + + + - - random - - **/* - - ${faketime.argLine} - - + + + io.github.faketime-java + faketime-junit + test + - - org.apache.maven.plugins - maven-failsafe-plugin - 2.22.1 + + junit + junit + test + - - random - - **/* - - - -agentpath:${project.build.directory}/${faketime.binary} - -XX:+UnlockDiagnosticVMOptions - -XX:DisableIntrinsic=_currentTimeMillis - -XX:CompileCommand=quiet - -XX:CompileCommand=exclude,java/lang/System.currentTimeMillis - -XX:CompileCommand=exclude,jdk/internal/misc/VM.getNanoTimeAdjustment - - + + org.assertj + assertj-core + 3.27.4 + test + + - - - - integration-test - verify - - - - + + + + kr.motd.maven + os-maven-plugin + 1.7.1 + + + initialize + + detect + + + + + + + + io.github.faketime-java + faketime-maven-plugin + ${project.version} + + + + prepare + + + + - - io.github.faketime-java - faketime-maven-plugin - 0-SNAPSHOT - - - - prepare - - - - + + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.3 + + + random + + **/* + + @{argLine} ${faketime.argLine} + + - - org.apache.maven.plugins - maven-jar-plugin - 3.1.0 - - - default-jar - none - - - - - - \ No newline at end of file + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.5.3 + + + random + + **/* + + @{argLine} ${faketime.argLine} + + + + + integration-test + verify + + + + + + + diff --git a/pom.xml b/pom.xml index 76d91dd..e0bf887 100644 --- a/pom.xml +++ b/pom.xml @@ -53,6 +53,11 @@ faketime-api ${project.version} + + io.github.faketime-java + faketime-junit + ${project.version} + junit junit