原典 : https://blog.3qe.us/entry/2019/04/15/194201
わかる。正直いって全然わからん。
どうでもいい実験を書くときや、手元で動けばいいスクリプトを書くときには、そもそも defsystem を書いたりしない。
「CL:LOAD
で順に読む」というだけで十分なので。
(まあそもそも、 asdf がやってることも「いい感じに compile / load する」のだと考えられるが。)
その段階を超え、「あーなんかソース管理するか・・」と思うと defsystem を書き始める。 この時につくる asdf はもはやテンプレを使い回している。
一方、 Allegro Common Lisp を使うときは Allegro 付属の excl:defsystem を使ってたりする。 こっちの方が文法も概念も簡単なのだが、 Allegro 以外で使えないのが悲しい。 https://franz.com/support/documentation/current/doc/defsystem.htm
実はあまり気になったことがない。一つの system に module が複数入るような構成になる前に system 切ってる気がする。 (・・というより、 module ってよくわからないので使わないようにしてるのかもしれない。)
僕も難しすぎると思う。
- package 名, ファイル名, ファイル配置、 package 配置を一致させなければいけない。ずれたらエラー。検証する方法は load してみるしかない。
- 一体何がどうやって load されるのかを知るには、全ての lisp ファイルを見る必要がある。
まだ asd にファイルを並べて書いてたほうがマシだと思ってる。
ファイルを書くのがめんどくさいというのはある。これもわかる。 しかし、 package と path が同じようにあるというのは前提におけない。
Lisp の場合は、コンパイル済みの fasl を作り置きし、それを頒布し、 load することができる。
この場合、 path なんてものは失われている。 *compile-file-pathname*
と *load-pathname*
も一般的に違う。
(個人的に package-inferred-system に思う不思議な点はこのあたりで、 Load したら消え失せる pathname の情報を、 Load した後も残るパッケージ名に埋め込まないといけない点に違和感がある。)
package と path が独立してるのは、個人的には柔軟性の発露だと思っているけど、まああんまり fasl 運ぶこともしないので面倒が多い説もある。 一方でそれを規約で繋いだ package-inferred-system では、全貌が全くつかめない。 (package-inferred-system のソースってどこから読むのか分からない。ただ load できるだけ、という印象。)
どうなんでしょうね、という。
slime-package-fu では、 slime-export-symbol-at-point
すると、 export されると同時に対応するファイルの defpackage も更新されるわけだけど、
それみたいなのが asdf に出来たら嬉しいんじゃないかなあ。。と昔思った気もする。
Lisp の場合はマクロのせいでそうもいかない、らしい。
以下では、マクロ展開を *macroexpand-hook*
で頑張って追跡しているらしいが、 readtable が書き換えられるとか困り事例がとっても多いらしい。
https://github.com/fare/asdf-dependency-grovel
一方で、他の言語みたいに import とか書きまくることをあてにするのなら、いっそそういうビルドシステム立ち上げちゃってもいいんじゃないの? という気もしてきた。
相互依存しないもの同士ならやりたい放題ともいえる。
完全にローカルで、相互依存しないファイルなら・・
デカpackageを定義した後で
(mapc #'load (directory "*.lisp"))
なんてやって他のはざっくり読んじゃえばいいじゃん説まである。
wild-package-inferred-system とかあるけどどうなんだろ。 https://github.com/privet-kitty/wild-package-inferred-system
そうかな。。今の所、 Allegro と SBCL で動作がぶれて困ったことはない気がする。 ただ、以下のことには気をつかっている。
-
asdf を使う場合、
*compile-file-pathname*
や*load-pathname*
相対でファイルにアクセスしないようにする。asdf が ~/.cache/ などのディレクトリでファイルをコンパイルするので、上記 の path も当然 cache のディレクトリになり、 結果そこから相対的に探しても該当ファイルは見つからない。 asdf:defsystem 相対で読まないといけない。
-
namestring のパースに依存すると大抵パスがずれるので、
#.(make-pathname :directory '(:relative "test"))
とか明示的に書く。例えばSBCLは
(merge-pathnames #p"hoge.txt" #p"/var/tmp")
は#P"/var/hoge.txt"
を返す。 後者が '/var' ディレクトリの 'tmp' という名前のファイルだ、と解釈されるからで、まあ 事前知識がなくて、 さらに realpath を取らないなら仕方ないのだが、それでもハマる挙動ではある。。#p"/var/tmp/"
とやると tmp がディレクトリと見なされるのでいいのだが、こんな tweak に依存してられないので、 最近はmake-pathname
を直書きしている。
( Common Lisp の意図に従うなら、 logical-pathname を使うべきなのかもしれないけど・・)
動作がぶれるというなら、 asdf のバージョンの問題の様な気もする。
わかる。何度か目を通したけど、例えば後半の "Controlling where ASDF searches for systems" は読んだことがない。 標準の場所で困ったことが今の所ないので・・
defsystem の文法は、まあ「そう書くのか」くらいだけど、 asdf のオブジェクトシステムはよく分からない。
asdf:test-system
を使う部分だけは勉強したけど、後は・・いつ読むのか・・
(ビルド時に asdf でフックしてやりたいことが今の所あまりない、というのもある)
うまく?は付き合っていない。 「順にファイルを読んでくれる奴」以上のものを期待していない。
でも excl:defsystem や mk-defsystem や quickbuild を差し置いてデファクトスタンダードなので勉強しています, という程
そのうち書く: asd-generator を使うといい感じになる説
quicklisp + asdf-install (local-projects に入れる) は今でも意味がある気がする
require 依存とか