Skip to content

[2.x] feat: Support Maven BOM (Bill of Materials) #8675

Merged
eed3si9n merged 19 commits intosbt:developfrom
bitloi:feature/sbt-4531-bom
Feb 2, 2026
Merged

[2.x] feat: Support Maven BOM (Bill of Materials) #8675
eed3si9n merged 19 commits intosbt:developfrom
bitloi:feature/sbt-4531-bom

Conversation

@bitloi
Copy link
Copy Markdown
Contributor

@bitloi bitloi commented Feb 2, 2026

Summary

This PR adds BOM support along the lines of eed3si9n’s comment on #4531:

For the consumption, we reuse the existing .pomOnly() construct:

libraryDependendencies += ("com.fasterxml.jackson" % "jackson-bom" % "2.21.0").pomOnly()

Interestingly https://mvnrepository.com/artifact/com.fasterxml.jackson/jackson-bom/2.21.0 even suggests that sbt users use that. Next we'd need a way to specify a versionless dependency. For now, we can use "*" for example:

libraryDependendencies += "com.fasterxml.jackson.core" % "jackson-core" % "*"

Expectation

  1. The resulting update contains jackson-core 2.21.0
  2. makePom translates POM-only dependencies to
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>com.fasterxml.jackson</groupId>
        <artifactId>jackson-bom</artifactId>
        <version>2.21.0</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

What’s in this PR

Consuming BOMs

  • You can declare a BOM with .pomOnly() and versionless deps with "*":
    • libraryDependencies += ("com.fasterxml.jackson" % "jackson-bom" % "2.21.0").pomOnly()
    • libraryDependencies += "com.fasterxml.jackson.core" % "jackson-core" % "*"
  • BOMs are passed to Coursier via Resolve.addBom(); version "*" is resolved from the BOM.

makePom

  • POM-only dependencies are emitted under <dependencyManagement><dependencies>...</dependencies></dependencyManagement> with <type>pom</type> and <scope>import</scope>.
  • Dependencies with version "*" are emitted without a <version> element so Maven uses the BOM-managed version.

Implementation

  • lm-coursier: dependencies with only a pom artifact are treated as BOMs and passed to Resolve.withBoms(); the rest stay as normal dependencies (including "*").
  • lm-ivy (MakePom): BOM deps go into <dependencyManagement>; "*" version is omitted in the dependency element. Scala 3: explicit NodeSeq/Elem types in makeDependencyElem to fix cyclic inference and return type.
  • Removed the previous custom BOM path (csrBomDependencies, BomSupport, PomParser) in favor of Coursier’s native addBom support.

Ivy / publishLocal emulation

  • When publishing to Ivy (e.g. publishLocal), BOM-resolved versions (deps that had "*") are written into the published ivy.xml as forced dependencies (force="true"), so consumers that depend on this module get those versions.

Scripted test

  • dependency-management/bom: BOM (jackson-bom 2.21.0 .pomOnly()) + jackson-core "*"; asserts resolved version is 2.21.0.
  • Per eed3si9n’s suggestion, the scripted test validates Coursier’s BOM behavior on this feature branch before opening the PR.

How to verify

From the sbt build root:

./sbt "scripted dependency-management/bom"

Fixes #4531

