custom-load: Cautious Bytecode Loaders
This package provides a function for building compiled-load handlers that avoid loading stale ".zo" files, thus avoiding errors of the form “link: module mismatch.”
To be more precise, a “link: module mismatch” error arises when Racket loads a ".zo" file with an ancestor whose ".zo" file is stale or missing; the ancestor is recompiled in a way inconsistent with the descendant, but it is too late to recompile to descendant, because its bytecode is already loaded. The handlers produced by this library recursively check ancestors before loading a descendant’s ".zo" file.
This library uses a logger named custom-load; to see its output, try setting PLTSTDERR="info@custom-load".
1 Custom Compiled-Load Handlers
(require custom-load) | package: custom-load |
procedure
(make-custom-load/use-compiled [ #:blacklist blacklist #:load-zo load-zo #:load-src load-src])
→
(-> path? (or/c #f symbol? (cons/c (or/c #f symbol?) (listof symbol?))) any)
blacklist : (treeof (or/c regexp? (-> path? any/c))) = (lambda (file) #f)
load-zo :
(-> path? (or/c #f symbol? (cons/c (or/c #f symbol?) (listof symbol?))) any) = (current-load/use-compiled)
load-src :
(-> path? (or/c #f symbol? (cons/c (or/c #f symbol?) (listof symbol?))) any) = (lambda (file want) ((current-load) file want))
When loader is called to load file, it performs the following checks, loading the ".zo" version of file only if all of them pass.
If file is “zo blacklisted”—
that is, if (blacklist file) returns a true value— then file must be loaded from source. The corresponding ".zo" file zo-file is located according to the rules of the default compiled-load handler. If no zo-file can be located, or if file is newer than zo-file, then file must be loaded from source.
The dependencies of zo-file are recursively checked; if any of them must be loaded from source, file must be loaded from source. The result of dependency checking is cached.
Otherwise, file is loaded from ".zo" file.
To load file from source, loader calls (load-src file what), where what is the module or submodule requested (see compiled-load handler). The current-load-relative-directory parameter is first set to the directory containing file.
To load file from ".zo" file, loader calls (load-zo file name). Note that load-zo is called with the original file, not with the zo-file; thus the previous value of (current-load/use-compiled) is an appropriate value of load-zo.
The blacklist argument is useful when using an instrumenting compiler that intercepts loads of certain modules and recompiles them after performing some sort of instrumentation. Examples include debuggers, profilers, and coverage testers. Set the blacklist argument to a predicate that recognizes the files to be instrumented and supply the following function for load-src:
(lambda (file what) (cond [(blacklist? file) ; compile this file with instrumentation ....] [else ((current-load) file what)]))
As an alternative to supplying a load-src argument, you can also override current-load, chaining to the previous value in the default branch.
2 Automatic Installation of Loader
(require custom-load/top) | package: custom-load |
Requiring the custom-load/top module automatically installs a custom loader as the value of current-load/use-compiled, using the old value as the load-zo argument.
You can also run a program with a custom loader using a command line like racket -l custom-load/top -t program.rkt.
parameter
(current-zo-blacklist) → (-> path? any/c)
(current-zo-blacklist pred) → void? pred : (treeof (or/c (-> path? any/c) regexp?))