alejandrohdezma / sbt-modules   0.4.1

Apache License 2.0 GitHub

SBT plugin that simplifies modules creation

Scala versions: 2.12
sbt plugins: 1.x

SBT plugin that simplifies modules creation

- publish / skip := true
- 
lazy val docs = project
-  .settings(publish / skip := true)
-  .dependsOn(allProjects: _*)
+  .dependsOn(allModules)
  .in(file("docs"))

+ lazy val `my-library-core` = module
- lazy val core = project
-   .in(file("modules/core"))
-   .settings(name := "my-library-core")

+ lazy val `my-library-plugin` = module 
- lazy val plugin = project
-   .in(file("modules/plugin"))
-   .settings(name := "my-library-plugin")
-   .dependsOn(core)
+   .dependsOn(`my-library-core`)
-
- lazy val allProjects: Seq[ClasspathDep[ProjectReference]] = Seq(
-   core,
-   plugin
- )

Installation

Add the following line to your plugins.sbt file:

addSbtPlugin("com.alejandrohdezma" % "sbt-modules" % "0.4.1")

Usage

Use module instead of project to create your SBT modules. Unlike project, module expects your modules to live in modules folder and uses the name of the variable for the project's ID and base folder (just like project does).

For example, the following SBT configuration:

lazy val `my-library-core` = module

lazy val `my-library-plugin` = module.dependsOn(`my-library-core`) 

Would expect the following directory structure:

.
+-- modules
|   +-- my-library-core
|       +-- src
|   +-- my-library-plugin
|       +-- src
+-- build.sbt
+-- project

Retrieveing all modules created with module

sbt-modules creates a special variable called allModules that aggregates all the modules created with module, so you can pass it along as a dependency to other projects in your build, like:

lazy val documentation = project.dependsOn(allModules)

lazy val `my-library-core` = module

lazy val `my-library-plugin` = module.dependsOn(`my-library-core`)

Important ‼️ The allModules variable is created by listing all the directories in the modules directory so ensure: (1) that all your modules have a corresponding directory inside modules and (2) that there are no directories inside modules that aren't a module.

packageIsModule setting

Every project created with module has an packageIsModule setting key automatically set to true. Regular projects and the root project have it set to false. This can be used by other plugins to detect which projects are modules.

Auto-publish / skip

Forget about setting publish / skip := true again. Adding this plugin to your build will disable publishing for all the projects in the build (including the auto-generated root plugin), except for those created with module.

The behavior is driven by the packageIsModule setting: projects with packageIsModule := true will have publish / skip := false (i.e., they will be published), while all others will have publish / skip := true. Other plugins that depend on ModulesPlugin can override publish / skip based on packageIsModule to implement custom publishing logic.

If you want to exclude any module from publishing you can always add .settings(publish / skip := true).

Example:

// Will not be published
lazy val documentation = project.dependsOn(allModules)

// Will be published
lazy val `my-library-plugin` = module.dependsOn(`my-library-core`)

// Will be published
lazy val `my-library-core` = module

// Will not be published
lazy val `my-library-util` = module.settings(publish / skip := true)

moduleMetadata task key

The moduleMetadata task key provides a Map[String, ModuleMetadata] containing metadata for all modules in the build. Each ModuleMetadata includes:

  • version: the module's version (from the SBT version setting)
  • internalDeps: names of modules this module directly depends on
  • dependents: names of modules that directly depend on this module
  • transitiveDependencies: names of all modules this module transitively depends on
  • transitiveDependents: names of all modules that transitively depend on this module

This is useful for plugins that need to inspect the module dependency graph, for example to implement cascading version bumps or detect affected modules.

You can also call ModuleMetadata.from(state) directly in SBT commands where State is available.