Skip to main content

Dependencies

Built-in dependencies

Prism automatically adds the following to each version's common subproject:

  • org.spongepowered:mixin:0.8.5 (compileOnly, always)
  • io.github.llamalad7:mixinextras-common:0.3.5 (compileOnly + annotation processor, only when Forge is not a loader for that version)

MixinExtras is bundled by Fabric Loader and NeoForge, but not by Forge. If your version targets Forge, MixinExtras is not added to common. You can add it per-loader if needed.

For Fabric, Minecraft, Fabric Loader, and optionally Fabric API are added automatically.

For NeoForge and Forge, the loader handles Minecraft and loader dependencies through the extension.

Common dependencies

Dependencies shared across all loaders for a version:

version("1.21.1") {
common {
implementation("some:shared-library:1.0")
compileOnly("some:api:2.0")
}

fabric { loaderVersion = "0.16.2" }
neoforge { loaderVersion = "21.1.26" }
}

Common dependencies are added to the common subproject's configurations and are available to all loader subprojects through the source wiring.

Per-loader dependencies

Each loader has its own dependencies block:

fabric {
loaderVersion = "0.16.2"
fabricApi("0.102.1")

dependencies {
modImplementation("curse.maven:jei-238222:4613379")
modCompileOnly("modrinth:sodium:0.5.3")
implementation("com.google.code.gson:gson:2.10.1")
jarJar("some:library:[1.0,2.0)")
}
}

forge {
loaderVersion = "47.4.16"

dependencies {
modImplementation("curse.maven:jei-238222:7391695")
modCompileOnly("curse.maven:polymorph-388800:6450982")
implementation("com.google.code.gson:gson:2.10.1")
}
}

neoforge {
loaderVersion = "21.1.26"

dependencies {
implementation("curse.maven:jei-238222:4613379")
jarJar("some:library:[1.0,2.0)")
}
}

Available configurations

MethodDescription
api(dep)Exported API dependency
implementation(dep)Compile and runtime dependency (no remapping)
modApi(dep)Exported mod dependency, remapped when supported
compileOnlyApi(dep)Exported compile-only API dependency
modImplementation(dep)Mod dependency, remapped to dev mappings
compileOnly(dep)Compile-time only (no remapping)
modCompileOnlyApi(dep)Exported compile-only mod dependency, remapped when supported
modCompileOnly(dep)Mod compile-time only, remapped to dev mappings
runtimeOnly(dep)Runtime only (no remapping)
modRuntimeOnly(dep)Mod runtime only, remapped to dev mappings
jarJar(dep)Embed dependency in output JAR
shadow(dep)Shade dependency into output JAR (merges classes, avoids split packages)
localJar(path)Local JAR file (defaults to compileOnly)
localJar(path, config)Local JAR file with custom configuration
configuration(name, dep)Add a dependency to a custom Gradle configuration
modConfiguration(name, dep)Add a dependency to mod{Name} when present

Use mod* variants for Minecraft mod JARs (from CurseMaven, Modrinth Maven, or mod maven repos). These remap the dependency from production mappings (SRG/intermediary) to dev mappings so you don't get NoSuchMethodError / NoSuchFieldError crashes.

Use plain implementation / compileOnly / runtimeOnly for regular Java libraries that don't reference Minecraft classes (e.g. Gson, Apache Commons). These don't need remapping.

On Fabric, mod* maps to Loom's remapping configurations. On Forge, mod* maps to MDG Legacy's remapping transform. On NeoForge, no remapping is needed so mod* behaves the same as the plain variants.

Custom configurations

Create an extra configuration in the loader block, then add dependencies to it:

forge {
loaderVersion = "47.4.16"
configuration("localRuntime")
remapConfiguration("optionalMods")

dependencies {
configuration("localRuntime", "com.example:helper:1.0")
modConfiguration("optionalMods", "curse.maven:jei-238222:7391695")
}
}

Notes:

  • configuration("name") creates a plain custom Gradle configuration for that loader project.
  • remapConfiguration("name") is currently Forge-only and creates both name and mod{Name} through MDG Legacy.
  • modConfiguration(name, dep) falls back to the plain configuration with a warning if mod{Name} does not exist.

Shared common dependencies

Dependencies in the sharedCommon block are propagated to all loader subprojects:

prism {
sharedCommon {
dependencies {
implementation("com.example:my-library:1.0")
}
}
}

For Forge and NeoForge loaders, shared common implementation, api, and runtimeOnly dependencies are automatically:

  • Added as compileOnly so they don't end up on Forge's module path (avoids SecureJarHandler crashes)
  • Added to additionalRuntimeClasspath so they are visible during dev runs (runClient/runServer)

