Optional Gradle build for apps, cn1libs and backends, on a shared build engine - #5922
Conversation
…ld engine Adds a Gradle plugin (id com.codenameone) that builds Codename One applications, cn1libs and backends with a single small project: one settings line, and native directories or a backend only when they are created. It reuses the Maven plugin's implementation rather than duplicating it: - maven/project-model: one project-layout API for Ant, Maven and Gradle, now used by the simulator, CSS compiler, Designer and the GUI tools. - maven/build-engine: the Maven-free build logic moved out of the Maven plugin behind a ProjectHost interface; the mojos are thin adapters. - maven/codenameone-gradle-plugin and its marker artifact. Also: initializr build-tool and project-type options, cn1:convert-to-gradle, Gradle skill text, the developer guide chapter, and gradle-smoke.yml, which holds Gradle to Maven parity (upload jars and generated android-source and ios-source projects) and to the minimum Gradle version. Maven fixes found on the way: the app archetype's win/linux modules never packaged src/main/c, and the four desktop tool launchers now share one implementation with the Gradle tasks. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Compared 12 screenshots: 12 matched. |
|
Developer Guide build artifacts are available for download from this workflow run:
Developer Guide quality checks: |
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
Cloudflare Preview
|
|
Compared 157 screenshots: 157 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
✅ ByteCodeTranslator Quality ReportTest & Coverage
Benchmark Results
Static Analysis
Generated automatically by the PR CI workflow. |
|
Compared 193 screenshots: 193 matched. |
…w setup - build-engine: declare JUnit before the ports. Maven orders the test classpath by declaration, and the Android platform jar's junit.* stubs shadowed JUnit 4, so the Vintage engine discovered no tests in a reactor build. Move the JavaScript proxy test-resource copy here with its test. - Gradle plugin: pin Kotlin compile tasks to the Java 17 target; on JDK 21 the Kotlin plugin refused the differing Java and Kotlin targets. - Integration scripts skip without a JDK 17+ (ant.yml runs all.sh on JDK 8 only); gradle-smoke.yml sets CN1_GRADLE_REQUIRED so it cannot skip. - gradle-smoke.yml: Zulu 8 on macOS ARM64, a display for the Settings build. - GUI Builder: its test still expected file://C:/, the form the shared fsUrl replaced with file:///C:/; drop the stale doc comment. - Close files in compare_generated_projects.py. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts: # maven/build-engine/src/main/java/com/codename1/builders/JavaScriptBuildHints.java # maven/build-engine/src/test/java/com/codename1/builders/JavaScriptBuildHintsTest.java
|
@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: ff31b922b3
ℹ️ 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".
- Gradle apps now take the platform artifacts of every cn1lib in the graph, not only declared ones: Maven activates codename1.platform in each pom, so a cn1lib used by another cn1lib contributes its native code too. Gradle cn1libs can use cn1libs (api scope), published as <type>pom</type>. - A cn1lib without CSS publishes no cn1css bundle (publishing failed). - Conversion keeps the backend's own dependencies in backend/build.gradle.kts and maps test-scoped dependencies to testImplementation. - cn1Css clears its output when CSS is switched off or theme.css is gone. - prepareSimulator reruns when the classpath or settings change. - A versionless com.codenameone dependency gets the framework version. - Cached native outputs are rebuilt when a build hint changes, tracked by a digest of the codename1.* properties. 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: 74764975a5
ℹ️ 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".
- Native uploads carry src/<platform>/resources beside the native sources, as a Maven platform module packages src/main/resources (parity test covers it). - cn1Test scans every test output directory, so Kotlin tests are found; the runner gains a multi-directory prepare(). - Kotlin + Java projects: jars keep one copy of the ORM enhancer's per-directory bookkeeping file instead of failing on the duplicate. - Hot reload's direct recompile uses the project's Java level (17 for Gradle, the settings file's for Maven and Ant) instead of a fixed 1.8. - compileJava/compileKotlin declare skipComplianceCheck and the codename1.* overrides as inputs, so a native build after a hot-reload compile reruns the compliance check. - Conversion keeps com.codenameone cn1libs and add-ons, dropping only the artifacts the plugin supplies, and carries an Ant project's own lib/ jars. - Versionless com.codenameone cn1libs get the framework version in the platform-artifact walk too; a Gradle cn1lib's JavaSE code compiles against the JavaSE jars of the cn1libs it uses. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
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 regression is a ratio more than 15% (time) / 15% (RAM) above its baseline in
Result: no regression |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fbe34d5f9b
ℹ️ 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".
- Native-interface generation and verification scan every main classes
directory, so Kotlin interfaces are checked and a pure Kotlin project no
longer fails input validation.
- Kotlin cn1libs get the compliance check.
- Java and Kotlin keep separate class directories (a shared one lost the
Kotlin classes on a Java full recompile); a generated file present in both
now fails the build by name instead of shipping one language's registry.
- Conversion interpolates ${...} versions from the pom and its parents and
comments out, with a warning, any it cannot resolve; a Kotlin backend gets
the Kotlin plugin in its own script, and counts as touched.
- transcodeSvg tracks src/main/lottie; cn1Css honours codename1.cssTheme from
Gradle properties and overrides.
- The initializr offers Gradle only once the plugin is published at the
version it generates against; update-cn1-version.sh sets the flag from the
repository.
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: 146c72e503
ℹ️ 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".
- Backends process Kotlin controllers and entities, and runBackend finds the
generated entry point in either classes directory.
- Annotation processing gets the source set's real directories, and reruns
when the settings file changes (it picks the entry point).
- transcodeSvg starts from empty outputs, so a deleted asset's class and
registry entry go away.
- Cached native outputs are rebuilt when a file on the upload classpath
changes, such as a jar replaced in place.
- codenameone { mainClass } now reaches every task, as the settings file's
packageName and mainName overrides.
- Conversion resolves versions left to dependencyManagement, keeps
classifiers and artifact types, comments out what it cannot resolve, and a
Kotlin backend under a Kotlin app names no second plugin version.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Compared 155 screenshots: 155 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6b09f581af
ℹ️ 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".
|
Compared 154 screenshots: 154 matched. Benchmark Results
Detailed Performance Metrics
|
…eload - Conversion reads dependencies as Maven resolves them: inherited from parent poms, with exclusions, system-scoped jars carried into libs/, the pom's repositories declared, and only the Kotlin artifacts the Kotlin plugin supplies left out (kotlin-reflect and org.jetbrains:annotations stay). - A backend counts as the untouched skeleton only when its code and settings match the generated template, so customised generated routes are kept. - cn1Css and generateGuiSources start from empty outputs, so a deleted theme or CodeRAD view no longer lingers. - Hot reload compiles against, and writes Kotlin classes to, Gradle's Kotlin classes directory. - backendPackage compiles the source set's configured directories. - addBackend in a build that applies the plugin from the root build script writes a backend script that applies it too. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…; hot reload outside the project
Codename One builds Java 17 bytecode only -- Android runs nothing newer, and
the compliance check transpiles newer class files down to 17 on purpose.
Two earlier review fixes assumed a build may target a higher release; they
are withdrawn:
- the Kotlin JVM target is pinned to 17 again, not to compileJava's release;
- hot reload recompiles at 17; the cn1.hotReload.release property is gone.
The release check, the guide and the skill no longer say "17 or newer", and
conversion keeps forcing 17, with the reason in a comment.
Also:
- cn1lib(project(":maps")) packages that library's platform jars: a Gradle
cn1lib exposes each one in a consumable configuration, and the build
tasks no longer capture the Project in lambdas, which the configuration
cache had to store once a dependency is a project of the build.
- A cn1lib platform profile's dependency takes its version from
<dependencyManagement> when the pom leaves it out.
- Hot reload treats a source root the launch names as the running
project's, even outside the project directory.
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: b99fa20e7f
ℹ️ 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".
…rectory
- A Gradle cn1lib exposes its cn1css zip to applications of the same build,
and an application declaring cn1lib(project(":maps")) compiles it into its
theme, as it does a published library's.
- Gradle's run and debug pass the build directory (cn1.buildDir), and the
simulator's project layout honours it, so simulator.properties, the
classes and the processed resources are found under a relocated build
directory.
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: 2ae983c4b9
ℹ️ 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".
…epositories warn - A cn1lib's -javase pom carries each javaseImplementation dependency's exclusions (a non-transitive one as *:*), so consumers drop what the library dropped. - Conversion reads <scope> and <type> through the pom's properties, as Maven's effective model does. - When the settings script declares the repositories (or a strict mode), the plugin still adds none -- under the default mode a project repository would make Gradle drop the settings' ones, a mirror with them -- but warns, naming the line to add, when none is the Codename One repository. 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: 555d4f6aec
ℹ️ 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".
… in conversion - The app-extension signing preflight looks where packaging takes the extensions from (layout().iosAppExtensionsDir()), so a Gradle build's src/ios/app_extensions is checked before the build is sent. - Conversion resolves properties defined by profiles a plain Maven build activates. - backendPackage keeps the compile classpath, as Maven's backend-package does; a comment says why a runtimeOnly library has no place in a ParparVM-translated binary. 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: aa778898b4
ℹ️ 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".
|
@codex review |
… stays literal - Gradle's run passes the project's path (cn1.gradleProjectPath), and the simulator's layout uses it for the build-tool fallback's cn1Compile, so a project whose path is decoupled from its directory recompiles. - The project name is escaped for the Kotlin string in settings.gradle.kts: a main class may hold a $, which Kotlin would read as a template. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aa778898b4
ℹ️ 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".
- Conversion resolves source and resource roots through the pom's
properties, and never deletes a conventional root because of one it
cannot resolve (that cost the project its sources).
- A scope given by <dependencyManagement> applies to a dependency that
declares none, as in Maven's effective model.
- A Gradle cn1lib that uses cn1lib(project(":maps")) publishes a dependency
on maps-lib (type pom), which is what Maven consumers resolve, rather
than the project's name or its -common publication.
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: f1b690b817
ℹ️ 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".
…sion - The staged Ant project gets the icon codename1.icon names at its relative path, which build.xml hands every target; only icon.png was staged, so a custom icon never reached the cloud build (Maven's builds too). - Conversion reads <sourceDirectory>, <testSourceDirectory>, <resources> and build-helper sources through the local parent poms, as Maven's effective model does. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…plates Master's Spring-style backend beans (#5908) land in build-engine, where the annotation processors moved: the dev-tools switch goes through BackendPackager for both plugins (-Pcn1.backend.devTools for Gradle), the bean tests run there with their SQLite driver, and the Gradle backend templates gain the Greeter service the archetype now injects into Api. Conversion's untouched-skeleton check expects that pair, and the Gradle backend checks call /greet so the wiring is exercised, not just /healthz. The skill's new backend references give the Gradle tasks beside the Maven goals. 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: bffdc7502f
ℹ️ 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".
…in Settings A published cn1lib's common jar no longer carries Gradle module metadata. Gradle prefers the .module, and java-library's named a project cn1lib by its plain -common jar, so a Gradle application got the inner library's classes and none of its platform jars. Without it Gradle reads the same pom Maven reads, and the build host now leaves a <type>pom</type> dependency's .pom file off the classpath, as Maven does, instead of opening it as a jar -- which also covers Maven-built cn1libs that depend on another cn1lib. A cn1lib platform dependency reached on two paths keeps both edges when their exclusions differ, so one path's exclusion no longer drops what the other keeps. codename1.kind applies to the root project only: a -P or gradle.properties value reaches every subproject and turned the included backend into an app. Settings writes Maven's LATEST/RELEASE as Gradle's latest.release. Conversion says when it leaves an untouched backend skeleton behind. 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: 4ec9f72410
ℹ️ 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".
| for (Element dep : children(dependencies, "dependency")) { | ||
| String scope = interpolate(text(child(dep, "scope")), props); | ||
| if ("test".equals(scope) || "provided".equals(scope) || "system".equals(scope)) { | ||
| continue; |
There was a problem hiding this comment.
Skip optional dependencies in cn1lib platform profiles
When a Maven-published cn1lib marks a dependency inside a codename1.platform profile as <optional>true</optional>, Maven does not propagate that dependency to applications consuming the cn1lib, but this parser filters only by scope and adds the optional coordinate to the Gradle platform configuration. A Gradle application therefore packages platform code and transitives that the library deliberately kept optional, potentially introducing conflicting native implementations; exclude optional profile dependencies when constructing the consumer configurations.
Useful? React with 👍 / 👎.
| Set<org.gradle.api.artifacts.result.ResolvedComponentResult> components; | ||
| try { | ||
| components = graph.getIncoming().getResolutionResult().getAllComponents(); |
There was a problem hiding this comment.
Traverse cn1libs introduced by platform profiles
When cn1lib A declares cn1lib B only inside a codename1.platform profile, B is absent from this one-time runtimeClasspath component set because Gradle does not activate A's profile. Reading A later adds B's -lib POM to the platform configuration, which brings in B's common classes, but B's own platform profiles are never inspected, so the native build omits B's Android/iOS implementation; expand or iterate over the platform graphs until newly introduced cn1libs have contributed their profiles too.
Useful? React with 👍 / 👎.
| upload.from(platformProvider.map(p -> platformFiles.containsKey(p) | ||
| ? platformFiles.get(p) : Collections.emptyList())); |
There was a problem hiding this comment.
Resolve platform dependencies with the runtime graph
When the application/runtime graph selects g:a:2 but a cn1lib's active platform profile requests g:a:1, these independently resolved platform files are appended to the runtime classpath rather than participating in the same conflict resolution. The upload therefore contains both versions, and jar merging can overwrite duplicate classes according to iteration order, whereas Maven's profile-enabled graph selects one version; constrain or resolve the platform edges together with the runtime graph before assembling the upload.
Useful? React with 👍 / 👎.
| File dir = from.nativeSourceDir(p); | ||
| if (hasFiles(dir)) { | ||
| copyTreeExcept(dir, to.nativeSourceDir(p), extras); |
There was a problem hiding this comment.
Move converted JavaSE resources to the resource source set
When an Ant project's native/javase directory contains non-Java resources used by its simulator implementation, the Ant build copies those files into native/internal_tmp, but conversion copies them into src/javase/java alongside the sources. The Gradle JavaSE source set reads resources only from src/javase/resources, so these files are omitted from its output and resource lookups fail after conversion; separate non-source files into the JavaSE resource directory.
Useful? React with 👍 / 👎.
…ilation Master moved the builders into maven/build-engine (#5922); this branch's builder changes and its builder tests (NativeThemes, desktop window size, iOS icons, macOS strip settings) follow them there. Conflicts: - GenerateAppProjectMojo: master's header. - copyright-header-exclusions.txt: both sides' entries. - SKILL.md description: master's Maven-or-Gradle wording plus the Flutter triggers. flutter-bench.yml also watches maven/build-engine/**, as master's other plugin-watching workflows now do. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…and-cleanup #5922 moved the plugin's processors and the backend packager into maven/build-engine. Resolved by moving this branch's work onto that layout: - The backend test pass (BackendTestGenerator, BackendTests) lives in the build engine, on its Log/BuildExecutionException types. - The compiled test run is BackendTestPackager, a BackendPackager subclass in the engine, over extension hooks added to BackendPackager. BackendTestMojo is a thin Maven front for it, as BackendPackageMojo is for BackendPackager; the AbstractBackendNativeMojo this branch had is gone. - Gradle backends get the same support: codenameone-backend-test and JUnit 5 on the test classpath, a JVM per test class, the test pass after compileTestJava, and a backendTest task for the compiled run. The Gradle backend template and the initializr's Gradle downloads carry the sample tests, and gradle-smoke runs them. - The Gradle Greeter template uses @component, not the removed @service. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An optional Gradle build for Codename One applications, cn1libs and backends, built on the Maven plugin's own implementation rather than beside it.
What a user gets
A single Gradle project:
settings.gradle.kts(one plugin line), an optionalbuild.gradle.kts, the wrapper, andsrc/main/.... Native directories (src/<platform>/<lang>) andbackend/appear only whengenerateNativeInterfacesoraddBackendcreate them. Gradle projects are Java 17+ and leave out Maven-era legacy (legacy.cn1libfiles, the legacy Designer task, the Java 8 target).cn1lib-archetype, so Maven apps can consume it and vice versa.run/debug, CSS,cn1Test, every cloud target plus localandroid-source/ios-source,-Pcodename1.stageOnly, native interfaces with a pre-build check that names a missing implementation, the desktop tools,runBackend/backendPackage,cn1Update. The configuration cache is on by default.mvn cn1:convert-to-gradleconverts a Maven or Ant project;cn1:generate-app-project -Dcn1.buildTool=gradle.How it is built
maven/project-model: one project-layout API for Ant, Maven and Gradle. The simulator, CSS compiler, Designer and the four GUI tools use it in place of their own copies of "where is the project".maven/build-engine: the Maven-free build logic moved out of the Maven plugin (builders, annotation processors, compliance, CSS, packaging, native-interface stubs), behind aProjectHostinterface. The Maven mojos are now thin adapters; their 402 tests pass unchanged.maven/codenameone-gradle-plugin(idcom.codenameone) plus its marker artifact, released through the same R2 pipeline.Maven fixes found along the way
win/linuxmodules never packagedsrc/main/c, so a Windows or Linux native-interface implementation never reached the build server. Found by the Maven/Gradle upload parity test.cn1:settings/guibuilder/gamebuilder/certificatewizardlaunchers now share the Gradle tasks'DesktopTool(-824 lines);-onow applies to all of them, and each fails fast on a missing dependency.Tests
maven/integration-tests/gradle-*.sh, new workflowgradle-smoke.yml):gradle-app-test.sh: convert, build, native-interface lifecycle, every target's upload jar,addBackend+/healthz.gradle-maven-parity-test.sh: one app built by Maven and by Gradle uploads the same entries for seven cloud targets and generates equivalentandroid-sourceandios-sourceprojects, compared file by file (macOS job for iOS).gradle-cn1lib-test.sh: a Gradle-built cn1lib consumed by a Gradle app and a Maven app.gradle-migrate-test.sh: Ant (Java + Kotlin) and Maven to Gradle; a legacy.cn1libis refused by name.gradle-initializr-test.sh: all three initializr Gradle downloads build; the backend-only one packages to a native binary that serves/healthz.gradle-tools-test.sh: Settings renders fromcn1:settingsand from./gradlew settings.Docs
New
Gradle-Project-Workflowchapter in the developer guide, plus updates to the Maven getting-started, native-interface, backend and appendix pages.Not included
pom.xml.🤖 Generated with Claude Code