Minimal and backend-only Maven projects, default from 7.0.275 - #5937
Conversation
Maven projects can now omit every platform module: the root pom and common/ build all platforms, run the simulator and tests, and package the desktop app. A platform has its own module exactly when <platform>/pom.xml exists; adding one later moves that platform's build into it. A backend-only project is a single module at the root. The archetype generates the minimal layout by default (-DplatformModules, -DprojectType); the Initializr does once its plugin is 7.0.275 or newer, with the full layout as an opt-in. Also fixes JUnit tests in generated apps, which never ran: Surefire only had Codename One's stub provider. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Developer Guide build artifacts are available for download from this workflow run:
Developer Guide quality checks: |
Cloudflare Preview
|
|
Compared 157 screenshots: 157 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
|
Compared 193 screenshots: 193 matched. |
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
|
Compared 154 screenshots: 154 matched. Benchmark Results
Detailed Performance Metrics
|
✅ ByteCodeTranslator Quality ReportTest & Coverage
Benchmark Results
Static Analysis
Generated automatically by the PR CI workflow. |
|
Compared 166 screenshots: 166 matched. Benchmark Results
Detailed Performance Metrics
ParparVM vs HotSpot (JDK 25): macOS arm64Runner CPU: Apple M1 (Virtual) (baseline Ratios are ParparVM / JDK 25: below 1.00x ParparVM is faster (time) or smaller (RAM). Median of 5 interleaved, paired rounds; every run's output was verified. A ratio more than 15% (time) / 15% (RAM) away from its baseline in
Result: no regression |
|
Compared 155 screenshots: 155 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 150 screenshots: 150 matched. |
|
Compared 155 screenshots: 155 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
Compared 223 screenshots: 223 matched. |
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d1c060c49d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- The archetype build injected the hosted profiles with Ant's <replace>, which
rewrites through an owner-only (0600) temp file. The staged common/pom.xml
was then unreadable to the runner and hashFiles('**/pom.xml') failed the
guibuilder job's cache step. Use a filtered <copy> of a deleted target.
- cn1-binaries-javase carries ${cn1.version}: the initializr's root pom does
not manage it, so its simulator profiles had no version. A test now checks
every fragment dependency against both root poms, and the initializr build
hook resolves the simulator profile.
- compile-javase-natives re-extracts cn1lib natives from scratch and records
resource names, so removed sources and deleted resources rebuild.
- cn1:update works for a backend-only project at the root.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9dbddc3a2f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- The hosted simulator refuses a JDK older than 11 up front, as cn1:run and cn1:debug do, instead of letting a Java 8 launcher read its argument file as a class name. The simulator needs JDK 11+ at runtime whatever the project's source level; the integration test prepares it on the newer JDK CI names. - Desktop profiles that run JavaSE code from common, executable-jar and test included, ship cn1-binaries-javase like the javase module, so the packaged desktop app keeps the bundled FFmpeg binaries. - compile-javase-natives keys its cache on each cn1lib archive's content hash. - cn1:update fails with a clear message when a project lacks the cn1.version or cn1.plugin.version property, instead of an NPE. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The Java CI leg runs integration-tests/all.sh on JDK 8 with no newer JDK named, so preparing the simulator there now refuses (it needs JDK 11+). Assert that refusal and its message on an older JDK; prepare and check the classpath on a newer one. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a195783e67
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- generate-desktop-app-wrapper deletes a stub it generated earlier once a custom javase/src/desktop/java stub appears, so the two are never compiled together. - compile-javase-natives skips builds for a platform other than javase: a device build uploads none of it, and a desktop-only compile error must not stop it. Builds that name no platform (mvn test) still compile it. - Its cache requires the output directory to exist, and the stamp goes with the output when there is nothing left to compile. - The hosted desktop jar takes the javase natives, resources and desktop resources before common's classes, the order a full layout's classpath resolves them in. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
@codex review |
|
Codex Review: Didn't find any major issues. Swish! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Merged master (#5937, minimal and backend-only Maven projects). The backend-only Maven project now gets the @backendtest setup and the two sample tests every other backend layout has; the generated project's mvn test runs them (3 tests). Review fixes: - CORS same-origin detection compares the scheme too: the request's own (X-Forwarded-Proto behind a TLS terminating proxy, else whether the server speaks TLS). http://api.example calling https://api.example skipped the policy. - Surefire %regex[...] includes, excludes and -Dtest entries select as Surefire does, over the class path. - hasTests() counts Kotlin test sources, so a Kotlin-only suite reaches the explicit "Kotlin tests cannot be compiled" failure. - assertEquals with a negative or NaN delta fails on the delta first, with JUnit 5.9's own failure (measured: AssertionFailedError, not IllegalArgumentException). - TestRestTemplate targets the server's real scheme and listen address. - A test or lifecycle method that returns a value is a build error for the compiled run, as JUnit does not run it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ilation Brings in #5937 (minimal and backend-only Maven projects), whose cn1app-minimal-layout-test.sh generates a project on JDK 8. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s for 17 This branch had changed the default from "auto" to 17, so a project generated on JDK 8 targeted Java 17 and did not compile there. Master's cn1app-minimal-layout-test.sh (#5937) generates on JDK 8 and failed with "invalid target release: 17" in archetype-smoke and build-linux-jdk8. "auto" already resolves to 17 on any JDK >= 17, which is what a Flutter project needs; the Flutter benchmark now passes -DjavaVersion=17 explicitly rather than depending on the JDK it runs on. Verified: generated on JDK 8 the project gets java.version=8 and common compiles. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…layout Since #5937 the archetype generates the minimal layout, which has no android/ or ios/ module: the builds write their Gradle and Xcode source projects under common/target. build_apps.sh looked only in android/target and ios/target, so the Android leg reported "no generated Gradle project" after a successful build. Both lookups now search the project's target directories. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Gradle projects got two shapes in #5922 that Maven lacked: a minimal tree with no per-OS modules, and a backend-only project. This brings both to Maven and makes them the default for new projects. The archetype switches over immediately. The Initializr switches once its plugin is 7.0.275 or newer, which happens automatically when
update-cn1-version.shbumps it.The layouts
common+javaseandroidiosjavascriptwinlinux+backendcommon-DplatformModules=all/ "Include all platform modules"common+backend-DprojectType=app-with-backend-DprojectType=backend-only-DplatformModules=all -DprojectType=app-with-backendreproduces the old layout exactly.How a project with no platform modules builds
One rule decides it: a platform has a module of its own exactly when
<root>/<platform>/pom.xmlexists.common's stand-ins skip themselves, so a project that adds a module later never builds a platform twice.commondoes the work.common/pom.xmlcarries one shared fragment,scripts/initializr/common/src/main/resources/common-hosted-platform-profiles.xml, which the archetype and the Initializr both inject. It contains:cn1-host-<platform>profiles, active on-Dcodename1.platform=<p>and a missing../<p>/pom.xml(Maven ANDs the two). They bindcn1:buildfromcommon.cn1-javase-natives, which compilesjavase/src/main/java(plus cn1libnativesesources and the desktop stub) intocommon/target/cn1-javase/classes. That is nevertarget/classes, which every device build uploads, and it is outside the bytecode-compliance check.javasemodule used to own:simulator,idea-simulator,debug-simulator,debug-eclipse,run-desktop,executable-jar,testandrun-android. Each of their goals carries<hostedPlatform>, and each third-party execution reads thecn1.hosted.<p>.skipproperty those goals set.<module>/pom.xmlto exist.activeByDefaultis dropped when there is nojavasemodule, because Maven applies it even when the profile's own conditions fail.<platform>/src/main/....cn1:generate-native-interfacescreates those directories with nopom.xml, and a build fromcommonuploads them exactly as a module would package them.New in the plugin:
HostedPlatformsandAbstractCN1Mojo.hostedPlatform.hosted-platform,compile-javase-nativesandjavase-executable-jar.cn1:build,prepare-simulator-classpath,generate-desktop-app-wrapper,cn1:test,cn1:run,cn1:debugandcn1:simulator.exec:exec's<classpath/>cannot be extended. The file also keeps long classpaths under the Windows command-line limit.ProjectLayoutgainshasPlatformModule,nativeResourcesDirandplatformUploadDirs; the Gradle plugin now uses the sharedplatformUploadDirs.MAVEN/BACKEND.The version gate:
origin/masterfor every Maven and Gradle download), apart from the JUnit fix below and the agent-skill text.hosted-platform/compile-javase-nativesgoal, rather than building nothing.cn1:updaterefuses to move such a project below 7.0.275.update-cn1-version.shnow fails if it did not rewriteCN1_PLUGIN_VERSION.A pre-existing bug this fixes: JUnit tests never ran
Generated Maven apps advertise
mvn testfor JUnit 5 tests, but the root pom gives Surefire Codename One's stub provider, which returns no tests. A deliberately failing@Testpassed the build in the full layout on master. Thejavasemodule,common.zipand the newcommonprofile now also declaresurefire-junit-platform, so JUnit tests run, a failing one fails the build, and-DskipTestsstill skips. Existing downloads change in this one respect.How this was verified
New integration test
maven/integration-tests/cn1app-minimal-layout-test.sh, inarchetype-smoke.ymlandall.sh. It generates a minimal app and a backend-only project and checks:pom.xml;cn1:testand JUnit both reach a JavaSE native that only a JDK compiles;-Pexecutable-jardesktop jar has the right Main-Class, stub, natives, icons and native theme;commonwith exactly their own native files, and no JavaSE classes reach the Android upload;android/pom.xmlmoves the Android build into the module;/healthz.Run locally against a fresh full install of the reactor:
cn1app-minimal-layout-test.sh(withCN1_BACKEND_PACKAGE_REQUIRED=1),cn1app-archetype-test.sh(full layout, including the native backend),cn1app-staged-jar-test.sh, and these integration scripts, which now pass the full-layout flags:build-hint-annotations-test.sh,cn1app-desktop-build-test.sh,initializr-roundtrip-test.sh,gradle-maven-parity-test.sh,gradle-migrate-test.shandnative-interfaces.sh.cn1:run,-pl common cn1:run, andverify -Psimulatorwith and without-Dcodename1.platform, on both layouts. This used a stand-injavaon PATH, so no window opened.GeneratorModelIntegrationBuildTestnow does this whenCN1_MAVEN_PLUGIN_VERSIONis set (opt-in, like its Gradle half).HostedPlatformsTestis new, and includes a structural test that every goal in the shared fragment steps aside for a module), Gradle plugin 19, and the Initializr's 6 tests (including the version gate and the Maven layout matrix across templates and IDEs).Docs
The developer guide covers the layouts and the opt-in flags in the archetype appendix, which pom to edit when there are no platform modules, backend-only projects in the backend chapter, and the native interface paths. The generated project's README has a project layout section, and the agent skill now uses root-level
mvn package -Dcodename1.platform=...commands that work in either layout.🤖 Generated with Claude Code