如何使用类路径从 sbt 运行 编码?

how to run code from sbt with a classpath?

我正在尝试 运行 使用自定义生成器(我的 ExampleCodeGenerator)生成 Slick 代码。我将 ExampleCodeGenerator.scala 放入 project 子目录中,以便构建脚本可以使用它。我构建了一个 classpath: Seq[File],其中包含编译 ExampleCodeGeneratorclasses 目录,以及来自 Compile / dependencyClasspath.

的 JAR

如果我按照 the lead given in the Slick documentation for sbt 并在我的 .sbt 文件中写入:

runner.value.run("slick.codegen.SourceCodeGenerator",
  classpath, Seq(profile, driver, url, outputDir.getPath, pkg, "", "", "true", className, "true"), logger
)

我得到一个ClassNotFoundException: scala.Serializable

如果我尝试 standalone instructions 并写:

slick.codegen.SourceCodeGenerator.main(
  Array(profile, driver, url, outputDir.getPath, pkg, "", "", "true", className, "true")
)

我得到的是 ClassNotFoundException: ExampleCodeGenerator,即使 sbt 代码可以找到 class,并且被调用的代码正在同一个线程中执行 Class.forName()

如果我将 Scala 库添加到项目的 libraryDependencies 并重试第一种方法,我仍然会收到 Serializable 错误。


我看过Chris Vogt's really old example。但我认为没有必要将项目拆分为两个项目来执行此操作。

我的代码在 https://github.com/performantdata/custom-slickgen.

我想我明白了。

第一种情况的问题是,为了让我的 ExampleCodeGenerator 在主构建脚本中可用,我将它放在 project 子目录中。不过,这些文件是使用 sbt 使用的 Scala 编译器版本编译的——在本例中为 2.12.14。在 2.12 中,scala.Serializable 存在,但在 2.13 中它被替换为类型别名。所以这通常是行不通的,因为我正在 run-ing 代码与基础项目的 Scala 版本,它可能不同,实际上是 2.13。我可以将此 2.12 classes 目录强制放入 class 路径,但无济于事。

在第二种情况下,我的猜测是从 SourceCodeGenerator.main 调用的 Class.forName() 正在使用 SourceCodeGenerator 对象的 class 的 class 加载程序,并且该加载器是 sbt.internal.PluginManagement.PluginClassLoader 的一个实例,一个 java.net.URLClassLoader subclass 包含(基础或构建,不确定)项目中 JAR 的所有 URL ,但 不是 构建项目的 classes 目录 URL。所以加载程序找不到 ExampleCodeGenerator.

解决方法好像是我平时看到的:再创建一个子项目,构建一个基础项目所依赖的JAR。这似乎是不可避免的。