# Research on Mill vs SBT - 2025-04-02 ## Key Components of Current SBT Infrastructure ### 1. IWMaterialsVersions - Simple object with val declarations for all library versions - Centralized version management through a single file - Versioning for all major libraries (ZIO, Akka, HTTP clients, etc.) - Used as a reference in IWMaterialsDeps ### 2. IWMaterialsDeps - Contains dependency definitions with proper cross-platform support - Groups related dependencies with helper methods like `useZIO()`, `useZIOAll()` - Handles Scala.js dependencies with `%%%` cross-version support - Implements specialized library sets (ZIO, Akka, HTTP, etc.) - Provides standard compiler options for certain libraries (like ZIO JSON) ### 3. IWScalaProjectPlugin - Implements an SBT AutoPlugin for standardizing projects - Sets default Scala version (currently prioritizing Scala 3.6.3) - Enables SemanticDB for tooling - Sets up scalafmt and scalafix integration - Configures publishing to IW Maven repositories - Sets test logging preferences ### 4. IWPluginPresets - Centralizes SBT plugin management - Provides helper methods for adding common plugin sets - Handles complex plugin dependencies (like Scala.js ecosystem) ### 5. VitePlugin - Example of custom SBT plugin for JavaScript tooling - Shows integration with external tools like Vite - Manages dev server lifecycle - Configures environment variables and file monitoring ## Mill Build Tool Overview Based on our research from the Mill documentation, here are the key aspects of Mill: ### 1. Core Features - Supports multiple languages (Java, Scala, Kotlin) - Faster builds through aggressive caching and parallelism - Better IDE support with superior autocomplete and navigation - Requires fewer plugins for common workflows - Build files are regular Scala code (build.sc) ### 2. Module System - Uses a module tree and task graph with immutable configuration - Modules are defined as objects extending traits (like `ScalaModule`) - Example: ```scala object foo extends ScalaModule { def scalaVersion = "3.6.3" def ivyDeps = Agg( ivy"com.lihaoyi::scalatags:0.13.1" ) } ``` - Tasks are defined as methods that can reference other tasks - Automatic caching and incremental computation ### 3. Dependency Management - Uses Ivy syntax: `ivy"org::name:version"` (with :: for Scala deps) - Dependencies defined in module definition: - `def ivyDeps = Agg(...)` for external dependencies - `def moduleDeps = Seq(...)` for internal module dependencies - Can define custom resolvers and credentials ### 4. Publishing - Uses `PublishModule` trait - Requires `def publishVersion` and `def pomSettings` - Example: ```scala object foo extends ScalaModule with PublishModule { def publishVersion = "0.0.1" def pomSettings = PomSettings( description = "Hello", organization = "com.lihaoyi", url = "https://github.com/lihaoyi/example", licenses = Seq(License.MIT) ) } ``` ### 5. Extension Development - Mill uses traits for sharing functionality between modules - Can create custom modules that extend existing Mill modules - Extensions are regular JVM libraries that can be published to Maven repos - Isolated classloaders for worker modules to avoid conflicts ## Differences Between SBT and Mill ### 1. Configuration Syntax - SBT: DSL in build.sbt files with key-value pairs - Mill: Regular Scala code in build.sc files, with modules as objects ### 2. Plugin System - SBT: Formal plugin system with AutoPlugin - Mill: Traits and regular libraries, no formal plugin system ### 3. Dependency Notation - SBT: `"org" %% "name" % "version"` - Mill: `ivy"org::name:version"` ### 4. Cross Building - SBT: Uses `+` prefix for commands, crossScalaVersions setting - Mill: Uses `Cross[Module]` for multi-version builds, with version-specific source dirs ### 5. Task Definition - SBT: Tasks defined as settings with complex DSL - Mill: Tasks defined as methods with explicit dependencies ## Mill Equivalent Components Design ### 1. IWMillVersions - Object with the same version constants as IWMaterialsVersions - Example: ```scala object IWMillVersions { val zio = "2.1.16" val zioConfig = "4.0.3" // ... other versions } ``` ### 2. IWMillDeps - Object with methods to create dependencies with proper Mill notation - Example: ```scala object IWMillDeps { def zio = ivy"dev.zio::zio:${IWMillVersions.zio}" def zioConfig = ivy"dev.zio::zio-config:${IWMillVersions.zioConfig}" def useZIO() = Agg( zio, zioTest, zioTestSbt ) } ``` ### 3. IWScalaModule trait - Trait that can be mixed into ScalaModule - Sets default Scala version and compiler options - Example: ```scala trait IWScalaModule extends ScalaModule { def scalaVersion = "3.6.3" // Standard compiler options def scalacOptions = super.scalacOptions() ++ Seq( "-Xfatal-warnings", "-deprecation" ) } ``` ### 4. IWPublishModule trait - Extension of PublishModule for IW Maven repository setup - Example: ```scala trait IWPublishModule extends PublishModule { def publishVersion: T[String] def pomSettings: T[PomSettings] def repositoryURL = if (publishVersion().endsWith("-SNAPSHOT")) "https://dig.iterative.works/maven/snapshots" else "https://dig.iterative.works/maven/releases" } ``` ## Implementation Planning For each component we'll need to: 1. Create the basic structure of the Mill support library 2. Implement the version and dependency objects 3. Create traits for standard module configuration 4. Implement publishing support 5. Create example modules and migration guides Mill's trait-based approach should make our implementation more natural and flexible than SBT plugins, as we can create composable traits that work directly with Mill's module system.