What if there are transitive dependencies I do not want to use?

← Getting Started · Ref: Q11

When your package depends on library A, and library A depends on library B, then B is a transitive dependency. Sometimes you need to exclude B: it may conflict with another version, have a security vulnerability, or pull in functionality you do not need.

EK9 provides `excludeDeps` inside `defines package` for this:

  excludeDeps <- {
    "unwanted.module.name": "parent.that.brings.it.in"
  }

The key is the module you want to EXCLUDE. The value is the module that DEPENDS on it (the one pulling it in as a transitive dependency).

Example scenario:

  Your package depends on `ekopen.network.utils` version 1.6.1-9.
  That library depends on `ekopen.old.logging` version 0.9.0-0.
  You do not want `ekopen.old.logging`. So you write:
  excludeDeps <- {
    "ekopen.old.logging": "ekopen.network.utils"
  }

This tells the dependency resolver: when processing `ekopen.network.utils`, skip its dependency on `ekopen.old.logging`.

EK9 also protects you automatically:
- Circular dependencies are detected and rejected at resolve time
- Version rationalization selects the highest compatible PATCH version
- Major version conflicts (different MAJOR numbers) fail the build
- Duplicate dependency entries are handled gracefully

Run `ek9 -Dp -v app.ek9` to resolve and see which dependencies were accepted and which were rejected (with reasons like MANUAL, RATIONALISATION, OPTIMISED).

The code example below shows a package that excludes an unwanted transitive dependency.

See Q7 for managing dependencies. See Q10 for dev vs production dependencies. See Q14 for listing resolved dependencies.

Example

#!ek9
defines module qa.getting.started.exclude.transitive.deps

  defines package

    version as Version: 1.0.0-0
    description as String = "Shows how to exclude transitive dependencies"
    license <- "Apache-2.0"
    publicAccess <- true

    tags <- [
      "example"
    ]

    applyStandardIncludes <- true

    deps <- {
      "ekopen.network.support.utils": "1.6.1-9",
      "ekopen.net.handy.tools": "3.2.1-0"
    }

    //Exclude: block ekopen.some.unwanted.pack from being pulled in
    //via ekopen.network.support.utils
    excludeDeps <- {
      "ekopen.some.unwanted.pack": "ekopen.network.support.utils"
    }

  defines program
    ExcludeTransitiveDeps()
      stdout <- Stdout()

      stdout.println("Transitive dependency excluded")
      stdout.println("Run: ek9 -Dp thisFile.ek9 to resolve and verify")
Other ways to ask this
  • How do I exclude a transitive dependency?
  • What is excludeDeps in EK9?
  • How do I block an unwanted indirect dependency?
  • How do I prevent a dependency of a dependency from being included?
  • What is the EK9 equivalent of Maven exclusions or Gradle exclude?

Coming from another language?

Python: pip has no built-in exclusion (manual override). Java: Maven <exclusions> inside <dependency>, Gradle exclude group/module. Rust: no direct exclusion (use [patch] or fork). npm: overrides field. Go: go.mod exclude directive. EK9 uses excludeDeps as a Dict mapping excluded module to its parent.

Keywords: beginner, conflict, dependency, exclude, excludeDeps, exclusions, first, gradle, indirect, intro, maven, resolve, start, transitive, unwanted, version