diff --git a/emacs/Makefile.local b/emacs/Makefile.local index fb82247f..456700ac 100644 --- a/emacs/Makefile.local +++ b/emacs/Makefile.local @@ -22,6 +22,18 @@ emacs_images := \ emacs_bytecode = $(emacs_sources:.el=.elc) +# Because of defmacro's and defsubst's, we have to account for load +# dependencies between Elisp files when byte compiling. Otherwise, +# the byte compiler may load an old .elc file when processing a +# "require" or we may fail to rebuild a .elc that depended on a macro +# from an updated file. +$(dir)/.eldeps: $(dir)/Makefile.local $(dir)/make-deps.el $(emacs_sources) + $(call quiet,EMACS) --directory emacs -batch -l make-deps.el \ + -f batch-make-deps $(emacs_sources) > $@.tmp && \ + (cmp -s $@.tmp $@ || mv $@.tmp $@) +-include $(dir)/.eldeps +CLEAN+=$(dir)/.eldeps $(dir)/.eldeps.tmp + %.elc: %.el $(global_deps) $(call quiet,EMACS) --directory emacs -batch -f batch-byte-compile $< diff --git a/emacs/make-deps.el b/emacs/make-deps.el new file mode 100644 index 00000000..a1cd731f --- /dev/null +++ b/emacs/make-deps.el @@ -0,0 +1,66 @@ +;; make-deps.el --- compute make dependencies for Elisp sources +;; +;; Copyright © Austin Clements +;; +;; This file is part of Notmuch. +;; +;; Notmuch is free software: you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; Notmuch is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with Notmuch. If not, see . +;; +;; Authors: Austin Clements + +(defun batch-make-deps () + "Invoke `make-deps' for each file on the command line." + + (setq debug-on-error t) + (dolist (file command-line-args-left) + (let ((default-directory command-line-default-directory)) + (find-file-literally file)) + (make-deps command-line-default-directory)) + (kill-emacs)) + +(defun make-deps (&optional dir) + "Print make dependencies for the current buffer. + +This prints make dependencies to `standard-output' based on the +top-level `require' expressions in the current buffer. Paths in +rules will be given relative to DIR, or `default-directory'." + + (setq dir (or dir default-directory)) + (save-excursion + (goto-char (point-min)) + (condition-case nil + (while t + (let ((form (read (current-buffer)))) + ;; Is it a (require 'x) form? + (when (and (listp form) (= (length form) 2) + (eq (car form) 'require) + (listp (cadr form)) (= (length (cadr form)) 2) + (eq (car (cadr form)) 'quote) + (symbolp (cadr (cadr form)))) + ;; Find the required library + (let* ((name (cadr (cadr form))) + (fname (locate-library (symbol-name name)))) + ;; Is this file and the library in the same directory? + ;; If not, assume it's a system library and don't + ;; bother depending on it. + (when (and fname + (string= (file-name-directory (buffer-file-name)) + (file-name-directory fname))) + ;; Print the dependency + (princ (format "%s.elc: %s.elc\n" + (file-name-sans-extension + (file-relative-name (buffer-file-name) dir)) + (file-name-sans-extension + (file-relative-name fname dir))))))))) + (end-of-file nil))))