[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/compat 12774be87c 2/3: Fix using compat libraries uncom
From: |
ELPA Syncer |
Subject: |
[elpa] externals/compat 12774be87c 2/3: Fix using compat libraries uncompiled |
Date: |
Sun, 5 Jun 2022 10:57:25 -0400 (EDT) |
branch: externals/compat
commit 12774be87c7d52640be4c3d54e65236ba69b9a0e
Author: Jonas Bernoulli <jonas@bernoul.li>
Commit: Philip Kaludercic <philipk@posteo.net>
Fix using compat libraries uncompiled
`compat-entwine' is called in two and only three distinct situations.
1. When "compat.el" is being loaded without having been compiled
before. This can happen while a third-party library is being
compiled, which requires `compat'.
2. When "compat.el" is being evaluated, such as when using
`eval-buffer'.
3. When "compat.el" is being compiled.
In all cases we need to detect where "compat.el" is located, because
that also tells us where the "compat-XY.el" libraries are located and
`compat-entwine' needs to read the contents of those files. To detect
the location of "compat.el" we consult various variables, which we
expect to either be nil or "/path/to/compat.el". We didn't use the
correct variables.
Some time ago Stefan added a call to `macro-file-name' to the front
of that search, which fixes the search for Emacs 28.1. Older Emacs
releases lack that function, so for those we still ended up consulting
the wrong variables. To fix that use `current-load-list' directly,
treating it the same way as `macro-file-name' does.
If that gives us a non-nil value, then we are dealing with one of the
first two cases and we are done. Otherwise we are dealing with the
third case and `byte-compile-current-file' gives us the correct value.
One of these sources is always non-nil, so drop the variables we used
to fall back to.
Then we pass the version from `compat-entwine' to the
`compat--generate-function' function by binding the new variable
`compat--entwine-version'. Previously this was done by binding
`byte-compile-current-file`. The caller then had to extract the
version from the name of that file.
Binding `byte-compile-current-file` was also part of the bug that
prevented compilation of a third-party library, which depends on
"compat-XY.el", when compat's libraries have not been compiled yet.
To fix that we have to change the order of the possible sources of the
version string in `compat--generate-function' functions. As before we
use the version explicitly specified for the function being processed,
if any. Then we use value of the new `compat--entwine-version'
variable, if that is bound and non-nil, i.e., if the binding from
`compat-entwine' is in effect.
Previously we would have tried `byte-compile-current-file' at this
point instead, but while that might be non-nil because we used to bind
it in `compat--generate-function', it could also be non-nil because an
arbitrary third-party library is being compiled.
That is a problem if that third-party library depends on
"compat-XY.el" and the latter hasn't been compiled before: The
`compat--generate-function' function is called directly in that case,
without the binding from `compat-entwine' in effect. We need
`byte-compile-current-file' to be some "compat-XY.el" library; not
some arbitrary third-party library.
Then we try `current-load-list' like in `compat-entwine', which here
is some "compat-XY.el" library when some third-party library is being
compiled and that requires that "compat-XY.el" library.
Finally, if we could not determine a version any other way, then we
know that some "compat-XY.el" library is being compiled. In that
case, and only then, we can get the version string from
`byte-compile-current-file'.
---
compat-macs.el | 54 ++++++++++++++++++++++++++++--------------------------
compat.el | 30 ++++++++++++++++++++----------
2 files changed, 48 insertions(+), 36 deletions(-)
diff --git a/compat-macs.el b/compat-macs.el
index fec167a99a..85f31b8804 100644
--- a/compat-macs.el
+++ b/compat-macs.el
@@ -82,19 +82,22 @@ DEF-FN, INSTALL-FN, CHECK-FN, ATTR and TYPE."
(max-version (plist-get attr :max-version))
(feature (plist-get attr :feature))
(cond (plist-get attr :cond))
- (version (or (plist-get attr :version)
- (let ((file (or (bound-and-true-p
byte-compile-current-file)
- load-file-name
- (buffer-file-name))))
- ;; Guess the version from the file the macro is
- ;; being defined in.
- (cond
- ((not file) emacs-version)
- ((string-match
- "compat-\\([[:digit:]]+\\)\\.\\(?:elc?\\)\\'"
- file)
- (concat (match-string 1 file) ".1"))
- ((error "No version number could be extracted"))))))
+ (version ; If you edit this, also edit `compat--generate-verbose'.
+ (or (plist-get attr :version)
+ (bound-and-true-p compat--entwine-version)
+ (let* ((file (car (last current-load-list)))
+ (file (if (stringp file)
+ ;; Some library, which requires compat-XY.el,
+ ;; is being compiled and compat-XY.el has not
+ ;; been compiled yet.
+ file
+ ;; compat-XY.el is being compiled.
+ (bound-and-true-p byte-compile-current-file))))
+ (if (and file
+ (string-match
+ "compat-\\([[:digit:]]+\\)\\.\\(?:elc?\\)\\'" file))
+ (concat (match-string 1 file) ".1")
+ (error "BUG: No version number could be extracted")))))
(realname (or (plist-get attr :realname)
(intern (format "compat--%S" name))))
(check (cond
@@ -155,19 +158,18 @@ DEF-FN, INSTALL-FN, CHECK-FN, ATTR and TYPE."
(max-version (plist-get attr :max-version))
(feature (plist-get attr :feature))
(cond (plist-get attr :cond))
- (version (or (plist-get attr :version)
- (let ((file (or (bound-and-true-p
byte-compile-current-file)
- load-file-name
- (buffer-file-name))))
- ;; Guess the version from the file the macro is
- ;; being defined in.
- (cond
- ((not file) emacs-version)
- ((string-match
- "compat-\\([[:digit:]]+\\)\\.\\(?:elc?\\)\\'"
- file)
- (concat (match-string 1 file) ".1"))
- ((error "No version number could be extracted"))))))
+ (version ; If you edit this, also edit `compat--generate-minimal'.
+ (or (plist-get attr :version)
+ (bound-and-true-p compat--entwine-version)
+ (let* ((file (car (last current-load-list)))
+ (file (if (stringp file)
+ file
+ (bound-and-true-p byte-compile-current-file))))
+ (if (and file
+ (string-match
+ "compat-\\([[:digit:]]+\\)\\.\\(?:elc?\\)\\'" file))
+ (concat (match-string 1 file) ".1")
+ (error "BUG: No version number could be extracted")))))
(realname (or (plist-get attr :realname)
(intern (format "compat--%S" name))))
(body `(progn
diff --git a/compat.el b/compat.el
index ed60ba53ab..a5d6346af1 100644
--- a/compat.el
+++ b/compat.el
@@ -49,6 +49,7 @@
;; separately, by explicitly requiring the feature that defines them.
(eval-when-compile
(defvar compat--generate-function)
+ (defvar compat--entwine-version)
(defmacro compat-entwine (version)
(cond
((or (not (eq compat--generate-function 'compat--generate-minimal))
@@ -58,11 +59,24 @@
(file (expand-file-name
(format "compat-%d.el" version)
(file-name-directory
- (or (if (fboundp 'macroexp-file-name)
- (macroexp-file-name)
- (or (bound-and-true-p byte-compile-current-file)
- load-file-name))
- (buffer-file-name)))))
+ (or
+ ;; Some third-party library, which requires
+ ;; compat.el, is being compiled, loaded or
+ ;; evaluated, and compat.el hasn't been compiled
+ ;; yet.
+ ;; cd compat && make clean && cd ../other && \
+ ;; make clean all
+ ;;
+ ;; Or compat.el is being evaluated.
+ ;; cd compat && make clean && emacs -Q -L . compat.el
+ ;; M-x eval-buffer
+ ;;
+ ;; (Like `macroexp-file-name' from Emacs 28.1.)
+ (let ((file (car (last current-load-list))))
+ (and (stringp file) file))
+ ;; compat.el is being compiled.
+ ;; cd compat && make clean all
+ (bound-and-true-p byte-compile-current-file)))))
defs)
(with-temp-buffer
(insert-file-contents file)
@@ -70,11 +84,7 @@
(while (progn
(forward-comment 1)
(not (eobp)))
- ;; We bind `byte-compile-current-file' before
- ;; macro-expanding, so that `compat--generate-function'
- ;; can correctly infer the compatibility version currently
- ;; being processed.
- (let ((byte-compile-current-file file)
+ (let ((compat--entwine-version (number-to-string version))
(form (read (current-buffer))))
(cond
((memq (car-safe form)