2

I am teaching myself autoloads for "home-made" packages.

Official Docs suggest to use update-file-autoloads or update-directory-autoloads on the related package file or directory, which will add the corresponding autoload calls into loaddefs.el. This does not seem to be the strategy followed by most packages, which instead create a distinct *-autoloads.el file for each source equipped with the magic autoload comments (perhaps to avoid cluttering loaddefs.el).

I haven't found any tutorial on this, by the way a user suggested to use package-generate-autoloads. Indeed, it works up to a certain point, and this is my attempt.

I created the file ...site-lisp/foo/foo.el:

;;;###autoload
(defun foofunc () (message "I'm foo"))
(provide 'foo)

Then, I executed on the foo folder:

(package-generate-autoloads "foo" "foo")

Much like for any package, it generates in foo the foo-autoloads.el file, where there is a line:

(autoload 'foofunc "foo" nil nil nil)

When restarting Emacs, by inspecting the value of the variable load-path, I see that the foo is automatically included, being under site-lisp. However, evaluating foofunc, gives:

Debugger entered--Lisp error: (void-function foofunc)

Not surprisingly, if I manually evaluate (autoload 'foofunc "foo" nil nil nil) or

(load "foo-autoloads.el")

foofunc works. However, there should be some way to have this done automatically by Emacs for all autoloads files in the path.

Note that, while this question focuses on package-generate-autoloads function, if there is a better way to activate autoloads, your answer is welcomed.

Side Question

As a side note, I have seen that applying package-generate-autoloads to some ELPA packages adds to the corresponding *-autoloads.el files a convenient call to register-definition-prefix. As I understand, with this function you can add a custom prefix mypref-, such that, whenever you try to autocomplete mypref- in the minibuffer, you autoload the relevant lisp file.
What (magic cookies) in the source files trigger(s) the insertion of these calls in the *-autoloads.el files?

Basil
  • 12,019
  • 43
  • 69
antonio
  • 1,762
  • 12
  • 24

1 Answers1

1

This does not seem to be the strategy followed by most packages, which instead create a distinct *-autoloads.el file for each source equipped with the magic autoload comments

It is not the package that is responsible for this, but the built-in package manager, package.el.

(perhaps to avoid cluttering loaddefs.el).

I'm not familiar with the history behind -autoloads.el files, but I'd say they are distinct from loaddefs.el so that the former can be automatically detected and loaded by package.el.

However, there should be some way to have this done automatically by Emacs for all autoloads files in the path.

AFAIK, only package.el has such a mechanism built-in; see package-directory-list:

;;;###autoload
(defcustom package-directory-list
  ;; Defaults are subdirs named "elpa" in the site-lisp dirs.
  (let (result)
    (dolist (f load-path)
      (and (stringp f)
           (equal (file-name-nondirectory f) "site-lisp")
           (push (expand-file-name "elpa" f) result)))
    (nreverse result))
  "List of additional directories containing Emacs Lisp packages.
Each directory name should be absolute.

These directories contain packages intended for system-wide; in
contrast, `package-user-dir' contains packages for personal use."
  :type '(repeat directory)
  :initialize #'custom-initialize-delay
  :risky t
  :version "24.1")

So if you put your foo package directory under package-user-dir or site-lisp/elpa/ it should be picked up by package.el automatically (after calling package-activate-all, package-initialize, or similar).

Otherwise, I think non-package.el loaddefs files need to be explicitly loaded.

What (magic cookies) in the source files trigger(s) the insertion of these calls in the *-autoloads.el files?

The lack of a cookie ;). The following file:

;;; -*- lexical-binding: t -*-

;;;###autoload
(defun foo-bar ())

(provide 'foo)

will produce only the following autoload:

(autoload 'foo-bar "foo" nil nil nil)

There is no need to register a prefix in this case, because Emacs already knows where to find foo-bar by virtue of it being autoloaded from a specific file.

OTOH the following file:

;;; -*- lexical-binding: t -*-

;;;###autoload
(defun foo-bar ())
(defun foo-baz ())

(provide 'foo)

results in:

(autoload 'foo-bar "foo" nil nil nil)
(register-definition-prefixes "foo" '("foo-baz"))
Basil
  • 12,019
  • 43
  • 69
  • Thanks for all your insights. It seems that being under "elpa" is just one condition. `package-initialize` requires `*-pgk.el`, which is autogenerated during the setup process. The main takeaway here is that `package-generate-autoloads` could be not suitable to be used outside package.el framework. – antonio Apr 25 '21 at 22:50
  • @antonio Yes, I wanted to emphasise that `package.el` and `autoload.el` should be thought of as separate systems, although the former obviously builds on the latter. – Basil Apr 25 '21 at 23:30