Skip to content

Support Maven's BOM "Bill of Materials" #4531

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
dwijnand opened this issue Jan 31, 2019 · 17 comments
Open

Support Maven's BOM "Bill of Materials" #4531

dwijnand opened this issue Jan 31, 2019 · 17 comments

Comments

@dwijnand
Copy link
Member

dwijnand commented Jan 31, 2019

It would help scala's ecosystem if sbt supported Maven's BOM "Bill of Materials" that (IIUC) would help maintain version coherence across artefacts of the same project.

One current workaround is verifying this at runtime like Akka does: https://github.com/akka/akka/blob/v2.5.17/akka-actor/src/main/scala/akka/util/ManifestInfo.scala

@eed3si9n
Copy link
Member

@gumartinm
Copy link

With Maven's BOM you can also rule how plugins work across projects and subprojects. The BOM file enables developers to centralize plugins configuration and dependencies in only one place.

It is great when you work in a big company with many projects and you need to govern common plugins and dependencies across your whole organization.

@eed3si9n
Copy link
Member

eed3si9n commented Jun 9, 2020

In sbt/librarymanagement#293 @LogicalTime wrote

When working behind proxies trying to resolve artifacts that do not exist can slow things down unbearably. Currently SBT v1.2.8 seems to request jar artifacts when the pom.xml says packaging=pom. So resolution can stall out for minutes trying to fetch jar files that the pom indicates are not there. Can we please fix this, or have a property that toggles it so SBT can be more widely adopted?

@simpadjo
Copy link

I'd like to work on this one.
Mu plan is the following:

  1. Add a Bom(module: ModuleID) class that stores the mapping between module's direct dependencies and their versions

  2. Add an extension method to OrganizationArtifactName so a bom can be used as an artifact version.

Am I missing something?

@suztomo
Copy link

suztomo commented Nov 21, 2021

In Maven, importing a BOM also overrides versions in transitive dependencies:

However often BOMs are not only providing versions as recommendations, but also a way to override any other version found in the graph.

https://docs.gradle.org/current/userguide/platforms.html#sub:bom_import

@simpadjo Thank you for taking this. Would this fit in sbt's behavior?

@simpadjo
Copy link

@suztomo no, my proposal is quite minimalistic: make possible to set dependency version to mach another artifact's dependency version. It even doesn't need to be a BOM.
I guess full-blown BOM is much more complicated and I'm not ready to pick it up yet.
Let's see what the maintainers think.

@eed3si9n
Copy link
Member

Let's see what the maintainers think.

