Note: I use CCL 64-bit on Linux. I have not checked this on anything else.

I discovered that Buildapp fails to build a project when the FASLs1 for some ‘standard’ libraries are not available. ‘Standard’ meaning well known, mature libraries like Alexandria.

When I started using Common Lisp I tended to use the reader macros #+ and #- to conditionally compile for development or production. Since ASDF uses file modification times instead of code dependencies to determine what to recompile it would often happen that the project’s various files were compiled using different compilation conditions. This caused many mysterious bugs.

The solution to this environment mismatch is to force a recompile of the whole project. I use a two-phase process of generating a manifest and then building the application binary. The recompile is forced by deleting2 the project FASLs before each phase.

At one point I tracked an elusive bug to a library which uses conditional reader macros for conditions which differ between my development and production environments. I extended my FASL deletion to include all the Quicklisp libraries for both building phases. This caused Buildapp to fail.

By using (ql:quickload) in its verbose mode during the build process I saw that CCL emitted ‘compilation failure’ warnings for some libraries while generating the manifest. Many mature and often used libraries caused such warnings. Compilation completed successfully in spite of the warnings and these libraries have been used like that for years so it does not seem to be a serious problem.

During the binary creation phase Buildapp exited at the first occurrence of a ‘compiler failure’ warning with an error. It seems that Buildapp escalated all warnings to errors which caused it to fail.

When your own code triggers this behaviour it is useful because it helps you ship better software. However, when external libraries trigger the failure it is extremely annoying because it blocks your development effort.

The solution for making a complete build in a consistent environment is to do a full clean before generating the manifest and project-only clean before building the binary. This enables Buildapp to load the libraries while still compiling the complete set in a known environment but it requires that the environment conditions for the libraries remain constant during the manifest generation and building phases3.

  1. ‘FASL’ is short for ‘FASt Loading’. It is a binary file containing compiled code. ASDF prefers to load code from a FASL rather than a source file when it determines that the source has not changed since being compiled. 

  2. ASDF documentation provides three options for forcing a recompile: (1) The (clear-system) API call, (2) touching the system’s .asd file, and (3) deleting the project FASLs. 

  3. This can be a tricky requirement because some libraries use #+quicklisp which definitely changes from manifest to building.