Skip to main content

Dependencies

A project's dependencies are Maven coordinates listed under dependencies:. By default each dep is on the project's compile-and-runtime classpath. The four standard Maven configurations (provided, optional, runtime, test) are available when you need them, as a per-dep configuration: field, see Maven configurations below.

What bleep doesn't have is the parallel-namespace axis that Gradle (implementation { } / api { } / compileOnly { } / runtimeOnly { }) and sbt (Compile / scalacOptions, Test / fork, custom configurations like IntegrationTest) graft on top. Dependencies live in one list. Different contexts, a test code path with its own dependency tree, an integration suite that needs Testcontainers but only on a tag, are different projects.

The colon shorthands

FormWhenResolves as
groupId:artifactId:versionJava or Kotlin librariesslf4j-api-2.0.9.jar
groupId::artifactId:versionScala libraries (binary-version suffix)fansi_3-0.5.0.jar (or _2.13, etc.)
groupId:::artifactId:versionScala libraries (full-version suffix, compiler plugins, scala-reflect macros)paradise_3.8.3-2.1.1.jar
projects:
myapp:
dependencies:
- org.slf4j:slf4j-api:2.0.9 # Java/Kotlin
- com.lihaoyi::fansi:0.5.0 # Scala
- org.scalamacros:::paradise:2.1.1 # Scala (full version)

For platform-specific resolution (Scala.js / Scala Native), bleep picks the right artifact suffix from the project's platform.name , you don't write _sjs1 or _native0.5 yourself.

Inter-project: dependsOn

To depend on another project in the same build:

projects:
app:
dependsOn: core # one
# or
dependsOn: [core, utils] # multiple

dependsOn: is the build graph. Bleep compiles core before app when the dependency exists, and the CI invalidation command walks this graph to compute what needs rebuilding when source changes.

The long form

A bare string entry is shorthand. The full record exposes everything bleep stores about a dependency:

dependencies:
- module: org.scala-sbt::librarymanagement-core:1.7.1
configuration: provided
exclusions:
org.scala-sbt: util-logging_2.13
for3Use213: true
transitive: false
FieldApplies toMeaning
modulebothThe coordinate (the same string you'd put as the bare entry).
configurationbothMaven configuration: provided, optional, runtime, test. See below.
exclusionsbothMap of org -> [moduleName] to drop from this dep's transitive closure.
transitivebothDefault true. Set false to pin only the named artifact and ignore its dependencies.
attributesbothExtra Maven module attributes (rarely needed).
publicationbothOverride the resolved artifact's name / type / ext / classifier.
isSbtPluginJavaAdds sbtVersion=1.0 and scalaVersion=2.12 attributes, needed when consuming an sbt plugin as a normal dependency.
forceJvmScalaPin the JVM artifact even on a JS or Native project.
for3Use213ScalaWhen the project is on Scala 3, resolve the Scala 2.13 build. The standard escape hatch for libraries not yet published for 3.
for213Use3ScalaThe opposite. Rarely useful; binary compatibility usually doesn't carry that direction.

Maven configurations

Most builds don't set configuration:; the default is the compile-and-runtime classpath. The cases that matter:

  • provided, on this project's compile and runtime classpaths, but not inherited by anything that depends on it. Servlet APIs, and any library a container or host supplies.
  • optional, treated exactly like provided inside a bleep build. The two differ only in the POM bleep publishes, which carries whichever you wrote.
  • runtime, present at runtime, not at compile time.
  • test, only resolves when the project is a test project.

Worth calling out: when project A dependsOn: project B, deps that B declared provided or optional are dropped from both of A's classpaths — Maven's rule, that those scopes don't travel to a consumer. If A needs the library, A declares it. There is no way to say "provided at this layer, needed at the leaf" and have it propagate; that is the point of the scope, not a limitation of it.

Bleep's own build relies on this. bleep-test-runner declares junit-platform-launcher as provided, because it compiles against the Launcher API but the junit version a test fork runs is chosen per project. Were that inherited, every project depending on bleep-test-runner would carry junit classes that shadow the ones the project actually resolved.

BOMs and version-less dependencies

A project can import Maven BOMs with boms:. Each entry is an ordinary coordinate pointing at a BOM (a "platform" POM). Its dependencyManagement then pins every version in this project's resolutions — transitives included — the way Maven does with a scope=import entry.

projects:
app:
boms:
- com.fasterxml.jackson:jackson-bom:2.17.2
dependencies:
- com.fasterxml.jackson.core:jackson-databind # no version — the BOM supplies it
- com.fasterxml.jackson.core:jackson-annotations

Once a BOM manages a coordinate, you write the dependency without a versiongroupId:artifactId (Java) or groupId::artifactId (Scala). The BOM fills it in, and so do the transitives: everything jackson-* above resolves at 2.17.2. A version you write yourself still wins over the BOM (Maven's rule), and a version-less dependency that no BOM manages fails at resolution rather than resolving to something arbitrary.

Sibling BOMs are first-wins: the first one to manage a coordinate keeps it.

BOMs travel along dependsOn

A BOM declared on one project constrains every project that (transitively) dependsOn it. Put the platform BOM on a shared library and the whole application resolves against one version set — which is exactly how a Quarkus or Spring Boot platform governs an app's entire dependency universe from a single line:

projects:
platform:
boms:
- io.quarkus.platform:quarkus-bom:3.17.2
app:
dependsOn: platform
dependencies:
- io.quarkus:quarkus-rest # no version — pinned by platform's BOM

bleep import-maven produces this shape directly: it reads <dependencyManagement> imports out of the raw POM chain into boms:, and any dependency the POM wrote version-less stays version-less in bleep.yaml, so the imported build reads like the Maven one instead of freezing the versions the BOM owns.

What this page doesn't cover

  • Conflict resolution (library version schemes, the eviction model bleep inherits from sbt, the project-level ignoreEvictionErrors kill switch, the bleep build evicted inspection) lives on its own page: Conflict resolution.
  • Updating dependencies (bleep build update-deps and bleep build update-dep) is in the Refactor your build guide.
  • Custom configurations beyond the standard four, ivy resolvers other than Maven-style, custom artifact patterns: by design. These aren't modelled. The intricate ivyisms were dropped on purpose, what's left has a closed, hashable shape, which makes the build model cheap to cache (locally and in the remote build cache) and cheap to round-trip through the refactor commands.

See also