(ASDF 3) 如何将文件|组件标记为“脏”或需要重建?

Posted

技术标签:

【中文标题】(ASDF 3) 如何将文件|组件标记为“脏”或需要重建?【英文标题】:(ASDF 3) How do you flag a file|component as "dirty" or in need of rebuilding? 【发布时间】:2021-07-23 09:05:44 【问题描述】:

我想告诉 ASDF 某个特定组件的状态已经改变,下次加载封闭系统时应该重新编译它。动机:我设想有配置变量在被修改时触发这个过程。

如果我不得不猜测的话,必要的工具似乎在 asdf/plan 包中。

【问题讨论】:

【参考方案1】:

我首先添加了一个依赖于环境变量当前值的新组件类型来测试以下内容。包和定义如下,基于手册的Object Model of ASDF部分(这取决于osicat):

(defpackage env-var-asdf
  (:use :cl)
  (:export #:cl-source-file-env-var
           #:depends-on-env-var))

(in-package env-var-asdf)

;; mixin
;;
;; this component depends on a posix environment variable (`varname`) and
;; stores the last known value (`last-value`). AFAIK objects are rebuilt when the 
;; asd file is reloaded, so you can preserve some state in the components if
;; the system definition does not change.
;;
(defclass depends-on-env-var ()
  ((varname :initarg :varname :reader env-var-varname)
   (last-value :accessor env-var-last-value)))

;; this method defines if the operation is already done, we return NIL if
;; the file needs to be recompiled; here, if no last known value exist for the
;; environment variable, or if the current value differs from the last one.
;;
;; I made it an `:around` method but this might be wrong (it never 
;; calls the next method; the behavior depends only on the 
;; environment variable).
;;
(defmethod asdf:operation-done-p :around (operation (component depends-on-env-var))
  (let ((value (osicat-posix:getenv (env-var-varname component))))
    (prog1 (and (slot-boundp component 'last-value)
                (string= value (env-var-last-value component)))
      (setf (env-var-last-value component) value))))

;; a cl-source-file with that mixin being the first superclass,
;; again to prioritize the modified behaviour.
(defclass cl-source-file-env-var (depends-on-env-var asdf:cl-source-file) ())

为了测试这一点,我在quicklisp/local-projects 中创建了test-asdf,并带有以下test-asdf.asd 文件:

(defsystem test-asdf
  :depends-on ()
  :components ((env-var-asdf:cl-source-file-env-var "a"
                :varname "LANG")))

这里,当LANG 环境变量被修改时,组件a 被重新编译/重新加载。这里是a.lisp

(defpackage :test-asdf (:use :cl))
(in-package :test-asdf)

(print "loaded")

在 REPL 中,当我第一次快速加载系统时,"loaded" 被打印到标准输出。如果我触摸文件a.lisp,它会重新加载,我想我不确定为什么(ASDF 很复杂),我的意思是组件的input-files 更新,因此即使operation-done-p 返回 NIL,它也可能会强制重新编译. 最后,如果我不触摸文件而是从进程中更改 LANG 环境变量,那么文件会再次加载。

【讨论】:

以上是关于(ASDF 3) 如何将文件|组件标记为“脏”或需要重建?的主要内容,如果未能解决你的问题,请参考以下文章

使用 ASDF 加载可选组件

对单个文件使用 ASDF 的 :around-compile

如何将本地项目添加到quicklisp配置的asdf

Vue.js 3.0 组件是如何渲染为 DOM 的?

Angular4从脏检查中排除属性

游戏编程模式-脏标记模式