-*-indented-text-*- First, for the purposes of this policy, some terminology: - a particular flavor of Emacs, for example: xemacs20 xemacs21 emacs22 emacs23 - either a or the generic value "emacs", i.e.: emacs xemacs20 xemacs21 emacs22 emacs23 add-on package - any package which wishes to use the emacsen-common infrastructure, usually in order to byte-compile itself for some subset of the currently installed emacs flavors. - the name of an add-on package, for example: auctex bbdb gnus 1) Guarding use of emacsen-common infrastructure Any use of the emacsen-common infrastructure must be guarded by a test for the existence of the emacsen-common installed state file. i.e.: if test -e /var/lib/emacsen-common/state/package/installed/emacsen-common then emacs-package-install ... fi Of course this requirement does not apply for the maintainer scripts of any package that depends on emacsen-common (i.e. for each emacsen main package: emacs23, etc.). 2) Flavor indication Each emacs binary must set the variable debian-emacs-flavor to be the same as the name of the debian-package. For example, the emacs23 package does this in startup.el: (defconst debian-emacs-flavor 'emacs23 "A symbol representing the particular debian flavor of emacs running. Something like 'emacs20, 'xemacs20, etc.") For now, debian-emacs-flavor should be defined regardless of the use of -q or --no-site-file. [ NOTE: We may eventually consider moving debian-emacs-flavor to emacsen-common and have emacsen-common set it based on the argument to debian-startup. That would minimize changes to startup.el, but it was attempted briefly in the past, too close to a freeze, and caused enough trouble that we backed off.] 3) Emacs startup strategy We have the following startup files/directories: emacsen-common: /etc/emacs/site-start.{el,d} xemacs20: /etc/xemacs20/site-start.d xemacs21: /etc/xemacs21/site-start.d emacs22: /etc/emacs22/site-start.d emacs23: /etc/emacs23/site-start.d /etc/emacs/site-start.el is a conffile, and is owned by emacsen-common. This file should not be modified by *any* add-on packages, or by any emacsen package maintainer. It is solely for the use of the local admin. It should be empty unless the local admin modifies it. The load-path for a given emacs flavor must include /etc/ and /etc/emacs in that order (see section 8 below), and on startup each emacsen must call (debian-startup ) and then load "site-start". This means that /etc/emacs/site-start.el will be loaded if it exists, unless there's an /etc//site-start.el{,c} or /etc/emacs/site-start.elc which will take precedence. These site-start.el files are also the sole domain of the local system admin, and should be empty unless modified by the local admin. Given that the site-startup.el files are "off-limits" to the emacsen maintainers, the next question is, "Where should we run debian-startup?" The safest possibility, and the one I had originally intended was to modify lisp/startup.el to do the right thing, and I had also intended that --no-site-file would disable all of the Debian startup bits, including calling Debian startup. So here's what emacs23 has in startup.el: ;; Debian startup (if site-run-file (progn ;; Load all the Debian package snippets. ;; It's in here because we want -q to kill it too. (if (load "debian-startup" t t nil) (debian-startup debian-emacs-flavor)) ;; Now the normal site file... (load site-run-file t t nil))) This makes sure that Debian's bits are setup as early as possible, and requires only minor modifications to the emacs source. An alternate possibility might be to use lisp/site-init.el, but I'm not sure that would work right. Feel free to contact me if you know better. debian-startup, among other things, calls debian-run-directories. debian-run-directories collects the union of all the file base names (i.e. without any .el or .elc extension, and without the directory component: i.e. /etc/xemacs/site-start.d/50foo.elc => 50foo), then temporarily augments the emacs load path to include /etc//site-start.d and /etc/emacs/site-start.d in that order, and then calls (load base-name) in alphabetical order. This result is that .elc files will take precedence over .el files in a given directory, and files in the site-start.d directory will take precedence over those in the emacs common directory. 4) Code locations In addition to the /etc//site-start* directories, we have the following directories (their use will be described shortly): emacsen-common: /usr/share/emacs/site-lisp/ xemacs20: /usr/share/xemacs20/site-lisp/ xemacs21: /usr/share/xemacs21/site-lisp/ emacs22: /usr/share/emacs22/site-lisp/ emacs23: /usr/share/emacs23/site-lisp/ These are treated as part of the normal emacsen load path with the dir taking precedence over the emacs (common) dir. /usr/share//site-lisp should be used instead of the normal site-lisp directory for that flavor of emacs, and the package for a given flavor of emacs should not have the normal site-lisp directory. For example, instead of the emacs23 package having /usr/share/emacs/23.2/site-lisp, it should only have /usr/share/emacs23/site-lisp. This is important because it allows us to avoid having dangling directories for old versions across upgrades. We could have chosen to keep a compatibility symlink, but that seemed likely to mask bugs in the debianized packages. 5) Emacs add-on package support (examples below should make this much clearer) A) Each add-on package must add a "Conflicts: emacsen-common (< 2.0.0)" and include a file like this that indicates its emacsen-common compatibility level: /usr/lib/emacsen-common/packages/compat/ This file should contain a single integer, which at the moment should be 0. (Currently, the file is just used to distinguish between old-style packages and new-style packages.) B) Each add-on package may place a file named the same as the package in /usr/lib/emacsen-common/packages/install/ /usr/lib/emacsen-common/packages/remove/ and the package must make these calls from the given maintainer scripts: preinst: if test -e /var/lib/emacsen-common/state/package/installed/emacsen-common then /usr/lib/emacsen-common/emacs-package-install --preinst fi postinst: if test -e /var/lib/emacsen-common/state/package/installed/emacsen-common then /usr/lib/emacsen-common/emacs-package-install --postinst fi prerm: if test -e /var/lib/emacsen-common/state/package/installed/emacsen-common then /usr/lib/emacsen-common/emacs-package-remove --prerm fi The postinst call must not be made until the package is completely configured and otherwise ready for use, and the prerm call must be made before any changes that would make the package not completely configured and ready for use. These calls will ensure that the add-on package's emacsen-common install and remove scripts are called at the appropriate times. In particular the postinst call will trigger the install script for every flavor of emacs that's already completely installed. If flavors are being installed simultaneously, the install script may be delayed until that flavor's postinst runs. When the install or remove script is called, the add-on package can assume that the flavor for which it is being invoked is completely installed (i.e. past the significant parts of its postinst). The install and remove scripts will be invoked with a single argument, the being installed or removed. So if emacs23 and xemacs21 are fully installed, installing add-on foo will result in calls to: /usr/lib/emacsen-common/packages/install/foo emacs23 /usr/lib/emacsen-common/packages/install/foo xemacs21 emacs-package remove does the symmetric thing. C) Add-on packages need not declare a dependency on emacsen-common, nor on any emacs flavors, but they must (of course) declare dependencies on any other relevant packages, including relevant add-on packages, or tools needed by the install/remove scripts. The emacsen-common infrastructure will ensure that the install/remove script invocations are ordered to respect inter-add-on package dependencies. D) Each add-on package has the right to place files into the following directories: /etc//site-start.d /usr/share//site-lisp/ E) If an add-on package compiles any of its Emacs Lisp sources (which must be compiled to a subdirectory of /usr/share//site-lisp/ -- see section 4 above) it must also create a symlink in the same directory as the compiled output that points to the corresponding source file. For example, if add-on package foo produces /usr/share/emacs23/site-lisp/foo/bar.elc, then it must also create a symlink /usr/share/emacs23/site-lisp/foo/bar.el pointing to the corresponding source file. This ensures that Emacs will be able to locate the source code for the add-on package when using M-x find-function, etc. F) Each emacsen main package (i.e. emacs23, emacs23-nox, etc.) must depend on emacsen-common (>= 2.0.0). G) Each emacsen main package (i.e. emacs23, emacs23-nox, etc.) must make these calls from the given maintainer scripts: preinst: /usr/lib/emacsen-common/emacs-install --preinst postinst: /usr/lib/emacsen-common/emacs-install --postinst prerm: /usr/lib/emacsen-common/emacs-remove --prerm The postinst call must not be made until the package is completely configured and ready for use, and the prerm call must be made before any changes that would make the package not completely configured and ready for use. These calls will ensure that all of the relevant add-on packages' emacsen-common install and remove scripts are called at the appropriate times. In particular the postinst call may trigger the install scripts and the prerm script may trigger the remove scripts for any package that is ready. If add-on packages are being installed simultaneously, the add-on install scripts may be delayed until their postinst scripts are run. 6) Mandatory binary symlink Each emacsen main package must have a symlink /usr/bin/ to /usr/bin/ so that when add-on package install/remove scripts are called, they can just use /usr/bin/$ARGV[0] to get the right binary for byte-compilation. 7) Virtual package Each emacsen main package must "Provides: emacsen", and packages that just need to make sure some flavor of emacs is installed should "Depends: emacsen". If they depend on specific flavors of emacs, then they should list those dependencies explicitly instead. 8) Emacs lisp load path. At a minimum, each emacs must have the following directories in the given order in their load path: /etc/ /etc/emacs /usr/local/share/emacs//site-lisp /usr/local/share/emacs/site-lisp /usr/share/emacs//site-lisp /usr/share/emacs/site-lisp where is the normal emacs upstream version number for the relevant flavor like 20.2 or 23.2. Emacs add-on packages may not modify load-path directly. They must use (debian-pkg-add-load-path-item ). This function will make sure that their additions end up in the right place -- before the emacs system directories, but after the /usr/local/ directories. Also, add-on packages will need to either check (fboundp 'debian-pkg-add-load-path-item) before calling this function, or add a dependency on emacsen-common (>= 1.4.14). 9) Usage of autoload instead of load in the site-start.d files. It's been suggested, and is probably a good idea that maintainers switch to using autoload rather than load when possible in their site-start.d files. For example, instead of (load "some-package"), you should use autoloads for all the top level, user visible functions. That's it. Hopefully this gives the add-on package maintainers the flexibility they need to be able to DTRT, and the common case won't be all that difficult. Examples: 1) xemacs21 and the add-on packages tm and auctex are already installed, and now someone installs emacs23. In its prerm, emacs23 would make this call: /usr/lib/emacsen-common/emacs-install --postinst emacs23 which would result in calls to /usr/lib/emacsen-common/packages/install/auctex emacs23 /usr/lib/emacsen-common/packages/emacs/install/tm emacs23 2) Now, given (1), assume that someone removes xemacs21. In its prerm, xemacs21 would make this call: /usr/lib/emacsen-common/emacs-remove --prerm xemacs21 which would result in calls to /usr/lib/emacsen-common/packages/remove/auctex xemacs21 /usr/lib/emacsen-common/packages/remove/tm xemacs21 3) Now assume emacs23 and xemacs21 are installed, and that someone removes tm. The call to emacsen-package-remove in tm's prerm will result in the following calls: /usr/lib/emacsen-common/packages/remove/tm emacs23 /usr/lib/emacsen-common/packages/remove/tm xemacs21 In the remove/tm file, tm is responsible for cleaning up any files it put into its allowed locations: /etc//site-start.d/ /usr/share//site-lisp/tm 4) Now assume that emacs23 and auctex are not installed, and that someone installs both at the same time. At some point during the installation, after emacs23 and auctex are fully configured, this command will be invoked: /usr/lib/emacsen-common/packages/remove/auctex emacs23 This call may happen from either emacs23 or auctex's postinst as a result of their respective calls to emacs-install and emacs-package-install. Which package causes the invocation will depend on the order in which dpkg decides to invoke their postint scripts. The emacsen-common infrastructure makes sure that the last one wins. 5) Finally, please see sample-package-install-foo and sample-package-remove-foo in /usr/share/doc/emacsen-common/. These are sample install and remove scripts for a hypothetical package "foo" that only needs to byte compile a list of files for each flavor.