Subject: bug#37527: closed (Re: bug#37527: [PATCH] Install C source code for for debugging help)

From: [email-masked] (GNU bug Tracking System)
Date: Sat, 25 Jan 2020 00:49:02 +0000

Your bug report

#37527: [PATCH] Install C source code for for debugging help

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
37527: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=37527
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#37527: [PATCH] Install C source code for for debugging help
From: Paul Eggert <[email-masked]>
To: Eli Zaretskii <[email-masked]>
Cc: [email-masked], [email-masked], [email-masked], [email-masked]
Date: Fri, 24 Jan 2020 16:47:49 -0800
List-Id: <debbugs-submit.debbugs.gnu.org>

On 1/23/20 10:24 AM, Eli Zaretskii wrote:

> In that case, I will repeat my suggestion to have a separate variable
> for the installed sources, because otherwise we are making an
> incompatible behavior change.

OK, I did it that way by installing the attached patch instead; the new 
separate variable is 'emacs-source-directory'.
>From a0a70d7e1fe2237c1b0f374b72aba324b7de95fa Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Fri, 24 Jan 2020 16:41:38 -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 (emacs_srcdir): New macro.
(epaths-force): Substitute PATH_EMACS_SOURCE.
(install-c-src): New rule, that installs a copy of the C source
code if emacs_srcdir says to.
(install-arch-indep): Depend on it.
* configure.ac (emacs_srcdir): New var.
Add support for --disable-install-srcdir.
* lisp/emacs-lisp/find-func.el (find-function-C-source-directory):
Look in emacs-source-directory first.
(find-function-C-source): Also look for gzipped source files.
* lisp/startup.el (normal-top-level):
Also recode emacs-source-directory.
* src/epaths.in (PATH_EMACS_SOURCE): New macro.
* src/lread.c: Include dosname.h, for IS_ABSOLUTE_FILE_NAME.
(syms_of_lread): New var emacs-source-directory.
---
 INSTALL                      | 65 ++++++++++++++++++------------------
 Makefile.in                  | 31 +++++++++++++++--
 configure.ac                 | 14 ++++++++
 etc/NEWS                     |  9 +++++
 lisp/emacs-lisp/find-func.el | 11 ++++--
 lisp/startup.el              |  3 +-
 src/epaths.in                |  4 +++
 src/lread.c                  | 10 +++++-
 8 files changed, 108 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..adefa98fd0 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -266,6 +266,9 @@ etcdir=
 # once.
 archlibdir=@archlibdir@
 
+# Where to install Emacs C source code, or empty if it is not installed.
+emacs_srcdir=@emacs_srcdir@
+
 # Where to put the etc/DOC file.
 etcdocdir=@etcdocdir@
 
