scala - SBT build structure for a mono repository -
i'd use sbt build structured around single git repository tens of projects. i'd have following possibilities build:
- one-click build/test/release of projects in build.
- define , apply common settings projects in build.
- define project-specific settings in project sub-directories, keeping root of build clean.
- project should able depend on each other, but...
- most of projects not depend on each other in classpath sense.
- some of projects sbt plugins should included other projects (but not of them).
now these requirements in mind, should structure of build? because of requirement 3, can't go single build.sbt
in root of build, because don't want put projects settings there, since lot of text, , every change in single project reflected on top level.
i've heard usage of *.sbt
files both root project , sub-projects error-prone , not recommended (producing no artifact root project package under multi-project build in sbt, or how can use sbt plugin dependency in multi-project build?, sbt: plugins.sbt in subproject ignored? etc.). i've tried simple multi-projects builds *.sbt
files on different levels, , worked. pitfalls need keep in mind if i'll go multi *.sbt
files approach, given requirements above?
ok, since no 1 have posted far, i've figured post i've learned doing mono repository sbt far.
some facts first: our sbt build consists of 40+ projects, 10+ common projects (in sense other projects depend on them), , 5 groups of projects related single product (5-7 projects in each group). in each group, there's typically 1 group-common project.
build organization
we have following build structure:
- one main
build.sbt
whole build. - one
build.sbt
per project. - several local sbt plugins in
project
directory.
let's talk each of these items.
1. main build.sbt
in file, general build structure defined. namely, keep cross-project dependencies in there. don't use standard commonsettings
approach, in:
val commonsettings = seq(scalaversion := "2.12.3", ...) ... val proj1 = (project in file("p1")).settings(commonsettings) val proj2 = (project in file("p2")).settings(commonsettings) ...
this wordy , easy wrong new project. instead use local sbt project automatically applies every project in build (more on later).
2. per-project build.sbt
in files, define project settings (non-auto plugins, library dependencies, etc.). don't define cross-project dependencies in these files, because doesn't work expected. sbt loads *.sbt
files in order, , project definition in every build overrides found ones. in other words, if avoid (re-)defining projects in per-project *.sbt
files, things work well. other settings can kept there, avoid clutter in main build.sbt
.
3. local sbt plugins
we use trick define sbt auto-plugin in <root_dir>/project/
directory, , make them load automatically projects in build. use plugins automatically define settings , tasks projects (for things scalastyle, scalafmt, sonar, deployment, etc.). keep common settings there (scalaversion, etc.). thing keep in <root_dir>/project/
common dependencies versions (not in plugin, pure *.scala
file).
summary
using sbt mono repository seems work, , has advantages , disadvantages.
advantages: it's super easy re-use code between products. common sbt stuff scalastyle, scalafmt, etc. defined once, , new projects free. upgrading dependency version done in 1 place projects, when upgrades version, or projects @ once, different teams benefit that. requires discipline between teams, worked far.
another advantage use of common tooling. have gerrit+jenkins continuous integration, , have single job e.g. pre-submit verification. new projects lot of machinery pretty free, again.
disadvantages: one, build load time. on top 13" macbook pro can last 30+ seconds (this time starting sbt getting sbt's command prompt). not bad if can keep sbt running though. it's worse intellij refreshing build information, can take around 15 minutes. don't know why takes longer in sbt, here's that. can mitigated avoiding refreshing intellij unless absolutely necessary, it's real pain.
yet problem can't load individual project or group of projects intellij idea. forced load build of whole mono repository. if possible, then, guess, intellij's situation have been better.
another disadvantage fact 1 can't use different versions of same sbt plugin different projects. when 1 project can't upgraded new plugin version reason, whole repository has wait. useful, is, expedites maintenance work, , forces keep projects in maintenance mode date. legacy projects can challenging.
conclusion
all in all, have worked around year in mode, , intend keep doing in foreseeable future. concerns long intellij idea refresh time, , gets worse add more projects build. might evaluate alternative build systems later avoid loading projects in isolation intellij performance, sbt seems task.
Comments
Post a Comment