nixpkgs mirror (for testing)
github.com/NixOS/nixpkgs
nix
1{
2 callPackage,
3 jdk11,
4 jdk17,
5 jdk21,
6 nix-update-script,
7}:
8
9let
10 wrapGradle =
11 {
12 lib,
13 callPackage,
14 mitm-cache,
15 replaceVars,
16 symlinkJoin,
17 concatTextFile,
18 makeSetupHook,
19 gradle-unwrapped,
20 runCommand,
21 ...
22 }@args:
23 let
24 gradle = gradle-unwrapped.override args;
25 in
26 symlinkJoin {
27 pname = "gradle";
28 inherit (gradle) version;
29
30 paths = [
31 (makeSetupHook { name = "gradle-setup-hook"; } (concatTextFile {
32 name = "setup-hook.sh";
33 files = [
34 (mitm-cache.setupHook)
35 (replaceVars ./setup-hook.sh {
36 # jdk used for keytool
37 inherit (gradle) jdk;
38 init_script = "${./init-build.gradle}";
39 })
40 ];
41 }))
42 gradle
43 mitm-cache
44 ];
45
46 passthru = {
47 fetchDeps = callPackage ./fetch-deps.nix { inherit mitm-cache; };
48 inherit (gradle) jdk;
49 unwrapped = gradle;
50 tests = {
51 toolchains =
52 let
53 javaVersion = lib.getVersion jdk11;
54 javaMajorVersion = lib.versions.major javaVersion;
55 in
56 runCommand "detects-toolchains-from-nix-env"
57 {
58 # Use JDKs that are not the default for any of the gradle versions
59 nativeBuildInputs = [
60 (gradle.override {
61 javaToolchains = [
62 jdk11
63 ];
64 })
65 ];
66 src = ./tests/toolchains;
67 }
68 ''
69 cp -a $src/* .
70 substituteInPlace ./build.gradle --replace-fail '@JAVA_VERSION@' '${javaMajorVersion}'
71 env GRADLE_USER_HOME=$TMPDIR/gradle GRADLE_OPTS=-Dorg.gradle.native.dir=$TMPDIR/native \
72 gradle run --no-daemon --quiet --console plain > $out
73 actual="$(<$out)"
74 if [[ "${javaVersion}" != "$actual"* ]]; then
75 echo "Error: Expected '${javaVersion}', to start with '$actual'" >&2
76 exit 1
77 fi
78 '';
79 }
80 // gradle.tests;
81 };
82
83 meta = gradle.meta // {
84 # prefer normal gradle/mitm-cache over this wrapper, this wrapper only provides the setup hook
85 # and passthru
86 priority = (gradle.meta.priority or lib.meta.defaultPriority) + 1;
87 };
88 };
89
90 # Creates a Gradle without calling the package.
91 mkGradle' =
92 {
93 version,
94 hash,
95
96 # The default JDK/JRE that will be used for derived Gradle packages.
97 # A current LTS version of a JDK is a good choice.
98 defaultJava,
99
100 # The platforms supported by this Gradle package.
101 # Gradle Native-Platform ships some binaries that
102 # are compatible only with specific platforms.
103 # As of 2022-04 this affects platform compatibility
104 # of multiple Gradle releases, so this is used as default.
105 # See https://github.com/gradle/native-platform#supported-platforms
106 platforms ? [
107 "aarch64-darwin"
108 "aarch64-linux"
109 "i686-windows"
110 "x86_64-cygwin"
111 "x86_64-darwin"
112 "x86_64-linux"
113 "x86_64-windows"
114 ],
115
116 # Extra attributes to be merged into the resulting derivation's
117 # meta attribute.
118 meta ? { },
119
120 # Put the update script in passthru. Should only be on a single attrpath
121 # so that nixpkgs-update doesn't create duplicate PRs.
122 enableUpdateScript ? false,
123 }@genArgs:
124
125 {
126 lib,
127 stdenv,
128 fetchurl,
129 callPackage,
130 makeWrapper,
131 unzip,
132 coreutils,
133 findutils,
134 ncurses5,
135 ncurses6,
136 gnused,
137 udev,
138 testers,
139 runCommand,
140 writeText,
141 autoPatchelfHook,
142 buildPackages,
143
144 # The JDK/JRE used for running Gradle.
145 java ? defaultJava,
146
147 # Additional JDK/JREs to be registered as toolchains.
148 # See https://docs.gradle.org/current/userguide/toolchains.html
149 javaToolchains ? [ ],
150
151 # Ignored arguments from calling .override on the wrapper.
152 ...
153 }:
154 stdenv.mkDerivation (finalAttrs: {
155 pname = "gradle";
156 inherit version;
157
158 src = fetchurl {
159 inherit hash;
160 url = "https://services.gradle.org/distributions/gradle-${version}-bin.zip";
161 };
162
163 dontBuild = true;
164
165 nativeBuildInputs = [
166 makeWrapper
167 unzip
168 ]
169 ++ lib.optionals stdenv.hostPlatform.isLinux [
170 autoPatchelfHook
171 ];
172
173 buildInputs = [
174 stdenv.cc.cc
175 ncurses5
176 ncurses6
177 ];
178
179 # We only need to patchelf some libs embedded in JARs.
180 dontAutoPatchelf = true;
181
182 # All the installed Gradle libraries and binaries go here. Note that the Gradle wrapper
183 # will look for a lib directory above its own directory (which is presumed to be bin)
184 # for loading the main Gradle jar.
185 gradleLibexec = "${placeholder "out"}/libexec/gradle";
186
187 installPhase =
188 let
189 # set toolchains via installations.path property in gradle.properties.
190 # See https://docs.gradle.org/current/userguide/toolchains.html#sec:custom_loc
191 toolchainPaths = "org.gradle.java.installations.paths=${lib.concatStringsSep "," javaToolchains}";
192 jnaLibraryPath = lib.optionalString stdenv.hostPlatform.isLinux (lib.makeLibraryPath [ udev ]);
193 jnaFlag = lib.optionalString stdenv.hostPlatform.isLinux ''--add-flags "-Djna.library.path=${jnaLibraryPath}"'';
194 in
195 ''
196 # Install all the Gradle jars.
197 mkdir -vp $gradleLibexec
198 cp -av lib/ $gradleLibexec
199 [ -f $gradleLibexec/lib/gradle-launcher-*.jar ] || { echo "No Gradle launcher jar found!" >&2 && exit 1; }
200
201 # Set up toolchain paths in the gradle.properties.
202 echo ${lib.escapeShellArg toolchainPaths} > $gradleLibexec/gradle.properties
203
204 # Just use the existing gradle wrapper (usually called `gradlew`) as the main program.
205 mkdir -vp $gradleLibexec/bin
206 cp -v bin/gradle $gradleLibexec/bin/gradlew
207 chmod +x $gradleLibexec/bin/gradlew
208 patchShebangs --host $gradleLibexec/bin/gradlew
209
210 # Ensure that JAVA_HOME is set so the installed Gradle wrapper picks it up.
211 # The wrapper also needs coreutils, xargs, and sed.
212 mkdir -vp $out/bin
213 makeWrapper $gradleLibexec/bin/gradlew $out/bin/gradle \
214 --set-default JAVA_HOME ${java} \
215 --suffix PATH : ${
216 lib.makeBinPath [
217 coreutils
218 findutils
219 gnused
220 ]
221 } \
222 ${jnaFlag}
223 '';
224
225 dontFixup = !stdenv.hostPlatform.isLinux;
226
227 fixupPhase =
228 let
229 arch = if stdenv.hostPlatform.is64bit then "amd64" else "i386";
230 newFileEvents = toString (lib.versionAtLeast version "8.12");
231 in
232 ''
233 # get the correct jar executable for cross
234 export PATH="${buildPackages.jdk}/bin:$PATH"
235 . ${./patching.sh}
236
237 nativeVersion="$(extractVersion native-platform $gradleLibexec/lib/native-platform-*.jar)"
238 for variant in "" "-ncurses5" "-ncurses6"; do
239 autoPatchelfInJar \
240 $gradleLibexec/lib/native-platform-linux-${arch}$variant-''${nativeVersion}.jar \
241 "${lib.getLib stdenv.cc.cc}/lib64:${
242 lib.makeLibraryPath [
243 stdenv.cc.cc
244 ncurses5
245 ncurses6
246 ]
247 }"
248 done
249
250 # The file-events library _seems_ to follow the native-platform version, but
251 # we won’t assume that.
252 if [ -n "${newFileEvents}" ]; then
253 fileEventsVersion="$(extractVersion gradle-fileevents $gradleLibexec/lib/gradle-fileevents-*.jar)"
254 autoPatchelfInJar \
255 $gradleLibexec/lib/gradle-fileevents-''${fileEventsVersion}.jar \
256 "${lib.getLib stdenv.cc.cc}/lib64:${lib.makeLibraryPath [ stdenv.cc.cc ]}"
257 else
258 fileEventsVersion="$(extractVersion file-events $gradleLibexec/lib/file-events-*.jar)"
259 autoPatchelfInJar \
260 $gradleLibexec/lib/file-events-linux-${arch}-''${fileEventsVersion}.jar \
261 "${lib.getLib stdenv.cc.cc}/lib64:${lib.makeLibraryPath [ stdenv.cc.cc ]}"
262 fi
263
264 # The scanner doesn't pick up the runtime dependency in the jar.
265 # Manually add a reference where it will be found.
266 mkdir $out/nix-support
267 echo ${stdenv.cc.cc} > $out/nix-support/manual-runtime-dependencies
268 # Gradle will refuse to start without _both_ 5 and 6 versions of ncurses.
269 echo ${ncurses5} >> $out/nix-support/manual-runtime-dependencies
270 echo ${ncurses6} >> $out/nix-support/manual-runtime-dependencies
271 ${lib.optionalString stdenv.hostPlatform.isLinux "echo ${udev} >> $out/nix-support/manual-runtime-dependencies"}
272 '';
273
274 passthru.tests = {
275 version = testers.testVersion {
276 package = finalAttrs.finalPackage;
277 command = ''
278 env GRADLE_USER_HOME=$TMPDIR/gradle GRADLE_OPTS=-Dorg.gradle.native.dir=$TMPDIR/native \
279 gradle --version
280 '';
281 };
282
283 java-application = testers.testEqualContents {
284 assertion = "can build and run a trivial Java application";
285 expected = writeText "expected" "hello\n";
286 actual =
287 runCommand "actual"
288 {
289 nativeBuildInputs = [ finalAttrs.finalPackage ];
290 src = ./tests/java-application;
291 }
292 ''
293 cp -a $src/* .
294
295 # Make sure GRADLE_OPTS works.
296 env \
297 GRADLE_USER_HOME=$TMPDIR/gradle \
298 GRADLE_OPTS="-Dorg.gradle.native.dir=$TMPDIR/native -Dnix.test.mainClass=Main" \
299 gradle run --no-daemon --quiet --console plain > $out
300 '';
301 };
302 };
303 passthru.jdk = defaultJava;
304 passthru.wrapped = callPackage wrapGradle {
305 gradle-unwrapped = mkGradle genArgs;
306 };
307 passthru.updateScript =
308 if enableUpdateScript then
309 nix-update-script {
310 extraArgs = [
311 "--url=https://github.com/gradle/gradle"
312 # Gradle’s .0 releases are tagged as `vX.Y.0`, but the actual
313 # release version omits the `.0`, so we’ll wanto to only capture
314 # the version up but not including the the trailing `.0`.
315 "--version-regex=^v(\\d+\\.\\d+(?:\\.[1-9]\\d?)?)(\\.0)?$"
316 ];
317 }
318 else
319 null;
320
321 meta =
322
323 {
324 inherit platforms;
325 description = "Enterprise-grade build system";
326 longDescription = ''
327 Gradle is a build system which offers you ease, power and freedom.
328 You can choose the balance for yourself. It has powerful multi-project
329 build support. It has a layer on top of Ivy that provides a
330 build-by-convention integration for Ivy. It gives you always the choice
331 between the flexibility of Ant and the convenience of a
332 build-by-convention behavior.
333 '';
334 homepage = "https://www.gradle.org/";
335 changelog = "https://docs.gradle.org/${version}/release-notes.html";
336 downloadPage = "https://gradle.org/next-steps/?version=${version}";
337 sourceProvenance = with lib.sourceTypes; [
338 binaryBytecode
339 binaryNativeCode
340 ];
341 license = lib.licenses.asl20;
342 maintainers = with lib.maintainers; [
343 britter
344 liff
345 lorenzleutgeb
346 ];
347 teams = [ lib.teams.java ];
348 mainProgram = "gradle";
349 }
350 // meta;
351 });
352
353 # Calls the generated Gradle package with default arguments.
354 mkGradle = args: callPackage (mkGradle' args) { };
355in
356rec {
357 # Keep these exposed (but not at toplevel) so users can call
358 # `gradle-packages.mkGradle` as we do below,
359 # and still have wrapGradle available if necessary.
360 inherit mkGradle wrapGradle;
361
362 # NOTE: Default JDKs that are hardcoded below must be LTS versions
363 # and respect the compatibility matrix at
364 # https://docs.gradle.org/current/userguide/compatibility.html
365
366 gradle_9 = mkGradle {
367 version = "9.3.0";
368 hash = "sha256-DVhfadoJH8Wyvs7Yd/6rVaMGTUO4odRq6weZawkV4OA=";
369 defaultJava = jdk21;
370 };
371 gradle_8 = mkGradle {
372 version = "8.14.4";
373 hash = "sha256-8XcSmKcPbbWina9iN4xOGKF/wzybprFDYuDN9AYQOA0=";
374 defaultJava = jdk21;
375 # Only enable this on *one* version to avoid duplicate PRs.
376 enableUpdateScript = true;
377 };
378 gradle_7 = mkGradle {
379 version = "7.6.6";
380 hash = "sha256-Zz2XdvMDvHBI/DMp0jLW6/EFGweJO9nRFhb62ahnO+A=";
381 defaultJava = jdk17;
382 meta.knownVulnerabilities = [
383 "Gradle 7 no longer receives security updates with the release of Gradle 9 on 31 July 2025. https://endoflife.date/gradle"
384 ];
385 };
386
387 # Default version of Gradle in nixpkgs.
388 gradle = gradle_8;
389}