@@ -374,6 +377,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_EMACS_SOURCE\).*$$;\1 "${emacs_srcdir}";'	\
 	  -e 's;\(#.*PATH_DOC\).*$$;\1 "${etcdocdir}";') &&		\
 	${srcdir}/build-aux/move-if-change epaths.h.$$$$ src/epaths.h
 
@@ -461,7 +465,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-c-src install-etc install-strip install-$(NTDIR)
 .PHONY: uninstall uninstall-$(NTDIR)
 
 ## If we let lib-src do its own installation, that means we
@@ -568,7 +572,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-c-src \
+  $(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 +705,28 @@ install-man:
 	  ${GZIP_PROG} -9n "$(DESTDIR)${man1dir}/$${dest}" || true; \
 	done
 
+install-c-src:
+ifneq (,$(emacs_srcdir))
+	-unset CDPATH; \
+	umask 022; $(MKDIR_P) "$(DESTDIR)$(emacs_srcdir)/src" && \
+	exp_sourcesrcdir=`cd "$(DESTDIR)$(emacs_srcdir)/src" && /bin/pwd` && \
+	[ "`cd $(srcdir)/src && /bin/pwd`" = "$$exp_sourcesrcdir" ] || { \
+	  $(set_installuser); \
+	  printf 'Copying compressed C sources to %s ...\n' \
+		 "$(DESTDIR)$(emacs_srcdir)/src"; \
+	  for file in `cd $(srcdir) && echo src/*.[cm]`; do \
+	    installed_file="$(DESTDIR)$(emacs_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 27e44dacfb..4de83c6b26 100644
--- a/configure.ac
+++ b/configure.ac
@@ -194,6 +194,7 @@
 lisppath='${locallisppath}:${standardlisppath}'
 etcdir='${datadir}/emacs/${version}/etc'
 archlibdir='${libexecdir}/emacs/${version}/${configuration}'
+emacs_srcdir='${datadir}/emacs/${version}'
 etcdocdir='${datadir}/emacs/${version}/etc'
 gamedir='${localstatedir}/games/emacs'
 
@@ -540,6 +541,15 @@ 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.])],
+  [case $enableval in
+     yes) ;;
+     no) emacs_srcdir=;;
+     *) AC_MSG_ERROR([invalid install-srcdir]);;
+   esac])
+
 AC_ARG_ENABLE(checking,
 [AS_HELP_STRING([--enable-checking@<:@=LIST@:>@],
 		[enable expensive checks.  With LIST,
@@ -2048,6 +2058,9 @@ AC_DEFUN
      dnl This one isn't really used, only archlibdir is.
      libexecdir="\${ns_appbindir}/libexec"
      archlibdir="\${ns_appbindir}/libexec"
+     case $emacs_srcdir in
+       ?*) emacs_srcdir="\${ns_appresdir}";;
+     esac
      etcdocdir="\${ns_appresdir}/etc"
      etcdir="\${ns_appresdir}/etc"
      dnl FIXME maybe set datarootdir instead.
@@ -5230,6 +5243,7 @@ AC_DEFUN
 AC_SUBST(x_default_search_path)
 AC_SUBST(etcdir)
 AC_SUBST(archlibdir)
+AC_SUBST([emacs_srcdir])
 AC_SUBST(etcdocdir)
 AC_SUBST(bitmapdir)
 AC_SUBST(gamedir)
diff --git a/etc/NEWS b/etc/NEWS
index 5395f2ccfb..c3a71ade8a 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -58,6 +58,12 @@ shaping, so 'configure' now recommends that combination.
 ** 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
 
@@ -142,6 +148,9 @@ called when the function object is garbage-collected.  Use
 ** 'parse-time-string' can now parse ISO 8601 format strings,
 such as "2020-01-15T16:12:21-08:00".
 
+** The new variable 'emacs-source-directory' gives the Emacs source
+code location.
+
 
 * Changes in Emacs 28.1 on Non-Free Operating Systems
 
diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el
index 167ead3ce0..be53324f14 100644
--- a/lisp/emacs-lisp/find-func.el
+++ b/lisp/emacs-lisp/find-func.el
@@ -219,8 +219,10 @@ find-library--from-load-history
             (locate-file basename (list dir) (find-library-suffixes)))))))
 
 (defvar find-function-C-source-directory
-  (let ((dir (expand-file-name "src" source-directory)))
-    (if (file-accessible-directory-p dir) dir))
+  (let ((dir (expand-file-name "src" emacs-source-directory)))
+    (if (file-accessible-directory-p dir) dir
+      (setq dir (expand-file-name "src" source-directory))
+      (if (file-accessible-directory-p dir) dir)))
   "Directory where the C source files of Emacs can be found.
 If nil, do not try to find the source code of functions and variables
 defined in C.")
@@ -245,7 +247,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/lisp/startup.el b/lisp/startup.el
index 1f545c6692..676fb35e00 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -623,7 +623,8 @@ normal-top-level
 		(set pathsym (mapcar (lambda (dir)
 				       (decode-coding-string dir coding t))
 				     path)))))
