无需外部SBT插件实现多子项目依赖共享及自定义方法
没问题,这两个需求都能在不开发外部SBT插件的前提下完成,我会给你拆解每个场景的具体实现方式,再聊聊如何把逻辑迁移到所有项目都能访问的公共位置:
1. 在ProjectSetB/build.sbt中直接实现someHow()函数
SBT的build.sbt本质上就是一段Scala代码(基于SBT的DSL),所以你可以直接在文件里定义顶层函数,只要符合Scala语法,就能在同一个文件的项目配置里直接调用。
举个实际的例子,假设someHow()是用来给依赖统一加版本号的:
// 直接在build.sbt里定义自定义函数 def someHow(depGroupIdArtifactId: String): String = { // 这里写你的业务逻辑,比如拼接固定版本 s"$depGroupIdArtifactId:1.0.0" } // 在项目配置里调用这个函数 lazy val projectB = (project in file(".")) .settings( name := "ProjectSetB", libraryDependencies += someHow("com.example:core-library") )
如果你的ProjectSetB包含多个子项目,把这个函数放在build.sbt的最顶部,所有子项目的配置块都能直接访问它。
2. 在ProjectSetB/project/Dependencies.scala中实现someHow()函数
SBT的project/目录属于元构建(也就是构建自身的构建),这个目录下的Scala文件会在主构建(build.sbt)之前编译完成,所以在这里定义的函数可以被主构建轻松引用。
具体步骤:
- 创建
ProjectSetB/project/Dependencies.scala文件,用对象封装你的函数(避免命名冲突):
import sbt._ object Dependencies { // 定义someHow函数,比如把字符串转成SBT的ModuleID类型 def someHow(depStr: String): ModuleID = { depStr % "2.0.0" // 给依赖加上版本号 } // 还可以在这里集中管理公共依赖列表 val commonDeps = Seq( someHow("com.example:utils"), someHow("org.scalatest:scalatest") % Test ) }
- 在
ProjectSetB/build.sbt中导入并使用:
// 导入元构建里的Dependencies对象 import Dependencies._ lazy val projectB = (project in file(".")) .settings( name := "ProjectSetB", // 直接用公共依赖列表 libraryDependencies ++= commonDeps, // 单独调用someHow添加依赖 libraryDependencies += someHow("com.example:service") )
这种方式更适合把依赖管理、工具逻辑集中起来,让build.sbt保持简洁,也方便后续维护。
迁移到所有项目可访问的公共位置
如果你的多个项目(比如ProjectSetA、ProjectSetB)需要共享someHow()函数,有两种常用的方案:
方案1:根项目元构建共享(适合多项目聚合场景)
如果你的项目是聚合结构(比如有一个根目录包含所有子项目),可以把公共函数放在根目录的project/下:
root-project/ ├── project/ │ └── CommonSbtFunctions.scala // 这里放公共的someHow() ├── ProjectSetA/ │ └── build.sbt └── ProjectSetB/ └── build.sbt
在root-project/project/CommonSbtFunctions.scala里定义:
import sbt._ object CommonSbtFunctions { def someHow(dep: String): ModuleID = dep % "1.5.0" }
然后在ProjectSetA和ProjectSetB的build.sbt里直接导入使用:
import CommonSbtFunctions._ // 项目配置中调用someHow即可
方案2:独立元构建JAR(适合完全独立的项目)
如果各个项目是完全独立的,你可以把公共函数打包成一个Scala JAR,然后把这个JAR放到每个项目的project/lib/目录下。这样每个项目的元构建都能访问到这个JAR里的函数。不过这种方式比较繁琐,除非你有大量复杂的公共逻辑要复用,否则优先选方案1。
内容的提问来源于stack exchange,提问作者abroy

