25 , gsettings-desktop-schemas
64 , withNativeCompilation ? stdenv.buildPlatform.canExecute stdenv.hostPlatform
71 , withDbus ? stdenv.isLinux
73 , withGTK3 ? withPgtk && !noGui
75 , withGlibNetworking ? withPgtk || withGTK3 || (withX && withXwidgets)
76 , withGpm ? stdenv.isLinux
77 , withImageMagick ? lib.versionOlder version "27" && (withX || withNS)
79 , withNS ? stdenv.isDarwin && !(variant == "macport" || noGui)
81 , withSelinux ? stdenv.isLinux
82 , withSQLite3 ? lib.versionAtLeast version "29"
83 , withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd
84 , withToolkitScrollBars ? true
85 , withTreeSitter ? lib.versionAtLeast version "29"
86 , withWebP ? lib.versionAtLeast version "29"
87 , withX ? !(stdenv.isDarwin || noGui || withPgtk)
88 , withXinput2 ? withX && lib.versionAtLeast version "29"
89 , withXwidgets ? !stdenv.isDarwin && !noGui && (withGTK3 || withPgtk)
90 , withSmallJaDic ? false
91 , withCompressInstall ? true
94 , siteStart ? ./site-start.el
96 if withGTK2 then "gtk2"
97 else if withGTK3 then "gtk3"
98 else if withMotif then "motif"
99 else if withAthena then "athena"
102 # macOS dependencies for NS and macPort
114 , UniformTypeIdentifiers
118 assert (withGTK2 && !withNS && variant != "macport") -> withX;
119 assert (withGTK3 && !withNS && variant != "macport") -> withX || withPgtk;
121 assert noGui -> !(withX || withGTK2 || withGTK3 || withNS || variant == "macport");
122 assert withAcl -> stdenv.isLinux;
123 assert withAlsaLib -> stdenv.isLinux;
124 assert withGTK2 -> !(withGTK3 || withPgtk);
125 assert withGTK3 -> !withGTK2 || withPgtk;
126 assert withGconf -> withX;
127 assert withGpm -> stdenv.isLinux;
128 assert withNS -> stdenv.isDarwin && !(withX || variant == "macport");
129 assert withPgtk -> withGTK3 && !withX;
130 assert withXwidgets -> !noGui && (withGTK3 || withPgtk);
133 libGccJitLibraryPaths = [
134 "${lib.getLib libgccjit}/lib/gcc"
135 "${lib.getLib stdenv.cc.libc}/lib"
136 ] ++ lib.optionals (stdenv.cc?cc.libgcc) [
137 "${lib.getLib stdenv.cc.cc.libgcc}/lib"
140 inherit (if variant == "macport"
141 then llvmPackages_14.stdenv
142 else stdenv) mkDerivation;
144 mkDerivation (finalAttrs: {
146 + (if noGui then "-nox"
147 else if variant == "macport" then "-macport"
148 else if withPgtk then "-pgtk"
149 else if withGTK3 then "-gtk3"
150 else if withGTK2 then "-gtk2"
156 patches = patches fetchpatch ++ lib.optionals withNativeCompilation [
158 src = if lib.versionOlder finalAttrs.version "29"
159 then ./native-comp-driver-options-28.patch
160 else ./native-comp-driver-options.patch;
161 backendPath = (lib.concatStringsSep " "
162 (builtins.map (x: ''"-B${x}"'') ([
163 # Paths necessary so the JIT compiler finds its libraries:
164 "${lib.getLib libgccjit}/lib"
165 ] ++ libGccJitLibraryPaths ++ [
166 # Executable paths necessary for compilation (ld, as):
167 "${lib.getBin stdenv.cc.cc}/bin"
168 "${lib.getBin stdenv.cc.bintools}/bin"
169 "${lib.getBin stdenv.cc.bintools.bintools}/bin"
174 postPatch = lib.concatStringsSep "\n" [
175 (lib.optionalString srcRepo ''
179 # Add the name of the wrapped gvfsd
180 # This used to be carried as a patch but it often got out of sync with
181 # upstream and was hard to maintain for emacs-overlay.
182 (lib.concatStrings (map (fn: ''
183 sed -i 's#(${fn} "gvfs-fuse-daemon")#(${fn} "gvfs-fuse-daemon") (${fn} ".gvfsd-fuse-wrapped")#' lisp/net/tramp-gvfs.el
185 "tramp-compat-process-running-p"
186 "tramp-process-running-p"
189 # Reduce closure size by cleaning the environment of the emacs dumper
191 substituteInPlace src/Makefile.in \
192 --replace 'RUN_TEMACS = ./temacs' 'RUN_TEMACS = env -i ./temacs'
196 substituteInPlace lisp/international/mule-cmds.el \
197 --replace /usr/share/locale ${gettext}/share/locale
199 for makefile_in in $(find . -name Makefile.in -print); do
200 substituteInPlace $makefile_in --replace /bin/pwd pwd
207 nativeBuildInputs = [
210 ] ++ lib.optionals (variant == "macport") [
212 ] ++ lib.optionals srcRepo [
215 ] ++ lib.optional (withPgtk || withX && (withGTK3 || withXwidgets)) wrapGAppsHook;
224 ] ++ lib.optionals withGconf [
226 ] ++ lib.optionals withAcl [
228 ] ++ lib.optionals withAlsaLib [
230 ] ++ lib.optionals withGpm [
232 ] ++ lib.optionals withDbus [
234 ] ++ lib.optionals withSelinux [
236 ] ++ lib.optionals (!stdenv.isDarwin && withGTK3) [
237 gsettings-desktop-schemas
238 ] ++ lib.optionals (stdenv.isLinux && withX) [
241 ] ++ lib.optionals (withX && withGTK2) [
243 ] ++ lib.optionals (withX && withGTK3) [
245 ] ++ lib.optionals (withX && withMotif) [
247 ] ++ lib.optionals withGlibNetworking [
249 ] ++ lib.optionals withNativeCompilation [
251 ] ++ lib.optionals withImageMagick [
253 ] ++ lib.optionals withPgtk [
261 ] ++ lib.optionals withSQLite3 [
263 ] ++ lib.optionals withSystemd [
265 ] ++ lib.optionals withTreeSitter [
267 ] ++ lib.optionals withWebP [
269 ] ++ lib.optionals withX [
279 ] ++ lib.optionals withXinput2 [
281 ] ++ lib.optionals withXwidgets [
283 ] ++ lib.optionals stdenv.isDarwin [
285 ] ++ lib.optionals withNS [
290 ] ++ lib.optionals (variant == "macport") [
299 UniformTypeIdentifiers
301 # TODO are these optional?
307 hardeningDisable = [ "format" ];
310 "--disable-build-details" # for a (more) reproducible build
312 ] ++ (if withNS then [
313 "--disable-ns-self-contained"
314 ] else if withX then [
315 "--with-x-toolkit=${toolkit}"
318 ] else if withPgtk then [
328 ++ lib.optionals (variant == "macport") [
329 "--enable-mac-app=$$out/Applications"
334 ++ (lib.optional stdenv.isDarwin (lib.withFeature withNS "ns"))
336 (lib.withFeature withCompressInstall "compress-install")
337 (lib.withFeature withToolkitScrollBars "toolkit-scroll-bars")
338 (lib.withFeature withNativeCompilation "native-compilation")
339 (lib.withFeature withImageMagick "imagemagick")
340 (lib.withFeature withSmallJaDic "small-ja-dic")
341 (lib.withFeature withTreeSitter "tree-sitter")
342 (lib.withFeature withXinput2 "xinput2")
343 (lib.withFeature withXwidgets "xwidgets")
344 (lib.withFeature withDbus "dbus")
345 (lib.withFeature withSelinux "selinux")
348 env = lib.optionalAttrs withNativeCompilation {
349 NATIVE_FULL_AOT = "1";
350 LIBRARY_PATH = lib.concatStringsSep ":" libGccJitLibraryPaths;
351 } // lib.optionalAttrs (variant == "macport") {
352 # Fixes intermittent segfaults when compiled with LLVM >= 7.0.
353 # See https://github.com/NixOS/nixpkgs/issues/127902
354 NIX_CFLAGS_COMPILE = "-include ${./macport_noescape_noop.h}";
357 enableParallelBuilding = true;
359 installTargets = [ "tags" "install" ];
362 mkdir -p $out/share/emacs/site-lisp
363 cp ${siteStart} $out/share/emacs/site-lisp/site-start.el
365 $out/bin/emacs --batch -f batch-byte-compile $out/share/emacs/site-lisp/site-start.el
367 siteVersionDir=`ls $out/share/emacs | grep -v site-lisp | head -n 1`
369 rm -r $out/share/emacs/$siteVersionDir/site-lisp
370 '' + lib.optionalString withCsrc ''
371 for srcdir in src lisp lwlib ; do
372 dstdir=$out/share/emacs/$siteVersionDir/$srcdir
374 find $srcdir -name "*.[chm]" -exec cp {} $dstdir \;
375 cp $srcdir/TAGS $dstdir
376 echo '((nil . ((tags-file-name . "TAGS"))))' > $dstdir/.dir-locals.el
378 '' + lib.optionalString withNS ''
379 mkdir -p $out/Applications
380 mv nextstep/Emacs.app $out/Applications
381 '' + lib.optionalString (withNativeCompilation && (withNS || variant == "macport")) ''
382 ln -snf $out/lib/emacs/*/native-lisp $out/Applications/Emacs.app/Contents/native-lisp
383 '' + lib.optionalString withNativeCompilation ''
384 echo "Generating native-compiled trampolines..."
385 # precompile trampolines in parallel, but avoid spawning one process per trampoline.
386 # 1000 is a rough lower bound on the number of trampolines compiled.
387 $out/bin/emacs --batch --eval "(mapatoms (lambda (s) \
388 (when (subr-primitive-p (symbol-function s)) (print s))))" \
389 | xargs -n $((1000/NIX_BUILD_CORES + 1)) -P $NIX_BUILD_CORES \
390 $out/bin/emacs --batch -l comp --eval "(while argv \
391 (comp-trampoline-compile (intern (pop argv))))"
392 mkdir -p $out/share/emacs/native-lisp
393 $out/bin/emacs --batch \
394 --eval "(add-to-list 'native-comp-eln-load-path \"$out/share/emacs/native-lisp\")" \
395 -f batch-native-compile $out/share/emacs/site-lisp/site-start.el
398 postFixup = lib.optionalString (stdenv.isLinux && withX && toolkit == "lucid") ''
399 patchelf --add-rpath ${lib.makeLibraryPath [ libXcursor ]} $out/bin/emacs
400 patchelf --add-needed "libXcursor.so.1" "$out/bin/emacs"
404 inherit withNativeCompilation;
405 inherit withTreeSitter;
406 pkgs = recurseIntoAttrs (emacsPackagesFor finalAttrs.finalPackage);
407 tests = { inherit (nixosTests) emacs-daemon; };
411 broken = withNativeCompilation && !(stdenv.buildPlatform.canExecute stdenv.hostPlatform);