Daniel
Daniel

Reputation: 9524

How to reference a project definition in a parent build.sbt file?

I'm playing around with the scala-forklift library and wanted to test an idea by modifying the code in the library and example project.

This is how the project is structured:

lazy val slickMigrationProject =
  Project("scala-forklift-slick", file(...))
    .dependsOn(...)
    .settings(...)
    ...

My goal is to replace the scala-forklift-slick Maven package reference with a reference to the code in the parent directory, perhaps via .dependsOn(slickMigrationProject)?

Attempts:

According to the documentation:

Any .sbt files in foo, say foo/build.sbt, will be merged with the build definition for the entire build, but scoped to the hello-foo project.

But this does not seem to apply to lazy val values, as I can't access slickMigrationProject from the parent project directly.

I have been successful copying the entire contents of /example/build.sbt into /build.sbt and tweaking things a bit, but I was wondering if there was a better "one-liner" kind of solution instead. Here is what my combined /build.sbt file looks like:

val repoKind = SettingKey[String]("repo-kind",
  "Maven repository kind (\"snapshots\" or \"releases\")")

lazy val slickVersion = "3.3.3"

lazy val scala212 = "2.12.11"
lazy val scala213 = "2.13.1"
lazy val supportedScalaVersions = List(scala212, scala213)

lazy val coreDependencies = libraryDependencies ++= List(
  "org.scala-lang" % "scala-compiler" % scalaVersion.value,
  "com.typesafe" % "config" % "1.3.2",
  "org.eclipse.jgit" % "org.eclipse.jgit" % "4.0.1.201506240215-r"
)

lazy val slickDependencies = List(
  "com.typesafe.slick" %% "slick" % slickVersion,
  "com.typesafe.slick" %% "slick-codegen" % slickVersion,
  "io.github.nafg" %% "slick-migration-api" % "0.7.0",
  "org.scala-lang.modules" %% "scala-collection-compat" % "2.0.0"
)

lazy val slickDependenciesWithTests = slickDependencies ++ List(
  "org.scalatest" %% "scalatest" % "3.1.0",
  "com.lihaoyi" %% "ammonite-ops" % "2.0.4",
  "commons-io" % "commons-io" % "2.6",
  "com.typesafe.slick" %% "slick-hikaricp" % slickVersion,
  "com.h2database" % "h2" % "1.4.200",
  "org.xerial" % "sqlite-jdbc" % "3.8.11.2",// 3.30.1 crashes SQLiteCommandTests
  "mysql" % "mysql-connector-java" % "5.1.38",
  "org.postgresql" % "postgresql" % "42.2.9",
  "org.hsqldb" % "hsqldb" % "2.5.0",
  "org.apache.derby" % "derby" % "10.14.2.0",
  "ch.qos.logback" % "logback-classic" % "1.2.3"
).map(_ % "test")

lazy val commonSettings = Seq(
  organization := "com.liyaos",
  licenses := Seq("Apache 2.0" ->
    url("https://github.com/lastland/scala-forklift/blob/master/LICENSE")),
  homepage := Some(url("https://github.com/lastland/scala-forklift")),
  scalaVersion := scala213,
  scalacOptions += "-deprecation",
  scalacOptions += "-feature",
  resolvers += Resolver.jcenterRepo,
  publishMavenStyle := true,
  publishArtifact in Test := false,
  repoKind := { if (version.value.trim.endsWith("SNAPSHOT")) "snapshots"
                else "releases" },
  publishTo := { repoKind.value match {
    case "snapshots" => Some("snapshots" at
        "https://oss.sonatype.org/content/repositories/snapshots")
    case "releases" =>  Some("releases"  at
        "https://oss.sonatype.org/service/local/staging/deploy/maven2")
  }},
  credentials += Credentials(Path.userHome / ".ivy2" / ".credentials"),
  pomExtra := (
    <scm>
      <url>[email protected]:lastland/scala-forklift.git</url>
      <connection>scm:git:[email protected]:lastland/scala-forklift.git</connection>
      </scm>
      <developers>
      <developer>
      <id>lastland</id>
      <name>Yao Li</name>
      </developer>
      </developers>))

// Derby is running is secured mode since version 10.12.1.1, so security manager must be disabled for tests  
// https://stackoverflow.com/questions/48008343/sbt-test-does-not-work-for-spark-test
// https://issues.apache.org/jira/browse/DERBY-6648
Test / testOptions += Tests.Setup(() => System.setSecurityManager(null))

lazy val root = Project(
  "scala-forklift", file(".")).settings(
  crossScalaVersions := Nil,
  publishArtifact := false).aggregate(
  coreProject, slickMigrationProject, plainMigrationProject, gitToolProject, example)

