 generated at the end of an init from the keys of
 `straight--profile-cache'.")
 
+(defvar straight--build-cache-version :jes
+  "The current version of the build cache format.
+When the format on disk changes, this value is changed, so that
+straight.el knows to regenerate the whole cache.")
+
 (defun straight--load-build-cache ()
-  "Load the build cache from build-cache.el into `straight--build-cache'.
-If build-cache.el does not both exist and contain a valid Elisp
-hash table with the appropriate `:test', then
-`straight--build-cache' is set to an empty hash table."
-  (with-temp-buffer
-    (ignore-errors
+  "Load data from build-cache.el into memory.
+This sets the variables `straight--build-cache' and
+`straight--eagerly-checked-packages'. If the build cache is
+malformed, don't signal an error, but set these variables to
+empty values (all packages will be rebuilt, with no caching)."
+  ;; Start by clearing the build cache. If the one on disk is
+  ;; malformed (or outdated), these values will be use.
+  (setq straight--build-cache (make-hash-table :test #'equal))
+  (setq straight--eagerly-checked-packages nil)
+  (ignore-errors
+    (with-temp-buffer
       ;; Using `insert-file-contents-literally' avoids
       ;; `find-file-hook', etc.
       (insert-file-contents-literally
-       (straight--file "build-cache.el")))
-    (setq straight--build-cache
-          ;; We have to use `ignore-errors' because of the potential
-          ;; for an error during parsing.
-          (or (ignore-errors
-                (let ((table (read (current-buffer))))
-                  (when (and (hash-table-p table)
-                             (eq (hash-table-test table) #'equal))
-                    table)))
-              ;; If hash table is malformed, make a new one instead
-              ;; and rebuild all packages. As for :test, the keys are
-              ;; package names as *strings*.
-              (make-hash-table :test #'equal)))
-    (setq straight--eagerly-checked-packages
-          (ignore-errors
-            (let ((list (read (current-buffer))))
-              ;; If list is malformed, use empty list instead.
-              (when (and (listp list)
-                         (cl-every #'stringp list))
-                list))))))
+       (straight--file "build-cache.el"))
+      (let ((version (read (current-buffer)))
+            (find-flavor (read (current-buffer)))
+            (cache (read (current-buffer)))
+            (packages (read (current-buffer))))
+        (unless (and
+                 ;; Format version should be the symbol currently in
+                 ;; use.
+                 (symbolp version)
+                 (eq version straight--build-cache-version)
+                 ;; Find flavor should be the symbol currently in use.
+                 (symbolp find-flavor)
+                 (eq find-flavor straight-find-flavor)
+                 ;; Build cache should be a hash table.
+                 (hash-table-p cache)
+                 (eq (hash-table-test cache) #'equal)
+                 ;; Eagerly checked packages should be a list of
+                 ;; strings.
+                 (listp packages)
+                 (cl-every #'stringp packages))
+          ;; If anything is wrong, abort and use the default values.
+          (error "Malformed or outdated build cache"))
+        ;; Otherwise, we can load from disk.
+        (setq straight--build-cache cache)
+        (setq straight--eagerly-checked-packages packages)))))
 
 (defun straight--save-build-cache ()
-  "Write the build cache from `straight--build-cache' into build-cache.el."
+  "Write data from memory into build-cache.el."
   (with-temp-file (straight--file "build-cache.el")
     ;; Prevent mangling of the form being printed in the case that
     ;; this function was called by an `eval-expression' invocation of
     ;; `straight-use-package'.
     (let ((print-level nil)
           (print-level nil))
+      ;; The version of the build cache.
+      (print straight--build-cache-version (current-buffer))
+      ;; The format of the timestamps that were saved; if this changes
+      ;; (due to a new find(1) command installed), we will have to
+      ;; re-generate the build cache. It would be more efficient to
+      ;; save the timestamps in an OS-independent way, but this
+      ;; approach is simpler.
+      (print straight-find-flavor (current-buffer))
+      ;; The actual build cache.
       (print straight--build-cache (current-buffer))
+      ;; Which packages should be checked eagerly next init.
       (print (hash-table-keys straight--profile-cache) (current-buffer)))))
 
 ;;;;; Bulk checking

              ;; know.
              (or (not (stringp last-mtime))
                  (with-temp-buffer
                    (let* ((default-directory
                             (straight--dir "repos" local-repo))
                           ;; This find(1) command ignores the .git
                           ;; directory, and prints the names of any
                           ;; files or directories with a newer mtime
                           ;; than the one specified.
                           (args `("." "-name" ".git" "-prune"
                                   "-o" "-newermt" ,last-mtime "-print"))
                           (return (apply #'call-process "find"
                                          nil '(t t) nil args)))
                      (unless (= 0 return)
                        (error "Command failed: find %s:\n%s"
                               (string-join
                                (mapcar #'shell-quote-argument args)
                                " ")
                               (buffer-string)))
                      ;; If anything was printed, the package has
                      ;; (maybe) been modified.
                      (> (buffer-size) 0))))))))))

;;;; Building packages
;;;;; Files directive processing


;;;;; Cache handling

(defun straight--format-timestamp (&optional timestamp)
  "Format an Elisp TIMESTAMP for the operating system.
See `format-time-string' for the format of TIMESTAMP."
  (pcase straight-find-flavor
    (`gnu/bsd (format-time-string "%F %T%z" timestamp))
    (`busybox (format-time-string "%F %T" timestamp))
    (_ (error "Unexpected `straight-find-flavor': %S" straight-find-flavor))))

(defun straight--finalize-build (recipe)
  "Update `straight--build-cache' to reflect a successful build of RECIPE.
RECIPE should be a straight.el-style plist. The build mtime and
