1{
2 featureVersion,
3
4 lib,
5 stdenv,
6
7 fetchurl,
8 fetchpatch,
9
10 buildPackages,
11 autoPatchelfHook,
12 pkg-config,
13 autoconf,
14 lndir,
15 unzip,
16 ensureNewerSourcesForZipFilesHook,
17 pandoc,
18
19 cpio,
20 file,
21 which,
22 zip,
23 zlib,
24 cups,
25 freetype,
26 harfbuzz,
27 alsa-lib,
28 libjpeg,
29 giflib,
30 libpng,
31 lcms2,
32 libX11,
33 libICE,
34 libXext,
35 libXrender,
36 libXtst,
37 libXt,
38 libXi,
39 libXinerama,
40 libXcursor,
41 libXrandr,
42 fontconfig,
43
44 setJavaClassPath,
45
46 versionCheckHook,
47
48 liberation_ttf,
49 cacert,
50 jre-generate-cacerts,
51
52 nixpkgs-openjdk-updater,
53
54 # TODO(@sternenseemann): gtk3 fails to evaluate in pkgsCross.ghcjs.buildPackages
55 # which should be fixable, this is a no-rebuild workaround for GHC.
56 headless ? lib.versionAtLeast featureVersion "21" && stdenv.targetPlatform.isGhcjs,
57
58 enableJavaFX ? false,
59 openjfx17,
60 openjfx21,
61 openjfx23,
62 openjfx24,
63 openjfx25,
64 openjfx_jdk ?
65 {
66 "17" = openjfx17;
67 "21" = openjfx21;
68 "23" = openjfx23;
69 "24" = openjfx24;
70 "25" = openjfx25;
71 }
72 .${featureVersion} or (throw "JavaFX is not supported on OpenJDK ${featureVersion}"),
73
74 enableGtk ? true,
75 gtk3,
76 gtk2,
77 glib,
78
79 temurin-bin-8,
80 temurin-bin-11,
81 temurin-bin-17,
82 temurin-bin-21,
83 temurin-bin-23,
84 temurin-bin-24,
85 temurin-bin-25,
86 jdk-bootstrap ?
87 {
88 "8" = temurin-bin-8.__spliced.buildBuild or temurin-bin-8;
89 "11" = temurin-bin-11.__spliced.buildBuild or temurin-bin-11;
90 "17" = temurin-bin-17.__spliced.buildBuild or temurin-bin-17;
91 "21" = temurin-bin-21.__spliced.buildBuild or temurin-bin-21;
92 "23" = temurin-bin-23.__spliced.buildBuild or temurin-bin-23;
93 "24" = temurin-bin-24.__spliced.buildBuild or temurin-bin-24;
94 "25" = temurin-bin-25.__spliced.buildBuild or temurin-bin-25;
95 }
96 .${featureVersion},
97}:
98
99let
100 sourceFile = ./. + "/${featureVersion}/source.json";
101 source = nixpkgs-openjdk-updater.openjdkSource {
102 inherit sourceFile;
103 featureVersionPrefix = tagPrefix + featureVersion;
104 };
105
106 atLeast11 = lib.versionAtLeast featureVersion "11";
107 atLeast17 = lib.versionAtLeast featureVersion "17";
108 atLeast21 = lib.versionAtLeast featureVersion "21";
109 atLeast23 = lib.versionAtLeast featureVersion "23";
110 atLeast24 = lib.versionAtLeast featureVersion "24";
111 atLeast25 = lib.versionAtLeast featureVersion "25";
112
113 tagPrefix = if atLeast11 then "jdk-" else "jdk";
114 version = lib.removePrefix "refs/tags/${tagPrefix}" source.src.rev;
115 versionSplit = builtins.match (if atLeast11 then "(.+)+(.+)" else "(.+)-b(.+)") version;
116 versionBuild = lib.elemAt versionSplit 1;
117
118 # The JRE 8 libraries are in directories that depend on the CPU.
119 architecture =
120 if atLeast11 then
121 ""
122 else
123 {
124 i686-linux = "i386";
125 x86_64-linux = "amd64";
126 aarch64-linux = "aarch64";
127 powerpc64le-linux = "ppc64le";
128 }
129 .${stdenv.system} or (throw "Unsupported platform ${stdenv.system}");
130
131 jdk-bootstrap' = jdk-bootstrap.override {
132 # when building a headless jdk, also bootstrap it with a headless jdk
133 gtkSupport = !headless;
134 };
135in
136
137assert lib.assertMsg (lib.pathExists sourceFile)
138 "OpenJDK ${featureVersion} is not a supported version";
139
140stdenv.mkDerivation (finalAttrs: {
141 pname = "openjdk" + lib.optionalString headless "-headless";
142 inherit version;
143
144 outputs = [
145 "out"
146 ]
147 ++ lib.optionals (!atLeast11) [
148 "jre"
149 ];
150
151 inherit (source) src;
152
153 patches = [
154 (
155 if atLeast24 then
156 ./24/patches/fix-java-home-jdk24.patch
157 else if atLeast21 then
158 ./21/patches/fix-java-home-jdk21.patch
159 else if atLeast11 then
160 ./11/patches/fix-java-home-jdk10.patch
161 else
162 ./8/patches/fix-java-home-jdk8.patch
163 )
164 (
165 if atLeast24 then
166 ./24/patches/read-truststore-from-env-jdk24.patch
167 else if atLeast11 then
168 ./11/patches/read-truststore-from-env-jdk10.patch
169 else
170 ./8/patches/read-truststore-from-env-jdk8.patch
171 )
172 ]
173 ++ lib.optionals (!atLeast23) [
174 (
175 if atLeast11 then
176 ./11/patches/currency-date-range-jdk10.patch
177 else
178 ./8/patches/currency-date-range-jdk8.patch
179 )
180 ]
181 ++ lib.optionals atLeast11 [
182 (
183 if atLeast17 then
184 ./17/patches/increase-javadoc-heap-jdk13.patch
185 else
186 ./11/patches/increase-javadoc-heap.patch
187 )
188 ]
189 ++ lib.optionals atLeast17 [
190 (
191 if atLeast21 then
192 ./21/patches/ignore-LegalNoticeFilePlugin-jdk18.patch
193 else
194 ./17/patches/ignore-LegalNoticeFilePlugin-jdk17.patch
195 )
196 ]
197 ++ lib.optionals (!atLeast21) [
198 (
199 if atLeast17 then
200 ./17/patches/fix-library-path-jdk17.patch
201 else if atLeast11 then
202 ./11/patches/fix-library-path-jdk11.patch
203 else
204 ./8/patches/fix-library-path-jdk8.patch
205 )
206 ]
207 ++ lib.optionals (atLeast17 && !atLeast23) [
208 # -Wformat etc. are stricter in newer gccs, per
209 # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79677
210 # so grab the work-around from
211 # https://src.fedoraproject.org/rpms/java-openjdk/pull-request/24
212 (fetchurl {
213 url = "https://src.fedoraproject.org/rpms/java-openjdk/raw/06c001c7d87f2e9fe4fedeef2d993bcd5d7afa2a/f/rh1673833-remove_removal_of_wformat_during_test_compilation.patch";
214 sha256 = "082lmc30x64x583vqq00c8y0wqih3y4r0mp1c4bqq36l22qv6b6r";
215 })
216 ]
217 ++ lib.optionals (featureVersion == "17") [
218 # Patch borrowed from Alpine to fix build errors with musl libc and recent gcc.
219 # This is applied anywhere to prevent patchrot.
220 (fetchurl {
221 url = "https://git.alpinelinux.org/aports/plain/community/openjdk17/FixNullPtrCast.patch?id=41e78a067953e0b13d062d632bae6c4f8028d91c";
222 sha256 = "sha256-LzmSew51+DyqqGyyMw2fbXeBluCiCYsS1nCjt9hX6zo=";
223 })
224 ]
225 ++ lib.optionals (atLeast11 && !atLeast25) [
226 # Fix build for gnumake-4.4.1:
227 # https://github.com/openjdk/jdk/pull/12992
228 (fetchpatch {
229 name = "gnumake-4.4.1";
230 url = "https://github.com/openjdk/jdk/commit/9341d135b855cc208d48e47d30cd90aafa354c36.patch";
231 hash = "sha256-Qcm3ZmGCOYLZcskNjj7DYR85R4v07vYvvavrVOYL8vg=";
232 })
233 ]
234 ++ lib.optionals atLeast25 [
235 ./25/patches/make-4.4.1.patch
236 ]
237 ++ lib.optionals (!headless && enableGtk) [
238 (
239 if atLeast17 then
240 ./17/patches/swing-use-gtk-jdk13.patch
241 else if atLeast11 then
242 ./11/patches/swing-use-gtk-jdk10.patch
243 else
244 ./8/patches/swing-use-gtk-jdk8.patch
245 )
246 ];
247
248 strictDeps = true;
249
250 depsBuildBuild = [ buildPackages.stdenv.cc ];
251
252 nativeBuildInputs = [
253 autoPatchelfHook
254 pkg-config
255 unzip
256 zip
257 which
258 # Probably for BUILD_CC but not sure, not in closure.
259 zlib
260 ]
261 ++ lib.optionals atLeast11 [
262 autoconf
263 ]
264 ++ lib.optionals (!atLeast11) [
265 lndir
266 ]
267 ++ lib.optionals (!atLeast11 && !stdenv.buildPlatform.canExecute stdenv.hostPlatform) [
268 # Certificates generated using keytool in `installPhase`
269 buildPackages.jdk8
270 ]
271 ++ lib.optionals atLeast21 [
272 ensureNewerSourcesForZipFilesHook
273 ]
274 ++ lib.optionals atLeast24 [
275 pandoc
276 ];
277
278 buildInputs = [
279 # TODO: Many of these should likely be in `nativeBuildInputs`.
280 cpio
281 # `-lmagic` in NIX_LDFLAGS
282 file
283 cups
284 freetype
285 alsa-lib
286 libjpeg
287 giflib
288 libX11
289 libICE
290 libXext
291 libXrender
292 libXtst
293 libXt
294 libXi
295 libXinerama
296 libXcursor
297 libXrandr
298 fontconfig
299 ]
300 ++ lib.optionals (atLeast11 && !atLeast21) [
301 harfbuzz
302 ]
303 ++ lib.optionals atLeast11 [
304 libpng
305 zlib # duplicate
306 lcms2
307 ]
308 ++ lib.optionals (!headless && enableGtk) [
309 (if atLeast11 then gtk3 else gtk2)
310 glib
311 ];
312
313 propagatedBuildInputs = [ setJavaClassPath ];
314
315 nativeInstallCheckInputs = lib.optionals atLeast23 [
316 versionCheckHook
317 ];
318
319 # JDK's build system attempts to specifically detect
320 # and special-case WSL, and we don't want it to do that,
321 # so pass the correct platform names explicitly
322 configurePlatforms = lib.optionals atLeast17 [
323 "build"
324 "host"
325 ];
326
327 # https://openjdk.org/groups/build/doc/building.html
328 configureFlags = [
329 # https://github.com/openjdk/jdk/blob/471f112bca715d04304cbe35c6ed63df8c7b7fee/make/autoconf/util_paths.m4#L315
330 # Ignoring value of READELF from the environment. Use command line variables instead.
331 "READELF=${stdenv.cc.targetPrefix}readelf"
332 "AR=${stdenv.cc.targetPrefix}ar"
333 "STRIP=${stdenv.cc.targetPrefix}strip"
334 "NM=${stdenv.cc.targetPrefix}nm"
335 "OBJDUMP=${stdenv.cc.targetPrefix}objdump"
336 "OBJCOPY=${stdenv.cc.targetPrefix}objcopy"
337 "--with-boot-jdk=${jdk-bootstrap'.home}"
338 "--enable-unlimited-crypto"
339 "--with-native-debug-symbols=internal"
340 "--with-stdc++lib=dynamic"
341 "--with-zlib=system"
342 "--with-giflib=system"
343 ]
344 ++ (
345 if atLeast23 then
346 [
347 "--with-version-string=${version}"
348 "--with-vendor-version-string=(nix)"
349 ]
350 else if atLeast11 then
351 lib.optionals atLeast17 [
352 "--with-version-build=${versionBuild}"
353 "--with-version-opt=nixos"
354 ]
355 ++ [
356 "--with-version-pre="
357 ]
358 else
359 [
360 "--with-update-version=${lib.removePrefix "${featureVersion}u" (lib.elemAt versionSplit 0)}"
361 "--with-build-number=${versionBuild}"
362 "--with-milestone=fcs"
363 ]
364 )
365 ++ lib.optionals (!atLeast21) (
366 if atLeast11 then
367 [
368 "--with-freetype=system"
369 "--with-harfbuzz=system"
370 ]
371 else
372 [
373 "--disable-freetype-bundling"
374 ]
375 )
376 ++ lib.optionals atLeast11 [
377 "--with-libjpeg=system"
378 "--with-libpng=system"
379 "--with-lcms=system"
380 ]
381 ++ lib.optionals (featureVersion == "11") [
382 "--disable-warnings-as-errors"
383 ]
384 # OpenJDK 11 cannot be built by recent versions of Clang, as far as I can tell (see
385 # https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=260319). Known to
386 # compile with LLVM 12.
387 ++ lib.optionals (atLeast11 && stdenv.cc.isClang) [
388 "--with-toolchain-type=clang"
389 # Explicitly tell Clang to compile C++ files as C++, see
390 # https://github.com/NixOS/nixpkgs/issues/150655#issuecomment-1935304859
391 "--with-extra-cxxflags=-xc++"
392 ]
393 # This probably shouldn’t apply to OpenJDK 21; see
394 # b7e68243306833845cbf92e2ea1e0cf782481a51 which removed it for
395 # versions 15 through 20.
396 ++ lib.optional (
397 (featureVersion == "11" || featureVersion == "21") && stdenv.hostPlatform.isx86_64
398 ) "--with-jvm-features=zgc"
399 ++ lib.optional headless (if atLeast11 then "--enable-headless-only" else "--disable-headful")
400 ++ lib.optional (!headless && enableJavaFX) "--with-import-modules=${openjfx_jdk}";
401
402 buildFlags = if atLeast17 then [ "images" ] else [ "all" ];
403
404 separateDebugInfo = true;
405 __structuredAttrs = true;
406
407 # -j flag is explicitly rejected by the build system:
408 # Error: 'make -jN' is not supported, use 'make JOBS=N'
409 # Note: it does not make build sequential. Build system
410 # still runs in parallel.
411 enableParallelBuilding = false;
412
413 preConfigure =
414 # Set number of jobs to use when building.
415 ''
416 configureFlags+=("--with-jobs=''${NIX_BUILD_CORES}")
417 '';
418
419 env = {
420 NIX_CFLAGS_COMPILE =
421 if atLeast17 then
422 "-Wno-error"
423 else if atLeast11 then
424 # Workaround for
425 # `cc1plus: error: '-Wformat-security' ignored without '-Wformat' [-Werror=format-security]`
426 # when building jtreg
427 "-Wformat"
428 else
429 lib.concatStringsSep " " (
430 [
431 # glibc 2.24 deprecated readdir_r so we need this
432 # See https://www.mail-archive.com/openembedded-devel@lists.openembedded.org/msg49006.html
433 "-Wno-error=deprecated-declarations"
434 ]
435 ++ lib.optionals stdenv.cc.isGNU [
436 # https://bugzilla.redhat.com/show_bug.cgi?id=1306558
437 # https://github.com/JetBrains/jdk8u/commit/eaa5e0711a43d64874111254d74893fa299d5716
438 "-fno-lifetime-dse"
439 "-fno-delete-null-pointer-checks"
440 "-std=gnu++98"
441 "-Wno-error"
442 ]
443 ++ [
444 # error by default in GCC 14
445 "-Wno-error=int-conversion"
446 "-Wno-error=incompatible-pointer-types"
447 ]
448 );
449
450 NIX_LDFLAGS = lib.concatStringsSep " " (
451 lib.optionals (!headless) [
452 "-lfontconfig"
453 "-lcups"
454 "-lXinerama"
455 "-lXrandr"
456 "-lmagic"
457 ]
458 ++ lib.optionals (!headless && enableGtk) [
459 (if atLeast11 then "-lgtk-3" else "-lgtk-x11-2.0")
460 "-lgio-2.0"
461 ]
462 );
463 }
464 // lib.optionalAttrs (!atLeast11) {
465 # OpenJDK 8 Hotspot cares about the host(!) version otherwise
466 DISABLE_HOTSPOT_OS_VERSION_CHECK = "ok";
467 };
468
469 versionCheckProgram = lib.optionalString atLeast23 "${placeholder "out"}/bin/java";
470
471 # Fails with "No rule to make target 'y'."
472 doCheck = false;
473
474 doInstallCheck = atLeast23;
475
476 postPatch = ''
477 chmod +x configure
478 patchShebangs --build configure
479 ''
480 + lib.optionalString atLeast24 ''
481 chmod +x make/scripts/*.{template,sh,pl}
482 patchShebangs --build make/scripts
483 '';
484
485 installPhase = ''
486 mkdir -p $out/lib
487 mv build/*/images/${if atLeast11 then "jdk" else "j2sdk-image"} $out/lib/openjdk
488 ''
489 # Remove some broken manpages.
490 + ''
491 rm -rf $out/lib/openjdk/man/ja*
492 ''
493 # Mirror some stuff in top-level.
494 + ''
495 mkdir -p $out/share
496 ln -s $out/lib/openjdk/bin $out/bin
497 ln -s $out/lib/openjdk/include $out/include
498 ln -s $out/lib/openjdk/man $out/share/man
499 ''
500 # IDEs use the provided src.zip to navigate the Java codebase (https://github.com/NixOS/nixpkgs/pull/95081)
501 + lib.optionalString atLeast11 ''
502 ln -s $out/lib/openjdk/lib/src.zip $out/lib/src.zip
503 ''
504 # jni.h expects jni_md.h to be in the header search path.
505 + ''
506 ln -s $out/include/linux/*_md.h $out/include/
507 ''
508 # Remove crap from the installation.
509 + (
510 ''
511 rm -rf $out/lib/openjdk/demo
512 ''
513 + lib.optionalString (!atLeast11) ''
514 rm -rf $out/lib/openjdk/sample
515 ''
516 + lib.optionalString headless (
517 if atLeast11 then
518 ''
519 rm $out/lib/openjdk/lib/{libjsound,libfontmanager}.so
520 ''
521 else
522 ''
523 rm $out/lib/openjdk/jre/lib/${architecture}/{libjsound,libjsoundalsa,libsplashscreen,libfontmanager}.so
524 rm $out/lib/openjdk/jre/bin/policytool
525 rm $out/lib/openjdk/bin/{policytool,appletviewer}
526 ''
527 )
528 )
529 + lib.optionalString (!atLeast11) (
530 # Move the JRE to a separate output
531 ''
532 mkdir -p $jre/lib/openjdk
533 mv $out/lib/openjdk/jre $jre/lib/openjdk/jre
534 mkdir $out/lib/openjdk/jre
535 lndir $jre/lib/openjdk/jre $out/lib/openjdk/jre
536
537 ln -s $jre/lib/openjdk/jre $out/jre
538 ln -s $jre/lib/openjdk/jre/bin $jre/bin
539 ''
540 # Make sure cmm/*.pf are not symlinks:
541 # https://youtrack.jetbrains.com/issue/IDEA-147272
542 + ''
543 rm -rf $out/lib/openjdk/jre/lib/cmm
544 ln -s {$jre,$out}/lib/openjdk/jre/lib/cmm
545 ''
546 # Setup fallback fonts
547 + lib.optionalString (!headless) ''
548 mkdir -p $jre/lib/openjdk/jre/lib/fonts
549 ln -s ${liberation_ttf}/share/fonts/truetype $jre/lib/openjdk/jre/lib/fonts/fallback
550 ''
551 # Remove duplicate binaries.
552 + ''
553 for i in $(ls $out/lib/openjdk/bin); do
554 if [ "$i" = java ]; then continue; fi
555 if cmp -s $out/lib/openjdk/bin/$i $jre/lib/openjdk/jre/bin/$i; then
556 ln -sfn $jre/lib/openjdk/jre/bin/$i $out/lib/openjdk/bin/$i
557 fi
558 done
559 ''
560 # Generate certificates.
561 + ''
562 cd $jre/lib/openjdk/jre/lib/security
563 rm cacerts
564 ${jre-generate-cacerts} ${
565 if stdenv.buildPlatform.canExecute stdenv.hostPlatform then
566 "$jre/lib/openjdk/jre/bin/keytool"
567 else
568 "keytool"
569 } ${cacert}/etc/ssl/certs/ca-bundle.crt
570 ''
571 );
572
573 preFixup =
574 # Set JAVA_HOME automatically.
575 ''
576 mkdir -p $out/nix-support
577 cat <<EOF > $out/nix-support/setup-hook
578 if [ -z "\''${JAVA_HOME-}" ]; then export JAVA_HOME=$out/lib/openjdk; fi
579 EOF
580 ''
581 # Propagate the setJavaClassPath setup hook from the JRE so that
582 # any package that depends on the JRE has $CLASSPATH set up
583 # properly.
584 + lib.optionalString (!atLeast11) ''
585 mkdir -p $jre/nix-support
586 printWords "${setJavaClassPath}" > $jre/nix-support/propagated-build-inputs
587 '';
588
589 # If binaries in the jre output have RPATH dependencies on libraries from the out output, Nix will
590 # detect a cyclic reference and abort the build.
591 # To fix that, we need to patch the binaries from each output in separate auto-patchelf executions.
592 dontAutoPatchelf = true;
593 postFixup = ''
594 autoPatchelf -- $out
595 ''
596 + lib.optionalString (!atLeast11) ''
597 autoPatchelf -- $jre
598 '';
599
600 disallowedReferences = [ jdk-bootstrap' ];
601
602 passthru = {
603 home = "${finalAttrs.finalPackage}/lib/openjdk";
604 # Shouldn't this be `jdk-bootstrap = jdk-bootstrap'`?
605 inherit jdk-bootstrap;
606 inherit (source) updateScript;
607 }
608 // (if atLeast11 then { inherit gtk3; } else { inherit gtk2; })
609 // lib.optionalAttrs (!atLeast23) {
610 inherit architecture;
611 };
612
613 meta = {
614 description = "Open-source Java Development Kit";
615 homepage = "https://openjdk.java.net/";
616 license = lib.licenses.gpl2Only;
617 maintainers = with lib.maintainers; [
618 edwtjo
619 infinidoge
620 ];
621 teams = [ lib.teams.java ];
622 mainProgram = "java";
623 platforms = [
624 "i686-linux"
625 "x86_64-linux"
626 "aarch64-linux"
627 ]
628 ++ lib.optionals atLeast11 [
629 "armv7l-linux"
630 "armv6l-linux"
631 "powerpc64le-linux"
632 ]
633 ++ lib.optionals atLeast17 [
634 "riscv64-linux"
635 ];
636 # OpenJDK 8 was broken for musl at 2024-01-17. Tracking issue:
637 # https://github.com/NixOS/nixpkgs/issues/281618
638 # error: ‘isnanf’ was not declared in this scope
639 broken = !atLeast11 && stdenv.hostPlatform.isMusl;
640 };
641})