From 74cb99b9c826d81e8d2349b6e6b9c112af306e54 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 20 Jan 2020 23:37:24 -0800 Subject: [PATCH] Install C source code for C-h f etc. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without this change, on typical GNU/Linux distributions like Debian, the first button of ‘C-h f car RET’ does not work because the source code for ‘car’ is not installed (Bug#37527). Fix this by installing the (compressed) C source code alongside the (compressed) Lisp source code that is already installed. This adds about 3 MB (about 2%) to the size of the installed files on my platform. * Makefile.in (install_srcdir, enable_install_srcdir): New macros. (epaths-force): Substitute PATH_SOURCE. (install-srcdir): New rule, that installs a copy of the C source code if enable_install_srcdir says to. (install-arch-indep): Depend on it. * configure.ac (install_srcdir): New var. Add support for --disable-install-srcdir (to disable installation of source) and for --enable-install-srcdir='.' (to have Emacs refer to its source dir). * lisp/emacs-lisp/find-func.el (find-function-C-source): Also look for gzipped source files. * src/emacs.c (init_cmdargs): Set source-directory to be the same as installation-directory when running with an uninstalled Emacs. * src/epaths.in (PATH_SOURCE): New macro. * src/lread.c: Include dosname.h, for IS_ABSOLUTE_FILE_NAME. (syms_of_lread): When initializing source-directory, use PATH_SOURCE as-is if it is absolute; otherwise, use it relative to PATH_DUMPLOADSEARCH/.. as before. --- INSTALL | 65 ++++++++++++++++++------------------ Makefile.in | 32 ++++++++++++++++-- configure.ac | 19 +++++++++++ etc/NEWS | 6 ++++ lisp/emacs-lisp/find-func.el | 5 ++- src/emacs.c | 2 ++ src/epaths.in | 3 ++ src/lread.c | 11 +++--- 8 files changed, 104 insertions(+), 39 deletions(-) diff --git a/INSTALL b/INSTALL index 2d257f9ce6..cb12e4a17a 100644 --- a/INSTALL +++ b/INSTALL @@ -214,41 +214,42 @@ like 'apt-get build-dep emacs' (on older systems, replace 'emacs' with eg 'emacs25'). On Red Hat-based systems, the corresponding command is 'dnf builddep emacs' (on older systems, use 'yum-builddep' instead). + +DEBUGGING AN INSTALLED EMACS + +* Installed Emacs source code + +Emacs installs a compressed copy of much of its source code, to make +it easy for users to read the source code of Emacs via commands like +M-x describe-function (C-h f) to display the definition of a function. +This compressed copy ordinarily includes both the Elisp source code +that Emacs is mostly written in, as well as the C source code for the +core Emacs executable. + * GNU/Linux source and debug packages Many GNU/Linux systems provide separate packages containing the -sources and debug symbols of Emacs. They are useful if you want to -check the source code of Emacs primitive functions or debug Emacs on -the C level. - -The names of the packages that you need vary according to the -GNU/Linux distribution that you use. On Debian-based systems, you can -install a source package of Emacs with a command like 'apt-get source -emacs' (on older systems, replace 'emacs' with eg 'emacs25'). The -target directory for unpacking the source tree is the current -directory. On Red Hat-based systems, the corresponding command is -'dnf install emacs-debugsource', with target directory /usr/src/debug -(this requires to add the *-debuginfo repositories first, via 'dnf -config-manager --set-enabled fedora-debuginfo updates-debuginfo'). - -Once you have installed the source package, for example at -/path/to/emacs-26.1, add the following line to your startup file: - - (setq find-function-C-source-directory - "/path/to/emacs-26.1/src") - -The installation directory of the Emacs source package will contain -the exact package name and version number Emacs is installed on your -system. If a new Emacs package is installed, the source package must -be reinstalled as well, and the setting in your startup file must be -updated. - -Emacs debugging symbols are distributed by a debug package. It does -not exist for every released Emacs package, this depends on the -distribution. On Debian-based systems, you can install a debug -package of Emacs with a command like 'apt-get install emacs-dbg' (on -older systems, replace 'emacs' with eg 'emacs25'). On Red Hat-based -systems, the corresponding command is 'dnf debuginfo-install emacs'. +sources and debug symbols of Emacs. They can help you debug the +installed Emacs on the C level. The procedures for installing these +packages depend on the GNU/Linux system that you use. + +Emacs debugging symbols are distributed by a debug package if one +exists for your system. On Debian-based systems, you can +install a debug package of Emacs with a command like 'apt-get install +emacs-dbg' (on older systems, replace 'emacs' with e.g. 'emacs25'). +On Red Hat-based systems, the corresponding command is 'dnf +debuginfo-install emacs'; this may require adding the *-debuginfo +repositories first, via 'dnf config-manager --set-enabled +fedora-debuginfo updates-debuginfo'. + +Some systems also have an Emacs source package that is also helpful +when debugging the installed Emacs. To unpack an Emacs source package +into the current directory on Debian-based systems, you can use a +command like 'apt-get source emacs' (on older systems, replace 'emacs' +with e.g. 'emacs25'); you may first need to add the appropriate +'source' URIs to your sources.list. On Red Hat-based systems, +installing the debugging symbols automatically installs the +corresponding source package in the appropriate location. DETAILED BUILDING AND INSTALLATION: diff --git a/Makefile.in b/Makefile.in index 2c82c49fba..cadc5dac97 100644 --- a/Makefile.in +++ b/Makefile.in @@ -266,6 +266,10 @@ etcdir= # once. archlibdir=@archlibdir@ +# Where to put installed source code, and whether to install it at all. +install_srcdir=@install_srcdir@ +enable_install_srcdir=@enable_install_srcdir@ + # Where to put the etc/DOC file. etcdocdir=@etcdocdir@ @@ -374,6 +378,7 @@ epaths-force: -e 's;\(#.*PATH_BITMAPS\).*$$;\1 "${bitmapdir}";' \ -e 's;\(#.*PATH_X_DEFAULTS\).*$$;\1 "${x_default_search_path}";' \ -e 's;\(#.*PATH_GAME\).*$$;\1 $(PATH_GAME);' \ + -e 's;\(#.*PATH_SOURCE\).*$$;\1 "${install_srcdir}";' \ -e 's;\(#.*PATH_DOC\).*$$;\1 "${etcdocdir}";') && \ ${srcdir}/build-aux/move-if-change epaths.h.$$$$ src/epaths.h @@ -461,7 +466,7 @@ $(srcdir)/configure: # ==================== Installation ==================== .PHONY: install install-arch-dep install-arch-indep install-etcdoc install-info -.PHONY: install-man install-etc install-strip install-$(NTDIR) +.PHONY: install-man install-srcdir install-etc install-strip install-$(NTDIR) .PHONY: uninstall uninstall-$(NTDIR) ## If we let lib-src do its own installation, that means we @@ -568,7 +573,8 @@ set_installuser= ## work correctly, and therefore no idea when tar can be replaced. ## See also these comments from 2004 about cp -r working fine: ## https://lists.gnu.org/r/autoconf-patches/2004-11/msg00005.html -install-arch-indep: lisp install-info install-man ${INSTALL_ARCH_INDEP_EXTRA} +install-arch-indep: lisp install-info install-man install-srcdir \ + $(INSTALL_ARCH_INDEP_EXTRA) umask 022 && $(MKDIR_P) "$(DESTDIR)$(includedir)" $(INSTALL_DATA) src/emacs-module.h "$(DESTDIR)$(includedir)/emacs-module.h" -set ${COPYDESTS} ; \ @@ -700,6 +706,28 @@ install-man: ${GZIP_PROG} -9n "$(DESTDIR)${man1dir}/$${dest}" || true; \ done +install-srcdir: +ifneq ($(enable_install_srcdir),no) + -unset CDPATH; \ + umask 022; $(MKDIR_P) "$(DESTDIR)$(install_srcdir)/src" && \ + exp_sourcesrcdir=`cd "$(DESTDIR)$(install_srcdir)/src" && /bin/pwd` && \ + [ "`cd $(srcdir)/src && /bin/pwd`" = "$$exp_sourcesrcdir" ] || { \ + $(set_installuser); \ + printf 'Copying compressed C sources to %s ...\n' \ + "$(DESTDIR)$(install_srcdir)/src"; \ + for file in `cd $(srcdir) && echo src/*.[cm]`; do \ + installed_file="$(DESTDIR)$(install_srcdir)/$$file" && \ + $(INSTALL_DATA) "$$file" "$$installed_file" && \ + [ -z "$(GZIP_PROG)" ] || { \ + rm -f "$$installed_file.gz" && \ + $(GZIP_PROG) -9n "$$installed_file" && \ + installed_file=$$installed_file.gz; \ + } || exit; \ + chown $$installuser "$$installed_file" || true; \ + done; \ + } +endif + ## Install those items from etc/ that need to end up elsewhere. ## If you prefer, choose "emacs22" at installation time. diff --git a/configure.ac b/configure.ac index d7b4d0352c..b4de343371 100644 --- a/configure.ac +++ b/configure.ac @@ -194,6 +194,7 @@ lisppath='${locallisppath}:${standardlisppath}' etcdir='${datadir}/emacs/${version}/etc' archlibdir='${libexecdir}/emacs/${version}/${configuration}' +install_srcdir='${datadir}/emacs/${version}' etcdocdir='${datadir}/emacs/${version}/etc' gamedir='${localstatedir}/games/emacs' @@ -540,6 +541,21 @@ AC_DEFUN locallisppath=${enableval} locallisppathset=yes fi) +AC_ARG_ENABLE([install-srcdir], + [AS_HELP_STRING([--disable-install-srcdir], + [do not install low-level Emacs source code useful for debugging. + Use --enable-install-srcdir='.' to have Emacs refer to the + source directory it was configured from.])], + [], + [enable_install_srcdir=yes]) +case $enable_install_srcdir in + yes | no) ;; + .) install_srcdir=`cd "$srcdir" && /bin/pwd` || + AC_MSG_ERROR([cannot get srcdir name]) + enable_install_srcdir=no;; + *) AC_MSG_ERROR([invalid install-srcdir]);; +esac + AC_ARG_ENABLE(checking, [AS_HELP_STRING([--enable-checking@<:@=LIST@:>@], [enable expensive checks. With LIST, @@ -2048,6 +2064,7 @@ AC_DEFUN dnl This one isn't really used, only archlibdir is. libexecdir="\${ns_appbindir}/libexec" archlibdir="\${ns_appbindir}/libexec" + install_srcdir="\${ns_appresdir}" etcdocdir="\${ns_appresdir}/etc" etcdir="\${ns_appresdir}/etc" dnl FIXME maybe set datarootdir instead. @@ -5230,6 +5247,8 @@ AC_DEFUN AC_SUBST(x_default_search_path) AC_SUBST(etcdir) AC_SUBST(archlibdir) +AC_SUBST([enable_install_srcdir]) +AC_SUBST([install_srcdir]) AC_SUBST(etcdocdir) AC_SUBST(bitmapdir) AC_SUBST(gamedir) diff --git a/etc/NEWS b/etc/NEWS index 7f1f50759e..dde72dea53 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -42,6 +42,12 @@ and 'ftcr' otherwise. You can determine this by checking ** The ftx font backend driver has been removed. It was declared obsolete in Emacs 27.1. +--- +** Emacs now installs a copy of its C source code, used for debugging help. +For example, pressing the first button in the *Help* buffer generated +by 'C-h f car RET' now takes you to a copy of the C-language +implementation of the function 'car'. + * Startup Changes in Emacs 28.1 diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el index 167ead3ce0..631ecac73f 100644 --- a/lisp/emacs-lisp/find-func.el +++ b/lisp/emacs-lisp/find-func.el @@ -245,7 +245,10 @@ find-function-C-source (let ((dir (or find-function-C-source-directory (read-directory-name "Emacs C source dir: " nil nil t)))) (setq file (expand-file-name file dir)) - (if (file-readable-p file) + (if (or (file-readable-p file) + (let ((file-gz (concat file ".gz"))) + (and (file-readable-p file-gz) + (setq file file-gz)))) (if (null find-function-C-source-directory) (setq find-function-C-source-directory dir)) (error "The C source file %s is not available" diff --git a/src/emacs.c b/src/emacs.c index c5a760d29f..d847e888b9 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -522,6 +522,7 @@ init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd) if (!NILP (etc_exists)) { Vinstallation_directory = Ffile_name_as_directory (dir); + Vsource_directory = Vinstallation_directory; break; } } @@ -547,6 +548,7 @@ init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd) { tem = Fexpand_file_name (build_string (".."), dir); Vinstallation_directory = Ffile_name_as_directory (tem); + Vsource_directory = Vinstallation_directory; break; } } diff --git a/src/epaths.in b/src/epaths.in index 3cadd160ec..b1d20508d5 100644 --- a/src/epaths.in +++ b/src/epaths.in @@ -73,5 +73,8 @@ along with GNU Emacs. If not, see . */ /* Where Emacs should store game score files. */ #define PATH_GAME "/usr/local/var/games/emacs" +/* Where Emacs should look for installed sources. */ +#define PATH_SOURCE "/usr/local/share/emacs" + /* Where Emacs should look for the application default file. */ #define PATH_X_DEFAULTS "/usr/lib/X11/%L/%T/%N%C%S:/usr/lib/X11/%l/%T/%N%C%S:/usr/lib/X11/%T/%N%C%S:/usr/lib/X11/%L/%T/%N%S:/usr/lib/X11/%l/%T/%N%S:/usr/lib/X11/%T/%N%S" diff --git a/src/lread.c b/src/lread.c index 69dd73912b..05afef7ada 100644 --- a/src/lread.c +++ b/src/lread.c @@ -44,6 +44,7 @@ #define DEFINE_SYMBOLS #include "blockinput.h" #include "pdumper.h" #include +#include #include #ifdef MSDOS @@ -4991,11 +4992,13 @@ syms_of_lread (void) load_convert_to_unibyte = 0; DEFVAR_LISP ("source-directory", Vsource_directory, - doc: /* Directory in which Emacs sources were found when Emacs was built. -You cannot count on them to still be there! */); + doc: /* Directory where Emacs sources are looked for. */); Vsource_directory - = Fexpand_file_name (build_string ("../"), - Fcar (decode_env_path (0, PATH_DUMPLOADSEARCH, 0))); + = (IS_ABSOLUTE_FILE_NAME (PATH_SOURCE) + ? build_string (PATH_SOURCE) + : Fexpand_file_name (build_string ("../" PATH_SOURCE), + Fcar (decode_env_path (0, PATH_DUMPLOADSEARCH, + false)))); DEFVAR_LISP ("preloaded-file-list", Vpreloaded_file_list, doc: /* List of files that were preloaded (when dumping Emacs). */); -- 2.17.1