What I would recommend is to set up a fake component type for the host system, and then the system definition will automatically detect a change.

The difficulty would be having the host system version be recorded in the filesystem so that ASDF can see it.

I'd suggest you have an operation that reads a file with a version number in it, and updates that file if the SBCL version number has increased. Then if ASDF sees that the file's date is new, it will know that SBCL has been updated and rebuild everything.

But... that requires comparing dates on input and output files, so you might need a pair of such files that you rotate -- you read the input file, and then write an output file, and ASDF will compare the dates on the two and decide whether it needs to update.

That should be enough to get you started.

On 17 Nov 2020, at 11:47, Pierre Neidhardt wrote:

Ha, that's a good starting point indeed!

So I made the following system:

--8<---------------cut here---------------start------------->8---
(defsystem "ambrevar/dump"
:class :package-inferred-system
:depends-on #.(append
'(ambrevar/all asdf)
#+sbcl
'(sb-bsd-sockets sb-posix sb-introspect sb-cltl2))
:build-operation image-op
:build-pathname
#+sbcl "sbcl.core-for-sly"
#+ccl "ccl.core-for-sly")
--8<---------------cut here---------------end--------------->8---


And I'm building it with:

--8<---------------cut here---------------start------------->8---
sbcl --no-userinit --eval '(require :asdf)' --eval '(asdf:make :ambrevar/dump)' --eval '(quit)'

## And to test portability...
ccl --no-init --eval '(require :asdf)' --eval '(asdf:make :ambrevar/dump)' --eval '(quit)'
--8<---------------cut here---------------end--------------->8---

What's missing is a way to rebuild the image when the compiler changes
(e.g. SBCL gets updated).

One way would be to load the core, return the
(lisp-implementation-version), compare against the current compiler
(lisp-implementation-version). But that's too much code.

Alternatively, I can just try to start the implementation with the given
core. If the version is wrong, it will fail. This is less code, but
still (untested):

--8<---------------cut here---------------start------------->8---
(defun ambrevar/dump-lisp-core (implementation core-flag extra-flags)
(cl-flet ((find-core ()
(first (directory-files ambrevar/lisp-core-root nil (format "%s.*" implementation)))))
(let ((core (find-core)))
(when (or (not core)
;; Not right version
(/= 0 (call-process implementation nil nil nil
core-flag core
extra-flags
"--eval" "(quit)")))
(let ((lisp-output-buffer (get-buffer-create " *Lisp dump log*")))
(with-current-buffer lisp-output-buffer (erase-buffer))
(apply #'call-process
implementation nil (list lisp-output-buffer t) nil
"--eval" "(require :asdf)"
"--eval" "(asdf:make :ambrevar/dump)"
"--eval" "(quit)"))))
(or core (find-core))))
--8<---------------cut here---------------end--------------->8---

Would there be a way to tell ASDF "dump image only if version differs"?

I'm not sure this is doable with ASDF, because this means starting an
implementation and loading ASDF, which is already too slow.

So we need a way to tell that the image is out of date in a fraction of
a second (<50ms I'd say), i.e. without loading ASDF.

Maybe create a new (contrib?) system that loads in an instant with just
one function, one that checks if a core is valid or not.

Thoughts?

--
Pierre Neidhardt
https://ambrevar.xyz/