26 gsettings-desktop-schemas,
65 withNativeCompilation ? stdenv.buildPlatform.canExecute stdenv.hostPlatform,
72 withDbus ? stdenv.hostPlatform.isLinux,
73 withGTK3 ? withPgtk && !noGui,
74 withGlibNetworking ? withPgtk || withGTK3 || (withX && withXwidgets),
75 withGpm ? stdenv.hostPlatform.isLinux,
76 withImageMagick ? lib.versionOlder version "27" && (withX || withNS),
77 # Emacs 30+ has native JSON support
78 withJansson ? lib.versionOlder version "30",
81 withNS ? stdenv.hostPlatform.isDarwin && !(variant == "macport" || noGui),
83 withSelinux ? stdenv.hostPlatform.isLinux,
84 withSQLite3 ? lib.versionAtLeast version "29",
85 withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd,
86 withToolkitScrollBars ? true,
87 withTreeSitter ? lib.versionAtLeast version "29",
88 withWebP ? lib.versionAtLeast version "29",
89 withX ? !(stdenv.hostPlatform.isDarwin || noGui || withPgtk),
90 withXinput2 ? withX && lib.versionAtLeast version "29",
92 !stdenv.hostPlatform.isDarwin
94 && (withGTK3 || withPgtk)
95 && (lib.versionOlder version "30"), # XXX: upstream bug 66068 precludes newer versions of webkit2gtk (https://lists.gnu.org/archive/html/bug-gnu-emacs/2024-09/msg00695.html)
96 withSmallJaDic ? false,
97 withCompressInstall ? true,
100 siteStart ? ./site-start.el,
104 else if withMotif then
106 else if withAthena then
112 # macOS dependencies for NS and macPort
124 UniformTypeIdentifiers,
128 assert (withGTK3 && !withNS && variant != "macport") -> withX || withPgtk;
130 assert noGui -> !(withX || withGTK3 || withNS || variant == "macport");
131 assert withAcl -> stdenv.hostPlatform.isLinux;
132 assert withAlsaLib -> stdenv.hostPlatform.isLinux;
133 assert withGpm -> stdenv.hostPlatform.isLinux;
134 assert withNS -> stdenv.hostPlatform.isDarwin && !(withX || variant == "macport");
135 assert withPgtk -> withGTK3 && !withX;
136 assert withXwidgets -> !noGui && (withGTK3 || withPgtk);
139 libGccJitLibraryPaths =
141 "${lib.getLib libgccjit}/lib/gcc"
142 "${lib.getLib stdenv.cc.libc}/lib"
144 ++ lib.optionals (stdenv.cc ? cc.lib.libgcc) [
145 "${lib.getLib stdenv.cc.cc.lib.libgcc}/lib"
148 inherit (if variant == "macport" then llvmPackages_14.stdenv else stdenv)
152 mkDerivation (finalAttrs: {
158 else if variant == "macport" then
160 else if withPgtk then
162 else if withGTK3 then
173 ++ lib.optionals withNativeCompilation [
176 if lib.versionOlder finalAttrs.version "29" then
177 ./native-comp-driver-options-28.patch
178 else if lib.versionOlder finalAttrs.version "30" then
179 ./native-comp-driver-options.patch
181 ./native-comp-driver-options-30.patch;
183 lib.concatStringsSep " " (
184 builtins.map (x: ''"-B${x}"'') (
186 # Paths necessary so the JIT compiler finds its libraries:
187 "${lib.getLib libgccjit}/lib"
189 ++ libGccJitLibraryPaths
191 # Executable paths necessary for compilation (ld, as):
192 "${lib.getBin stdenv.cc.cc}/bin"
193 "${lib.getBin stdenv.cc.bintools}/bin"
194 "${lib.getBin stdenv.cc.bintools.bintools}/bin"
202 postPatch = lib.concatStringsSep "\n" [
203 (lib.optionalString srcRepo ''
207 # Add the name of the wrapped gvfsd
208 # This used to be carried as a patch but it often got out of sync with
209 # upstream and was hard to maintain for emacs-overlay.
213 sed -i 's#(${fn} "gvfs-fuse-daemon")#(${fn} "gvfs-fuse-daemon") (${fn} ".gvfsd-fuse-wrapped")#' lisp/net/tramp-gvfs.el
216 "tramp-compat-process-running-p"
217 "tramp-process-running-p"
221 # Reduce closure size by cleaning the environment of the emacs dumper
223 substituteInPlace src/Makefile.in \
224 --replace 'RUN_TEMACS = ./temacs' 'RUN_TEMACS = env -i ./temacs'
228 substituteInPlace lisp/international/mule-cmds.el \
229 --replace /usr/share/locale ${gettext}/share/locale
231 for makefile_in in $(find . -name Makefile.in -print); do
232 substituteInPlace $makefile_in --replace /bin/pwd pwd
244 ++ lib.optionals (variant == "macport") [
247 ++ lib.optionals srcRepo [
251 ++ lib.optionals (withPgtk || withX && (withGTK3 || withXwidgets)) [ wrapGAppsHook3 ];
257 (lib.getDev harfbuzz)
259 ++ lib.optionals withJansson [
266 ++ lib.optionals withAcl [
269 ++ lib.optionals withAlsaLib [
272 ++ lib.optionals withGpm [
275 ++ lib.optionals withDbus [
278 ++ lib.optionals withSelinux [
281 ++ lib.optionals (!stdenv.hostPlatform.isDarwin && withGTK3) [
282 gsettings-desktop-schemas
284 ++ lib.optionals (stdenv.hostPlatform.isLinux && withX) [
288 ++ lib.optionals (withX && withGTK3) [
291 ++ lib.optionals (withX && withMotif) [
294 ++ lib.optionals withGlibNetworking [
297 ++ lib.optionals withNativeCompilation [
301 ++ lib.optionals withImageMagick [
304 ++ lib.optionals withPgtk [
313 ++ lib.optionals withSQLite3 [
316 ++ lib.optionals withSystemd [
319 ++ lib.optionals withTreeSitter [
322 ++ lib.optionals withWebP [
325 ++ lib.optionals withX [
336 ++ lib.optionals withXinput2 [
339 ++ lib.optionals withXwidgets [
342 ++ lib.optionals stdenv.hostPlatform.isDarwin [
345 ++ lib.optionals withNS [
351 ++ lib.optionals (variant == "macport") [
361 # TODO are these optional?
366 ++ lib.optionals (variant == "macport" && stdenv.hostPlatform.isAarch64) [
367 UniformTypeIdentifiers
370 # Emacs needs to find movemail at run time, see info (emacs) Movemail
371 propagatedUserEnvPkgs = lib.optionals withMailutils [
375 hardeningDisable = [ "format" ];
379 (lib.enableFeature false "build-details") # for a (more) reproducible build
380 (lib.withFeature true "modules")
385 (lib.enableFeature false "ns-self-contained")
389 (lib.withFeatureAs true "x-toolkit" toolkit)
390 (lib.withFeature true "cairo")
391 (lib.withFeature true "xft")
393 else if withPgtk then
395 (lib.withFeature true "pgtk")
399 (lib.withFeature false "gif")
400 (lib.withFeature false "jpeg")
401 (lib.withFeature false "png")
402 (lib.withFeature false "tiff")
403 (lib.withFeature false "x")
404 (lib.withFeature false "xpm")
407 ++ lib.optionals (variant == "macport") [
408 (lib.enableFeatureAs true "mac-app" "$$out/Applications")
409 (lib.withFeature true "gnutls")
410 (lib.withFeature true "mac")
411 (lib.withFeature true "xml2")
413 ++ lib.optionals stdenv.hostPlatform.isDarwin [
414 (lib.withFeature withNS "ns")
417 (lib.withFeature withCompressInstall "compress-install")
418 (lib.withFeature withToolkitScrollBars "toolkit-scroll-bars")
419 (lib.withFeature withNativeCompilation "native-compilation")
420 (lib.withFeature withImageMagick "imagemagick")
421 (lib.withFeature withMailutils "mailutils")
422 (lib.withFeature withSmallJaDic "small-ja-dic")
423 (lib.withFeature withTreeSitter "tree-sitter")
424 (lib.withFeature withXinput2 "xinput2")
425 (lib.withFeature withXwidgets "xwidgets")
426 (lib.withFeature withDbus "dbus")
427 (lib.withFeature withSelinux "selinux")
431 lib.optionalAttrs withNativeCompilation {
432 NATIVE_FULL_AOT = "1";
433 LIBRARY_PATH = lib.concatStringsSep ":" libGccJitLibraryPaths;
435 // lib.optionalAttrs (variant == "macport") {
436 # Fixes intermittent segfaults when compiled with LLVM >= 7.0.
437 # See https://github.com/NixOS/nixpkgs/issues/127902
438 NIX_CFLAGS_COMPILE = "-include ${./macport_noescape_noop.h}";
441 enableParallelBuilding = true;
450 mkdir -p $out/share/emacs/site-lisp
451 cp ${siteStart} $out/share/emacs/site-lisp/site-start.el
453 $out/bin/emacs --batch -f batch-byte-compile $out/share/emacs/site-lisp/site-start.el
455 siteVersionDir=`ls $out/share/emacs | grep -v site-lisp | head -n 1`
457 rm -r $out/share/emacs/$siteVersionDir/site-lisp
459 + lib.optionalString withCsrc ''
460 for srcdir in src lisp lwlib ; do
461 dstdir=$out/share/emacs/$siteVersionDir/$srcdir
463 find $srcdir -name "*.[chm]" -exec cp {} $dstdir \;
464 cp $srcdir/TAGS $dstdir
465 echo '((nil . ((tags-file-name . "TAGS"))))' > $dstdir/.dir-locals.el
468 + lib.optionalString withNS ''
469 mkdir -p $out/Applications
470 mv nextstep/Emacs.app $out/Applications
472 + lib.optionalString (withNativeCompilation && (withNS || variant == "macport")) ''
473 ln -snf $out/lib/emacs/*/native-lisp $out/Applications/Emacs.app/Contents/native-lisp
475 + lib.optionalString withNativeCompilation ''
476 echo "Generating native-compiled trampolines..."
477 # precompile trampolines in parallel, but avoid spawning one process per trampoline.
478 # 1000 is a rough lower bound on the number of trampolines compiled.
479 $out/bin/emacs --batch --eval "(mapatoms (lambda (s) \
480 (when (subr-primitive-p (symbol-function s)) (print s))))" \
481 | xargs -n $((1000/NIX_BUILD_CORES + 1)) -P $NIX_BUILD_CORES \
482 $out/bin/emacs --batch -l comp --eval "(while argv \
483 (comp-trampoline-compile (intern (pop argv))))"
484 mkdir -p $out/share/emacs/native-lisp
485 $out/bin/emacs --batch \
486 --eval "(add-to-list 'native-comp-eln-load-path \"$out/share/emacs/native-lisp\")" \
487 -f batch-native-compile $out/share/emacs/site-lisp/site-start.el
490 postFixup = lib.optionalString (stdenv.hostPlatform.isLinux && withX && toolkit == "lucid") ''
491 patchelf --add-rpath ${lib.makeLibraryPath [ libXcursor ]} $out/bin/emacs
492 patchelf --add-needed "libXcursor.so.1" "$out/bin/emacs"
496 inherit withNativeCompilation;
497 inherit withTreeSitter;
498 inherit withXwidgets;
499 pkgs = recurseIntoAttrs (emacsPackagesFor finalAttrs.finalPackage);
500 tests = { inherit (nixosTests) emacs-daemon; };
504 broken = withNativeCompilation && !(stdenv.buildPlatform.canExecute stdenv.hostPlatform);