Home Explore Blog Models CI



nixpkgs

1st chunk of `doc/languages-frameworks/gradle.section.md`
e700d63f82335bab486ea6714c4f48be4e07e4befb20d3870000000100000e57
# Gradle {#gradle}

Gradle is a popular build tool for Java/Kotlin. Gradle itself doesn't
currently provide tools to make dependency resolution reproducible, so
nixpkgs has a proxy designed for intercepting Gradle web requests to
record dependencies so they can be restored in a reproducible fashion.

## Building a Gradle package {#building-a-gradle-package}

Here's how a typical derivation will look:

```nix
stdenv.mkDerivation (finalAttrs: {
  pname = "pdftk";
  version = "3.3.3";

  src = fetchFromGitLab {
    owner = "pdftk-java";
    repo = "pdftk";
    tag = "v${finalAttrs.version}";
    hash = "sha256-ciKotTHSEcITfQYKFZ6sY2LZnXGChBJy0+eno8B3YHY=";
  };

  nativeBuildInputs = [
    gradle
    makeWrapper
  ];

  # if the package has dependencies, mitmCache must be set
  mitmCache = gradle.fetchDeps {
    inherit (finalAttrs) pname;
    data = ./deps.json;
  };

  # this is required for using mitm-cache on Darwin
  __darwinAllowLocalNetworking = true;

  gradleFlags = [ "-Dfile.encoding=utf-8" ];

  # defaults to "assemble"
  gradleBuildTask = "shadowJar";

  # will run the gradleCheckTask (defaults to "test")
  doCheck = true;

  installPhase = ''
    mkdir -p $out/{bin,share/pdftk}
    cp build/libs/pdftk-all.jar $out/share/pdftk

    makeWrapper ${lib.getExe jre} $out/bin/pdftk \
      --add-flags "-jar $out/share/pdftk/pdftk-all.jar"

    cp ${finalAttrs.src}/pdftk.1 $out/share/man/man1
  '';

  meta.sourceProvenance = with lib.sourceTypes; [
    fromSource
    binaryBytecode # mitm cache
  ];
})
```

To update (or initialize) dependencies, run the update script via
something like `$(nix-build -A <pname>.mitmCache.updateScript)`
(`nix-build` builds the `updateScript`, `$(...)` runs the script at the
path printed by `nix-build`).

If your package can't be evaluated using a simple `pkgs.<pname>`
expression (for example, if your package isn't located in nixpkgs, or if
you want to override some of its attributes), you will usually have to
pass `pkg` instead of `pname` to `gradle.fetchDeps`. There are two ways
of doing so.

The first is to add the derivation arguments required for getting the
package. Using the pdftk example above:

```nix
{
  lib,
  stdenv,
  gradle,
  # ...
  pdftk,
}:

stdenv.mkDerivation (finalAttrs: {
  # ...
  mitmCache = gradle.fetchDeps {
    pkg = pdftk;
    data = ./deps.json;
  };
})
```

This allows you to `override` any arguments of the `pkg` used for the update script (for example, `pkg = pdftk.override { enableSomeFlag = true };)`.

The second is to use `finalAttrs.finalPackage` like this:

```nix
stdenv.mkDerivation (finalAttrs: {
  # ...
  mitmCache = gradle.fetchDeps {
    pkg = finalAttrs.finalPackage;
    data = ./deps.json;
  };
})
```
The limitation of this method is that you cannot override the `pkg` derivations's arguments.

In the former case, the update script will stay the same even if the derivation is called with different arguments. In the latter case, the update script will change depending on the derivation arguments. It's up to you to decide which one would work best for your derivation.

## Update Script {#gradle-update-script}

The update script does the following:

- Build the derivation's source via `pkgs.srcOnly`
- Enter a `nix-shell` for the derivation in a `bwrap` sandbox (the
  sandbox is only used on Linux)
- Set the `IN_GRADLE_UPDATE_DEPS` environment variable to `1`
- Run the derivation's `unpackPhase`, `patchPhase`, `configurePhase`
- Run the derivation's `gradleUpdateScript` (the Gradle setup hook sets
  a default value for it, which runs `preBuild`, `preGradleUpdate`
  hooks, fetches the dependencies using `gradleUpdateTask`, and finally

Title: Gradle Package Building in Nixpkgs
Summary
This section details how to build Gradle packages reproducibly within Nixpkgs. Since Gradle lacks built-in tools for reproducible dependency resolution, Nixpkgs uses a proxy (`mitmCache`) to intercept and record dependencies. It outlines the structure of a typical Gradle derivation, emphasizing the use of `gradle.fetchDeps` for managing dependencies via a `deps.json` file. The `updateScript` is provided to initialize or update these dependencies. The text also explains two methods for passing the package (`pkg`) to `gradle.fetchDeps` when a simple `pname` is insufficient, discussing their implications for overriding derivation arguments. Finally, it elaborates on the steps the `updateScript` performs, including building the source, sandboxing, setting environment variables, and running various derivation phases and hooks to fetch dependencies.