lazy val coreProject = Project(
  "scala-forklift-core", file("core")).settings(
  commonSettings:_*).settings {Seq(
    crossScalaVersions := supportedScalaVersions,
    coreDependencies
  )}

lazy val slickMigrationProject = Project(
  "scala-forklift-slick", file("migrations/slick")).dependsOn(
  coreProject).settings(commonSettings:_*).settings { Seq(
    crossScalaVersions := supportedScalaVersions,
    libraryDependencies ++= slickDependenciesWithTests
  )} 

lazy val plainMigrationProject = Project(
  "scala-forklift-plain", file("migrations/plain")).dependsOn(
  coreProject).settings(commonSettings:_*).settings(crossScalaVersions := supportedScalaVersions)

lazy val gitToolProject = Project(
  "scala-forklift-git-tools", file("tools/git")).dependsOn(
  coreProject).settings(commonSettings:_*).settings(crossScalaVersions := supportedScalaVersions)

///////////////////////////////////////////////

name := "forklift-slick-example"

addCommandAlias("mgm", "example/migration_manager/run")

addCommandAlias("mg", "example/migrations/run")

lazy val exampleCommonSettings = Seq(
  organization := "com.liyaos",
  version := "2.0",
  scalaVersion := "2.13.1",
  scalacOptions += "-deprecation",
  scalacOptions += "-feature",
  resolvers += Resolver.sonatypeRepo("snapshots"),
  resolvers += Resolver.jcenterRepo,

)

lazy val loggingDependencies = List(
  "org.slf4j" % "slf4j-nop" % "1.6.4" // <- disables logging
)

lazy val exampleSlickDependencies = List(
  "com.typesafe.slick" %% "slick" % slickVersion
)

lazy val dbDependencies = List(
  "com.typesafe.slick" %% "slick-hikaricp" % slickVersion
  ,"com.h2database" % "h2" % "1.4.200"
)

lazy val forkliftDependencies = List(
//  "com.liyaos" %% "scala-forklift-slick" % forkliftVersion
)

lazy val appDependencies = dbDependencies ++ loggingDependencies

lazy val migrationsDependencies =
  dbDependencies ++ forkliftDependencies ++ loggingDependencies

lazy val migrationManagerDependencies = dbDependencies ++ forkliftDependencies

lazy val example = Project("example", file("example")).aggregate(
  app, migrations, migrationManager, generatedCode, tools).settings(
  exampleCommonSettings:_*)

lazy val app = Project("app", file("example/app"))
  .dependsOn(generatedCode)
  .settings(exampleCommonSettings:_*)
  .settings {libraryDependencies ++= appDependencies}

lazy val migrationManager = Project("migration_manager", file("example/migration_manager"))
  .dependsOn(slickMigrationProject)
  .settings(exampleCommonSettings:_*)
  .settings {libraryDependencies ++= migrationManagerDependencies}

lazy val migrations = Project("migrations", file("example/migrations"))
  .dependsOn(generatedCode, migrationManager, slickMigrationProject)
  .settings(exampleCommonSettings:_*)
  .settings {libraryDependencies ++= migrationsDependencies}

lazy val tools = Project("git-tools", file("example/tools/git"))
  .dependsOn(slickMigrationProject, gitToolProject)
  .settings(commonSettings:_*)
  .settings {
    libraryDependencies ++= forkliftDependencies ++ List(
//    "com.liyaos" %% "scala-forklift-git-tools" % forkliftVersion,
      "com.typesafe" % "config" % "1.3.0",
      "org.eclipse.jgit" % "org.eclipse.jgit" % "4.0.1.201506240215-r"
    )
  }

lazy val generatedCode = Project("generate_code", file("example/generated_code"))
  .settings(exampleCommonSettings:_*)
  .settings {libraryDependencies ++= exampleSlickDependencies}

Question:

Is there a simple way I can replace the scala-forklift-slick Maven package reference in /example/build.sbt with a link to the existing scala-forklift-slick project definition in the parent directory's build.sbt so I can use .dependsOn(...) instead?

Or maybe it's better to do something like build scala-forklift-slick and use a local disk package resolver?

Upvotes: 1

Views: 220

Answers (1)

Daniel
Daniel

Reputation: 9524

Luis Miguel Mejía Suárez's comment worked perfectly and was the easier approach.

In the context of this project, all I had to do was:

  1. Append -SNAPSHOT to the version in /version.sbt (should not be needed normally but for this project I had to do this)
  2. Run sbt publishLocal in the parent project.

After this, the example project (which already targets the -SNAPSHOT version) is able to pick up the locally built package.

Upvotes: 1

Related Questions