summaryrefslogtreecommitdiff
path: root/lisp/subr.el
diff options
context:
space:
mode:
authorStefan Kangas <stefankangas@gmail.com>2025-01-06 12:29:21 +0100
committerStefan Kangas <stefankangas@gmail.com>2025-01-06 20:04:20 +0100
commit3dc3dbc2e38340aba7f818eab21abfd93a132175 (patch)
tree1904060e201cf1c58f1d1bd26595998fcc731a9a /lisp/subr.el
parent888ff3755d499ca74f9d8cdf9e4d2c7dc0331236 (diff)
downloademacs-3dc3dbc2e38340aba7f818eab21abfd93a132175.tar.gz
emacs-3dc3dbc2e38340aba7f818eab21abfd93a132175.tar.bz2
emacs-3dc3dbc2e38340aba7f818eab21abfd93a132175.zip
Fix finding C headers with clang
This fixes following "#include" references in 'M-x man' buffers, and using ffap, both on macOS machines, and on systems where for some reason clang is available but gcc is not. * lisp/subr.el (internal--c-header-file-path): Fix finding C headers with clang. (internal--gcc-is-clang-p): New function factored out from... * lisp/emacs-lisp/ert-x.el (ert-gcc-is-clang-p): ...here. * lisp/man.el (Man-header-file-path): Bump :version tag. * test/lisp/subr-tests.el (subr-tests-internal--c-header-file-path/clang-mocked): New test.
Diffstat (limited to 'lisp/subr.el')
-rw-r--r--lisp/subr.el57
1 files changed, 47 insertions, 10 deletions
diff --git a/lisp/subr.el b/lisp/subr.el
index 9044a92c5f5..5be8d8f52d4 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -7556,6 +7556,17 @@ and return the value found in PLACE instead."
,(funcall setter val)
,val)))))
+(defun internal--gcc-is-clang-p ()
+ "Return non-nil if the `gcc' command actually runs the Clang compiler."
+ ;; Recent macOS machines run llvm when you type gcc by default. (!)
+ ;; We can't even check if it's a symlink; it's a binary placed in
+ ;; "/usr/bin/gcc". So we need to check the output.
+ (when-let* ((out (ignore-errors
+ (with-temp-buffer
+ (call-process "gcc" nil t nil "--version")
+ (buffer-string)))))
+ (string-match "Apple \\(LLVM\\|[Cc]lang\\)\\|Xcode\\.app" out)))
+
(defun internal--c-header-file-path ()
"Return search path for C header files (a list of strings)."
;; FIXME: It's not clear that this is a good place to put this, or
@@ -7563,15 +7574,41 @@ and return the value found in PLACE instead."
;; See also (Bug#10702):
;; cc-search-directories, semantic-c-dependency-system-include-path,
;; semantic-gcc-setup
- (let ((arch (with-temp-buffer
- (when (eq 0 (ignore-errors
- (call-process "gcc" nil '(t nil) nil
- "-print-multiarch")))
- (goto-char (point-min))
- (buffer-substring (point) (line-end-position)))))
- (base '("/usr/include" "/usr/local/include")))
- (if (zerop (length arch))
- base
- (append base (list (expand-file-name arch "/usr/include"))))))
+ (delete-dups
+ (let ((base '("/usr/include" "/usr/local/include")))
+ (cond ((or (internal--gcc-is-clang-p)
+ (and (executable-find "clang")
+ (not (executable-find "gcc"))))
+ ;; This is either macOS, or a system with clang only.
+ (with-temp-buffer
+ (ignore-errors
+ (call-process (if (internal--gcc-is-clang-p) "gcc" "clang")
+ nil t nil
+ "-v" "-E" "-"))
+ (goto-char (point-min))
+ (narrow-to-region
+ (save-excursion
+ (re-search-forward
+ "^#include <\\.\\.\\.> search starts here:\n" nil t)
+ (point))
+ (save-excursion
+ (re-search-forward "^End of search list.$" nil t)
+ (pos-bol)))
+ (while (search-forward "(framework directory)" nil t)
+ (delete-line))
+ (append base
+ (reverse
+ (split-string (buffer-substring-no-properties
+ (point-min) (point-max)))))))
+ ;; Prefer GCC.
+ ((let ((arch (with-temp-buffer
+ (when (eq 0 (ignore-errors
+ (call-process "gcc" nil '(t nil) nil
+ "-print-multiarch")))
+ (goto-char (point-min))
+ (buffer-substring (point) (line-end-position))))))
+ (if (zerop (length arch))
+ base
+ (append base (list (expand-file-name arch "/usr/include"))))))))))
;;; subr.el ends here