ASDF:UPGRADE-ASDF leaves UIOP system definition broken
It appears that
asdf:upgrade-asdf can leave the UIOP system definition in a broken state. A side effect of this (and how I noticed it) is that a dependency such as
(:version "uiop" "3.3.2") is very difficult to satisfy on SBCL if you follow the recommended install procedure.
Example using SBCL (ships with ASDF 3.3.1) and asdf cloned to
sbcl --noinform --no-userinit --no-sysinit --eval '(require :asdf)' --eval '(asdf:upgrade-asdf)' --eval '(format t "UIOP system version: ~S~%" (asdf:component-version (asdf:find-system "uiop")))' --eval '(format t "UIOP:*UIOP-VERSION*: ~S~%" uiop:*uiop-version*)' --quit UIOP system version: "3.3.1" UIOP:*UIOP-VERSION*: "18.104.22.168"
sbcl --noinform --no-userinit --no-sysinit --eval '(require :asdf)' --eval '(asdf:find-system "uiop")' --eval '(asdf:upgrade-asdf)' --eval '(format t "UIOP system version: ~S~%" (asdf:component-version (asdf:find-system "uiop")))' --eval '(format t "UIOP:*UIOP-VERSION*: ~S~%" uiop:*uiop-version*)' --quit WARNING: redefining ASDF/INTERFACE::CALL-WITHOUT-REDEFINITION-WARNINGS in DEFUN UIOP system version: "22.214.171.124" UIOP:*UIOP-VERSION*: "126.96.36.199"
The only difference is that in the second there's a call to
(asdf:find-system "uiop") before ASDF is upgraded.
In addition to the version number being broken, things like
system-relative-pathname and basically anything else you can do with a system object are broken in the first example.
Here's what I think is happening in the first case:
- It seems that since 3.3, the asdf system no longer depends on UIOP directly. Instead, its files are transcluded into the asdf/driver system.
- UIOP's sources are loaded via the asdf/driver system, so uiop really is v188.8.131.52 like
- Any further calls to
(find-system "uiop")silently ignore uiop.asd since its version is not strictly greater than ASDF's version https://gitlab.common-lisp.net/asdf/asdf/-/blob/ecd378670b3dd3dba476e9d3110f831b81b2c16e/find-system.lisp#L147. Instead, the original preloaded UIOP system that came from
(require "asdf")is returned.
The second case bypasses this because
(find-system "uiop") does not trigger an ASDF upgrade. So ASDF successfully finds and registers uiop.asd, replacing the preloaded system.
I see three options to fix this:
upgrade-asdfdo something like
(if-let ((uiop (find-system "uiop" nil))) (load-system uiop))before loading asdf. I really don't want to do this.
find-systemto return a system for UIOP so long as the found system is at least as new as the currently loaded version.
- Fix things up so that https://gitlab.common-lisp.net/asdf/asdf/-/blob/1a69ba6c6cd6dedaf9f923dbb3dfc2bab29aeb18/footer.lisp#L23 causes the preloaded systems to be re-registered. I believe this doesn't work currently because
ensure-preloaded-system-registeredshort-circuits if the system to be registered is already registered, even if there's a version mismatch.
Now that I've written this all down, I think 3 is the best way to go, with 2 as a close second. 3 in isolation would make the version number on the system object correct, but everything else would remain blank. This means things like
system-relative-pathname wouldn't work for UIOP, but it's highly unlikely people are currently using that.
In any case, chalk up another example for #83 (closed).