portability of *.elc (Re: APEL 問題、再燃?)

Shuhei KOBAYASHI shuhei @ aqua.ocn.ne.jp
1999年 11月 9日 (火) 11:59:29 JST


こばやしです. さっきのと関連するのでこれも.

>>>>> In <htxzowur09p.fsf @ mulelab3.etl.go.jp>,
>>>>> tomo @ etl.go.jp (守岡 知彦 /  MORIOKA Tomohiko) wrote:
> ただ、現実問題として、*.elc の互換性問題に関しては真摯に取り組むべき
> だと思っています。

これを徹底的に進めてもいいですか? ;-)

(1) APEL 上の application の *.elc の互換性に関する原則.
    APEL の制限によって APEL を利用する application の *.elc の互換性
    を制限してはいけない.

(2) APEL 自体の *.elc の互換性(の放棄;-))に関する原則.
    APEL の中でも VERSION_SPECIFIC_LISPDIR に install されるものにつ
    いては, static-* や *-maybe による compile 時の判定は既定の方針と
    して認める.

(1) は割と妥当に見えますね;-) (2) は既に合意されていると思います.

ただし, (2) については要請として,

  * XEmacs w/ Mule と w/o Mule では *.elc を共有できなければいけない.
    (XEmacs package の都合; 21.1 系と 21.2 系での共有も問題になる?)

  * 異なる OS 間で *.elc を共有できなければいけない.
    (NFS で site-lisp や home を共有する場合など)

というものがあります. 純粋に emacs の version に依るものだけを compile
時に判定するようにしなければなりません. (XEmacs 21.1/21.2 の事は未確認)

具体的には以下のような場合には compile 時の判定をしてはいけません.

;;; From modified poe.el:
(static-when (featurep 'xemacs)
  ;; must be load-time check to share .elc between w/ MULE and w/o MULE.
  (when (featurep 'mule)
    (provide 'file-coding)))

;;; From pces.el:
(eval-and-compile
  ;; must be load-time check to share .elc between different systems.
  (unless (fboundp 'open-network-stream)
    (require 'tcp)))

NTEmacs や Meadow などと Unix 系 OS とで *.elc を共有するのが現実的
ならば, convert-standard-filename なども compile 時に判定を行なって
はいけない事になります.


一方, (1) からは

  * version によって定義の異なるものは compile 時に展開してはいけない.

という制限が導き出されます.

例えば, enable-invisible などは現在は macro ですが, これは関数にする
べきです. (ところでなぜ enable- に対応するのが disable- ではないの?)

as-binary-* も version によって異なる定義に展開される macro なので,
application の *.elc の互換性を高めようとしたら用いるべきではありませ
ん. call-process-as-binary, start-process-as-binary などの関数を用意し,
それらによって置き換えられるべきです.

;;; From modified pces.el:
;; pces-* sub-module may provide better version of these functions.
(defun-maybe start-process-as-binary (name buffer program &rest args)
  "Like `start-process', q.v., but don't code conversion."
  (as-binary-process
   (apply (function start-process)
          name buffer program args)))


本質的に *.elc が非互換である場合に限り compile 時に展開しても良いので
はないかという話がありましたが, それでは *.elc の本質的な非互換性がどの
程度のものであるかを検討してみます.
各 Emacsen の bytecode.c や bytecomp.el を比較した結果です.

まず,

(a) 非 ASCII 文字の内部表現が各 Emacsen で異なる.

というのがありますが, これはどうしようもないので, 以下では非 ASCII
文字を含まない場合を仮定します.

(b) v19 で bytecode interpreter に多くの opcode が追加された.

これは FSF Emacs では compile 時に byte-compile-compatibility を non-
nil に設定する事で回避できます. (XEmacs の compiler にこの機能はない)

(c) Emacs 19.29/XEmacs 19.14 で dynamic docstring/function loading が
    導入された.

これは byte-compile-dynamic と byte-compile-dynamic-docstrings を nil
に設定する事で回避できます. なお, XEmacs-mule は dynamic function load
に未対応だそうです.

(d) Emacs 19.29 で keyboard の modifier bit が変更された.

Elisp manual によると, これらを含む場合には 19.28 以前と 19.29 以後で
*.elc の互換性はなくなるようです. (詳細は未確認)

(e) XEmacs 20 で eq, memq, equal, assq の bytecode が変更された.

新たな bytecode が割り当てられたのですが, 従来の bytecode も old_eq
などの形で残されています. byte-compile-emacs19-compatibility を t に
設定する事で v19 互換の *.elc を生成することもできます.

(f) v20 で save-current-buffer という special-form が builtin になり,
    v18 の Bread_char という bytecode を置き換える形で bytecode が割
    り当てられた.

XEmacs ではこれも byte-compile-emacs19-compatibility を t に設定する
と回避できます. XEmacs と同様の変更を compiler に加えると FSF 版でも
これは回避できるようになります.


まとめると, 非 ASCII 文字を含まない場合 (a) に問題になるのは (d) と,
(b) の XEmacs で compile した *.elc を v18 で load する場合, (f) の
v18 で compile した *.elc を v20 で load する場合だけです.

つまり, APEL の API では version に依存する定義を defmacro/defsubst
として提供する余地はほとんど残されていない事になります.

また, こうなると, 例えば FLIM や SEMI の場合に *.elc の互換性を阻害
している主要な原因は (a) の code-name だという事になります:-p

実際, 上に述べたように APEL の macro を関数に置き換えると, 19.34 で
compile した FLIM と SEMI(から code-name を除いたもの)を用いて 20.4
で Gnus を動かす事ができました.

-- 
Shuhei KOBAYASHI




More information about the APEL-ja mailing list