-	(dolist (filesym '(data-directory doc-directory exec-directory
+	(dolist (filesym '(data-directory doc-directory emacs-source-directory
+					  exec-directory
 					  installation-directory
 					  invocation-directory invocation-name
 					  source-directory
diff --git a/src/epaths.in b/src/epaths.in
index 3cadd160ec..554fdd7228 100644
--- a/src/epaths.in
+++ b/src/epaths.in
@@ -73,5 +73,9 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 /* Where Emacs should store game score files.  */
 #define PATH_GAME "/usr/local/var/games/emacs"
 
+/* Where Emacs should look for its own installed source code,
+   or the empty string if the source code is not installed.  */
+#define PATH_EMACS_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..274491f022 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -44,6 +44,7 @@ #define DEFINE_SYMBOLS
 #include "blockinput.h"
 #include "pdumper.h"
 #include <c-ctype.h>
+#include <dosname.h>
 #include <vla.h>
 
 #ifdef MSDOS
@@ -4992,11 +4993,18 @@ syms_of_lread (void)
 
   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!  */);
+You cannot count on them to still be there!  Also see
+`emacs-source-directory'.  */);
   Vsource_directory
     = Fexpand_file_name (build_string ("../"),
 			 Fcar (decode_env_path (0, PATH_DUMPLOADSEARCH, 0)));
 
+  DEFVAR_LISP ("emacs-source-directory", Vemacs_source_directory,
+	       doc: /* Directory where Emacs sources can be found.  */);
+  Vemacs_source_directory = (IS_ABSOLUTE_FILE_NAME (PATH_EMACS_SOURCE)
+			     ? build_string (PATH_EMACS_SOURCE)
+			     : Vsource_directory);
+
   DEFVAR_LISP ("preloaded-file-list", Vpreloaded_file_list,
 	       doc: /* List of files that were preloaded (when dumping Emacs).  */);
   Vpreloaded_file_list = Qnil;
-- 
2.24.1

Subject: [PATCH] Install C source code for for debugging help
From: Paul Eggert <[email-masked]>
To: [email-masked]
Cc: Paul Eggert <[email-masked]>
Date: Thu, 26 Sep 2019 13:07:52 -0700
List-Id: <debbugs-submit.debbugs.gnu.org>

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.
Fix this by installing the (compressed) C source code along with
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 too.
(exp_sourcesrcdir): Install copy of C source code if
enable_install_srcdir says to.
* 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 (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.
---
 Makefile.in                  | 25 +++++++++++++++++++++++++
 configure.ac                 | 19 +++++++++++++++++++
 etc/NEWS                     |  6 ++++++
 lisp/emacs-lisp/find-func.el |  5 ++++-
 src/emacs.c                  |  2 ++
 src/epaths.in                |  3 +++
 src/lread.c                  |  8 ++++++--
 7 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/Makefile.in b/Makefile.in
index aa11e6b0b7..6ffb8eb747 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
 
@@ -624,6 +629,26 @@ install-arch-indep:
 	  done; \
 	  ${GZIP_PROG} -9n "../etc/publicsuffix.txt"; \
 	}
+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
 	-chmod -R a+r "$(DESTDIR)${datadir}/emacs/${version}" ${COPYDESTS}
 
 ## The above chmods are needed because "umask 022; tar ..." is not
diff --git a/configure.ac b/configure.ac
index 7435f2e8da..ac50e6e297 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,
@@ -2061,6 +2077,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.
@@ -5211,6 +5228,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 0a4ada3cc6..7643905256 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -125,6 +125,12 @@ removed configure options.)
 ** The distribution tarball now has test cases; 'make check' runs them.
 This is intended mostly to help developers.
 
+---
+** 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'.
+
 ---
 ** Emacs now requires GTK 2.24 and GTK 3.10 for the GTK 2 and GTK 3
 builds respectively.
diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el
index 142c99edd4..2812ae6f22 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 21a05d337e..fa547b59f5 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 5fe35b64c8..4e15c3a3d6 100644
--- a/src/epaths.in
+++ b/src/epaths.in
@@ -73,5 +73,8 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 /* 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 5000b38a01..849632a7ec 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -4979,9 +4979,13 @@ syms_of_lread (void)
   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!  */);
+  char const *path_source = PATH_SOURCE;
   Vsource_directory
-    = Fexpand_file_name (build_string ("../"),
-			 Fcar (decode_env_path (0, PATH_DUMPLOADSEARCH, 0)));
+    = (file_name_absolute_p (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.21.0