diff --git a/BUILDING.md b/BUILDING.md index 7e13a0714b..d62623f736 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -4,7 +4,8 @@ This guide explains how to build Codename One from source using Maven. It provid ## Prerequisites -- **JDK 8** +- **JDK 8** for compiling the core framework (the core modules use `-source 1.5 -target 1.5` for backward compatibility) +- **JDK 11 through 25** for *running* the simulator and the "Run as desktop app" target - **JDK 17** for building the Android port - **Apache Maven 3.6+** - macOS with Xcode (required only for the iOS port) diff --git a/CLAUDE.md b/CLAUDE.md index 2c2f4690b8..781e8ece65 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -20,7 +20,8 @@ The project is transitioning from Ant to Maven. **Maven is the preferred build s ### Building from Source **Requirements:** -- JDK 8 (required for core build) +- JDK 8 (required for the core framework build) +- JDK 11 through 25 (required at *runtime* for the simulator and "Run as desktop app") - JDK 17 (required for Android port) - Apache Maven 3.6+ - macOS with Xcode (for iOS port only) @@ -166,7 +167,8 @@ To use locally-built version, edit the generated `pom.xml`: - **Tooling/Plugins**: Can use Java 8+ - **Tests**: Can use Java 11+ - **Android build**: Requires JDK 17 in JAVA17_HOME -- **Main JAVA_HOME**: Must be JDK 8 +- **Main JAVA_HOME (for building the framework)**: Must be JDK 8 +- **Runtime JDK for simulator / desktop run**: JDK 11 through 25 is supported. The Codename One Maven plugin checks this on entry to `cn1:run` and `cn1:debug` and aborts with a friendly error when an older JDK is in use. The build-time goals (`generate-desktop-app-wrapper`, `prepare-simulator-classpath`, the `executable-jar` profile) are not gated -- they still work on JDK 8 because they only generate icons / classpath metadata. ### Working with Native Code @@ -251,7 +253,8 @@ The JavaSE port serves as the simulator with: ### Common Issues -- **JDK version mismatch**: Ensure JAVA_HOME is JDK 8, JAVA17_HOME is JDK 17 +- **JDK version mismatch**: Ensure JAVA_HOME is JDK 8 for building the framework, JAVA17_HOME is JDK 17 for the Android port +- **`Unrecognized option: --add-exports=...`** when running the simulator or desktop app: the project is being executed on a JDK older than 11. Switch to JDK 11 through 25 (Eclipse Temurin from ) and re-run. The Codename One Maven plugin now detects this and prints a friendly error before the JVM is forked. - **Missing cn1-binaries**: Run `setup-workspace.sh` or manually clone to `../cn1-binaries` - **Build client missing**: Copy `maven/CodeNameOneBuildClient.jar` to `~/.codenameone/` - **macOS ARM JDK8**: Setup script downloads x64 version (works via Rosetta) diff --git a/README.md b/README.md index 6d31deb4e4..ccecde3525 100644 --- a/README.md +++ b/README.md @@ -177,7 +177,9 @@ The setup is covered in depth in [this article and video](https://www.codenameon " img width="80%"> -**IMPORTANT:** Building Codename One requires **JDK 8**, currently. You cannot use JDK 11 as some sub-modules must use `-source 1.5` and `-target 1.5` to maintain backward compatibility with parts of the toolchain. +**IMPORTANT:** *Building* the Codename One framework from source requires **JDK 8** -- some sub-modules must use `-source 1.5` and `-target 1.5` to maintain backward compatibility with parts of the toolchain, and newer JDKs cannot emit those targets. + +*Running* a Codename One application (the simulator or the "Run as desktop app" target) supports **JDK 11 through 25** (Eclipse Temurin: ). ### Quick Start with Maven diff --git a/docs/developer-guide/Index.asciidoc b/docs/developer-guide/Index.asciidoc index 3a530f23b7..2221d5bd52 100644 --- a/docs/developer-guide/Index.asciidoc +++ b/docs/developer-guide/Index.asciidoc @@ -214,7 +214,7 @@ This means that in runtime a user might revoke a permission. A good example for === Installing Codename One -IMPORTANT: Codename One requires either JDK 11 or JDK 8. Other JDK versions aren't supported now. +IMPORTANT: Codename One supports JDK 11 through 25 for running the simulator and the desktop ("Run as desktop app") target. Eclipse Temurin (https://adoptium.net) is the easiest way to install a supported JDK. Codename One projects are built with Maven. Typical Maven targets such as `package`, `clean` and `install` work out of the box, but the Codename One integrations that ship with each IDE provide dedicated Run and Build actions for a smoother workflow. diff --git a/docs/developer-guide/Maven-Getting-Started.adoc b/docs/developer-guide/Maven-Getting-Started.adoc index 45747bc260..acdf985307 100644 --- a/docs/developer-guide/Maven-Getting-Started.adoc +++ b/docs/developer-guide/Maven-Getting-Started.adoc @@ -1,5 +1,25 @@ == Getting started +[#prerequisites] +=== Prerequisites + +Codename One supports JDK 11 through 25 for running the simulator and the +"Run as desktop app" target. https://adoptium.net[Eclipse Temurin] is the +easiest source of a supported JDK on macOS, Windows, and Linux. + +After installing the JDK, point `JAVA_HOME` at it and confirm with: + +[source,bash] +---- +java -version +mvn -v +---- + +Both should report Java 11 or newer. The Codename One Maven plugin checks the +runtime JDK version when you invoke `mvn cn1:run` or `mvn cn1:debug` and fails +fast with a friendly message if it is older than 11. Build-only goals (such as +`-Pexecutable-jar`) still work on older JDKs. + [#creating-app-project] === Creating a new project diff --git a/docs/developer-guide/Working-With-CodenameOne-Sources.asciidoc b/docs/developer-guide/Working-With-CodenameOne-Sources.asciidoc index d5e9dc68cc..4af76abbaf 100644 --- a/docs/developer-guide/Working-With-CodenameOne-Sources.asciidoc +++ b/docs/developer-guide/Working-With-CodenameOne-Sources.asciidoc @@ -11,7 +11,9 @@ Codename One uses multiple JDKs and Maven profiles during the build. Make sure your development machine includes the following tooling (see `BUILDING.md` for platform-specific installation tips): -* JDK 8 (required for the core build and Maven invocations) +* JDK 8 (required for the core build of the framework itself) +* JDK 11 through 25 (required at *runtime* to launch the simulator or + "Run as desktop app" target) * JDK 17 (required when compiling the Android port) * Apache Maven 3.6 or newer * macOS with Xcode (if you plan to build or test the iOS port) diff --git a/maven/codenameone-maven-plugin/src/main/java/com/codename1/maven/CN1DebugMojo.java b/maven/codenameone-maven-plugin/src/main/java/com/codename1/maven/CN1DebugMojo.java index e148a8c0f8..b80f005d73 100644 --- a/maven/codenameone-maven-plugin/src/main/java/com/codename1/maven/CN1DebugMojo.java +++ b/maven/codenameone-maven-plugin/src/main/java/com/codename1/maven/CN1DebugMojo.java @@ -24,6 +24,9 @@ protected void executeImpl() throws MojoExecutionException, MojoFailureException return; } + JavaVersionUtil.requireRuntimeJavaVersion(JavaVersionUtil.MIN_RUNTIME_JAVA_VERSION, + "debug the Codename One simulator"); + InvocationRequest request = new DefaultInvocationRequest(); diff --git a/maven/codenameone-maven-plugin/src/main/java/com/codename1/maven/CN1RunMojo.java b/maven/codenameone-maven-plugin/src/main/java/com/codename1/maven/CN1RunMojo.java index 05f0c0c021..769e534b75 100644 --- a/maven/codenameone-maven-plugin/src/main/java/com/codename1/maven/CN1RunMojo.java +++ b/maven/codenameone-maven-plugin/src/main/java/com/codename1/maven/CN1RunMojo.java @@ -25,6 +25,9 @@ protected void executeImpl() throws MojoExecutionException, MojoFailureException return; } + JavaVersionUtil.requireRuntimeJavaVersion(JavaVersionUtil.MIN_RUNTIME_JAVA_VERSION, + "run the Codename One simulator"); + InvocationRequest request = new DefaultInvocationRequest(); diff --git a/maven/codenameone-maven-plugin/src/main/java/com/codename1/maven/JavaVersionUtil.java b/maven/codenameone-maven-plugin/src/main/java/com/codename1/maven/JavaVersionUtil.java index 13dd8bc5f1..3fdd006ecb 100644 --- a/maven/codenameone-maven-plugin/src/main/java/com/codename1/maven/JavaVersionUtil.java +++ b/maven/codenameone-maven-plugin/src/main/java/com/codename1/maven/JavaVersionUtil.java @@ -3,9 +3,13 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.maven.plugin.MojoFailureException; + final class JavaVersionUtil { private static final Pattern MAJOR_VERSION_PATTERN = Pattern.compile("^(?:1\\.)?(\\d+)"); + static final int MIN_RUNTIME_JAVA_VERSION = 11; + private JavaVersionUtil() { } @@ -27,4 +31,47 @@ static int parseJavaVersion(String version, int defaultValue) { return defaultValue; } } + + /** + * Returns the major Java version of the JVM running this code (e.g. 8, 11, 17). + * Falls back to {@code defaultValue} if the version cannot be parsed. + */ + static int getRuntimeMajorVersion(int defaultValue) { + String spec = System.getProperty("java.specification.version"); + int parsed = parseJavaVersion(spec, -1); + if (parsed > 0) { + return parsed; + } + return parseJavaVersion(System.getProperty("java.version"), defaultValue); + } + + /** + * Aborts the current Maven goal with a friendly, actionable message when the JVM + * Maven is running on is older than the supplied minimum. + * + * @param minimumMajorVersion smallest acceptable major version (e.g. 11) + * @param operationLabel short description of what the user was trying to do (used in the error message) + */ + static void requireRuntimeJavaVersion(int minimumMajorVersion, String operationLabel) throws MojoFailureException { + int current = getRuntimeMajorVersion(-1); + if (current >= minimumMajorVersion) { + return; + } + String detected = current > 0 + ? "Java " + current + : "an unknown Java version (java.version=" + System.getProperty("java.version") + ")"; + String javaHome = System.getProperty("java.home"); + StringBuilder msg = new StringBuilder(); + msg.append('\n'); + msg.append("Codename One supports JDK ").append(minimumMajorVersion).append(" through 25 to ") + .append(operationLabel).append(".\n"); + msg.append("Detected ").append(detected); + if (javaHome != null) { + msg.append(" at ").append(javaHome); + } + msg.append(".\n\n"); + msg.append("Install JDK ").append(minimumMajorVersion).append(" or newer (e.g. Eclipse Temurin\n") + .append("from https://adoptium.net), point JAVA_HOME at it, and re-run this goal.\n"); + throw new MojoFailureException(msg.toString()); + } }