On Fabric, shared common dependencies are added normally (Fabric's classloading handles them without issues).

Shading with Shadow

Use shadow(dep) to shade a dependency into the output JAR. This merges the dependency's classes directly into your mod JAR, avoiding split-package errors that jarJar() can cause when multiple JARs share the same Java package.

prism {
sharedCommon {
dependencies {
shadow("com.example:my-library:1.0") // shaded into output JAR
shadow("com.example:my-other-lib:2.0") // also shaded
implementation("com.google.code.gson:gson:2.10.1") // NOT shaded, just a normal dep
}
}
}

// Also works in per-loader dependency blocks:
forge {
dependencies {
shadow("some:library:1.0")
}
}

On Forge/NeoForge, shadow(dep) dependencies are:

  • Added to the shadow configuration (merged into the output JAR)
  • Added to additionalRuntimeClasspath when that configuration exists (so Forge dev runs can see them without putting them on the module path)

On Fabric, shadow(dep) maps to implementation + include (Loom's Jar-in-Jar).

Prism automatically applies the Shadow Gradle plugin when any shadow() dependency is declared.

On Legacy Forge/MDG builds, Prism also wires the shaded artifact into reobfShadowJar, and publishing prefers reobfShadowJar when it exists.

Use shadow() instead of jarJar() when your dependencies share Java packages across multiple JARs, since Forge's jar-in-jar keeps those JARs separate and can still hit module split-package errors at runtime.

Shadow configuration

The shadow {} block (or shadow(dep) { } overload) exposes full control over the Shadow task:

dependencies {
shadow("com.example:my-library:1.0") {
// Auto-relocation: Prism relocates all packages to a default prefix by default.
// Disable with:
relocation(false)
// Or set a custom prefix (default: derived from mod group):
relocationPrefix("com.example.mymod.libs")
// Restrict which packages are relocated:
includeRelocation("com.example.somelibrary")
excludeRelocation("com.example.sharedapi")

// Explicit per-package relocation rules:
relocate("org.apache.commons", "com.example.mymod.libs.commons") {
include("org.apache.commons.lang3.*")
exclude("org.apache.commons.lang3.builder.*")
skipStringConstants(true)
}

// Exclude files from the shadow JAR:
exclude("META-INF/MANIFEST.MF", "*.SF")

// Strip file entries matching Ant patterns (removes the entry entirely):
strip("META-INF/services/some.ServiceInterface")

// Remove manifest attributes (Class-Path and Multi-Release are removed by default):
removeManifestAttribute("Implementation-Version")

// Merge service files:
mergeServiceFiles() // merges all META-INF/services/
mergeServiceFiles("META-INF/services/some.Service") // specific file only

// Direct access to the ShadowJar task for anything not covered above:
raw { shadowJar -> }
}
}

Top-level shorthands are also available directly on the dependencies {} block for quick overrides:

dependencies {
shadow("com.example:my-library:1.0")
shadowRelocation(false) // disable auto-relocation
shadowRelocationPrefix("com.example.mymod.shadow") // set prefix
}

Jar-in-Jar

The jarJar() method embeds a dependency inside your output JAR:

fabric {
dependencies {
jarJar("some:library:1.0")
}
}

On Fabric, this maps to Loom's include configuration. On NeoForge/Forge, this maps to MDG's jarJar configuration.

jarJar() is best for normal jar-in-jar embedding. If a library is split across multiple JARs that share packages, prefer shadow() instead.

Excluding entries

jarJar(dep) { } accepts a block to strip entries from the embedded JAR before it is bundled. This is useful for dropping native libraries for platforms you do not ship:

dependencies {
jarJar("org.rocksdb:rocksdbjni:10.2.1") {
excludeNatives("osx", "linux32", "musl", "s390x", "riscv64", "ppc64le", "aarch64")
exclude("some/unwanted/file.txt")
}
}

excludeNatives(tokens...) removes native library entries (.so, .dll, .dylib, .jnilib) whose path contains any of the given tokens. exclude(paths...) removes entries by exact path or suffix match. When either is set, Prism resolves the dependency, repackages it without the excluded entries, and embeds the repackaged JAR.

Local JARs

Use localJar() to depend on a JAR file from disk:

neoforge {
loaderVersion = "21.1.26"

dependencies {
localJar("libs/some-mod.jar") // compileOnly (default)
localJar("libs/some-lib.jar", "implementation") // implementation
}
}

Paths are relative to the root project directory. Absolute paths are also supported.

Maven repositories

Prism provides shortcuts for common Minecraft mod repositories:

prism {
curseMaven() // https://cursemaven.com
modrinthMaven() // https://api.modrinth.com/maven
maven("BlameJared", "https://maven.blamejared.com")
}

For artifacts hosted outside a Maven layout (such as GitHub release downloads), use ivy() with an artifact pattern:

prism {
ivy("github", "https://github.com/", "/[organisation]/[module]/releases/download/[revision]/[module]-[revision]-[classifier].[ext]")
}

Then depend on it with the matching coordinates, e.g. compileOnly("owner:repo:1.0:classifier@jar").

These repositories are added to all subprojects.

CurseMaven dependency format

curse.maven:{slug}-{projectId}:{fileId}

Example: curse.maven:jei-238222:4613379

Modrinth Maven dependency format

maven.modrinth:{slug}:{version}

Example: maven.modrinth:sodium:mc1.21-0.5.11