diff --git a/.ci/container/Dockerfile b/.ci/container/Dockerfile
new file mode 100644
index 0000000000..9434c5d45b
--- /dev/null
+++ b/.ci/container/Dockerfile
@@ -0,0 +1,97 @@
+FROM ubuntu:24.04
+
+ENV DEBIAN_FRONTEND=noninteractive
+
+# Install basics and tools
+RUN apt-get update && apt-get install -y \
+ curl \
+ wget \
+ gnupg \
+ ca-certificates \
+ git \
+ unzip \
+ zip \
+ python3 \
+ python3-pip \
+ xvfb \
+ libgl1-mesa-dri \
+ libxtst6 \
+ libxxf86vm1 \
+ ant \
+ maven \
+ libncurses6 \
+ libstdc++6 \
+ && rm -rf /var/lib/apt/lists/*
+
+# Setup Azul Repo
+RUN curl -s https://repos.azul.com/azul-repo.key | gpg --dearmor -o /usr/share/keyrings/azul.gpg \
+ && echo "deb [signed-by=/usr/share/keyrings/azul.gpg] https://repos.azul.com/zulu/deb stable main" | tee /etc/apt/sources.list.d/zulu.list
+
+# Install JDKs 11, 17, 21, 25
+RUN apt-get update && apt-get install -y \
+ zulu11-jdk \
+ zulu17-jdk \
+ zulu21-jdk \
+ zulu25-jdk \
+ && rm -rf /var/lib/apt/lists/*
+
+# Install ZuluFX 8 (Tarball)
+# URL for Zulu 8 + FX (x64 Linux)
+# Using a fixed version to ensure reproducibility.
+RUN mkdir -p /usr/lib/jvm/zulu8-fx && \
+ curl -L "https://cdn.azul.com/zulu/bin/zulu8.82.0.21-ca-fx-jdk8.0.432-linux_x64.tar.gz" -o /tmp/zulu8.tar.gz && \
+ tar -xzf /tmp/zulu8.tar.gz -C /usr/lib/jvm/zulu8-fx --strip-components=1 && \
+ rm /tmp/zulu8.tar.gz
+
+# Clone cn1-binaries
+RUN git clone --depth=1 https://github.com/codenameone/cn1-binaries /opt/cn1-binaries
+
+# Set Environment Variables for JDKs (Paths for apt installed JDKs usually symlinked to /usr/lib/jvm/zulu-XX-amd64)
+ENV JAVA8_HOME=/usr/lib/jvm/zulu8-fx
+ENV JDK8_HOME=/usr/lib/jvm/zulu8-fx
+ENV JAVA11_HOME=/usr/lib/jvm/zulu11-ca-amd64
+ENV JDK11_HOME=/usr/lib/jvm/zulu11-ca-amd64
+ENV JAVA17_HOME=/usr/lib/jvm/zulu17-ca-amd64
+ENV JDK17_HOME=/usr/lib/jvm/zulu17-ca-amd64
+ENV JAVA21_HOME=/usr/lib/jvm/zulu21-ca-amd64
+ENV JDK21_HOME=/usr/lib/jvm/zulu21-ca-amd64
+ENV JAVA25_HOME=/usr/lib/jvm/zulu25-ca-amd64
+ENV JDK25_HOME=/usr/lib/jvm/zulu25-ca-amd64
+
+# Install Android SDK
+ENV ANDROID_HOME=/opt/android-sdk
+ENV ANDROID_SDK_ROOT=/opt/android-sdk
+ENV CMDLINE_TOOLS_URL="https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip"
+
+RUN mkdir -p ${ANDROID_HOME}/cmdline-tools && \
+ wget -q ${CMDLINE_TOOLS_URL} -O /tmp/cmdline-tools.zip && \
+ unzip -q /tmp/cmdline-tools.zip -d ${ANDROID_HOME}/cmdline-tools && \
+ mv ${ANDROID_HOME}/cmdline-tools/cmdline-tools ${ANDROID_HOME}/cmdline-tools/latest && \
+ rm /tmp/cmdline-tools.zip
+
+ENV PATH=${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/platform-tools:${ANDROID_HOME}/emulator:${PATH}
+
+# Accept licenses and install packages
+# Note: sdkmanager requires Java 11+ to run. We use JAVA17_HOME for this step.
+# We dynamically locate Zulu 17 to ensure the correct path is used.
+RUN export JAVA17_REAL=$(find /usr/lib/jvm -maxdepth 1 -name "zulu*17*" -type d | head -n 1) && \
+ echo "Using JDK 17 at: $JAVA17_REAL" && \
+ yes | JAVA_HOME=$JAVA17_REAL sdkmanager --licenses && \
+ JAVA_HOME=$JAVA17_REAL sdkmanager "platform-tools" "platforms;android-31" "build-tools;31.0.0"
+
+# Set Default JAVA_HOME to Java 8 (as per user requirement for builds)
+ENV JAVA_HOME=/usr/lib/jvm/zulu8-fx
+ENV PATH=$JAVA_HOME/bin:$PATH
+
+ENV CN1_BINARIES=/opt/cn1-binaries
+
+# Verify installations
+RUN java -version && \
+ $JAVA11_HOME/bin/java -version && \
+ $JAVA17_HOME/bin/java -version && \
+ $JAVA21_HOME/bin/java -version && \
+ $JAVA25_HOME/bin/java -version && \
+ ant -version && \
+ mvn -version && \
+ python3 --version && \
+ JAVA_HOME=${JAVA17_HOME} sdkmanager --version
diff --git a/.github/workflows/ant.yml b/.github/workflows/ant.yml
index 9644107db0..2afbc2f86d 100644
--- a/.github/workflows/ant.yml
+++ b/.github/workflows/ant.yml
@@ -7,20 +7,19 @@ on:
paths-ignore:
- 'CodenameOneDesigner/**'
+permissions:
+ contents: read
+ packages: read
+
jobs:
build-linux-jdk8:
runs-on: ubuntu-latest
+ container:
+ image: ghcr.io/codenameone/codenameone/ci-container:latest
steps:
- uses: actions/checkout@v1
- - name: Set up JDK 8
- uses: actions/setup-java@v1
- with:
- java-version: 1.8
- java-package: jdk
- - name: Install dependencies
- run: sudo apt-get update && sudo apt-get install xvfb
- name: Build with Maven
run: |
cd maven
diff --git a/.github/workflows/build-container.yml b/.github/workflows/build-container.yml
new file mode 100644
index 0000000000..9c35af39c3
--- /dev/null
+++ b/.github/workflows/build-container.yml
@@ -0,0 +1,40 @@
+name: Build CI Container
+
+on:
+ push:
+ paths:
+ - '.ci/container/**'
+ - '.github/workflows/build-container.yml'
+ workflow_dispatch:
+
+env:
+ REGISTRY: ghcr.io
+
+jobs:
+ build-and-push:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Downcase Image Name
+ run: |
+ echo "IMAGE_NAME=${GITHUB_REPOSITORY,,}/ci-container" >> ${GITHUB_ENV}
+
+ - name: Log in to the Container registry
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Build and push Docker image
+ uses: docker/build-push-action@v5
+ with:
+ context: .ci/container
+ push: true
+ tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index e60a48aa8e..3ad7b2563a 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -32,30 +32,20 @@ permissions:
contents: write
pull-requests: write
issues: write
+ packages: read
jobs:
- build-test:
+ build-linux-jdk8-fx:
runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- java-version: [8, 17, 21, 25]
+ container:
+ image: ghcr.io/codenameone/codenameone/ci-container:latest
+ defaults:
+ run:
+ shell: bash
steps:
- uses: actions/checkout@v1
- - name: Set up JDK 8
- if: matrix.java-version == 8
- uses: actions/setup-java@v1
- with:
- java-version: 1.8
- java-package: jdk+fx
- - name: Set up JDK
- if: matrix.java-version != 8
- uses: actions/setup-java@v4
- with:
- distribution: 'zulu'
- java-version: ${{ matrix.java-version }}
- name: Cache Maven dependencies
uses: actions/cache@v4
with:
@@ -65,22 +55,13 @@ jobs:
${{ runner.os }}-m2
- name: Run Unit Tests
run: |
- MVN_ARGS=""
- if [ "${{ matrix.java-version }}" != "8" ]; then
- MVN_ARGS="-Dspotbugs.skip=true"
- fi
cd maven
- mvn clean verify -DunitTests=true -pl core-unittests -am -Dmaven.javadoc.skip=true -Plocal-dev-javase $MVN_ARGS
+ mvn clean verify -DunitTests=true -pl core-unittests -am -Dmaven.javadoc.skip=true -Plocal-dev-javase
cd ..
- - name: Prepare Codename One binaries for Maven plugin tests
- run: |
- set -euo pipefail
- rm -rf maven/target/cn1-binaries
- git clone --depth=1 --filter=blob:none https://github.com/codenameone/cn1-binaries maven/target/cn1-binaries
- name: Run Maven plugin tests
working-directory: maven
env:
- CN1_BINARIES: ${{ github.workspace }}/maven/target/cn1-binaries
+ CN1_BINARIES: /opt/cn1-binaries
run: |
mvn -B -Dmaven.javadoc.skip=true \
-DunitTests=true \
@@ -88,7 +69,7 @@ jobs:
-Dcn1.binaries="${CN1_BINARIES}" \
-pl codenameone-maven-plugin -am -Plocal-dev-javase test
- name: Generate static analysis HTML summaries
- if: ${{ always() && matrix.java-version == 8 }}
+ if: ${{ always() }}
env:
QUALITY_REPORT_TARGET_DIRS: maven/core-unittests/target
QUALITY_REPORT_SERVER_URL: ${{ github.server_url }}
@@ -97,7 +78,7 @@ jobs:
QUALITY_REPORT_GENERATE_HTML_ONLY: "1"
run: python3 .github/scripts/generate-quality-report.py
- name: Collect quality artifacts
- if: ${{ always() && matrix.java-version == 8 }}
+ if: ${{ always() }}
run: |
set -euo pipefail
mkdir -p quality-artifacts/static-analysis
@@ -125,14 +106,14 @@ jobs:
echo "No quality artifacts were generated." > quality-artifacts/README.txt
fi
- name: Upload quality artifacts
- if: ${{ always() && matrix.java-version == 8 }}
+ if: ${{ always() }}
id: upload-quality-artifacts
uses: actions/upload-artifact@v4
with:
name: quality-artifacts
path: quality-artifacts
- name: Publish quality report previews
- if: ${{ always() && matrix.java-version == 8 && github.server_url == 'https://github.com' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }}
+ if: ${{ always() && github.server_url == 'https://github.com' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }}
id: publish-quality-previews
env:
GITHUB_TOKEN: ${{ github.token }}
@@ -198,7 +179,7 @@ jobs:
echo "jacoco_url=${preview_base}/coverage/index.html" >> "$GITHUB_OUTPUT"
fi
- name: Generate quality report summary
- if: ${{ always() && matrix.java-version == 8 }}
+ if: ${{ always() }}
env:
QUALITY_REPORT_TARGET_DIRS: maven/core-unittests/target
QUALITY_REPORT_SERVER_URL: ${{ github.server_url }}
@@ -214,45 +195,30 @@ jobs:
JACOCO_HTML_URL: ${{ steps.publish-quality-previews.outputs.jacoco_url }}
run: python3 .github/scripts/generate-quality-report.py
- name: Upload quality report summary
- if: ${{ always() && matrix.java-version == 8 }}
+ if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: quality-report
path: quality-report.md
- name: Publish quality report comment
- if: ${{ github.event_name == 'pull_request' && matrix.java-version == 8 }}
+ if: ${{ github.event_name == 'pull_request' }}
uses: actions/github-script@v7
with:
script: |
const { publishQualityComment } = require('./.github/scripts/publish-quality-comment.js');
await publishQualityComment({ github, context, core });
- - name: Install dependencies
+ - name: Link cn1-binaries
run: |
- sudo apt-get update && sudo apt-get install xvfb
- wget https://github.com/codenameone/cn1-binaries/archive/refs/heads/master.zip
- unzip master.zip -d ..
- mv ../cn1-binaries-master ../cn1-binaries
- - name: Build CLDC11 JAR
- run: |
- ANT_OPTS_ARGS=""
- if [ "${{ matrix.java-version }}" != "8" ]; then
- ANT_OPTS_ARGS="-Djavac.source=1.8 -Djavac.target=1.8"
- fi
- ant $ANT_OPTS_ARGS -noinput -buildfile Ports/CLDC11/build.xml jar
+ ln -sf $CN1_BINARIES ../cn1-binaries
- name: Build with Ant
- run: |
- ANT_OPTS_ARGS=""
- if [ "${{ matrix.java-version }}" != "8" ]; then
- ANT_OPTS_ARGS="-Djavac.source=1.8 -Djavac.target=1.8"
- fi
- xvfb-run ant $ANT_OPTS_ARGS test-javase
+ run: xvfb-run ant test-javase
+ - name: Build CLDC11 JAR
+ run: ant -noinput -buildfile Ports/CLDC11/build.xml jar
- name: Build Release
- if: matrix.java-version == 8
run: ant -noinput -buildfile CodenameOne/build.xml weeklyLibUpdate
- name: Build JavaDocs
- if: matrix.java-version == 8
run: |
cd CodenameOne
mkdir -p build
@@ -267,18 +233,12 @@ jobs:
cd ..
- name: Build iOS Port
- run: |
- ANT_OPTS_ARGS=""
- if [ "${{ matrix.java-version }}" != "8" ]; then
- ANT_OPTS_ARGS="-Djavac.source=1.8 -Djavac.target=1.8"
- fi
- ant $ANT_OPTS_ARGS -noinput -buildfile Ports/iOSPort/build.xml jar
+ run: ant -noinput -buildfile Ports/iOSPort/build.xml jar
- name: Build iOS VM API
run: mvn -f vm/JavaAPI/pom.xml package
- name: Upload a Build Artifact
- if: matrix.java-version == 8
uses: actions/upload-artifact@v4
with:
name: JavaAPI.jar
@@ -288,41 +248,27 @@ jobs:
run: mvn -f vm/ByteCodeTranslator/pom.xml package
- name: Build CLDC 11 VM
- run: |
- ANT_OPTS_ARGS=""
- if [ "${{ matrix.java-version }}" != "8" ]; then
- ANT_OPTS_ARGS="-Djavac.source=1.8 -Djavac.target=1.8"
- fi
- ant $ANT_OPTS_ARGS -noinput -buildfile Ports/CLDC11/build.xml jar
+ run: ant -noinput -buildfile Ports/CLDC11/build.xml jar
- name: Upload a Build Artifact
- if: matrix.java-version == 8
uses: actions/upload-artifact@v4
with:
name: ByteCodeTranslator.jar
path: vm/ByteCodeTranslator/target/ByteCodeTranslator-1.0-SNAPSHOT.jar
- name: Upload a Build Artifact
- if: matrix.java-version == 8
uses: actions/upload-artifact@v4
with:
name: CLDC11.jar
path: Ports/CLDC11/dist/CLDC11.jar
- name: Build Android Port
- run: |
- ANT_OPTS_ARGS=""
- if [ "${{ matrix.java-version }}" != "8" ]; then
- ANT_OPTS_ARGS="-Djavac.source=1.8 -Djavac.target=1.8"
- fi
- ant $ANT_OPTS_ARGS -noinput -buildfile Ports/Android/build.xml jar
+ run: ant -noinput -buildfile Ports/Android/build.xml jar
- name: Packaging Everything
- if: matrix.java-version == 8
run: zip -j result.zip CodenameOne/javadocs.zip CodenameOne/dist/CodenameOne.jar CodenameOne/updatedLibs.zip Ports/JavaSE/dist/JavaSE.jar build/CodenameOneDist/CodenameOne/demos/CodenameOne_SRC.zip
- name: Copying Files to Server
- if: matrix.java-version == 8
uses: marcodallasanta/ssh-scp-deploy@v1.0.5
with:
host: ${{ secrets.WP_HOST }}
@@ -331,7 +277,6 @@ jobs:
local: result.zip
- name: Upload a Build Artifact
- if: matrix.java-version == 8
uses: actions/upload-artifact@v4
with:
name: JavaSE.jar
diff --git a/.github/workflows/scripts-android.yml b/.github/workflows/scripts-android.yml
index 097f422a7d..25137bc4ad 100644
--- a/.github/workflows/scripts-android.yml
+++ b/.github/workflows/scripts-android.yml
@@ -89,28 +89,22 @@ jobs:
contents: read
pull-requests: write
issues: write
+ packages: read
runs-on: ubuntu-latest
+ container:
+ image: ghcr.io/codenameone/codenameone/ci-container:latest
+ options: --privileged -v /dev/kvm:/dev/kvm
env:
GITHUB_TOKEN: ${{ secrets.CN1SS_GH_TOKEN }}
GH_TOKEN: ${{ secrets.CN1SS_GH_TOKEN }}
steps:
- uses: actions/checkout@v4
- - name: Free Disk Space
- if: matrix.id != 'default'
- run: |
- sudo rm -rf /usr/share/dotnet
- sudo rm -rf /usr/local/lib/android/sdk/ndk
- sudo rm -rf /opt/ghc
- sudo rm -rf /usr/share/swift
- - name: Setup JDK
- if: matrix.id != 'default'
- uses: actions/setup-java@v4
- with:
- java-version: ${{ matrix.java_version }}
- distribution: 'zulu'
- name: Set JDK_HOME
if: matrix.id != 'default'
- run: echo "JDK_HOME=${JAVA_HOME}" >> $GITHUB_ENV
+ run: echo "JDK_HOME=/usr/lib/jvm/zulu${{ matrix.java_version }}-ca-amd64" >> $GITHUB_ENV
+ - name: Set JDK_HOME (Default)
+ if: matrix.id == 'default'
+ run: echo "JDK_HOME=${JDK8_HOME}" >> $GITHUB_ENV
- name: Configure CN1SS options
if: matrix.id != 'default'
run: |
@@ -124,11 +118,6 @@ jobs:
- name: Build Hello Codename One Android app
id: build-android-app
run: ./scripts/build-android-app.sh -q -DskipTests
- - name: Enable KVM for Android emulator
- run: |
- echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
- sudo udevadm control --reload-rules
- sudo udevadm trigger --name-match=kvm
- name: Run Android instrumentation tests
uses: reactivecircus/android-emulator-runner@v2
with:
diff --git a/maven/codenameone-maven-plugin/pom.xml b/maven/codenameone-maven-plugin/pom.xml
index 98ef2e27bc..9cdc6079eb 100644
--- a/maven/codenameone-maven-plugin/pom.xml
+++ b/maven/codenameone-maven-plugin/pom.xml
@@ -219,6 +219,17 @@
maven-model
+
+
+ xalan
+ xalan
+ 2.7.3
+
+
+ xalan
+ serializer
+ 2.7.3
+
diff --git a/maven/codenameone-maven-plugin/src/main/java/com/codename1/builders/AndroidGradleBuilder.java b/maven/codenameone-maven-plugin/src/main/java/com/codename1/builders/AndroidGradleBuilder.java
index 2c54664a20..3ed83e6ec8 100644
--- a/maven/codenameone-maven-plugin/src/main/java/com/codename1/builders/AndroidGradleBuilder.java
+++ b/maven/codenameone-maven-plugin/src/main/java/com/codename1/builders/AndroidGradleBuilder.java
@@ -520,6 +520,7 @@ public boolean build(File sourceZip, final BuildRequest request) throws BuildExc
log("NOTICE: Enabling Java 8 source level for Gradle 8 build because RetroLambda is not supported on Java 17, which is required for gradle 8.");
useJava8SourceLevel = true;
}
+ defaultEnvironment.put("JAVA_HOME", getGradleJavaHome());
}
if (newFirebaseMessaging && !useGradle8) {
throw new BuildException("android.newFirebaseMessaging requires gradle version 8.1 or higher. Please remove the android.gradleVersion build hint");
@@ -577,10 +578,21 @@ public boolean build(File sourceZip, final BuildRequest request) throws BuildExc
if (!androidSDKDir.exists()) {
throw new BuildException("Cannot find Android SDK at "+androidHome+". Please install Android studio, or set the ANDROID_HOME environment variable to point to your android sdk directory.");
}
- if (!androidSDKDir.getName().equalsIgnoreCase("sdk")) {
- androidSDKDir = new File(androidSDKDir, "Sdk");
- if (!androidSDKDir.isDirectory()) {
- androidSDKDir = new File(androidSDKDir.getParentFile(), "sdk");
+ // Check if this looks like an SDK directory
+ if (!new File(androidSDKDir, "cmdline-tools").exists() &&
+ !new File(androidSDKDir, "platform-tools").exists() &&
+ !new File(androidSDKDir, "build-tools").exists() &&
+ !new File(androidSDKDir, "tools").exists()) {
+ if (!androidSDKDir.getName().equalsIgnoreCase("sdk")) {
+ File childSdk = new File(androidSDKDir, "Sdk");
+ if (childSdk.isDirectory()) {
+ androidSDKDir = childSdk;
+ } else {
+ File siblingSdk = new File(androidSDKDir.getParentFile(), "sdk");
+ if (siblingSdk.isDirectory()) {
+ androidSDKDir = siblingSdk;
+ }
+ }
}
}
diff --git a/maven/core/pom.xml b/maven/core/pom.xml
index 9a0c96f641..7759148db0 100644
--- a/maven/core/pom.xml
+++ b/maven/core/pom.xml
@@ -44,25 +44,13 @@
maven-compiler-plugin
- ${maven.compiler.source}
- ${maven.compiler.target}
+ 1.5
+ 1.5
-
-
- modern-jdk
-
- [9,)
-
-
- 1.8
- 1.8
-
-
-
\ No newline at end of file
diff --git a/maven/parparvm/pom.xml b/maven/parparvm/pom.xml
index 0c667f5286..b32196c368 100644
--- a/maven/parparvm/pom.xml
+++ b/maven/parparvm/pom.xml
@@ -43,8 +43,6 @@
../../vm/ByteCodeTranslator/src
../../vm/JavaAPI/src
- 1.5
- 1.5
@@ -87,6 +85,15 @@
org.apache.maven.plugins
maven-antrun-plugin
+
+
+ com.sun
+ tools
+ 1.5.0
+ system
+ ${java.home}/../lib/tools.jar
+
+
compile-java-api
@@ -98,8 +105,8 @@
@@ -153,40 +160,5 @@
-
-
- legacy-jdk-tools
-
- (,9)
-
-
-
-
- org.apache.maven.plugins
- maven-antrun-plugin
-
-
- com.sun
- tools
- 1.5.0
- system
- ${java.home}/../lib/tools.jar
-
-
-
-
-
-
-
- modern-jdk
-
- [9,)
-
-
- 1.8
- 1.8
-
-
-
\ No newline at end of file
diff --git a/scripts/build-android-app.sh b/scripts/build-android-app.sh
index 6d90a33c53..0b98bff463 100755
--- a/scripts/build-android-app.sh
+++ b/scripts/build-android-app.sh
@@ -131,7 +131,7 @@ if [ ! -f "$PATCH_GRADLE_SOURCE_PATH/$PATCH_GRADLE_MAIN_CLASS.java" ]; then
exit 1
fi
-PATCH_GRADLE_JAVA="${JDK_HOME:-$JAVA17_HOME}/bin/java"
+PATCH_GRADLE_JAVA="${JAVA17_HOME:-${JDK_HOME:-$JAVA_HOME}}/bin/java"
if [ ! -x "$PATCH_GRADLE_JAVA" ]; then
ba_log "JDK java binary missing at $PATCH_GRADLE_JAVA" >&2
exit 1
diff --git a/scripts/setup-workspace.sh b/scripts/setup-workspace.sh
index ec3f401399..231fb89d14 100755
--- a/scripts/setup-workspace.sh
+++ b/scripts/setup-workspace.sh
@@ -22,8 +22,11 @@ ENV_DIR="$DOWNLOAD_DIR/tools"
mkdir -p "$DOWNLOAD_DIR"
mkdir -p "$ENV_DIR"
CN1_BINARIES_PARENT="$(cd .. && pwd -P)"
-CN1_BINARIES="${CN1_BINARIES_PARENT%/}/cn1-binaries"
-mkdir -p "$CN1_BINARIES_PARENT"
+CN1_BINARIES="${CN1_BINARIES:-${CN1_BINARIES_PARENT%/}/cn1-binaries}"
+if [[ "$CN1_BINARIES" != /* ]]; then
+ CN1_BINARIES="$(cd "${CN1_BINARIES%/*}" && pwd -P)/${CN1_BINARIES##*/}"
+fi
+mkdir -p "$(dirname "$CN1_BINARIES")"
ENV_FILE="$ENV_DIR/env.sh"
@@ -183,36 +186,43 @@ log "Maven version:"; "$MAVEN_HOME/bin/mvn" -version
PATH="$JAVA_HOME/bin:$MAVEN_HOME/bin:$PATH"
log "Preparing cn1-binaries checkout"
-if [ -d "$CN1_BINARIES/.git" ]; then
+if [ "${CN1_SKIP_BINARIES_UPDATE:-0}" = "1" ]; then
+ log "Skipping cn1-binaries update as requested"
+elif [ -d "$CN1_BINARIES/.git" ]; then
log "Found existing cn1-binaries repository at $CN1_BINARIES"
if git -C "$CN1_BINARIES" remote get-url origin >/dev/null 2>&1; then
- if git -C "$CN1_BINARIES" fetch --depth=1 origin; then
- remote_head=$(git -C "$CN1_BINARIES" symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null || true)
- if [ -z "$remote_head" ]; then
- current_branch=$(git -C "$CN1_BINARIES" rev-parse --abbrev-ref HEAD 2>/dev/null || true)
- if [ -n "$current_branch" ] && [ "$current_branch" != "HEAD" ]; then
- remote_head="origin/$current_branch"
- else
- remote_head="origin/master"
- fi
- fi
- if ! git -C "$CN1_BINARIES" rev-parse --verify "$remote_head" >/dev/null 2>&1; then
- if git -C "$CN1_BINARIES" rev-parse --verify origin/main >/dev/null 2>&1; then
- remote_head="origin/main"
- elif git -C "$CN1_BINARIES" rev-parse --verify origin/master >/dev/null 2>&1; then
- remote_head="origin/master"
+ # Check if directory is writable before attempting update
+ if [ -w "$CN1_BINARIES" ] && [ -w "$CN1_BINARIES/.git" ]; then
+ if git -C "$CN1_BINARIES" fetch --depth=1 origin; then
+ remote_head=$(git -C "$CN1_BINARIES" symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null || true)
+ if [ -z "$remote_head" ]; then
+ current_branch=$(git -C "$CN1_BINARIES" rev-parse --abbrev-ref HEAD 2>/dev/null || true)
+ if [ -n "$current_branch" ] && [ "$current_branch" != "HEAD" ]; then
+ remote_head="origin/$current_branch"
+ else
+ remote_head="origin/master"
+ fi
+ fi
+ if ! git -C "$CN1_BINARIES" rev-parse --verify "$remote_head" >/dev/null 2>&1; then
+ if git -C "$CN1_BINARIES" rev-parse --verify origin/main >/dev/null 2>&1; then
+ remote_head="origin/main"
+ elif git -C "$CN1_BINARIES" rev-parse --verify origin/master >/dev/null 2>&1; then
+ remote_head="origin/master"
+ else
+ log "Unable to determine remote head for cached cn1-binaries; removing checkout"
+ rm -rf "$CN1_BINARIES"
+ fi
+ fi
+ if [ -d "$CN1_BINARIES/.git" ]; then
+ log "Updating cn1-binaries to $remote_head"
+ git -C "$CN1_BINARIES" reset --hard "$remote_head"
+ fi
else
- log "Unable to determine remote head for cached cn1-binaries; removing checkout"
+ log "Failed to fetch updates for cached cn1-binaries; removing checkout"
rm -rf "$CN1_BINARIES"
fi
- fi
- if [ -d "$CN1_BINARIES/.git" ]; then
- log "Updating cn1-binaries to $remote_head"
- git -C "$CN1_BINARIES" reset --hard "$remote_head"
- fi
else
- log "Failed to fetch updates for cached cn1-binaries; removing checkout"
- rm -rf "$CN1_BINARIES"
+ log "cn1-binaries directory is not writable. Skipping update."
fi
else
log "Cached cn1-binaries checkout missing origin remote; removing"
diff --git a/vm/ByteCodeTranslator/nbproject/project.properties b/vm/ByteCodeTranslator/nbproject/project.properties
index dffab45210..6c504978bc 100644
--- a/vm/ByteCodeTranslator/nbproject/project.properties
+++ b/vm/ByteCodeTranslator/nbproject/project.properties
@@ -29,9 +29,9 @@ dist.jar=${dist.dir}/ByteCodeTranslator.jar
dist.javadoc.dir=${dist.dir}/javadoc
endorsed.classpath=
excludes=
-file.reference.asm-9.8.jar=../../../cn1-binaries/vm/asm-9.8.jar
-file.reference.asm-commons-9.8.jar=../../../cn1-binaries/vm/asm-commons-9.8.jar
-file.reference.asm-tree-9.8.jar=../../../cn1-binaries/vm/asm-tree-9.8.jar
+file.reference.asm-5.0.3.jar=../../../cn1-binaries/vm/asm-9.8.jar
+file.reference.asm-commons-5.0.3.jar=../../../cn1-binaries/vm/asm-commons-9.8.jar
+file.reference.asm-tree-5.0.3.jar=../../../cn1-binaries/vm/asm-tree-9.8.jar
includes=**
jar.compress=false
javac.classpath=\
diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java
index 14f56f231c..66f722e1a4 100644
--- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java
+++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/BytecodeMethod.java
@@ -62,7 +62,6 @@
* @author Shai Almog
*/
public class BytecodeMethod implements SignatureSet {
- private static MethodDependencyGraph dependencyGraph;
/**
* @return the acceptStaticOnEquals
@@ -77,10 +76,6 @@ public static boolean isAcceptStaticOnEquals() {
public static void setAcceptStaticOnEquals(boolean aAcceptStaticOnEquals) {
acceptStaticOnEquals = aAcceptStaticOnEquals;
}
-
- public static void setDependencyGraph(MethodDependencyGraph dependencyGraph) {
- BytecodeMethod.dependencyGraph = dependencyGraph;
- }
private List arguments = new ArrayList();
private Set localVariables = new HashSet();
private ByteCodeMethodArg returnType;
@@ -243,10 +238,6 @@ public BytecodeMethod(String clsName, int access, String name, String desc, Stri
}
currentArrayDim = 0;
}
-
- if (dependencyGraph != null) {
- dependencyGraph.registerMethod(this);
- }
}
// use this instead of isMethodUsed to compare traditional with new results
@@ -359,40 +350,20 @@ public boolean isMethodUsedByNative(String[] nativeSources, ByteCodeClass cls) {
private Set usedMethods;
public boolean isMethodUsedOldWay(BytecodeMethod bm) {
- ensureUsedMethodsInitialized();
+ if(usedMethods == null) {
+ usedMethods = new TreeSet();
+ for(Instruction ins : instructions) {
+ String s = ins.getMethodUsed();
+ if(s != null && !usedMethods.contains(s)) {
+ usedMethods.add(s);
+ }
+ }
+ }
if(bm.methodName.equals("__INIT__")) {
return usedMethods.contains(bm.desc + ".");
}
return usedMethods.contains(bm.desc + "." + bm.methodName);
}
-
- public Set getCalledMethodSignatures() {
- ensureUsedMethodsInitialized();
- return usedMethods;
- }
-
- public String getLookupSignature() {
- if(methodName.equals("__INIT__")) {
- return desc + ".";
- }
- if(methodName.equals("__CLINIT__")) {
- return desc + ".";
- }
- return desc + "." + methodName;
- }
-
- private void ensureUsedMethodsInitialized() {
- if(usedMethods != null) {
- return;
- }
- usedMethods = new TreeSet();
- for(Instruction ins : instructions) {
- String s = ins.getMethodUsed();
- if(s != null && !usedMethods.contains(s)) {
- usedMethods.add(s);
- }
- }
- }
public void findWritableFields(Set outSet) {
int len = instructions.size();
@@ -979,48 +950,32 @@ public String getMethodName() {
}
public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (!(o instanceof BytecodeMethod)) {
- return false;
- }
-
BytecodeMethod bm = (BytecodeMethod)o;
-
- if (!methodName.equals(bm.methodName)) {
+ int val = bm.methodName.compareTo(methodName);
+ if(val != 0) {
return false;
}
- if (acceptStaticOnEquals) {
- if (bm.arguments.size() != arguments.size()) {
+ if(acceptStaticOnEquals) {
+ if(bm.arguments.size() != arguments.size()) {
return false;
}
} else {
- if (staticMethod || bm.staticMethod || bm.arguments.size() != arguments.size()) {
+ if(staticMethod || bm.staticMethod || bm.arguments.size() != arguments.size()) {
return false;
}
}
-
- for (int iter = 0; iter < arguments.size(); iter++) {
+ for(int iter = 0 ; iter < arguments.size() ; iter++) {
ByteCodeMethodArg arg1 = arguments.get(iter);
ByteCodeMethodArg arg2 = bm.arguments.get(iter);
- if (!arg1.equals(arg2)) {
+ if(!arg1.equals(arg2)) {
return false;
}
}
-
- if (returnType == null) {
- return bm.returnType == null;
- }
return returnType.equals(bm.returnType);
}
public int hashCode() {
- int result = methodName == null ? 0 : methodName.hashCode();
- result = 31 * result + arguments.size();
- result = 31 * result + (acceptStaticOnEquals || !staticMethod ? 0 : 1);
- result = 31 * result + (returnType == null ? 0 : returnType.hashCode());
- return result;
+ return methodName.hashCode();
}
public boolean isStatic() {
@@ -1094,12 +1049,6 @@ public void setMaxes(int maxStack, int maxLocals) {
private void addInstruction(Instruction i) {
instructions.add(i);
i.addDependencies(dependentClasses);
- if (dependencyGraph != null) {
- String methodUsed = i.getMethodUsed();
- if (methodUsed != null) {
- dependencyGraph.recordMethodCall(this, methodUsed);
- }
- }
}
public void addVariableOperation(int opcode, int var) {
diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/MethodDependencyGraph.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/MethodDependencyGraph.java
deleted file mode 100644
index 79a29af124..0000000000
--- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/MethodDependencyGraph.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Codename One designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Codename One through http://www.codenameone.com/ if you
- * need additional information or have any questions.
- */
-
-package com.codename1.tools.translator;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Maintains a hierarchical dependency index between classes and methods so we
- * can cheaply look up callers and prune eliminated elements without rescanning
- * bytecode.
- */
-public class MethodDependencyGraph {
- private final Map> callersByLookupSignature = new HashMap>();
- private final Map> methodToCalls = new IdentityHashMap>();
- private final Map> methodsByClass = new HashMap>();
-
- private static Set newIdentitySet() {
- return Collections.newSetFromMap(new IdentityHashMap());
- }
-
- public void clear() {
- callersByLookupSignature.clear();
- methodToCalls.clear();
- methodsByClass.clear();
- }
-
- public void registerMethod(BytecodeMethod method) {
- Set byClass = methodsByClass.get(method.getClsName());
- if (byClass == null) {
- byClass = newIdentitySet();
- methodsByClass.put(method.getClsName(), byClass);
- }
- byClass.add(method);
- }
-
- public void recordMethodCall(BytecodeMethod caller, String calleeSignature) {
- Set callers = callersByLookupSignature.get(calleeSignature);
- if (callers == null) {
- callers = newIdentitySet();
- callersByLookupSignature.put(calleeSignature, callers);
- }
- callers.add(caller);
-
- Set calls = methodToCalls.get(caller);
- if (calls == null) {
- calls = new HashSet();
- methodToCalls.put(caller, calls);
- }
- calls.add(calleeSignature);
- }
-
- public List getCallers(String calleeSignature) {
- Set callers = callersByLookupSignature.get(calleeSignature);
- if (callers == null) {
- return new ArrayList();
- }
- return new ArrayList(callers);
- }
-
- public void removeMethod(BytecodeMethod method) {
- Set calls = methodToCalls.remove(method);
- if (calls != null) {
- for (String call : calls) {
- Set callers = callersByLookupSignature.get(call);
- if (callers != null) {
- callers.remove(method);
- if (callers.isEmpty()) {
- callersByLookupSignature.remove(call);
- }
- }
- }
- }
-
- Set byClass = methodsByClass.get(method.getClsName());
- if (byClass != null) {
- byClass.remove(method);
- if (byClass.isEmpty()) {
- methodsByClass.remove(method.getClsName());
- }
- }
- }
-
- public void removeClass(String clsName) {
- Set methods = methodsByClass.remove(clsName);
- if (methods != null) {
- for (BytecodeMethod method : new ArrayList(methods)) {
- removeMethod(method);
- }
- }
- }
-}
diff --git a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/Parser.java b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/Parser.java
index c5c5603190..d6671d0c7e 100644
--- a/vm/ByteCodeTranslator/src/com/codename1/tools/translator/Parser.java
+++ b/vm/ByteCodeTranslator/src/com/codename1/tools/translator/Parser.java
@@ -50,20 +50,16 @@ public class Parser extends ClassVisitor {
private String clsName;
private static String[] nativeSources;
private static List classes = new ArrayList();
- private static MethodDependencyGraph dependencyGraph = new MethodDependencyGraph();
private int lambdaCounter;
public static void cleanup() {
- nativeSources = null;
- classes.clear();
- dependencyGraph.clear();
- BytecodeMethod.setDependencyGraph(null);
- LabelInstruction.cleanup();
+ nativeSources = null;
+ classes.clear();
+ LabelInstruction.cleanup();
}
public static void parse(File sourceFile) throws Exception {
if(ByteCodeTranslator.verbose) {
System.out.println("Parsing: " + sourceFile.getAbsolutePath());
}
- BytecodeMethod.setDependencyGraph(dependencyGraph);
ClassReader r = new ClassReader(new FileInputStream(sourceFile));
/*if(ByteCodeTranslator.verbose) {
System.out.println("Class: " + r.getClassName() + " derives from: " + r.getSuperName() + " interfaces: " + Arrays.asList(r.getInterfaces()));
@@ -503,8 +499,8 @@ private static int eliminateUnusedMethods(boolean forceFound, int depth) {
}
private static int cullMethods() {
- int nfound = 0;
- for(ByteCodeClass bc : classes) {
+ int nfound = 0;
+ for(ByteCodeClass bc : classes) {
bc.unmark();
if(bc.isIsInterface() || bc.getBaseClass() == null) {
continue;
@@ -523,7 +519,6 @@ private static int cullMethods() {
continue;
}
mtd.setEliminated(true);
- dependencyGraph.removeMethod(mtd);
nfound++;
}
}
@@ -601,7 +596,6 @@ private static int cullClasses(boolean found, int depth) {
int nfound = 0;
for (ByteCodeClass cls : removedClasses) {
nfound += cls.setEliminated(true);
- dependencyGraph.removeClass(cls.getClsName());
}
classes = tmp;
return nfound + eliminateUnusedMethods(nfound > 0, depth + 1);
@@ -619,13 +613,14 @@ private static boolean isMethodUsed(BytecodeMethod m, ByteCodeClass cls) {
if (!m.isEliminated() && m.isMethodUsedByNative(nativeSources, cls)) {
return true;
}
- List callers = dependencyGraph.getCallers(m.getLookupSignature());
- for (BytecodeMethod caller : callers) {
- if(caller.isEliminated() || caller == m) {
- continue;
- }
- if(caller.isMethodUsed(m)) {
- return true;
+ for(ByteCodeClass bc : classes) {
+ for(BytecodeMethod mtd : bc.getMethods()) {
+ if(mtd.isEliminated() || mtd == m) {
+ continue;
+ }
+ if(mtd.isMethodUsed(m)) {
+ return true;
+ }
}
}
return false;
diff --git a/vm/JavaAPI/pom.xml b/vm/JavaAPI/pom.xml
index 4b9eac6a49..a74120c9bb 100644
--- a/vm/JavaAPI/pom.xml
+++ b/vm/JavaAPI/pom.xml
@@ -13,24 +13,6 @@
jar
JavaAPI
-
- 1.5
- 1.5
-
-
-
-
- modern-jdk
-
- [9,)
-
-
- 1.8
- 1.8
-
-
-
-
src
@@ -39,8 +21,8 @@
maven-compiler-plugin
3.11.0
- ${maven.compiler.source}
- ${maven.compiler.target}
+ 1.5
+ 1.5
-Xlint:-options