If a project is using actual Maven to manage their build, the idea of parent POM / BOM (Bill of Materials) might make sense as a way of keeping things DRY (don't-repeat-yourself). For sbt, I don't see a huge benefit in emulating this contraption because you can already use project/Dependencies.scala as the single source of truth of version numbers across multple subprojects, or by creating a company plugin that does the same if you want coherence across multiple repos. In other words, sbt plugin / metabuild can play the role parent POMs play in Maven.

Should someone try to implement non-effective POM dependency, note that the actual work would likely need to happen in Coursier to represent the version-less dependency. Given that Coursier is able to resolve Maven ecosystem, its dependency resolver is likely able to handle it, but I am not sure how difficult it would be to model versionless direct dependency.

@simpadjo
Copy link

@eed3si9n thanks for you input! Yeah, the issue is more complicated than I initially thought.
FWIW, I can reassure you that the pain is very real. Dependencies.scala solves the problem of sharing the same version across different artifacts. But upgrading several different versions atomically is still problematic and requires discipline.
So eventually projects evolve according to the theory of broken windows.
Writing sbt plugins is neither easy nor fun, so it's not a universal solution for the problem.

Right now I'm trying to implement this functionality as a library that could possibly become a plugin.

@simpadjo
Copy link

This is an example how to get BOM functionality
https://github.com/simpadjo/sbt-bom/blob/main/project/Bom.scala

With this code, the following syntax works:

lazy val myBom = Bom("org.springframework" % "spring-framework-bom" % "5.3.13")

lazy val hello = (project in file("."))
  .settings(
    name := "Bom-example",
    resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots",
    myBom,
    libraryDependencies += "org.springframework" % "spring-core" % myBom.key.value
  )

I plan to polish this with the help of my coworkers and eventually publish it (from my company's account). But this is not a fast process, you know.
Until then feel free to copypaste it.

@vadeg
Copy link

vadeg commented Aug 19, 2022

@eed3si9n

For sbt, I don't see a huge benefit in emulating this contraption because you can already use project/Dependencies.scala as the single source of truth of version numbers across multple subprojects, or by creating a company plugin that does the same if you want coherence across multiple repos.

BOMs allow to align external transitive dependency versions. For example with Akka there is a common problem when versions are misaligned because of different transitive dependencies. When project uses akka-actors, akka-streams, akka-http, etc. it becomes a nightmare to align all these libraries to work together properly. Of course, developer can align all versions once in the Dependencies.scala, but when the major version upgrade is required a developer should play again the same "library poker" game to make everything aligned.

Also, in my practice quite often there are several independent projects which require to repeat the same exercise again.
Having a BOM support and centralized BOM management from ecosystems like Akka could simplify dependency management a lot. Akka already do this for Maven and Gradle.

@wiwa
Copy link

wiwa commented Mar 17, 2023

(+1)

@simpadjo
Copy link

simpadjo commented Sep 8, 2023

Better late than never: plugin for BOM support was finally opensourced.
https://github.com/heremaps/here-sbt-bom

@xuwei-k
Copy link
Member

xuwei-k commented Dec 5, 2024

This release changes the way "BOMs" or "dependency management" are handled during resolution, and allows users to add BOMs to a resolution. This changes the way versions are picked when BOMs or dependency management are involved, which has an impact on the resolution of libraries from many JVM ecosystems, such as Apache Spark, Springboot, Quarkus, etc.

@eed3si9n
Copy link
Member

eed3si9n commented Dec 6, 2024

sbt still does not have:

  1. A way of depending on existing BOM
  2. A way of defining our own BOM
  3. A way of defining versionless dependency

so while sbt 1.10.6 improves the dependency resolution that involves BOM, there are some tasks pending until we can support bill-of-materials (BOM) POM.

FYI - scalacenter/advisoryboard#168

@UnaiUribarri-TomTom
Copy link

UnaiUribarri-TomTom commented Jan 22, 2025

I have upgraded SBT to 1.10.6 and added a bom file (both using libraryDependencies and dependencyOverrides, with and without pomOnly()) and it is ignored in all cases. When I run show runtime:fullClasspath or dependencyTree and I still a dependency on "io.netty" % "netty-resolver-dns" % "4.1.112.Final" brought in by azure-storage-blob instead of the one included in netty-bom.

This is my little test project:

  • build.sbt:
name := "bom-test"

//dependencyOverrides += "io.netty" % "netty-bom" % "4.1.115.Final" pomOnly()
//libraryDependencies += "io.netty" % "netty-bom" % "4.1.115.Final"
libraryDependencies += "io.netty" % "netty-bom" % "4.1.115.Final" pomOnly()
libraryDependencies += "com.azure" % "azure-storage-blob" % "12.29.0"
  • project/build.properties:
sbt.version=1.10.6
  • project/plugins.sbt:
addDependencyTreePlugin

@gaeljw
Copy link

gaeljw commented Jan 22, 2025

@UnaiUribarri-TomTom , read the previous comment:

so while sbt 1.10.6 improves the dependency resolution that involves BOM, there are some tasks pending until we can support bill-of-materials (BOM) POM.

It's not supported yet.

You can use the SBT plugin https://github.com/heremaps/here-sbt-bom to do so though.

EDIT: this thread contain some answers.

@UnaiUribarri-TomTom
Copy link

UnaiUribarri-TomTom commented Jan 22, 2025

@gaeljw is right; SBT does not pass BOM dependencies to courier correctly; therefore, no direct BOM dependency support yet.

For now, SBT only supports BOM as a transitive dependency, when its parent package is not built using SBT, but Maven, Gradle or other build system that supports BOMs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy