Next: , Previous: , Up: コンポーネント   [Contents][Index]


7.2.1 コンポーネントの共通の属性

すべてのコンポーネントはその型にかかわらず、次の属性(attribute)を持っています。コンポーネント名以外の属性は任意です。

7.2.1.1 コンポーネント名

コンポーネント名(component name)は文字列またはシンボルであり、シンボルはasdf:coerce-nameによって小文字の文字列に変換されます。コンポーネント名には総称関数component-nameでアクセスできます。

:pathname属性を上書きしない限り、コンポーネント名はUNIXスタイルの相対パスとしてそのままパス名指定子に使われるでしょう。(→ パス名指定子

7.2.1.2 バージョン識別子(:version

この属性は任意であり、コンポーネントのバージョンを指定します。バージョンは、一般的にはドットで区切られた整数の文字列で、例えば‘1.0.11’などです。(→ バージョン指定子) コンポーネントのバージョンには総称関数component-versionでアクセスできます。

ASDFが、:depends-onで指定された依存コンポーネントの:versionオプションについて調べる時に、コンポーネントのバージョンをversion-satisfiesで問い合わせるかもしれません。例えばシステム定義に:depends-on (((:version "mydepname" "1.0.11"))という記述がある時は、mydepnameコンポーネントのバージョンが1.0.11以上であるかどうか確認されることになります。:versionオプションについてはdefsystemの文法を、version-satisfies関数については関連する関数を参照してください。

一般的には、バージョン番号が問題になるのはsystem型のコンポーネントだけであることに注意してください。ライブラリの作者が、システムに含まれる様々なファイルにバージョン番号を付けて自ら同期させるというような使い方は、おそらくまったく有用ではないでしょう。

7.2.1.3 必要なフィーチャー(:if-feature

defsystem内で処理系に応じてファイルを含めたり除外したりする時は、伝統的にはリーダーマクロ#+が使われていました。例えばポータブルなCのFFIであるCFFIには、システム定義に次のような一行があります:

     #+sbcl       (:file "cffi-sbcl")

しかしこの方法には、どの処理系もシステム全体を読み込むことができないという欠点があります。例えば、新しくarchive-opというオペレーションを作り、システムのすべてのソースファイルをまとめたアーカイブを作ろうとしたとしましょう。この時、上の例のcffi-sbcl.lispはSBCL以外の処理系では不可視であり、archive-opを実行してもアーカイブに収集されないという問題が起きます。

この問題を解決するため、ASDF 3からコンポーネントに:if-featureオプションが導入されました。このオプションの値はフィーチャー表現であり、つまり、#+と同じ文法を使います。フィーチャー表現が満たされないとき、そのコンポーネントはコンパイル、ロード、リンクの際に無視されます。なお、「同じ文法」と述べましたが、このフィーチャー表現は標準のリーダーで読まれるので、シンボルを使う際には:を前置して明示的にキーワードにしなくてはなりません。#+に続くフィーチャー表現は暗黙にキーワードパッケージを使いますから、その点は異なることになります。

例えば(:file "foo-sbcl" :if-feature (:and :x86 (:or :sbcl :cmu :scl)))という記述は、x86マシン上のSBCL、CMUCL、Scieneer CLにおいてのみ、foo-sbcl.lispのコンパイル、ロードがなされるという意味です。先に述べた通り、(:file "foo-sbcl" :if-feature (and x86 (or sbcl cmu scl)))と書くことはできません。

if-featureオプション

7.2.1.4 アクションの依存関係(:in-order-to

この属性には、当該コンポーネントに関するアクションが別のアクションに依存していることを記述します。任意の属性ですが、しばしば必要になります。

依存関係はオペレーションとコンポーネントのペアについて指定します。例えば次のように記述したとしましょう:

:in-order-to ((compile-op (load-op "a" "b") (compile-op "c"))
              (load-op (load-op "foo")))

このとき、このコンポーネントに対してcompile-opを実行する前に、ASDFはabに対してload-opを実行し、さらにcに対してcompile-opを実行しなければなりません。また、load-opを実行する前に、fooがロードされていなければなりません。

文法はおおむね次のようになります。

(this-op {(other-op required-components)}+)
                
required-components := component-name
                     | (required-components required-components)

component-name := simple-component-name
                | (:version simple-component-name minimum-version-object)
                
simple-component-name := string
                      |  symbol

[付記]

これはACLのdefsystemと同等の機能です。mk-defsystemはやや一般性に欠けていて、次のような暗黙の依存関係

  すべてのソースファイルxについて、(load x)は(compile x)に依存する

を導入していました。:depends-on引数でbaに依存すると指定したとき、それが実際に意味しているのは

  (compile b)は(load a)に依存する

ことだったのです。しかし、これは不十分な機能でした。McCLIMのように、何らかのファイルがコンパイルされる前に、まずはすべてロードされなければならないようなシステムを記述できなかったのです。

[付記終わり]

ASDFでは、与えられたアクションがどのアクションに依存しているかを(component-depends-on operation component)で問い合わせることができます。このフォームが返すリストは

((load-op "a" "b") (compile-op "c") (load-op "d") ...)

のような形式です。 component-depends-onメソッドは、特定のコンポーネント・オペレーションのクラスについて定義することも可能です。その際、(デフォルトの依存関係を完全に上書きしたいのでなければ)自分のメソッドの結果と(call-next-method)の返り値をappendして返す必要があります。

この結合は、CLISPのことを考えなければ、メソッドコンビネーションのlistを使って透過的に実現できるでしょうが、我々はCLISPもサポートする必要があるので、この仕様を使っていません。あなたにCLISPをハックする時間があれば、この部分の修正はきっと歓迎されることでしょう。

コンポーネント(通常はシステム)に特定のバージョン以降を要求したい場合は、ここでも:versionオプションが使えます。この場合、:in-order-to ((load-op (load-op "other-system'')))の代わりに:in-order-to ((load-op (load-op (:version "other-system" "1.2.3"))))などと記述することになるでしょう。

7.2.1.5 パス名(:pathname

この属性の指定は任意であり、たいていは省略されるでしょう。その場合、コンポーネント名が(相対パスとして)使われます。

パス名がどのように解釈されるかについては、パス名指定子を参照してください。

また、「トップレベル」のシステムを定義するdefsystemマクロは、システム直下のコンポーネントがファイルシステム上のどこにあるか決めるために、追加の処理をします。詳しくはdefsystemでシステムを定義するを参照してください。

総称関数: component-pathname component

componentに対応するパス名を返します。ソースファイルのようなコンポーネントに対しては、ファイルのパス名を返すでしょう。以下に例を挙げます:

CL-USER> (asdf:component-pathname (asdf:find-system "xmls"))
#P"/Users/rpg/lisp/xmls/"
CL-USER> (asdf:component-pathname
           (asdf:find-component
              (asdf:find-system "xmls") "xmls"))
#P"/Users/rpg/lisp/xmls/xmls.lisp"

7.2.1.6 プロパティ(:properties

この属性は任意です。

[訳者補足]

この属性は廃止予定であり、ASDF 2との後方互換性のためだけに存在します。また、その名に反して、:propertiesオプションにはプロパティリストではなく連想リストを指定します。昔のASDFでは独自の属性が必要な時にcomponent-propertyで読み書きしていた、という点だけ知っていれば十分でしょう。

[訳者補足終わり]

システムをパッケージングするにあたって、ASDFの組み込みの属性に指定した情報に加えて、ファイルやシステムについての他の情報が必要になることはしばしばあります。ASDFシステムからベンダーのパッケージを作るプログラムは、これらのシステムを満たすために「プレースホルダ―」情報を作る必要があります。ASDFシステムを作る方は、その付加的な情報を直接読み書きすることがあるでしょう。

(component-property component property-name)setfのプレースとしても使用可能で、この情報を読み書きすることができます。property-nameの同一性はeqlで判定されるので、シンボルやキーワード等を使いましょう。