在两个 ScalaJS SBT 项目之间使用 DependsOn
Using DependsOn between two ScalaJS SBT projects
(前面的问题很长。在底部简化了 tl;dr)。
我有两个使用 SBT 构建的 ScalaJS 项目 - "myapp" 和 "mylib",在以下目录结构中
root/build.sbt
root/myapp/build.sbt
root/myapp/jvm/
root/myapp/js/
root/myapp/shared/
root/mylib/build.sbt
root/mylib/jvm
root/mylib/js
root/mylib/shared
lib
导出名为 "com.example:mylib:0.1" 的工件,用作 myapp
.
的 libraryDependency
myapp 和 mylib 在不同的存储库中,包含它们自己的构建文件,并且应该能够完全独立地构建(即它们必须包含它们自己的单独构建配置)。
在生产中,它们将单独构建 mylib
在单独构建 myapp
之前首先作为 maven 工件发布。
然而,在开发中,我希望能够将它们合并到一个父 SBT 项目中,以便可以并行开发两者,而无需在每次更改后使用 publishLocal
。
在传统(不是 scalajs)项目中,这会很容易
$ROOT/build.sbt:
lazy val mylib = project
lazy val myapp = project.dependsOn(mylib)
然而在 ScalaJS 中,我们实际上在每个模块中有两个项目 - appJVM
、appJS
、libJVM
和 libJS
。因此,上述配置仅找到聚合根项目,并没有将 dependsOn
配置正确应用到实际的 JVM 和 JS 项目。
(即 myapp 和 mylib build.sbt 每个包含两个项目和一个聚合根项目)
理想情况下,我希望能够执行以下操作
lazy val mylibJVM = project
lazy val myappJVM = project.dependsOn(mylibJVM)
lazy val mylibJS = project
lazy val myappJS = project.dependsOn(myappJS)
不幸的是,这只会在根目录中创建新项目,而不是导入子项目本身。
我也尝试过各种路径组合(例如)
lazy val mylibJVM = project.in(file("mylib/jvm"))
但这在 mylib
的 build.sbt 文件中看不到配置
最终我 运行 遇到了同样的问题 - 当将现有的多项目 SBT 项目导入父 sbt 文件时,它会导入根项目,但似乎没有提供导入的方法来自现有多模块 SBT 文件的子项目,允许我向其添加 dependsOn
配置。
tl;博士
如果我有
root/mylib/build.sbt
定义了多个项目并且
root/myapp/build.sbt
定义了多个项目
是否可以将单个子项目导入 root/build.sbt
而不是子模块中的根项目?
即我可以有两层多项目构建吗?
在花了很多时间研究 SBT 源代码后,我设法找到了解决方案。这不干净,但它有效。 (对于奖励积分,它可以正确导入 IntelliJ)。
// Add this function to your root build.sbt file.
// It can be used to define a dependency between any
// `ProjectRef` without needing a full project definition.
def addDep(from:String, to:String) = {
buildDependencies in Global <<= (
buildDependencies in Global,
thisProjectRef in from,
thisProjectRef in to) {
(deps, fromref, toref) =>
deps.addClasspath(fromref, ResolvedClasspathDependency(toref, None))
}
}
// `project` will import the `build.sbt` file
// in the subdirectory of the same name as the `lazy val`
// (performed by an SBT macro). i.e. `./mylib/build.sbt`
//
// This won't reference the actual subprojects directly,
// will but import them into the namespace such that they
// can be referenced as "ProjectRefs", which are implicitly
// converted to from strings.
//
// We then aggregate the JVM and JS ScalaJS projects
// into the new root project we've defined. (Which unfortunately
// won't inherit anything from the child build.sbt)
lazy val mylib = project.aggregate("mylibJVM","mylibJS")
lazy val myapp = project.aggregate("myappJVM","myappJS")
// Define a root project to aggregate everything
lazy val root = project.in(file(".")).aggregate(mylib,myapp)
// We now call our custom function to define a ClassPath dependency
// between `myapp` -> `mylib` for both JVM and JS subprojects.
// In particular, this will correctly find exported artifacts
// so that `myapp` can refer to `mylib` in libraryDependencies
// without needing to use `publishLocal`.
addDep("myappJVM", "mylibJVM")
addDep("myappJS","mylibJS")
(前面的问题很长。在底部简化了 tl;dr)。
我有两个使用 SBT 构建的 ScalaJS 项目 - "myapp" 和 "mylib",在以下目录结构中
root/build.sbt
root/myapp/build.sbt
root/myapp/jvm/
root/myapp/js/
root/myapp/shared/
root/mylib/build.sbt
root/mylib/jvm
root/mylib/js
root/mylib/shared
lib
导出名为 "com.example:mylib:0.1" 的工件,用作 myapp
.
myapp 和 mylib 在不同的存储库中,包含它们自己的构建文件,并且应该能够完全独立地构建(即它们必须包含它们自己的单独构建配置)。
在生产中,它们将单独构建 mylib
在单独构建 myapp
之前首先作为 maven 工件发布。
然而,在开发中,我希望能够将它们合并到一个父 SBT 项目中,以便可以并行开发两者,而无需在每次更改后使用 publishLocal
。
在传统(不是 scalajs)项目中,这会很容易
$ROOT/build.sbt:
lazy val mylib = project
lazy val myapp = project.dependsOn(mylib)
然而在 ScalaJS 中,我们实际上在每个模块中有两个项目 - appJVM
、appJS
、libJVM
和 libJS
。因此,上述配置仅找到聚合根项目,并没有将 dependsOn
配置正确应用到实际的 JVM 和 JS 项目。
(即 myapp 和 mylib build.sbt 每个包含两个项目和一个聚合根项目)
理想情况下,我希望能够执行以下操作
lazy val mylibJVM = project
lazy val myappJVM = project.dependsOn(mylibJVM)
lazy val mylibJS = project
lazy val myappJS = project.dependsOn(myappJS)
不幸的是,这只会在根目录中创建新项目,而不是导入子项目本身。
我也尝试过各种路径组合(例如)
lazy val mylibJVM = project.in(file("mylib/jvm"))
但这在 mylib
最终我 运行 遇到了同样的问题 - 当将现有的多项目 SBT 项目导入父 sbt 文件时,它会导入根项目,但似乎没有提供导入的方法来自现有多模块 SBT 文件的子项目,允许我向其添加 dependsOn
配置。
tl;博士
如果我有
root/mylib/build.sbt
定义了多个项目并且root/myapp/build.sbt
定义了多个项目
是否可以将单个子项目导入 root/build.sbt
而不是子模块中的根项目?
即我可以有两层多项目构建吗?
在花了很多时间研究 SBT 源代码后,我设法找到了解决方案。这不干净,但它有效。 (对于奖励积分,它可以正确导入 IntelliJ)。
// Add this function to your root build.sbt file.
// It can be used to define a dependency between any
// `ProjectRef` without needing a full project definition.
def addDep(from:String, to:String) = {
buildDependencies in Global <<= (
buildDependencies in Global,
thisProjectRef in from,
thisProjectRef in to) {
(deps, fromref, toref) =>
deps.addClasspath(fromref, ResolvedClasspathDependency(toref, None))
}
}
// `project` will import the `build.sbt` file
// in the subdirectory of the same name as the `lazy val`
// (performed by an SBT macro). i.e. `./mylib/build.sbt`
//
// This won't reference the actual subprojects directly,
// will but import them into the namespace such that they
// can be referenced as "ProjectRefs", which are implicitly
// converted to from strings.
//
// We then aggregate the JVM and JS ScalaJS projects
// into the new root project we've defined. (Which unfortunately
// won't inherit anything from the child build.sbt)
lazy val mylib = project.aggregate("mylibJVM","mylibJS")
lazy val myapp = project.aggregate("myappJVM","myappJS")
// Define a root project to aggregate everything
lazy val root = project.in(file(".")).aggregate(mylib,myapp)
// We now call our custom function to define a ClassPath dependency
// between `myapp` -> `mylib` for both JVM and JS subprojects.
// In particular, this will correctly find exported artifacts
// so that `myapp` can refer to `mylib` in libraryDependencies
// without needing to use `publishLocal`.
addDep("myappJVM", "mylibJVM")
addDep("myappJS","mylibJS")