OK, so ASDF 2.27 has been 2 months in the doing, plus one month initial hyatus, that's three months since 2.26. Since then it has a bit over doubled in size, and the testing of it has caused a lot of breakage, for which I apologize again.
Here is a list of the major changes so far, glossing over buglet fixes and internal changes that should be invisible to users:
* ASDF-BUNDLE was merged into ASDF. This notably means fewer headaches for users of ECL; it also means a new load-fasl-op feature for all users of a modern CL, making it easier to deliver software as a single fasl. After release, I plan to offer a patch so SBCL use that for its contrib's. All remnants of asdf-bundle's predecessor asdf-ecl were removed.
* *decades-old* bugs of notable significance were fixed: (a) changes in dependencies now trigger a rebuild across systems, and https://bugs.launchpad.net/asdf/+bug/479522 (b) timestamps are now correctly propagated (they weren't at all!) https://bugs.launchpad.net/asdf/+bug/1087609 In olden days, some have argued for not rebuilding systems that :depend-on a modified one as a "feature". It really isn't. On the other hand, it is now possible to explicitly prevent a system from being rebuilt, using an actual feature, :force-not, which was released in 2.21 in April 2012. Someday I will write about those bugs.
* PREPARE-OP was introduced to fix a conceptual bug in the ASDF object model. It corresponds to "loading the dependencies of a component and its parents" and is explicitly depends-on'ed by LOAD-OP and COMPILE-OP of the component, instead of their implicitly depending on it via the TRAVERSE algorithm, which implicit dependency proved fatal in cases revealed by the above bugs. It propagates upward in the component hierarchy, rather than downward, like the TRAVERSE algorithm used to systematically propagate dependencies.
* TRAVERSE was gutted out and factored into reusable higher-order functions and objects, which not only fixes the above conceptual bug, but makes for semantics that are simpler to implement, possible to understand, easier to extend, and less limited in expressivity. TRAVERSE doesn't automatically propagate operations downward the component hierarchy anymore; propagation is now implemented through methods on COMPONENT-DEPENDS-ON.
* COMPONENT-DEPENDS-ON is now more powerful: it can express dependencies on arbitrary operation objects (i.e. operations of the same class can have different options) acting on arbitrary component objects (i.e. not necessarily siblings of the current component). The ASDF object model can now express arbitrary build graphs, with no more special magic for children components vs other dependencies.
* COMPONENT-DO-FIRST is no more. It used to specify some dependencies that were skipped if no re-build was triggered based on local timestamps. Instead, COMPONENT-DEPENDS-ON is used for all dependencies, and all are consulted to correctly propagate timestamps. However actions meant for in-image side-effects are included only if needed, and might be visited twice by TRAVERSE, first without the needed-in-image-p flag, another time with.
* FORCE and FORCE-NOT now correctly distinguish T from :ALL in addition to a list of system name specifiers, as per the original specification (which was never implemented in ASDF 1). Additionally, builtin systems (such as SB-BSD-SOCKETS on SBCL) cannot be forced (which doesn't work on SBCL).
* IF-FEATURE is a new attribute of components that accepts an arbitrary feature expression such as (:and :sbcl (:or :x86 :x86-64)), which when defined is a precondition to the component being enabled; when the expression is false, the component is disabled, and dependencies to it are removed. It replaces the misguided :if-component-dep-fails attribute of modules and the accompanying :feature feature, which were dropped. They were not very expressive, clunky to use, and relied on baking conceptually dubious non-local behavior in the old TRAVERSE algorithm, which belied the object model and defeated other features. Unhappily, this breaks backwards compatibility for the few who used it, namely sb-grovel, nibbles and ironclad. A minimal compatibility layer allows ASDF 2.27 or later to load the SB-GROVEL of old versions of SBCL, but it won't suffice to load an old version of nibbles or ironclad; please upgrade them a recent version that was updated to support ASDF 2.27.
* CONCATENATE-SOURCE-OP is a new operation that builds a single Lisp file from all the source files in a system, which allows you to develop in a structured way with many compact files, yet deliver a large single file. Other related operations allow you to load that source file, or compile and load it, or do the same while including all other system dependencies. ASDF was broken up into lots of small files, to be delivered that way.
* FOO/BAR/BAZ names will be recognized by defsystem as having to be located in a file called foo.asd. This is backward compatible in the case where you somehow arranged to load foo.asd before to use the other subsystems, except now ASDF can find the subsystems by name without the main system definition having been loaded. See uses of function PRIMARY-SYSTEM-NAME.
* BUILD-OP is a generic operation that can do the "right thing" for each system, without users having to maintain the knowledge of what the right thing is for each system they may indirectly depend on.
* Convenience methods were added to most exported generic functions, so you can (input-files 'compile-op '(system1 "file1")) instead of (input-files (make-instance 'compile-op) (find-component 'system1 "file1")) This notably makes it much easier to interact with ASDF at the REPL and debug your system definitions or ASDF extensions (or modifications).
* Packages were introduced as ASDF was broken up into small files. Each file now has its own package, importing and exporting functionality, following the style made popular by faslpath and quick-build. ASDF does not yet include builtin support for quick-build or faslpath systems and dependencies, however. Possibly in ASDF 2.28.
* ASDF-DRIVER is a separately-usable library for Common Lisp runtime support. It is transcluded in asdf.lisp (i.e. when delivering ASDF as a separate bootstrap file, the contents of ASDF-DRIVER have been included in it), but can also be used as a separate ASDF system on top of an old ASDF (within limits: CLISP and XCL still need a recent ASDF). The package ASDF/DRIVER (with short nickname :D) re-exports all the functions that ASDF needed to run portably.
* Pathnames are a notable part of ASDF-DRIVER, required to deal portably with pathnames despite the many bugs and variations from platform to platform. See notably in pathname.lisp, MERGE-PATHNAMES*, SUBPATHNAME, PARSE-UNIX-NAMESTRING, PARSE-NATIVE-NAMESTRING, ENSURE-PATHNAME, and many many more.
* Pathname use by ASDF was also improved in countless small ways, closing more buglets that appeared in as many corner cases. For instance, system pathname defaulting was improved, and systems not associated with a file will now have NIL as their pathname, which will otherwise be correctly treated. Many things that would vary depending on implementation will work better. Also, although we cannot strongly enough disrecommend the use of so-called "logical pathnames", especially where portability matters in any way, we support them better than ever within the limitations of the implementation.
* Image lifecycle support is included in ASDF-DRIVER (and thus ASDF); this standardizes things like access to *COMMAND-LINE-ARGUMENTS*, declaring an entry-point to a program, hook functions and/or a prelude to run before to start the main entry, and a postlude and/or hook functions to run before to dump an image, dumping or creating an image, etc.
* PROGRAM-OP allows you to create standalone executables on implementations that support it: CLISP, Clozure CL, CMUCL ECL, LispWorks, SBCL, SCL. A hello-world-example system shows demonstrates how to use it.
* Run-program is a replacement for the old run-shell-command. Unlike run-shell-command, it is portable to Windows as well as Unix, it can avoid going through a shell and will sensibly escape arguments when it does go through a shell, and it has a usable interface to either capture program output or run the program interactively. This supersedes run-program/ previously available from xcvb-driver, including several improvements and portability fixes.
* Conditions can be selectively muffled around compilation thanks to the an around-compile hook and the *UNINTERESTING-COMPILER-CONDITIONS* parameter, and around loading with *UNINTERESTING-LOADER-CONDITIONS* which is _appended_ to the former during loading. This supersedes the functionality previously available from xcvb-driver and its thin wrapper asdf-condition-control, which was retired.
* Deferred warnings for yet undefined functions, that in a single-session build are usually signaled at the end of a compilation unit, will be saved and reassembled to make each system a compilation unit of its own, even when compilation of file happens across multiple sessions; only CCL and SBCL support this feature at this time. I welcome patches for other compilers, for which ASDF will _not_ wrap an implicit WITH-COMPILATION-UNIT around its operate method anymore.
* COMPILE-FILE* was beefed up to support all these features and more, and the Right Thing(tm) on all implementations, including support for their various extensions.
* Internals have been refactored, and some sorry features were excised. The semantics of OPERATION-DONE-P is simplified and now well-specified. FIND-COMPONENT will pass component objects through, and a corresponding FIND-OPERATION replaces MAKE-SUB-OPERATION. Many internal accessors were renamed, after checking on Quicklisp that no one was using them.
* Portability updates were done for ABCL, CLISP, Clozure CL, CMUCL, ECL, LispWorks Personal Edition, MKCL, XCL. Working support for GCL 2.6 was restored, with notable limitations including lack of support for output-translations or logical-pathnames.
* TRUENAME resolution can be reliably turned off in all cases where ASDF was using them by setting the variable *RESOLVE-SYMLINKS* to NIL. This is useful if your operating system makes that operation slow, or if your build system uses symlinks to content-addressed storage in which case TRUENAME just does the wrong thing.
* VERSION strings can now be specified as having to be fetched from a file using a (:read-file-form <path>) specification, that can use an optional :at keyword argument to specify a form or subform other than the first form in the file, as per the utility asdf-driver:access-at. For instance, if your file specials.lisp is a defpackage, an in-package and a defparameter of the version, then you could use: (:read-file-form "specials.lisp" :at (2 2)) This makes it easier for developers to manage versioning of one or multiple systems with a single master version location.
* Self-Upgrade of ASDF will happen automatically as the first thing before any attempt to build anything, as it was determined that doing it in the midst of a build breaks everything, and it is not otherwise possible to reliably detect in advance whether ASDF may be needed in such midst. If you don't want an ASDF upgrade, just don't configure your source-registry to include any copy of ASDF.
* DEFINE-PACKAGE is provided as a replacement to DEFPACKAGE that supports hot upgrade of software where some packages have changed. It also provides new forms :MIX and :REEXPORT which can be quite practical.
* ASDF2.27 was added to the *features* so you can detect the presence of this massively updated ASDF and its new features with #+asdf2.27. This is *not* ASDF3, for we painfully maintained backwards compatibility, though it may have been temporarily broken during development.
* Documentation received some updates.
* Tests were updated, notably including support for bundles, encodings, run-program, and more. They were successfully run on ccl clisp sbcl ecl ecl_bytecodes cmucl abcl scl allegro lispworks allegromodern xcl Manual tests were run on gcl2.6 genera lispworks-personal-edition. Untested remain cormancl mkcl rmcl.
* ASDF-DEBUG is a simple utility to make your favorite debugging primitives available in the package you're debugging. See contrib/debug.lisp and the asdf/utility:*asdf-debug-utility* variable.
* ASDF-UTILS is now but an empty shell that depends-on ASDF-DRIVER. The ASDF-DRIVER package has the ASDF-UTILS nickname, and exports all the functionality that used to be in ASDF-UTILS, and much more, minus a few misdesigned things from ASDF1 that you ought not to have been using, and for which there are non-broken replacements. ASDF-UTILS was distributed separately from ASDF; ASDF-DRIVER is available both as part of ASDF 2.27 and later and separately.
* POIU was updated. This extension is still distributed separately from ASDF. It is now much simplified and made correct by construction by reusing the new TRAVERSE infrastructure of ASDF and now being able to assume the ASDF object model is a complete description of dependencies. On SBCL it will handle deferred warnings from background compilations. Where forking is not possible or not supported, it will gracefully fall back to serial compilation.
* INFERIOR-SHELL (distributed separately) was updated to use asdf-driver instead of xcvb-driver, providing a richer interface to the RUN-PROGRAM functionality.
* SLIME support for ASDF was significantly enhanced. It is distributed with SLIME, separately from ASDF. See latest slime checkin from 2013-01-20. We recommend that you should include slime-asdf in your slime-setup and that in your ~/.swank.lisp you should include: (in-package :swank) (pushnew 'try-compile-file-with-asdf *compile-file-for-emacs-hook*) This requires ASDF 2.014.6 or later (as used by older quicklisp releases).
There's one more feature pending, courtesy of Stelian Ionescu, that will hopefully make it to the release that I hope will happen next week.
In the meantime, I welcome all testing of the new ASDF and/or its ASDF-DRIVER.
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org Memory is like an orgasm... it's better when you dont have to fake it. — Seymour Cray
I am heartened to see the many fixes to long-deferred bugs, particularly the system dependency fail.
However, this ASDF is not ready for prime time, at least for use with ACL. Its behavior with ACL, because of getting rid of the WITH-COMPILATION-UNIT, is simply unacceptable.
On all our well-formed ASDF systems, compilation now spews out huge numbers of false-positive undefined function warnings that used to be handled acceptably by the WITH-COMPILATION-UNIT.
I really don't like the removal of W-C-U: it takes the normal ASDF use-case of single-process compilation and loading, and deprecates correct behavior there in order to achieve some improvements in a non-standard case of compiling lisp files in different processes, and to fix a problem with the less often used TEST-OP.
So far, the fix here is worse than the disease, since it fails any number of good ACL systems. For example, I believe every one of my company's systems would fail its continuous integration testing using the new ASDF, because of the spurious warnings.
At this point, I would have to advise implementations other than CCL and SBCL to decline to adopt 2.27, or to restore the WITH-COMPILATION-UNIT with some :AROUND methods.
I don't like to see divergence among implementations like this, so I can think of two short-term expedients
1. push the WITH-COMPILATION-UNIT removal out onto a topic branch until the community can ensure that all supported implementations defer the warnings correctly, or 2. keep a single ASDF, and restore the WITH-COMPILATION-UNIT in a #-(or sbcl ccl) block. Add more implementations to the #- as we can support them.
The advantage of 2 is that we can continue to test the new behavior on systems where it is implemented, and we have a single ASDF version; no forking.
The advantage of 1 is that it better handles the situation if there are implementations where warning throttling *cannot* be made to work properly. In that case, I believe it's better to have a single behavior, even if suboptimal, instead of having a divergence in ASDF semantics between different implementations. Another reason we might prefer alternative 1 is that it is robust to finding other behaviors that require W-C-U. I don't understand the semantics thoroughly enough to know whether undefined entity warnings are all that we need to worry about.
I will try to make a test that shows the bad behavior on ACL. Then we could see if this behavior happens on other CL implementations, and would have a criterion for good performance.
Best, r
I'm in the opinion that if you want W-C-U, you should do it yourself explicitly. However, for the sake of backward compatibility, and since you have a strong opinion otherwise, I'll restore the W-C-U :around perform-plan.
The deferred-warning feature (currently on CCL and SBCL only) will continue working because it uses W-C-U (:override t).
Now, if you would contribute deferred-warning support of ACL, that would be great.
My apologies for the breakage. That's one big reason why I ask people to test before release. Thank you for testing.
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org "I think sex is better than logic, but I can't prove it." — Monty Python
On Thu, Jan 24, 2013 at 7:50 PM, Robert Goldman rpgoldman@sift.info wrote:
I am heartened to see the many fixes to long-deferred bugs, particularly the system dependency fail.
However, this ASDF is not ready for prime time, at least for use with ACL. Its behavior with ACL, because of getting rid of the WITH-COMPILATION-UNIT, is simply unacceptable.
On all our well-formed ASDF systems, compilation now spews out huge numbers of false-positive undefined function warnings that used to be handled acceptably by the WITH-COMPILATION-UNIT.
I really don't like the removal of W-C-U: it takes the normal ASDF use-case of single-process compilation and loading, and deprecates correct behavior there in order to achieve some improvements in a non-standard case of compiling lisp files in different processes, and to fix a problem with the less often used TEST-OP.
So far, the fix here is worse than the disease, since it fails any number of good ACL systems. For example, I believe every one of my company's systems would fail its continuous integration testing using the new ASDF, because of the spurious warnings.
At this point, I would have to advise implementations other than CCL and SBCL to decline to adopt 2.27, or to restore the WITH-COMPILATION-UNIT with some :AROUND methods.
I don't like to see divergence among implementations like this, so I can think of two short-term expedients
- push the WITH-COMPILATION-UNIT removal out onto a topic branch until
the community can ensure that all supported implementations defer the warnings correctly, or 2. keep a single ASDF, and restore the WITH-COMPILATION-UNIT in a #-(or sbcl ccl) block. Add more implementations to the #- as we can support them.
The advantage of 2 is that we can continue to test the new behavior on systems where it is implemented, and we have a single ASDF version; no forking.
The advantage of 1 is that it better handles the situation if there are implementations where warning throttling *cannot* be made to work properly. In that case, I believe it's better to have a single behavior, even if suboptimal, instead of having a divergence in ASDF semantics between different implementations. Another reason we might prefer alternative 1 is that it is robust to finding other behaviors that require W-C-U. I don't understand the semantics thoroughly enough to know whether undefined entity warnings are all that we need to worry about.
I will try to make a test that shows the bad behavior on ACL. Then we could see if this behavior happens on other CL implementations, and would have a criterion for good performance.
Best, r
On Thu, Jan 24, 2013 at 7:50 PM, Robert Goldman rpgoldman@sift.info wrote:
However, this ASDF is not ready for prime time, at least for use with ACL. Its behavior with ACL, because of getting rid of the WITH-COMPILATION-UNIT, is simply unacceptable.
Please try 2.26.146, which restores W-C-U.
I really don't like the removal of W-C-U: it takes the normal ASDF use-case of single-process compilation and loading, and deprecates correct behavior there in order to achieve some improvements in a non-standard case of compiling lisp files in different processes, and to fix a problem with the less often used TEST-OP.
I dispute that W-C-U is correct in this normal use case: depending on the compiler, it incorrectly eliminates warnings from non-recompiled files, in the case that you're not building from clean, not forcing, and some of these files had warnings. I consider that a bug. Displaying too many warnings is also a bug, but the users can manually use W-C-U if there's none and they want it; they can't remove the W-C-U if there's one and they don't want it.
Anyway, I agree that backward compatibility is important enough here, and that if and when more implementations are supported, that WCU will become less relevant and may be removed for good later.
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org Instead of loving your enemies, treat your friends a little better. — Edgar Watson Howe