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