Reputation: 25865
I'd like to create an SBT project with inheritance and shared dependencies.
With Maven's POM files, there is the idea of Project Inheritance where you can set a parent
project. I'd like to do the same thing with SBT.
The xchange-stream
library uses Maven's Project Inheritance to resolve subproject dependencies when compiled from the parent project.
Here is my idea of what the file structure would look like:
sbt-project/
project/
dependencies.scala # Contains dependencies common to all projects
build.sbt # Contains definition of parent project with references
# to subprojects
subproject1/
build.sbt # Contains `subproject3` as a dependency
subproject2/
build.sbt # Contains `subproject3` as a dependency
subproject3/
build.sbt # Is a dependency for `subproject1` and `subproject2`
Where project1
and project2
can include project3
in their dependencies lists like this:
libraryDependencies ++= "tld.organization" % "project3" % "1.0.0"
Such that when subproject1
or subproject2
are compiled by invoking sbt compile
from within their subdirectories, or when the parent: sbt-project
is compiled from the main sbt-project
directory, then subproject3
will be compiled and published locally with SBT, or otherwise be made available to the projects that need it.
Also, how would shared dependencies be specified in sbt-project/build.sbt
or anywhere in the sbt-project/project
directory, such that they are useable within subproject1
and subproject2
, when invoking sbt compile
within those subdirectories?
The following examples don't help answer either of the above points:
jbruggem/sbt-multiproject-example
:
Uses recursive build.sbt
files, but doesn't share dependencies among child projects.
Defining Multi-project Builds with sbt: pbassiner/sbt-multi-project-example
:
Uses a single build.sbt
file for the projects in their subdirectories.
sachabarber/SBT_MultiProject_Demo
:
Uses a single build.sbt
file.
Upvotes: 6
Views: 1862
Reputation: 59
You can use Mecha super-repo concept. Take a look on the setup and docs here: https://github.com/storm-enroute/mecha
The basic idea is that you can combine dependent sbt projects (with their own build.sbt) under single root super-repo sbt project:
/root
/project/plugins.sbt
repos.conf
/project1
/src/..
/project/plugins.sbt
build.sbt
/project2
/src/..
/project/plugins.sbt
build.sbt
Please, note that there is no build.sbt
in the root folder!
Instead there is repos.conf
file. It contains definition of the sub-repos and looks like the folowing:
root {
dir = "."
origin = ""
mirrors = []
}
project1 {
dir = "project1"
origin = "[email protected]:some_user/project1.git"
mirrors = []
}
project2 {
dir = "project2"
origin = "[email protected]:some_user/project2.git"
mirrors = []
}
Then you can specify the Inter-Project, source-level Dependencies within individual projects.
There are two approaches:
dependencies.conf
fileFor more details, please, see the docs
Upvotes: 3
Reputation: 95654
Such that when
subproject1
orsubproject2
are compiled by invokingsbt compile
from within their subdirectories...
Maybe Maven is meant to be used together with the shell environment and cd
command, but that's not how sbt works at least as of sbt 1.x in 2019.
The sbt way is to use sbt
as an interactive shell, and start it at the top level. You can then either invoke compilation as subproject1/compile
, or switch into it using project subproject1
, and call compile
in there.
A feature similar to parent POM would be achieved by creating a custom plugin.
package com.example
import sbt._
import Keys._
object FooProjectPlugin extends AutoPlugin {
override def requires = plugins.JvmPlugin
val commonsIo = "commons-io" % "commons-io" % "2.6"
override def buildSettings: Seq[Def.Setting[_]] = Seq(
organization := "com.example"
)
override def projectSettings: Seq[Def.Setting[_]] = Seq(
libraryDependencies += commonsIo
)
}
It's not exactly what you are asking for, but I have an experimental plugin that allows you to switch between source dependency and binary dependency. See hot source dependencies using sbt-sriracha.
Using that you could create three individual sbt builds for project1
, project2
, and project3
, all located inside $HOME/workspace
directory.
ThisBuild / scalaVersion := "2.12.8"
ThisBuild / version := "0.1.1-SNAPSHOT"
lazy val project3Ref = ProjectRef(workspaceDirectory / "project3", "project3")
lazy val project3Lib = "tld.organization" %% "project3" % "0.1.0"
lazy val project1 = (project in file("."))
.enablePlugins(FooProjectPlugin)
.sourceDependency(project3Ref, project3Lib)
.settings(
name := "project1"
)
With this setup, you can launch sbt -Dsbt.sourcemode=true
and it will pick up project3 as a subproject.
Upvotes: 3