From 2580e43c661ca28f57062829030c1ff227ae6a6c Mon Sep 17 00:00:00 2001 From: syl20bnr Date: Sat, 31 Mar 2018 00:31:52 -0400 Subject: [PATCH] Add support for dumping Spacemacs Create dump with: ./emacs --batch -l ~/.emacs.d/dump-init.el \ -eval '(dump-emacs-portable "spacemacs.pdmp")' Load dump with: ./emacs --dump-file=spacemacs.pdmp User can require/load additional libraries in new dotfile function: dotspacemacs/user-load --- core/core-configuration-layer.el | 100 +++++++++--------- core/core-dump.el | 59 +++++++++++ core/core-spacemacs.el | 12 ++- core/core-versions.el | 2 +- core/templates/.spacemacs.template | 7 ++ dump-init.el | 2 + init.el | 19 +++- .../+spacemacs/spacemacs-editing/packages.el | 8 +- 8 files changed, 146 insertions(+), 63 deletions(-) create mode 100644 core/core-dump.el create mode 100644 dump-init.el diff --git a/core/core-configuration-layer.el b/core/core-configuration-layer.el index 6dc837a95..c612c4978 100644 --- a/core/core-configuration-layer.el +++ b/core/core-configuration-layer.el @@ -555,55 +555,57 @@ To prevent package from being installed or uninstalled set the variable `spacemacs-sync-packages' to nil." (run-hooks 'configuration-layer-pre-load-hook) (dotspacemacs|call-func dotspacemacs/layers "Calling dotfile layers...") - (setq dotspacemacs--configuration-layers-saved - dotspacemacs-configuration-layers) - (when (spacemacs-buffer//choose-banner) - (spacemacs-buffer//inject-version)) - ;; declare used layers then packages as soon as possible to resolve - ;; usage and ownership - (configuration-layer/discover-layers 'refresh-index) - (configuration-layer//declare-used-layers dotspacemacs-configuration-layers) - (configuration-layer//declare-used-packages configuration-layer--used-layers) - ;; then load the functions and finally configure the layers - (configuration-layer//load-layers-files configuration-layer--used-layers - '("funcs.el")) - (configuration-layer//configure-layers configuration-layer--used-layers) - ;; load layers lazy settings - (configuration-layer/load-auto-layer-file) - ;; install and/or uninstall packages - (when spacemacs-sync-packages - (let ((packages - (append - ;; install used packages - (configuration-layer//filter-distant-packages - configuration-layer--used-packages t - '(not (oref pkg :lazy-install))) - ;; also install all other packages if requested - (when (eq 'all dotspacemacs-install-packages) - (let (all-other-packages) - (dolist (layer (configuration-layer/get-layers-list)) - (let ((configuration-layer--declared-layers-usedp nil) - (configuration-layer--load-packages-files t)) - (configuration-layer/declare-layer layer) - (let* ((obj (configuration-layer/get-layer layer)) - (pkgs (when obj (oref obj :packages)))) - (configuration-layer/make-packages-from-layers - (list layer)) - (dolist (pkg pkgs) - (let ((pkg-name (if (listp pkg) (car pkg) pkg))) - (add-to-list 'all-other-packages pkg-name)))))) - (configuration-layer//filter-distant-packages - all-other-packages nil)))))) - (configuration-layer//install-packages packages) - (when (and (or (eq 'used dotspacemacs-install-packages) - (eq 'used-only dotspacemacs-install-packages)) - (not configuration-layer-force-distribution) - (not configuration-layer-exclude-all-layers)) - (configuration-layer/delete-orphan-packages packages)))) - ;; configure used packages - (configuration-layer//configure-packages configuration-layer--used-packages) - (configuration-layer//load-layers-files configuration-layer--used-layers - '("keybindings.el")) + (spacemacs|when-dumping + (setq dotspacemacs--configuration-layers-saved + dotspacemacs-configuration-layers) + (when (spacemacs-buffer//choose-banner) + (spacemacs-buffer//inject-version)) + ;; declare used layers then packages as soon as possible to resolve + ;; usage and ownership + (configuration-layer/discover-layers 'refresh-index) + (configuration-layer//declare-used-layers dotspacemacs-configuration-layers) + (configuration-layer//declare-used-packages configuration-layer--used-layers) + ;; then load the functions and finally configure the layers + (configuration-layer//load-layers-files configuration-layer--used-layers + '("funcs.el")) + (configuration-layer//configure-layers configuration-layer--used-layers) + ;; load layers lazy settings + (configuration-layer/load-auto-layer-file) + ;; install and/or uninstall packages + (when spacemacs-sync-packages + (let ((packages + (append + ;; install used packages + (configuration-layer//filter-distant-packages + configuration-layer--used-packages t + '(not (oref pkg :lazy-install))) + ;; also install all other packages if requested + (when (eq 'all dotspacemacs-install-packages) + (let (all-other-packages) + (dolist (layer (configuration-layer/get-layers-list)) + (let ((configuration-layer--declared-layers-usedp nil) + (configuration-layer--load-packages-files t)) + (configuration-layer/declare-layer layer) + (let* ((obj (configuration-layer/get-layer layer)) + (pkgs (when obj (oref obj :packages)))) + (configuration-layer/make-packages-from-layers + (list layer)) + (dolist (pkg pkgs) + (let ((pkg-name (if (listp pkg) (car pkg) pkg))) + (add-to-list 'all-other-packages pkg-name)))))) + (configuration-layer//filter-distant-packages + all-other-packages nil)))))) + (configuration-layer//install-packages packages) + (when (and (or (eq 'used dotspacemacs-install-packages) + (eq 'used-only dotspacemacs-install-packages)) + (not configuration-layer-force-distribution) + (not configuration-layer-exclude-all-layers)) + (configuration-layer/delete-orphan-packages packages)))) + ;; configure used packages + (configuration-layer//configure-packages configuration-layer--used-packages) + (configuration-layer//load-layers-files configuration-layer--used-layers + '("keybindings.el")) + (dotspacemacs|call-func dotspacemacs/user-load "Calling dotfile user-load...")) (run-hooks 'configuration-layer-post-load-hook)) (defun configuration-layer/load-auto-layer-file () diff --git a/core/core-dump.el b/core/core-dump.el new file mode 100644 index 000000000..2ab61ba28 --- /dev/null +++ b/core/core-dump.el @@ -0,0 +1,59 @@ +;;; core-dump.el --- Spacemacs Core File +;; +;; Copyright (c) 2012-2018 Sylvain Benner & Contributors +;; +;; Author: Sylvain Benner +;; URL: https://github.com/syl20bnr/spacemacs +;; +;; This file is not part of GNU Emacs. +;; +;;; License: GPLv3 + +(defvar spacemacs-dump-mode 'not-dumped + "Spacemacs dump mode, can be `not-dumped', `dumped' or `dumping'.") + +(defun spacemacs/defer () + "Return non-nil if dump is not supported." + (eq 'not-dumped spacemacs-dump-mode)) + +(defmacro spacemacs|require (&rest args) + "Require feature if dumping." + (spacemacs|when-dumping-strict `(require ,@args))) + +(defun spacemacs-is-dumping-p () + "Return non-nil if Spacemacs is dumping." + (eq 'dumping spacemacs-dump-mode)) + +(defmacro spacemacs|when-dumping (&rest body) + "Execute body if dumping. +This function considers that we are always dumping if dumping is not supported. +You should always use this function." + (declare (indent defun)) + `(when (not (eq 'dumped spacemacs-dump-mode)) + ,@body)) + +(defmacro spacemacs|when-dumping-strict (&rest body) + "Execute body if we are really dumping. +You should not used this function, it is reserved for some specific process." + (declare (indent defun)) + `(when (eq 'dumping spacemacs-dump-mode) + ,@body)) + +(defmacro spacemacs|unless-dumping (&rest body) + "Execute body if not dumping" + (declare (indent defun)) + `(unless (eq 'dumping spacemacs-dump-mode) + ,@body)) + +;; ;; Brute-force load all .el files in ELPA packages +;; (dolist (d (directory-files package-user-dir t nil 'nosort)) +;; (unless (or (string-equal ".." (substring d -2)) +;; (string-equal "." (substring d -1)) +;; (not (file-directory-p d))) +;; (message "%s" d) +;; (dolist (f (directory-files d t "\\.el$" 'nosort)) +;; (unless (string-match-p ".*pkg\\.el$" f) +;; (message "%s" f) +;; (ignore-errors (load f t)))))) + +(provide 'core-dump) diff --git a/core/core-spacemacs.el b/core/core-spacemacs.el index f1e84c667..9d5c2320d 100644 --- a/core/core-spacemacs.el +++ b/core/core-spacemacs.el @@ -9,9 +9,9 @@ ;; ;;; License: GPLv3 (setq message-log-max 16384) -(defconst emacs-start-time (current-time)) (require 'subr-x nil 'noerror) +(require 'core-dump) (require 'core-emacs-backports) (require 'page-break-lines) (require 'core-debug) @@ -86,7 +86,8 @@ the final step of executing code in `emacs-startup-hook'.") (unless (frame-parameter nil 'fullscreen) (toggle-frame-maximized)) (add-to-list 'default-frame-alist '(fullscreen . maximized))) - (dotspacemacs|call-func dotspacemacs/user-init "Calling dotfile user init...") + (spacemacs|unless-dumping + (dotspacemacs|call-func dotspacemacs/user-init "Calling dotfile user init...")) ;; Given the loading process of Spacemacs we have no choice but to set the ;; custom settings twice: ;; - once at the very beginning of startup (here) @@ -202,7 +203,8 @@ defer call using `spacemacs-post-user-config-hook'." (add-hook 'spacemacs-post-user-config-hook func))) (defun spacemacs/setup-startup-hook () - "Add post init processing." + "Add post init processing. +Note: the hooked function is not executed when in dumped mode." (add-hook 'emacs-startup-hook (defun spacemacs/startup-hook () @@ -214,9 +216,9 @@ defer call using `spacemacs-post-user-config-hook'." ;; Ultimate configuration decisions are given to the user who can defined ;; them in his/her ~/.spacemacs file (dotspacemacs|call-func dotspacemacs/user-config - "Calling dotfile user config...") + "Calling dotfile user config...") (dotspacemacs|call-func dotspacemacs/emacs-custom-settings - "Calling dotfile Emacs custom settings...") + "Calling dotfile Emacs custom settings...") (run-hooks 'spacemacs-post-user-config-hook) (setq spacemacs-post-user-config-hook-run t) (when (fboundp dotspacemacs-scratch-mode) diff --git a/core/core-versions.el b/core/core-versions.el index 17e619a0f..ab6bc77d6 100644 --- a/core/core-versions.el +++ b/core/core-versions.el @@ -10,4 +10,4 @@ ;;; License: GPLv3 (defconst spacemacs-version "0.300.0" "Spacemacs version.") -(defconst spacemacs-emacs-min-version "25.1" "Minimal version of Emacs.") +(defconst spacemacs-emacs-min-version "27.0" "Minimal version of Emacs.") diff --git a/core/templates/.spacemacs.template b/core/templates/.spacemacs.template index 2adf0c390..176e4ffb9 100644 --- a/core/templates/.spacemacs.template +++ b/core/templates/.spacemacs.template @@ -436,6 +436,13 @@ It is mostly for variables that should be set before packages are loaded. If you are unsure, try setting them in `dotspacemacs/user-config' first." ) +(defun dotspacemacs/user-load () + "Library to load while dumping. +This function is called while dumping Spacemacs configuration. You can +`require' or `load' the libraries of your choice that will be included +in the dump." + ) + (defun dotspacemacs/user-config () "Configuration for user code: This function is called at the very end of Spacemacs startup, after layer diff --git a/dump-init.el b/dump-init.el new file mode 100644 index 000000000..30e76be68 --- /dev/null +++ b/dump-init.el @@ -0,0 +1,2 @@ +(setq spacemacs-dump-mode 'dumping) +(load (concat (file-name-directory load-file-name) "init.el")) diff --git a/init.el b/init.el index 60d4f1772..66fa6cb4a 100644 --- a/init.el +++ b/init.el @@ -14,6 +14,7 @@ ;; Avoid garbage collection during startup. ;; see `SPC h . dotspacemacs-gc-cons' for more info +(defconst emacs-start-time (current-time)) (setq gc-cons-threshold 402653184 gc-cons-percentage 0.6) (load-file (concat (file-name-directory load-file-name) "core/core-versions.el")) @@ -27,12 +28,24 @@ ;; Disable file-name-handlers for a speed boost during init (let ((file-name-handler-alist nil)) (require 'core-spacemacs) + (spacemacs|unless-dumping + (when (boundp 'load-path-backup) + (setq load-path load-path-backup))) (configuration-layer/load-lock-file) (spacemacs/init) (configuration-layer/stable-elpa-download-tarball) (configuration-layer/load) (spacemacs-buffer/display-startup-note) (spacemacs/setup-startup-hook) - (when dotspacemacs-enable-server - (require 'server) - (unless (server-running-p) (server-start))))) + (spacemacs|unless-dumping + (global-font-lock-mode) + (global-undo-tree-mode 1)) + ;; (when dotspacemacs-enable-server + ;; (require 'server) + ;; (unless (server-running-p) (server-start))) + (spacemacs|when-dumping-strict + (setq load-path-backup load-path) + ;; disable undo-tree to prevent from segfaulting when loading the dump + (global-undo-tree-mode -1) + (setq spacemacs-dump-mode 'dumped) + (garbage-collect)))) diff --git a/layers/+spacemacs/spacemacs-editing/packages.el b/layers/+spacemacs/spacemacs-editing/packages.el index a3e146708..70a98034f 100644 --- a/layers/+spacemacs/spacemacs-editing/packages.el +++ b/layers/+spacemacs/spacemacs-editing/packages.el @@ -400,11 +400,9 @@ (defun spacemacs-editing/init-undo-tree () (use-package undo-tree - :init - (progn - (global-undo-tree-mode) - (setq undo-tree-visualizer-timestamps t - undo-tree-visualizer-diff t)) + :defer t + :init (setq undo-tree-visualizer-timestamps t + undo-tree-visualizer-diff t) :config (progn ;; restore diff window after quit. TODO fix upstream