bitloi and others added 10 commits February 1, 2026 23:40
- Add csrBomDependencies setting to declare BOM artifacts to import
- Implement BomSupport: resolve BOM POMs, extract dependencyManagement
  as force versions; fallback to POM XML parse when Coursier does not
  populate Project.dependencyManagement (coursier#1390)
- Add PomParser for dependencyManagement section in BOM POMs
- Wire BOM force versions into LMCoursier; dependencyOverrides override
  BOM versions (bomForceVersions ++ userForceVersions)
- Add BomSupportSpec: integration test with junit-bom
- LMCoursier: use userForceVersions instead of allForceVersions
- LMCoursier: remove extra force-versions arg from coursierConfiguration calls
- IvyXml: add bomForcedDeps param to writeFiles and pass to rawContent
- LMCoursier: remove erroneous extra argument from coursierConfiguration
  in updateSbtClassifierConfigurationTask and scalaCompilerBridgeConfigurationTask
  (fixes E007 type mismatch / too many arguments in CI)
- IvyXml: pass bomForcedDeps through writeFiles and set force="true"
  on dependency elements for BOM-resolved versions (publishLocal emulation)
…r BOM

- build.sbt: On Windows, limit to one task at a time to avoid
  OverlappingFileLockException when scalafix and Coursier write to cache.
- make-pom-type: Expect pom-only deps under dependencyManagement with
  scope import; check in dependencyManagement/dependencies for p1.
@bitloi
Copy link
Copy Markdown
Contributor Author

bitloi commented Feb 2, 2026

@eed3si9n Would you please check the implementation for #4531 ?

@eed3si9n

This comment was marked as resolved.

…r fills from BOM

- lm-coursier: for deps with version '*' or '' and BOMs present, pass empty
  version to Coursier so Resolution.processedRootDependencies fills from BOM
- Add bom-publish-local scripted test (a with BOM, b depends on a); comment
  notes env caveat if b/update fails with jackson-core:*
@bitloi bitloi force-pushed the feature/sbt-4531-bom branch from 6d16c92 to 686eb0b Compare February 2, 2026 05:04
@bitloi

This comment was marked as resolved.

Changed from 2.21.0 to 2.17.0 for more reliable CI testing.
@eed3si9n
Copy link
Copy Markdown
Member

eed3si9n commented Feb 2, 2026

[info] [error] (b / update) sbt.librarymanagement.ResolveException: Error downloading com.fasterxml.jackson.core:jackson-core:*
[info] [error]   Not found
[info] [error]   Not found
[info] [error]   not found: /tmp/sbt_59271d37/ivy/cache/local/com.fasterxml.jackson.core/jackson-core/*/ivys/ivy.xml
[info] [error]   not found: https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/*/jackson-core-*.pom

so it looks like at least in the case of publishLocal scenario, BOM needs to be added to all subprojects?

@bitloi
Copy link
Copy Markdown
Contributor Author

bitloi commented Feb 2, 2026

Thanks for the pointer. I’ve added the BOM to subproject b as well (so the BOM is on all subprojects in the publishLocal scenario). With that, b/update can resolve the transitive jackson-core:* from a’s published ivy. The scripted test dependency-management/bom-publish-local passes locally now.

@bitloi bitloi requested a review from eed3si9n February 2, 2026 07:52
@eed3si9n eed3si9n changed the title feat: Support Maven BOM (Bill of Materials) [2.x] feat: Support Maven BOM (Bill of Materials) Feb 2, 2026
@mzuehlke
Copy link
Copy Markdown
Contributor

mzuehlke commented Feb 2, 2026

Could you fix this compiler warning in the newly introduced test.

[info] Running dependency-management/bom-publish-local
[info] [info] welcome to sbt 2.0.0-RC9-bin-SNAPSHOT (Azul Systems, Inc. Java 25.0.2)
[error] -- Warning: /tmp/sbt_59271d37/build.sbt:2:20 -----------------------------------
[error] 2 |  .settings(common: _*)
[error]   |                    ^
[error]   |The syntax `x: _*` is no longer supported for vararg splices; use `x*` instead
[error]   |This construct can be rewritten automatically under -rewrite -source 3.4-migration.
[error] -- Warning: /tmp/sbt_59271d37/build.sbt:8:20 -----------------------------------
[error] 8 |  .settings(common: _*)
[error]   |                    ^
[error]   |The syntax `x: _*` is no longer supported for vararg splices; use `x*` instead
[error]   |This construct can be rewritten automatically under -rewrite -source 3.4-migration.

@bitloi bitloi requested a review from eed3si9n February 2, 2026 09:14
Copy link
Copy Markdown
Member

@eed3si9n eed3si9n left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution!

@eed3si9n eed3si9n merged commit 4c16466 into sbt:develop Feb 2, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support Maven's BOM "Bill of Materials"

3 participants