"object is not a member of package" 当通过 slick codegen 导入从另一个项目构建的依赖项时

"object is not a member of package" when importing dependency built from another project via slick codegen

我有一个这样的多项目设置:

lazy val kalosrpc = project
  .settings(
    libraryDependencies ++= Seq(
      "io.grpc" % "grpc-netty" % scalapb.compiler.Version.grpcJavaVersion
    )
  ).dependsOn(kalosgen)

lazy val kalosgen = project
  .settings(
    // settings not important
  )

kalosgen 的主要 class 通过 slick-codegen 生成模型并将其放置在:

kalosgen/target/scala-2.13/src_managed/main 

在包中 com.kalos.gen。它还在编译时将 protobufs 编译成 scala classes,但该包按预期位于 class 路径中。

然后我可以将这些文件从 kalosgen 导入到 kalosrpc,intelliJ 不会抱怨并且可以完全访问这些文件中定义的类型信息。所以我 运行 kalosgen/compile 并且包是按照我的预期生成的,但是当我用 kalosrpc/compile 跟进时,我得到:

object gen is not a member of package com.kalos

我试过更改包的名称,但没有解决任何问题。根据信息 presented here 我的项目配置似乎是正确的。

尝试从 sbt 执行 show sourceManaged,它应该输出 generated files 应该结束的位置,例如在我的项目中它是

.../myproject/target/scala-2.13/src_managed

应该是

kalosgen/target/scala-2.13/src_managed/main/com/kalos/gen

而不是

kalosgen/target/scala-2.13/main/com/kalos/gen

还要仔细检查生成的文件是否在顶部包含包

这里的问题是我通过 slick-codegen 实用程序在 scala 代码中生成源代码:

import slick.codegen.SourceCodeGenerator

object Main extends App {
  val url = "hidden"
  val user = "hidden"
  val password = "hidden"
  val dbDriver = "com.mysql.jdbc.Driver"
  val profile = "slick.jdbc.MySQLProfile"
  SourceCodeGenerator.main(
    Array(
      profile,
      dbDriver,
      url,
      "./kalosgen/target/scala-2.13/src_managed/main",
      "com.kalos.gen",
      user,
      password
    )
  )
}

我的猜测是,您必须通过 SBT 任务生成源代码才能让 SBT 将它们识别为有效源代码(至少对于项目间依赖性而言),因此我能够将上述代码翻译成在 build.sbt:

编译时运行的任务
lazy val gen = project
  .settings(
    libraryDependencies ++= Seq(
      "dependencies"
    ),
    sourceGenerators in Compile += Def.task {
      val outDir = (sourceManaged in Compile).value.getPath
      (runner in Compile).value.run(
        "slick.codegen.SourceCodeGenerator",
        (dependencyClasspath in Compile).value.files,
        Array(
          "slick.jdbc.MySQLProfile",
          "com.mysql.jdbc.Driver",
          "url",
          outDir,
          "com.kalos.gen",
          "username",
          "password"
        ),
        streams.value.log
      )
      Seq(file(outDir + "/com/kalos/gen/Tables.scala"))
    }.taskValue
  )

现在生成的 Tables.scala 出现在 class 路径中,我的项目编译成功。如果对 sbt 有更多了解的人可以更全面地解释为什么会发生这种情况,我会很乐意接受它作为正确答案。