Let's setup a simple multi-project build using sbt
, assuming we're already familiar with regular single-project builds.
We have two deliverable sub-projects (multi1
and multi2
) and a common-stuff sub-project (common
) on which they both depend on.
To simplify development and maintenance we can use a single build.sbt
file which allows for centralized configuration, dependency and build management.
Then each sub-project contains nothing but its source code, while they can depend on other sub-projects.
Finally, we only need to generate artifacts for deliverable sub-projects.
This is the project file tree:
Our build file will include all the configuration we need:
First of all we define our projects:
global
: the parent project, aggregating the otherscommon
: where the common code ismulti1
and multi2
: the two deliverables, which depend on common
Using aggregate
in global
implies that running a task on the aggregate project will also run it on the aggregated ones. On the other hand, using dependsOn
sets the code dependency between sub-projects.
By default, dependency is set for the compile
configuration. If we'd need to also depend on the test
configuration (i.e. we have tests depending on other sub-project's test source code), we'd need to define dependency as follows: common % "compile->compile;test->test"
.
Since the global
project is in the project root folder, we need to explicitly specify it using in(file(".")
. There's no need to do so with the other sub-projects since they are located in a folder with the same name.
We can setup some global settings as follows:
Settings that are subject to change can be defined as values that can later be used by each sub-project. Here we're defining the Scala compiler options and some extra repositories:
Then we can use them in the sub-projects:
We'll follow the same strategy with the dependencies. First we define our catalog of dependencies:
Then we identify the common ones used by all sub-projects:
And finally we define each sub-project's dependencies combining the common with the specific ones:
The parent project, global
, needs no dependencies since it has no code at all. The other sub-projects have the common dependencies along with some specific ones: multi1
requires monocle
and multi2
requires pureconfig
.
To generate artifacts for our deliverable sub-projects we'll use sbt-assembly to produce a fat-jar (if we'd need to generate Docker images we could use sbt-native-packager instead).
First we define the corresponding settings:
And then we add them only to the settings of our deliverable sub-projects multi1
and multi2
:
Simply running sbt clean compile test assembly
will clean, compile and test all the sub-projects and generate a fat-jar only for our two deliverable sub-projects.
The full source code of this example can be found at this repository.
Would you like to leave a comment? Since this blog is hosted on GitHub Pages there's no straightforward way to do so.
Instead, you can add a comment in this GitHub issue. If you'd like to see it here, refresh this page after posting the comment.