Reputation: 1941
An SO post containing a response by coredump shows how to apply a compiler policy to an ASDF system's component files:
(defsystem simple-system
:serial t
:around-compile (lambda (next)
(proclaim '(optimize (debug 3)
(safety 3)
(debug 3)
(speed 0)))
(funcall next))
:components ((:module "src"
:components
(...))))
It also mentions that you can "shadow" individual files, but how would this work. It's confusing to me because next
in the lambda expression is bound to a closure. Since I only need to apply the optimization to a couple of component files, how do you give those file names to :around-compile
?
Upvotes: 4
Views: 293
Reputation: 38799
You can add :around-compile
for a system, a module or a file.
More precisely, if you have a :file
component like this:
(:file "a")
Then you can add:
(:file "a" :around-compile ...)
If you only want to apply optimizations to a given set of files, group them in a module. You can even set the module's pathanme to ""
so that its files are in the same directories are the sibling components:
(:module #:MY-OPTIMIZED-FILES
:depends-on (...)
;; SAME DIRECTORY
:pathname ""
:serial t
:around-compile "my-meta-lib:around-compile"
:components ((:file "a")
(:file "b")
(:file "c")
(:file "d")))
You cannot refer to a symbol if the system that defines it is not loaded, and in the case of an ASDF system, you can't declare dependencies without reading first the form that defines the system. So you need to use strings to refer to a symbol in another package.
When the system is processed, the string must refer to an existing symbol,
so you need to have a different .asd
file, for example simple-system.meta.asd
, which defines the system "simple-system.meta"
. You add a dependency with :defsystem-depends-on
to make sure the meta system is loaded before simple-system
is processed.
That system could be for example:
(defsystem simple-system.meta
:depends-on ("trivial-cltl2")
:components ((:file "meta")))
The reason I am using trivial-cltl2
is to be able to introspect the declaration in the global environment and hopefully limit the effects of proclaim
:
(defun my-meta-lib:around-compile (next)
(let ((opt (trivial-cltl2:declaration-information 'optimize)))
(proclaim '(optimize (debug 3)
(safety 3)
(debug 3)
(speed 0)))
(unwind-protect (funcall next)
(proclaim (list* 'optimize opt)))))
As far as I know, proclaim
modifies the global environment and it could affect the compilation of other files, that's why I prefer to restore the environment after compilation finishes.
SBCL has an experimental :policy
option for with-compilation-unit
that is made for this use case, the policy is modified in the dynamic extent of the macro:
(flet ((debug () (assoc 'debug (sb-cltl2:declaration-information 'optimize))))
(list (debug)
(with-compilation-unit (:policy '(optimize (debug 3)))
(debug))
(debug)))
; => ((DEBUG 1) (DEBUG 3) (DEBUG 1))
Upvotes: 6