对单个文件使用 ASDF 的 :around-compile
Posted
技术标签:
【中文标题】对单个文件使用 ASDF 的 :around-compile【英文标题】:Using ASDF's :around-compile For Individual Files 【发布时间】:2021-04-10 20:34:06 【问题描述】:包含 coredump 响应的 SO post 显示了如何将编译器策略应用于 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
(...))))
它还提到您可以“隐藏”单个文件,但这将如何工作。这让我很困惑,因为 lambda 表达式中的 next
绑定到一个闭包。由于我只需要对几个组件文件进行优化,您如何将这些文件名赋予:around-compile
?
【问题讨论】:
【参考方案1】:您可以为系统、模块或文件添加: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
之前加载 meta 系统。
该系统可以是例如:
(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))
【讨论】:
我尝试为一个中间组件文件添加:around-compile (lambda (next) (proclaim '(optimize (debug 3))) (funcall next))
,效果很好。但是整个系统编译加载后,(sb-ext:describe-compiler-policy)
说debug还是设置为3,下面的组件文件是不是也在用(debug 3)
编译?如果是这样,这不是我想要的。
是的,因为我认为 proclaim 设置了全局编译策略,一旦你设置它就会一直设置;这就是为什么我尝试使用my-meta-lib:around-compile
实现一种更可组合的方法,它获取当前声明进行优化,调用声明,然后在展开时恢复以前的声明。我今天进行了编辑以修复我最初遇到的符号与字符串问题,它似乎有效,该策略仅适用于指定的文件
我也想过 (locally (declare (optimize ...)) (funcall next)) 但超规范不清楚这是否应该在动态范围内工作,我会尝试查找有关此的更多信息
SBCL 中 WITH-COMPILATION-UNIT 的文档字符串说它有一个 :POLICY
选项。这是一个依赖于实现的选项,但这是使用 SBCL 的正确方法。
请注意,所需的 SBCL 模块名称似乎是 sb-cltl2
。以上是关于对单个文件使用 ASDF 的 :around-compile的主要内容,如果未能解决你的问题,请参考以下文章