打开一个新应用,本该直接看到应用本身。可过去的默认体验是:先面对一屏平台模块目录,代码还没写一行,就得先学会这套构建的结构。Codename One 这次把顺序调了过来——项目先变小,结构按需再加。
Codename One 是一个开源框架,用同一套 Java 或 Kotlin 代码库构建原生 iOS、Android、桌面和 Web 应用。上周它刚加上更小的 Gradle 项目,现在 Maven 也从小起步:应用原型默认只生成根 POM 和 common,不带任何平台模块。模拟器照跑,目标应用照建。
新项目里真正相关的部分是这样一棵树:
- my-app/ 下的 pom.xml
- common/ 下的 pom.xml
- codenameone_settings.properties
- src/main/java/ 与 src/main/resources/
这是一棵精简过的树,不是对每个生成资源或启动脚本的计数。结构上的数字是两个 POM。源码、CSS 和资源仍然待在 Maven 用户习惯的位置。
某个平台没有对应模块时,由 common 接管它的构建。下面这些命令的含义保持不变:
- mvn cn1:run
- mvn package -Dcodename1.platform=android
- mvn package -Pexecutable-jar -Dcodename1.platform=javase
在这种布局下,桌面可执行 JAR 落在 common/target。平台模块的价值在于某个目标需要独立的依赖或插件,而不是因为每个可能的目标在第一天就得占一个目录。
原生实现也不需要再多一个 POM。mvn cn1:generate-native-interfaces 依然会生成平台专属的源码目录:Android 实现可以放在 android/src/main/java,iOS 实现可以放在 ios/src/main/objectivec,这两个目录都不必变成 Maven 模块。
构建把某个平台当作独立模块,判断依据是 /pom.xml 是否存在;光有原生源码目录不会触发这个决定。JavaSE 实现会被编译进 common/target/cn1-javase/classes,与应用类分开,因此不会被误传进设备构建里。
这也让上周五引入的 Android 迁移更好上手:导入的 Android 源码放在 common/src/main/android,初次移植不必从读懂每个目标模块的 POM 开始。
原型里的 platformModules 属性默认是 none。all 会恢复完整的平台布局,逗号分隔的值如 javase,android 则只创建这几个模块。projectType 默认是 app,app-with-backend 会加上服务端,backend-only 则创建一个独立的服务端项目。
例如下面这些是追加在常规原型生成命令后面的选项,不能单独当命令用:
- -DplatformModules=javase,android
- -DprojectType=app-with-backend
纯后端项目的 POM 和 src/main/java 都在根目录,旁边不需要再放一个空的客户端,用 ./mvnw cn1:backend 和 ./mvnw cn1:backend-package 即可。
最小默认只作用于用更新后原型新生成的项目,不会从已有检出里删掉模块。简化旧项目之前,先检查有没有平台专属的构建配置,别默认它的 POM 都是空脚手架。
更小的项目树能帮新贡献者更快找到真正重要的代码,也让 LLM 在被要求改一个界面时少读到一些生成出来的配置文件。这只是周边材料的减少,并不保证生成的代码正确——该看 diff 看 diff,该跑相关应用行为照旧跑。
这些项目形态由 PR #5937 引入,当前的 archetype 参考文档定义了目标选择与原生目录的工作方式。从默认开始,等你有了具体的配置要放,再加平台模块。
热门跟贴