使用Mill发布含平台特定代码的JVM/JS跨平台库遇类型冲突问题
问题核心分析
报错的本质是类型不匹配:xpShared.jvm和xpShared.js因混入XP_Publish(继承自PublishModule),其moduleDeps要求依赖的模块必须也是PublishModule类型;但你定义的xpJVM、xpJS只是普通的ScalaModule子类,未实现PublishModule接口,导致编译器类型校验失败。
解决方案(贴合你偏好的依赖方式)
方案1:让平台特定模块兼容PublishModule类型
直接修改xpJVM和xpJS,让它们也混入XP_Publish(或直接继承PublishModule),同时修改artifactName避免发布冲突:
// JVM-specific stuff object xpJVM extends AppScalaModule with XP_Publish { override def artifactName = "xp-jvm" } // JS-specific stuff object xpJS extends AppScalaJSModule with XP_Publish { override def artifactName = "xp-js" }
修改后xpShared.jvm/js的moduleDeps就能正常依赖这两个模块,类型匹配问题解决。
方案2:显式放宽moduleDeps的类型约束
如果不想让平台特定模块成为可发布模块,可以显式指定moduleDeps的类型为父类ScalaModule,绕过PublishModule的强制类型要求:
object jvm extends SharedModule with XP_Publish { // 显式指定类型为ScalaModule,兼容普通模块依赖 override def moduleDeps: Seq[ScalaModule] = Seq(xpJVM) object test extends ScalaTests { def ivyDeps = Agg(ivy"com.lihaoyi::utest::0.8.5") def testFramework = "utest.runner.Framework" } } object js extends SharedModule with AppScalaJSModule with XP_Publish { override def moduleDeps: Seq[ScalaModule] = Seq(xpJS) object test extends ScalaTests with ScalaJSTests { def ivyDeps = Agg(ivy"com.lihaoyi::utest::0.8.5") def testFramework = "utest.runner.Framework" } }
对你提出方案的评价
- 关于
CrossScalaModule:完全没必要采用。CrossScalaModule是用于多Scala版本编译的工具,和JVM/JS跨平台无关,反而会增加不必要的构建复杂度,直接排除该方案即可。 - 关于重写
sources纳入平台代码:该方案可行,但会模糊模块边界,不利于后续维护(尤其是平台代码量增加后)。如果平台特定代码极少,可临时用这种方式;但长期来看,依赖方式的模块化程度更高,更推荐采用前面的方案。
内容的提问来源于stack exchange,提问作者bwbecker
相关产品推荐
相关产品推荐

