13.3.12 Pitfalls of the upgrade to ASDF 3
While ASDF 3 is largely compatible with ASDF 2,
there are a few pitfalls when upgrading from ASDF 2,
due to limitations in ASDF 2.
- ASDF 2 was designed so it could be upgraded;
but upgrading it required a special setup at the beginning of your build files.
Failure to upgrade it early could result in catastrophic attempt to self-upgrade in mid-build.
- Starting with ASDF 3 (2.27 or later),
ASDF will automatically attempt to upgrade itself
as the first step before any system operation,
to avoid any possibility of such catastrophic mid-build self-upgrade.
But that doesn't help if your old implementation still provides ASDF 2.
- It was unsafe in ASDF 2 for a system definition to declare a dependency on ASDF,
since it could trigger such catastrophe for users who were not carefully configured.
If you declare a dependency on a recent enough ASDF,
yet want to be nice with these potentially misconfigured users,
we recommend that you not only specify a recent ASDF in your dependencies with
:depends-on ((:version "asdf" "3.1.2")),
but that you also check that ASDF 3 is installed,
or else the upgrade catastrophe might happen before that specification is checked,
by starting your .asd file with a version check as follows:
#-asdf3 (error "MY-SYSTEM requires ASDF 3.1.2")
- When you upgrade from too old a version of ASDF,
previously loaded ASDF extensions become invalid, and will need to be reloaded.
Example extensions include CFFI-Grovel, hacks used by ironclad, etc.
Since it isn't possible to automatically detect what extensions
need to be invalidated and what systems use them,
ASDF will invalidate all previously loaded systems
when it is loaded on top of a forward-incompatible ASDF version.
1
- To write a portable build script, you need to rely on a recent version of UIOP,
but until you have ensured a recent ASDF is loaded,
you can't rely on UIOP being present,
and thus must manually avoid all the pathname pitfalls when loading ASDF itself.
- Bugs in CMUCL and XCL prevent upgrade of ASDF from an old forward-incompatible version.
Happily, CMUCL comes with a recent ASDF,
and XCL is more of a working demo than something you'd use seriously anyway.
- For the above reasons, your build and startup scripts
should load, configure and upgrade ASDF among the very first things they do,
and ensure that ASDF 3 or later is present indeed,
before they start using ASDF to load anything else.
- Now that all implementations provide ASDF 3 or later (since May 2015),
the simple solution is just to use code as below in your setup,
and when it fails, upgrade your implementation or replace its ASDF.
(see Replacing your implementation's ASDF):
(require "asdf")
#-asdf3 (error "ASDF 3 or bust")
- For scripts that try to use ASDF simply via
require at first, and
make heroic attempts to load it the hard way if at first they don't succeed,
see tools/load-asdf.lisp distributed with the ASDF source repository,
or the code of cl-launch.
- Note that in addition to the pitfalls and constraints above,
these heroic scripts (should you wish to write or modify one),
must take care to configure ASDF twice.
A first time, right after you load the old ASDF 2 and before you upgrade to the new ASDF 3,
so it may find where you put ASDF 3.
A second time, because some implementations can't handle a smooth upgrade to ASDF 3,
and lose configuration as they do.
(ignore-errors (funcall 'require "asdf")) ;; <--- try real hard
;; <--- insert heroics here, if that failed to provide ASDF 2 or 3
;; <--- insert configuration here, if that succeeded
(asdf:load-system "asdf")
;; <--- re-configure here, too, in case at first you got ASDF 2