使用ASDF的:around-compileForIndividualFiles
包含 coredump 响应的SO 帖子展示了如何将编译器策略应用于 ASDF 系统的组件文件:
(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
(...))))
它还提到您可以“隐藏”单个文件,但这将如何工作。这让我感到困惑,因为next在 lambda 表达式中绑定到一个闭包。由于我只需要对几个组件文件应用优化,你如何将这些文件名赋予:around-compile?
回答
你可以加 :around-compile为系统、模块或文件添加。
更准确地说,如果您有这样的:file组件:
(:file "a")
然后你可以添加:
(:file "a" :around-compile ...)
如果您只想对给定的一组文件应用优化,请将它们分组到一个模块中。您甚至可以将模块的 pathanme 设置为,""以便其文件在同一个目录中是同级组件:
(: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")))
如果未加载定义它的系统,则不能引用符号,并且在 ASDF 系统的情况下,如果不先阅读定义系统的表单,则无法声明依赖项。所以你需要使用字符串来引用另一个包中的符号。
当系统被处理时,字符串必须引用一个现有的符号,所以你需要有一个不同的.asd文件,例如simple-system.meta.asd,它定义了系统"simple-system.meta"。您添加一个依赖项:defsystem-depends-on以确保在处理之前加载元系统simple-system。
例如,该系统可以是:
(defsystem simple-system.meta
:depends-on ("trivial-cltl2")
:components ((:file "meta")))
我使用的原因trivial-cltl2是能够内省全局环境中的声明,并希望限制以下影响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)))))
据我所知,proclaim修改全局环境可能会影响其他文件的编译,这就是为什么我更喜欢在编译完成后恢复环境。
SBCL 有一个为此用例制作的实验:policy选项with-compilation-unit,在宏的动态范围内修改策略:
(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))
- Yes, because I think proclaim sets the global compilation policy, once you set it keeps being set; that's why I tried to implement a more composable approach with `my-meta-lib:around-compile`, which grabs the current declaration for optimize, calls proclaim, then restores the previous declarations when unwinding. I did an edit today to fix the symbol vs. string problem I had originally, and it seems to work, the policy is applied only for the specified files
- I also though about (locally (declare (optimize ...)) (funcall next)) but the hyperspec was not clear about whether or not this should work in the dynamic extent, I'll try to find more information about that
- The docstring for WITH-COMPILATION-UNIT in SBCL says that it has a `:POLICY` option. This is an implementation-dependant option but this is the proper way to do it with SBCL.
- Note the required SBCL module name seems to be `sb-cltl2`.
THE END
二维码