summary refs log tree commit diff
path: root/pkgs/applications/editors/emacs/make-emacs.nix
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/applications/editors/emacs/make-emacs.nix')
-rw-r--r--pkgs/applications/editors/emacs/make-emacs.nix414
1 files changed, 414 insertions, 0 deletions
diff --git a/pkgs/applications/editors/emacs/make-emacs.nix b/pkgs/applications/editors/emacs/make-emacs.nix
new file mode 100644
index 00000000000..789420fdfc6
--- /dev/null
+++ b/pkgs/applications/editors/emacs/make-emacs.nix
@@ -0,0 +1,414 @@
+{ pname
+, version
+, variant
+, src
+, patches ? _: [ ]
+, meta
+}:
+
+{ lib
+, stdenv
+, Xaw3d
+, acl
+, alsa-lib
+, autoreconfHook
+, cairo
+, dbus
+, emacsPackagesFor
+, fetchpatch
+, gconf
+, gettext
+, giflib
+, glib-networking
+, gnutls
+, gpm
+, gsettings-desktop-schemas
+, gtk2-x11
+, gtk3
+, gtk3-x11
+, harfbuzz
+, imagemagick
+, jansson
+, libXaw
+, libXcursor
+, libXft
+, libXi
+, libXpm
+, libgccjit
+, libjpeg
+, libotf
+, libpng
+, librsvg
+, libselinux
+, libtiff
+, libwebp
+, libxml2
+, llvmPackages_14
+, m17n_lib
+, makeWrapper
+, motif
+, ncurses
+, nixosTests
+, pkg-config
+, recurseIntoAttrs
+, sigtool
+, sqlite
+, substituteAll
+, systemd
+, tree-sitter
+, texinfo
+, webkitgtk
+, wrapGAppsHook
+
+# Boolean flags
+, nativeComp ? null
+, withNativeCompilation ?
+  if nativeComp != null
+  then lib.warn "nativeComp option is deprecated and will be removed; use withNativeCompilation instead" nativeComp
+  else stdenv.buildPlatform.canExecute stdenv.hostPlatform
+, noGui ? false
+, srcRepo ? true
+, withAcl ? false
+, withAlsaLib ? false
+, withAthena ? false
+, withCsrc ? true
+, withGTK2 ? false
+, withGTK3 ? withPgtk && !noGui
+, withGconf ? false
+, withGlibNetworking ? withPgtk || withGTK3 || (withX && withXwidgets)
+, withGpm ? stdenv.isLinux
+, withImageMagick ? lib.versionOlder version "27" && (withX || withNS)
+, withMotif ? false
+, withNS ? stdenv.isDarwin && !(variant == "macport" || noGui)
+, withPgtk ? false
+, withSQLite3 ? lib.versionAtLeast version "29"
+, withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd
+, withToolkitScrollBars ? true
+, withTreeSitter ? lib.versionAtLeast version "29"
+, withWebP ? lib.versionAtLeast version "29"
+, withX ? !(stdenv.isDarwin || noGui || withPgtk)
+, withXinput2 ? withX && lib.versionAtLeast version "29"
+, withXwidgets ? !stdenv.isDarwin && !noGui && (withGTK3 || withPgtk)
+, withSmallJaDic ? false
+, withCompressInstall ? true
+
+# Options
+, siteStart ? ./site-start.el
+, toolkit ? (
+  if withGTK2 then "gtk2"
+  else if withGTK3 then "gtk3"
+  else if withMotif then "motif"
+  else if withAthena then "athena"
+  else "lucid")
+
+# macOS dependencies for NS and macPort
+, Accelerate
+, AppKit
+, Carbon
+, Cocoa
+, GSS
+, IOKit
+, ImageCaptureCore
+, ImageIO
+, OSAKit
+, Quartz
+, QuartzCore
+, UniformTypeIdentifiers
+, WebKit
+}:
+
+assert (withGTK2 && !withNS && variant != "macport") -> withX;
+assert (withGTK3 && !withNS && variant != "macport") -> withX || withPgtk;
+
+assert noGui -> !(withX || withGTK2 || withGTK3 || withNS || variant == "macport");
+assert withAcl -> stdenv.isLinux;
+assert withAlsaLib -> stdenv.isLinux;
+assert withGTK2 -> !(withGTK3 || withPgtk);
+assert withGTK3 -> !withGTK2 || withPgtk;
+assert withGconf -> withX;
+assert withGpm -> stdenv.isLinux;
+assert withNS -> stdenv.isDarwin && !(withX || variant == "macport");
+assert withPgtk -> withGTK3 && !withX;
+assert withXwidgets -> !noGui && (withGTK3 || withPgtk);
+
+let
+  libGccJitLibraryPaths = [
+    "${lib.getLib libgccjit}/lib/gcc"
+    "${lib.getLib stdenv.cc.libc}/lib"
+  ] ++ lib.optionals (stdenv.cc?cc.libgcc) [
+    "${lib.getLib stdenv.cc.cc.libgcc}/lib"
+  ];
+
+  inherit (if variant == "macport"
+           then llvmPackages_14.stdenv
+           else stdenv) mkDerivation;
+in
+mkDerivation (finalAttrs: {
+  pname = pname
+          + (if noGui then "-nox"
+             else if variant == "macport" then "-macport"
+             else if withPgtk then "-pgtk"
+             else if withGTK3 then "-gtk3"
+             else if withGTK2 then "-gtk2"
+             else "");
+  inherit version;
+
+  inherit src;
+
+  patches = patches fetchpatch ++ lib.optionals withNativeCompilation [
+    (substituteAll {
+      src = if lib.versionOlder finalAttrs.version "29"
+            then ./native-comp-driver-options-28.patch
+            else ./native-comp-driver-options.patch;
+      backendPath = (lib.concatStringsSep " "
+        (builtins.map (x: ''"-B${x}"'') ([
+          # Paths necessary so the JIT compiler finds its libraries:
+          "${lib.getLib libgccjit}/lib"
+        ] ++ libGccJitLibraryPaths ++ [
+          # Executable paths necessary for compilation (ld, as):
+          "${lib.getBin stdenv.cc.cc}/bin"
+          "${lib.getBin stdenv.cc.bintools}/bin"
+          "${lib.getBin stdenv.cc.bintools.bintools}/bin"
+        ])));
+    })
+  ];
+
+  postPatch = lib.concatStringsSep "\n" [
+    (lib.optionalString srcRepo ''
+      rm -fr .git
+    '')
+
+    # Add the name of the wrapped gvfsd
+    # This used to be carried as a patch but it often got out of sync with
+    # upstream and was hard to maintain for emacs-overlay.
+    (lib.concatStrings (map (fn: ''
+      sed -i 's#(${fn} "gvfs-fuse-daemon")#(${fn} "gvfs-fuse-daemon") (${fn} ".gvfsd-fuse-wrapped")#' lisp/net/tramp-gvfs.el
+    '') [
+      "tramp-compat-process-running-p"
+      "tramp-process-running-p"
+    ]))
+
+    # Reduce closure size by cleaning the environment of the emacs dumper
+    ''
+      substituteInPlace src/Makefile.in \
+        --replace 'RUN_TEMACS = ./temacs' 'RUN_TEMACS = env -i ./temacs'
+    ''
+
+    ''
+      substituteInPlace lisp/international/mule-cmds.el \
+        --replace /usr/share/locale ${gettext}/share/locale
+
+      for makefile_in in $(find . -name Makefile.in -print); do
+        substituteInPlace $makefile_in --replace /bin/pwd pwd
+      done
+    ''
+
+    ""
+  ];
+
+  nativeBuildInputs = [
+    makeWrapper
+    pkg-config
+  ] ++ lib.optionals (variant == "macport") [
+    texinfo
+  ] ++ lib.optionals srcRepo [
+    autoreconfHook
+    texinfo
+  ] ++ lib.optional (withPgtk || withX && (withGTK3 || withXwidgets)) wrapGAppsHook;
+
+  buildInputs = [
+    gettext
+    gnutls
+    harfbuzz.dev
+    jansson
+    libxml2
+    ncurses
+  ] ++ lib.optionals withGconf [
+    gconf
+  ] ++ lib.optionals withAcl [
+    acl
+  ] ++ lib.optionals withAlsaLib [
+    alsa-lib
+  ] ++ lib.optionals withGpm [
+    gpm
+  ] ++ lib.optionals stdenv.isLinux [
+    dbus
+    libselinux
+  ] ++ lib.optionals (!stdenv.isDarwin && withGTK3) [
+    gsettings-desktop-schemas
+  ] ++ lib.optionals (stdenv.isLinux && withX) [
+    libotf
+    m17n_lib
+  ] ++ lib.optionals (withX && withGTK2) [
+    gtk2-x11
+  ] ++ lib.optionals (withX && withGTK3) [
+    gtk3-x11
+  ] ++ lib.optionals (withX && withMotif) [
+    motif
+  ] ++ lib.optionals withGlibNetworking [
+    glib-networking
+  ] ++ lib.optionals withNativeCompilation [
+    libgccjit
+  ] ++ lib.optionals withImageMagick [
+    imagemagick
+  ] ++ lib.optionals withPgtk [
+    giflib
+    gtk3
+    libXpm
+    libjpeg
+    libpng
+    librsvg
+    libtiff
+  ] ++ lib.optionals withSQLite3 [
+    sqlite
+  ] ++ lib.optionals withSystemd [
+    systemd
+  ] ++ lib.optionals withTreeSitter [
+    tree-sitter
+  ] ++ lib.optionals withWebP [
+    libwebp
+  ] ++ lib.optionals withX [
+    Xaw3d
+    cairo
+    giflib
+    libXaw
+    libXpm
+    libjpeg
+    libpng
+    librsvg
+    libtiff
+  ] ++ lib.optionals withXinput2 [
+    libXi
+  ] ++ lib.optionals withXwidgets [
+    webkitgtk
+  ] ++ lib.optionals stdenv.isDarwin [
+    sigtool
+  ] ++ lib.optionals withNS [
+    librsvg
+    AppKit
+    GSS
+    ImageIO
+  ] ++ lib.optionals (variant == "macport") [
+    Accelerate
+    AppKit
+    Carbon
+    Cocoa
+    IOKit
+    OSAKit
+    Quartz
+    QuartzCore
+    UniformTypeIdentifiers
+    WebKit
+    # TODO are these optional?
+    GSS
+    ImageCaptureCore
+    ImageIO
+  ];
+
+  hardeningDisable = [ "format" ];
+
+  configureFlags = [
+    "--disable-build-details" # for a (more) reproducible build
+    "--with-modules"
+  ] ++ (if withNS then [
+    "--disable-ns-self-contained"
+  ] else if withX then [
+    "--with-x-toolkit=${toolkit}"
+    "--with-xft"
+    "--with-cairo"
+  ] else if withPgtk then [
+    "--with-pgtk"
+  ] else [
+    "--with-gif=no"
+    "--with-jpeg=no"
+    "--with-png=no"
+    "--with-tiff=no"
+    "--with-x=no"
+    "--with-xpm=no"
+  ])
+  ++ lib.optionals (variant == "macport") [
+    "--enable-mac-app=$$out/Applications"
+    "--with-gnutls=yes"
+    "--with-mac"
+    "--with-xml2=yes"
+  ]
+  ++ (lib.optional stdenv.isDarwin (lib.withFeature withNS "ns"))
+  ++ lib.optional (!withToolkitScrollBars) "--without-toolkit-scroll-bars"
+  ++ lib.optional withNativeCompilation "--with-native-compilation"
+  ++ lib.optional withImageMagick "--with-imagemagick"
+  ++ lib.optional withTreeSitter "--with-tree-sitter"
+  ++ lib.optional withXinput2 "--with-xinput2"
+  ++ lib.optional withXwidgets "--with-xwidgets"
+  ++ lib.optional withSmallJaDic "--with-small-ja-dic"
+  ++ lib.optional (!withCompressInstall) "--without-compress-install"
+  ;
+
+  env = lib.optionalAttrs withNativeCompilation {
+    NATIVE_FULL_AOT = "1";
+    LIBRARY_PATH = lib.concatStringsSep ":" libGccJitLibraryPaths;
+  } // lib.optionalAttrs (variant == "macport") {
+    # Fixes intermittent segfaults when compiled with LLVM >= 7.0.
+    # See https://github.com/NixOS/nixpkgs/issues/127902
+    NIX_CFLAGS_COMPILE = "-include ${./macport_noescape_noop.h}";
+  };
+
+  enableParallelBuilding = true;
+
+  installTargets = [ "tags" "install" ];
+
+  postInstall = ''
+    mkdir -p $out/share/emacs/site-lisp
+    cp ${siteStart} $out/share/emacs/site-lisp/site-start.el
+
+    $out/bin/emacs --batch -f batch-byte-compile $out/share/emacs/site-lisp/site-start.el
+
+    siteVersionDir=`ls $out/share/emacs | grep -v site-lisp | head -n 1`
+
+    rm -r $out/share/emacs/$siteVersionDir/site-lisp
+  '' + lib.optionalString withCsrc ''
+    for srcdir in src lisp lwlib ; do
+      dstdir=$out/share/emacs/$siteVersionDir/$srcdir
+      mkdir -p $dstdir
+      find $srcdir -name "*.[chm]" -exec cp {} $dstdir \;
+      cp $srcdir/TAGS $dstdir
+      echo '((nil . ((tags-file-name . "TAGS"))))' > $dstdir/.dir-locals.el
+    done
+  '' + lib.optionalString withNS ''
+    mkdir -p $out/Applications
+    mv nextstep/Emacs.app $out/Applications
+  '' + lib.optionalString (withNativeCompilation && (withNS || variant == "macport")) ''
+    ln -snf $out/lib/emacs/*/native-lisp $out/Applications/Emacs.app/Contents/native-lisp
+  '' + lib.optionalString withNativeCompilation ''
+    echo "Generating native-compiled trampolines..."
+    # precompile trampolines in parallel, but avoid spawning one process per trampoline.
+    # 1000 is a rough lower bound on the number of trampolines compiled.
+    $out/bin/emacs --batch --eval "(mapatoms (lambda (s) \
+      (when (subr-primitive-p (symbol-function s)) (print s))))" \
+      | xargs -n $((1000/NIX_BUILD_CORES + 1)) -P $NIX_BUILD_CORES \
+        $out/bin/emacs --batch -l comp --eval "(while argv \
+          (comp-trampoline-compile (intern (pop argv))))"
+    mkdir -p $out/share/emacs/native-lisp
+    $out/bin/emacs --batch \
+      --eval "(add-to-list 'native-comp-eln-load-path \"$out/share/emacs/native-lisp\")" \
+      -f batch-native-compile $out/share/emacs/site-lisp/site-start.el
+  '';
+
+  postFixup = lib.optionalString (stdenv.isLinux && withX && toolkit == "lucid") ''
+      patchelf --add-rpath ${lib.makeLibraryPath [ libXcursor ]} $out/bin/emacs
+      patchelf --add-needed "libXcursor.so.1" "$out/bin/emacs"
+  '';
+
+  passthru = {
+    inherit withNativeCompilation;
+    inherit withTreeSitter;
+    pkgs = recurseIntoAttrs (emacsPackagesFor finalAttrs.finalPackage);
+    tests = { inherit (nixosTests) emacs-daemon; };
+    # Backwards compatibility aliases. Remove this at some point before 23.11 release cut-off.
+    nativeComp = builtins.trace "emacs.passthru: nativeComp was renamed to withNativeCompilation and will be removed in 23.11" withNativeCompilation;
+    treeSitter = builtins.trace "emacs.passthru: treeSitter was renamed to withTreeSitter and will be removed in 23.11" withTreeSitter;
+  };
+
+  meta = meta // {
+    broken = withNativeCompilation && !(stdenv.buildPlatform.canExecute stdenv.hostPlatform);
+  };
+})