2010年2月13日土曜日

gccが誤ったコードを生成する(gcc 4.4.0)

最近Emacsが正しくビルドされないことがあり、少し原因を調べてみました。

gccに「-march=native -O3」オプションを渡して Emacs 23.1 をビルドすると make bootstrap が最後まで通りません。ビルドを通すためには、最適化レベルを落とすか、「-fno-tree-vectorize」オプションを加える必要があるようです(*)
*このオプションは@yunhさんから教えていただきました。

1.現象
make bootstapの最中に以下のコマンドが実行されたところでエラーダイアログが表示されます。
"./oo-spd/i386/temacs.exe" -batch -l loadup bootstrap




以下の環境でビルドしています。
OS:Windows 7 64bit
CPU: Core i7-860
ビルド環境:MinGW 5.1.6, MSYS 1.0.11, gcc 4.4.0 (mingw32)

2.解析(何がおきているのか?)
コマンドラインから上記のコマンドをたたくとエラーが再現できるので、gdbで様子を見てみました。gdbはMinGWのサイトからダウンロードした gdb-7.0.50.20100202-mingw32-bin.tar.gz を使っています。

C:\work\emacs-23.1\nt>mingw32-make.exe ARCH_CFLAGS="-c -mno-cygwin -march=native -O3" bootstrap

(中略)

echo oo-spd/i386/w32font.o oo-spd/i386/w32uniscribe.o >> oo-spd/i386/buildobj.lst
mingw32-make.exe[2]: Leaving directory `D:/temp/work/emacs-23.1/src'
"./oo-spd/i386/temacs.exe" -batch -l loadup bootstrap
mingw32-make.exe[1]: *** [bootstrap-emacs] Error 255
mingw32-make.exe[1]: Leaving directory `D:/temp/work/emacs-23.1/src'
mingw32-make.exe: *** [bootstrap-gmake] Error 2

エラーが発生したコマンドをgdb上で走らせてみます。
C:\work\emacs-23.1\nt>cd ..\src

C:\work\emacs-23.1\src>gdb .\oo-spd\i386\temacs.exe
GNU gdb (GDB) 7.0.50.20100202
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
...
Reading symbols from C:\work\emacs-23.1\src/.\oo-spd\i386\temacs.exe...done.
SIGINT is used by the debugger.
Are you sure you want to change it? (y or n) [answered Y; input not from terminal]
Environment variable "DISPLAY" not defined.
Environment variable "TERM" not defined.
Temporary breakpoint 1 at 0x10af525
(gdb) run -batch -l loadup bootstrap
Starting program: C:\work\emacs-23.1\src/.\oo-spd\i386\temacs.exe -batch -l loadup bootstrap
[New Thread 5208.0xa08]
Error: dll starting at 0x77630000 not found.
Error: dll starting at 0x76bf0000 not found.
Error: dll starting at 0x77630000 not found.
Error: dll starting at 0x77530000 not found.

Program received signal SIGSEGV, Segmentation fault.
0x010c6b52 in init_charset_once ()
(gdb) bt
#0  0x010c6b52 in init_charset_once ()
#1  0x01002ebf in main ()

Segmentation faultで落ちました。バックトレースすると main() から呼ばれた init_charset_once() の中で落ちているようです。
次に落ちている箇所のアセンブラコードとレジスタの状態を見てみることにします。
(gdb) disass
Dump of assembler code for function init_charset_once:
   0x010c6b30 <+0>:     push   %ebp
   0x010c6b31 <+1>:     mov    $0x16eedf8,%eax
   0x010c6b36 <+6>:     mov    %esp,%ebp
   0x010c6b38 <+8>:     push   %edi
   0x010c6b39 <+9>:     push   %esi
   0x010c6b3a <+10>:    push   %ebx
   0x010c6b3b <+11>:    sub    $0xc,%esp
   0x010c6b3e <+14>:    movdqa 0x16a4c30,%xmm0
   0x010c6b46 <+22>:    lea    0x400(%eax),%ecx
   0x010c6b4c <+28>:    lea    0x200(%eax),%edx
=> 0x010c6b52 <+34>:    movdqa %xmm0,(%eax)
   0x010c6b56 <+38>:    add    $0x10,%eax
   0x010c6b59 <+41>:    cmp    %edx,%eax

(中略)

   0x010c6f29 <+1017>:  lea    0x0(%esi,%eiz,1),%esi
End of assembler dump.

(gdb) info registers
eax            0x16eedf8        24047096
ecx            0x16ef1f8        24048120
edx            0x16eeff8        24047608
ebx            0x5      5
esp            0x88fe90 0x88fe90
ebp            0x88fea8 0x88fea8
esi            0x0      0
edi            0x1      1
eip            0x10c6b52        0x10c6b52
eflags         0x10206  [ PF IF RF ]
cs             0x23     35
ss             0x2b     43
ds             0x2b     43
es             0x2b     43
fs             0x53     83
gs             0x2b     43

(gdb)

 落ちた箇所は「0x010c6b52 <+34>:    movdqa %xmm0,(%eax)」で、このときの eaxレジスタの中身は「0x16eedf8(24047096)」です。

3.問題点
このmovdqa命令ですが、調べたところ128bit単位でmovするSSE2命令らしく、使用条件として「転送元/先のアドレスが16byte(128bit)でアラインメント」されている必要があります。

今回の場合は 0x16eedf8(24047096) なので16で割ると...割り切れません。正しくアラインメントされたアドレスを使っていないようです。。。

問題が発生したオプションは「-march=native -O3」でした。僕の環境では -march=native は以下の様に解釈されているようです。(CPUはCore i7-860)
-march=core2 -mcx16 -msahf --param l1-cache-size=32 --param l1-cache-line-size=64 --param l2-cache-size=256 -mtune=core2

#ここから色々推測が入ります
最適化レベルを-O2から-O3にすると、暗黙的に-ftree-vectorizeが指定されるようです。どうもこのオプションが有効になることで(-march=core2なので)SSEを使った最適化がされるようですが、アラインメントをミスったコードを生成してしまっているようです。このオプションが悪いわけではなく、gccが正しくアラインメントされたメモリアドレスを扱うコードを生成するべきでしょう。gccのバグっぽいです。

4.回避策
core2に特化したコード生成を行う場合で-O3以上の最適化レベルを指定する場合は「-fno-tree-vectorize」オプションを加えて逃げるというworkaroundをとるしかない(と思います)。新しいgccではもしかするとバグが修正されているかもしれません。


最後に、本件を調査する際に参考になったリンクをあげておきます。

最近はgdbを使ったり、SSE命令など調べたことがなかったので勉強になりました:)

2010年2月9日火曜日

Emacs Scratchバッファの自動保存とリストア

1年ほど前にどこかのサイトで発見して、ありがたく使わせていただいているのが「Scratchバッファの自動保存とリストア」をするためElisp。Emacs終了時に自動的にScratchバッファの内容を保存して、次回起動時に復元してくれる。
;;; auto save and restore scratch buffer
(defun save-scratch-data ()
  (let ((str (progn
               (set-buffer (get-buffer "*scratch*"))
               (buffer-substring-no-properties
                (point-min) (point-max))))
        (file "~/.scratch"))
    (if (get-file-buffer (expand-file-name file))
        (setq buf (get-file-buffer (expand-file-name file)))
      (setq buf (find-file-noselect file)))
    (set-buffer buf)
    (erase-buffer)
    (insert str)
    (save-buffer)
    (kill-buffer buf)))

(defadvice save-buffers-kill-emacs
  (before save-scratch-buffer activate)
  (save-scratch-data))

(defun read-scratch-data ()
  (let ((file "~/.scratch"))
    (when (file-exists-p file)
      (set-buffer (get-buffer "*scratch*"))
      (erase-buffer)
      (insert-file-contents file))
    ))

(read-scratch-data)
これを .emacs に記述して長い間使ってる。かなり便利で、即席のメモ帳として使える。どこのサイトでオリジナルを見つけたのか今となってはわからないのだが、、、ありがとうございます>作者の方。

#僕はEmacs Lisp初心者で勉強中。

2010年1月28日木曜日

Emacs (NTEmacs) 23.1 フォント設定

昨年MeadowからEmacs 23.1に移行して唯一つまずいたのがフォント設定。ぜんぜん意図したとおりの設定ができないんだなこれが。フォントの設定は素人なので、深く追求もできないし。

ASCIIは Consolas フォント を使い、日本語は メイリオ フォント を使いたかった。
しかし「欧文フォントと日本語のフォントでは高さが違う」問題を解決できずに結局メイリオを断念することにした。以下のサイトを見れば解決できそうではあるが、.emacsファイル 以外をいじるのは僕のポリシー?(*)に反するので当面様子をみることにする。
*Emacsの設定やソースをいじるのはOK、Emacs以外の環境設定で回避するのはNG
比較的簡単な解決方法は、Consolasとメイリオフォントを合成したフォントを作ることだと思う。どうぞ、どなたかお試しくだされ。

結局僕がいきついたところは、日本語に MSゴシック を使うことだった。これがまた簡単な設定でいける。Consolasにはアンチエイリアスがかかって、MSゴシックにはかかっていないようだが、慣れれば違和感ない。

 ;;; 標準フォント
(set-default-font "Consolas 11")

(set-fontset-font (frame-parameter nil 'font)
                  'japanese-jisx0208
                  '("MS ゴシック" . "unicode-bmp")
                  )

(set-fontset-font (frame-parameter nil 'font)
                  'katakana-jisx0201
                  '("MS ゴシック" . "unicode-bmp")
                  )

この設定を .emacs に書けば以下の用に表示される。
(見やすくするために背景色などかえています)





もっとEmacs(NTEmacs)ユーザ増えてくれないかなぁと思って比較的簡単だと思われるフォント設定をさらしてみた。

Emacs (NTEmacs) 23.1 on Windows 7 でタスクバーにEmacsアイコンを複数表示させない方法

文章を書き慣れていない=文章力が無いようで、昨年書いた記事(つーか、メモ)は微妙だった気がする。タイトルも曖昧で、内容もだらだら感がある。まぁ手順を書いている文章の場合はしかたない場合もあるけれど。今年はそこを直していければと思うこの頃。

Emacs (NTEmacs) 23.1 をWindows 7上で少し快適に使う - Part.1
Emacs (NTEmacs) 23.1 をWindows 7上で少し快適に使う - Part.2」で説明したかったことは、「Windows 7 でタスクバーにEmacsアイコンを複数表示させない方法」だった。また、技術的な観点で言うと「ショートカットファイルに “GNU.Emacs” AppID を埋め込む方法」とも言えるだろう。

いやいや後者をもっと大きな観点で言えば 「ショートカットファイルに任意の AppID を埋め込む方法」か。

文章わかりにくいな~と気になっていたので少し補足を書いてみた。後者の言い方は@yunhさんが言ってたんだけどね。そこで、俺のタイトル&文章わかりにくいな。。。と思った次第であります。
わかりやすい文章を書くって難しいね。

2009年12月16日水曜日

Emacs (NTEmacs) 23.1 をWindows 7上で少し快適に使う - Part.2

さてPart.1「パッチを当てたEmacsをWindows上でコンパイルする」の続きを説明する。前回も述べたが、今回説明する「少し快適に使うためのセッティング」が少しの快適をWindows 7上で動作するEmacsにもたらすのだ、だからこっちの説明が重要。

さて、説明に入る前に前回コンパイルして出来たバイナリと、パッチの当たったソースファイルをダウンロード出来るようにしておいた。コンパイラの最適化オプションなどに興味のない人などはこのバイナリファイルをダウンロードすれば前回の手順をスキップできる。
(2010/03/12:配布用に一部コードを修正中。バイナリはしばらくお待ちください。)
(2010/03/14:再アップロードしました。)
    2. 少し快適に使うためのセッティング
    それでは本題に入ろう。前回、”少し快適”とは「Windows 7で導入された新しいタスクバーに対応すること」と一言で説明した。Windows 7ではまるでMac OS XのDockに似た、そして、さらにそれを使いやすくしたらしい今までとは全く異なる新しいタスクバーが導入されている。その中でもまず目につくのが、タスクバーにアプリケーションをピン留めすることができ(よく使うアプリケーションなどをタスクバーに登録することが出来る)、アプリケーションが起動中でも昔のようにタスクバーにアイコンが増えていくのではなく、ピン留めされたアイコンが変化する動作だ。
    詳しい説明は「Microsoft、Windows 7のタスクバーを解説 (ITmedia)」などを参照してほしい。

    さて前回ビルドしたEmacsでこの機能を使おうとすると以下の現象が発生する。

    まず runemacs.exe でEmacsを起動すると以下のようにタスクバーにEmacsアイコンが出現し、起動していることを示す。




    次回からEmacsをサクッと起動しようとピン留めしてみる(タスクバーに登録する)。Emacsアイコンを右クリックして、「タスクバーにこのプログラムを表示する」を選択。









    そしてEmacsを終了すると、タスクバーは以下の状態になる。




    ここまでは期待通りの動作をしている。そしてこのアイコンをクリックして再度Emacsを起動すると、、、
    ←2つEmacsが起動しているように表示され


    かつ、意味のないコマンドプロンプトが起動してしまいます。もうここまでくると、(NT)Emacsに詳しい方はお気づきかとは思いますが、タスクバーに登録されたアプリケーションは runemacs.exe ではなく、 emacs.exe なのです。
    そして emacs.exe は元々Windowsアプリケーションではなく、コンソールアプリケーションだからこうなってしまう。runemacs.exe はコンソールアプリケーションのEmacsをWindowsアプリケーションのように起動するためのアプリケーション(コマンドプロンプトが出ない)なのです。

    じゃあ、runemacs.exe をタスクバーに登録すればいいじゃんということになりますね。さっそく登録してみます。(その前に、タスクバーにある emacs.exe への登録は消しましょう、ややこしくなるので。右クリックして「タスクバーにこのプログラムを表示しない」でできます。)
    エクスプローラーから runemacs.exe を選択し右クリック、「タスクバーに表示する」で登録されます。














    そして、タスクバーのアイコンをクリックしてEmacsを起動してみましょう。すると、、、

    ←何か別に表示されてる



    せっかくのタスクバーの新機能がいかされず、起動アイコンと起動中アイコンが別々に表示されるという悲しい現象が発生します。

    これが今回私が訴えたかった快適ではなくなっている問題です。
    bug#1849 - Windows 7 Taskbar Support で指摘されていることもこれに関連することです。では、なぜこんなことが起きてしまうのか簡単に説明すると、Windows 7からはアプリケーションにアプリケーション ユーザー モデル ID (AppID)という識別子が導入されました。このIDが同じであると上記の問題は発生せずに1つのアイコンで表示されます。上記の例では、runemacs.exe を右クリックして登録した際にシステムが(暗黙に)定義したAppIDと emacs.exe が持っているAppIDが違うことにより発生しています、と推測しています。
    アプリケーションが明示的にAppIDを定義しないと、システムがある一定の法則にのっとって勝手にAppIDを作るようです。ちなみに、前回Emacsをコンパイルする際にこの問題に対応するEmacsのMAINブランチに入ったパッチを適用しました。そのコードによれば、Emacsは ”GNU.Emacs” というAppIDを明示的に定義しているようです。runemacs.exe や emacs.exe はこのAppIDをシステムに宣言しています。
    では、なぜ問題が発生するのか?ここからは推測ですが、まず、runemacs.exe を右クリックしてタスクバーに登録した場合は runemacs.exe が実行された際にシステムに宣言される "GNU.Emacs" AppIDが、このオペレーションでは適用されないということ。おそらくAppIDのない状態又はシステムが定義したAppIDでタスクバーに登録されているのでしょう。そして、次に runemacs.exe は emacs.exe を呼び出してすぐに終了してしまうために、runemacs.exe を実行してもタスクバーには runemacs.exe のプログラムが表示されず、結果的にユーザに右クリックして「タスクバーにこのプログラムを表示する」を選択する猶予を与えないためでしょう。
    もし、runemacs.exe がすぐに終了しないアプリケーションであれば、内部で "GNU.Emacs" AppIDを定義しているのでタスクバーにアイコンが表示されていれば、タスクバーに "GNU.Emacs" AppID をもったアプリと登録することができ、期待通りの動作をするはずです。(期待通りの動作="GNU.Emacs" AppIDをもった runemacs.exe をタスクバーに登録でき、かつそのアイコンで起動すると emacs.exe はそのアイコン上で起動中と表示されること)


    さて、ここまでは問題となる現象の説明であり「少し快適になる=この問題をなくす」セッティングの説明に入れていませんでした。さっそく(やっと?)、2. 少し快適に使うためのセッティングに入ります。

    MSDNのサイトをいろいろ調べたところ、ショートカットにAppIDを持たせることが出来ると判明。ということは runemacs.exe のショートカットを作って、そのショートカットに "GNU.Emacs" AppID を入れて、タスクバーに登録すればうまくいくんじゃね?という結論に至った。で、実際にごにょごにょすると確かに期待通りの動作が出来た!
    しかーし、ここで少し時間を食ってしまった。なぜならばショートカットに好きなAppIDを持たせる簡単な方法を見つけることが出来なかったため、自前でWindows アプリケーションを作るはめになったからである。まぁ、たいしたコード量じゃないんだが。

    では、まず次のアプリケーションをダウンロードして欲しい。
    「Shortcut AppID Changer by 俺 (ダウンロード先→ShortcutAppIDChanger.zip)」
    このアプリケーションはWindows 7上で動くもので、ショートカットに好きなAppIDを設定することができる。

    さてダウンロードが終わったら手順の説明に入る。
    1. runemacs.exeのショートカットを作る。
    Emacsのインストールフォルダのbinにある runemacs.exe を右クリックし、ショートカットの作成を選択する。すると、同じディレクトリにショートカットが出来るはずだ。

    2. ショートカットの名前を変える。
    これは飛ばしてもいい手順だが、、最終的にこのショートカットをタスクバーに登録すると、(右クリックで表示される)登録された名前はこのショートカットのファイル名となる。手順1で作ったショートカットファイルの名前はおそらく「runemacs.exe - ショートカット」となっているので、これを「emacs」とでも変えておこう。

    3. ショートカットにAppIDを埋め込む
    さて重要なステップにきた。作成したショートカットファイルに "GNU.Emacs" AppID を埋め込む。まず、ShortcutAppIDChanger.exe を起動して欲しい。すると以下のウィンドウが現れるはずだ。
    このウィンドウに先ほど作成したショートカットをドラッグ&ドロップする。すると、「Loaded file name: None」と表示されていたところが、作成したショートカットファイルの名前を表示するようになる。こうなれば、このアプリケーションは正しくショートカットファイルを認識している。
    そして次に、「PKEY_AppUserModel_ID 」と表示されている枠内にあるテキストボックスに設定するAppIDを入力する。今回はもちろん GNU.Emacs だ。以下のような表示になればOK。Loaded file nameのところは皆さんの環境によって違うだろう。
     
     そして、Saveボタンを押す。新しく保存してもよいし、読み込んだショートカットに上書き保存してもよい。保存したら "GNU.Emacs" AppID を持ったショートカットのできあがりである。このアプリケーションはExitボタンでも押して終了する。

    4. AppIDをもったショートカットをタスクバーに登録する
    前述の手順で作成したショートカットファイルを右クリックし、「タスクバーに表示する」を選択する。するとタスクバーにEmacsアイコンが現れる。

    以上で少し快適に使うセッティングは終了だ。
    タスクバーにあるEmacsアイコンをクリックしてEmacsを起動して欲しい。うまくいけば以下のように表示されるはずだ。
    そして、タスクバーはこの状態であり、コマンドプロンプトは表示されていないはずだ。

    これが今回説明したかった EmacsをWindows 7上で少し快適に使う方法 である。
    小さなことかもしれないが、Windows 7の新しいタスクバーに慣れてしまった僕にとっては、頻繁に使うEmacsはタスクバーに登録して使いたかったのだ!!
    へんてこりんな動作無しでね。

    さて、Emacsのブランチに入った変更は runemacs.exe / emacs.exe / emacsclientw.exe にAppIDを設定するコードを埋め込んだこと。今回のような問題はどう対処するのであろうか?それとも私が何か勘違いしているのだろうか?emacsclientを使うとまた違ってくるとか??
    もし、何かご存じの方がいらっしゃれば是非教えていただきたいm(_ _)m

    まぁ、いまのところ期待通りの動作をしているので個人的には満足している。
    次回は、「コンパイラに渡す最適化パラメータについて」又は「.emacsと最低限設定すべき環境変数」について何か書きたいと思っている。

    「Emacs (NTEmacs) 23.1 をWindows 7上で少し快適に使う」はPart.2でとりあえず完!
    では、また次回!!

    Emacs (NTEmacs) 23.1 をWindows 7上で少し快適に使う - Part.1

    Emacs 23.1 をWindows 7上で少し快適に使う方法を書いてみた。なにが少し快適なのかは一言で言えば「Windows 7で導入された新しいタスクバーに対応すること(詳細はPart2を参照)」である。
    ここでの説明は2つのステップに分かれている。
    1. パッチを当てたEmacsをWindows上でコンパイルする
    2. 少し快適に使うためのセッティング
    1.パッチを当てたEmacsをWindows上でコンパイルする
    基本的な手順はWindows 上での Emacs コンパイル - とりぷる ぷぅで親切に解説されている。様々な方法でコンパイルしてみたが、このサイトで書かれている手順が比較的容易でわかりやすいのでおすすめである。ここでは、このサイトの手順をベースに説明しよう。

    コンパイル環境は、XP Mode on Windows 7である。すなわちXP SP3環境。

    まず最初に必要ファイルをダウンロードする。
    1. Emacs 23.1 のソースファイルを本家サイトからダウンロード (emacs-23.1.tar.gz)
    2. Automated MinGW Installer (from Minimalist GNU for Windows) をダウンロード (MinGW-5.1.6.exe)
    3. MSYS Base System (from Minimalist GNU for Windows) をダウンロード (MSYS-1.0.11.exe)
    4. 画像表示のためにライブラリを GnuWin32 Packages からダウンロード
     (Xpm, LibPng, Zlib, LibUnGif, LibJpeg, LibTiff)
     実際にダウンロードしたファイルは以下である。
     (xpm-3.5.1-1.exe, xpm-3.5.1-1-src.exe, libpng-1.2.37-setup.exe, zlib-1.2.3.exe, libungif-4.1.4-1.exe, jpeg-6b-4.exe, tiff-3.8.2-1.exe)
     xpmについてsrcが必要になる理由は上記のサイトで解説されているように、「simx.hが必要であるためであり、simx.hはsrcに含まれているから」である。

    さて次に、2つのパッチをダウンロードする。
    5. NTEmacs JP Projectから日本語入力を利便性を向上するパッチをダウンロード (Emacs-23.1-IME.patch)
     このパッチがないと日本語のインライン入力などが出来なくて不便。
    6. 私のサイトからWindows 7用のパッチをダウンロード (win7appid.patch)
     このパッチは bug#1849 - Windows 7 Taskbar Support で指摘されたもので、詳細はこのリンクの文章を読んで欲しい。すでに対応はMAINブランチ上にあるが、Emacs 23.1 には取り込まれなかったので、私がこのBugに関連する修正だけを最新のソースツリーから取り出してパッチにしたものである。Jason Rumneyさんが対応されている。Thanks!!
    修正が入るファイルは、w32term.c, runemacs.c, emacsclient.c であり、コミット時のコメントは以下の通り。

    bug#1849 - Windows 7 Taskbar Support

    * w32term.c (w32_initialize): Use GetModuleHandle for library that is already loaded.
    Set user model ID if supported (bug#1849).

    * runemacs.c (set_user_model_id): New function.
    (WinMain): Use it.

    * emacsclient.c (w32_give_focus): Use GetModuleHandle for library that is already loaded.
    (w32_set_user_model_id): New function.
    (main): Use it to associate emacsclient with emacs (bug#1849).
    以上で、コンパイルするのに必要なファイルは全部そろった。

    次にMinGWなどのインストール手順を簡単に述べよう。
    1. MinGWはDownload & Installを選択し、Choose PackageはCurrent、Choose componentsはFullでインストールする。
    2. MSYS Base Systemは最後のPostステップでは、すべてYを選択し、MinGWのインストール先は、前述のMinGWインストール先をデフォルトでインストールしていれば、C:\MinGW」を入力してインストールする。
    3.  画像表示のためにライブラリ群をすべてインストールする。ここでの注意点はインストール先をMinGWのインストール先にすることである。つまり、MinGWのインストール先をデフォルトでインストールしていれば「C:\MinGW」をライブラリ群のインストール先として入力しなければならない。
     そして最後に、 (C:\)MinGW\src\xpm\3.5.1\libXpm-3.5.1-src\libにある simx.h を (C:\)MinGW\includeにコピーする。

    以上でEmacsのコンパイル環境は整った。

    さて、やっとコンパイルである。ここからは C:\work というフォルダにEmacsのソースと2つのパッチ (emacs-23.1.tar.gz, Emacs-23.1-IME.patch.gz, win7appid.patch) があると仮定して手順を説明する。
    1. スタートメニューからコマンドプロンプトの起動
    2. 以下のコマンドでカレントディレクトリを変更し、Cygwinなど他の実行ファイルが参照されないようにPATHを限定する。
    Microsoft Windows XP [Version 5.1.2600]
    (C) Copyright 1985-2001 Microsoft Corp.

    C:\Documents and Settings\XPMUser>cd c:\work

    C:\work>set PATH=C:\MinGW\bin;C:\msys\1.0\bin;C:\WINDOWS\system32
    3. EmacsのソースとIMEパッチの解凍を行う。
    C:\work>tar xvf emacs-23.1.tar.gz
    (中略)
    emacs-23.1/nextstep/AUTHORS
    emacs-23.1/nextstep/ChangeLog
    emacs-23.1/nextstep/DEV-NOTES
    emacs-23.1/nextstep/FOR-RELEASE
    emacs-23.1/nextstep/README
    emacs-23.1/nextstep/INSTALL
    emacs-23.1/COPYING

    C:\work>gzip -d Emacs-23.1-IME.patch.gz
    4. 2つのパッチを適用する。
    ここでそのままIMEパッチを適用してしまうと、emacs-23.1/nt/configure.bat への適用に失敗してしまう。これはconfigure.batの改行コードがCR+LFであるが、パッチの方はLFとなっているためである。そのために、configure.batの改行コードをLFにする必要がある。
    C:\work>bash
    bash-3.1$ tr -d "\r" < ./emacs-23.1/nt/configure.bat > configure.bat
    bash-3.1$ exit
    exit

    C:\work>mv configure.bat .\emacs-23.1\nt\configure.bat
    以上で configure.bat の改行コードはLF形式に変換された。さっそくパッチを適用する。
    C:\work>cd emacs-23.1

    C:\work\emacs-23.1>patch -p3 < ..\Emacs-23.1-IME.patch
    patching file lib-src/makefile.w32-in
    patching file lisp/loadup.el
    patching file nt/configure.bat
    patching file src/keyboard.c
    patching file src/w32.c
    patching file src/w32fns.c
    patching file src/w32term.c
    patching file src/w32term.h
    patching file src/window.c
    patching file lisp/international/w32-ime.el

    C:\work\emacs-23.1>patch -p1 < ..\win7appid.patch
    patching file lib-src/emacsclient.c
    patching file nt/runemacs.c
    patching file src/w32term.c
    Hunk #2 succeeded at 6395 (offset 55 lines).
    Hunk #4 succeeded at 6477 (offset 55 lines).
    5. パッチの適用は完了したので、Makefileの生成を行う。
    まずは configure.bat を実行し Makefile を生成する。なお、ここではインストール先として c:\work\emacs_bin を指定することとする。
    C:\work\emacs-23.1>cd nt

    C:\work\emacs-23.1\nt>configure.bat --with-gcc --no-cygwin --enable-w32-ime --cflags -D_UNICODE --cflags -DRECONVERSION --prefix c:/work/emacs_bin
    Checking for 'cp'...
    Checking for 'rm'...
    Checking for Windows Version ...
    Checking whether W32 API headers are too old...

    C:\work\emacs-23.1\nt>gcc -D_UNICODE -DRECONVERSION -DWINVER=0x0501 -mno-cygwin
    -c junk.c
    Using 'gcc'
    Checking for libpng...
    ...PNG header available, building with PNG support.
    Checking for jpeg-6b...
    ...JPEG header available, building with JPEG support.
    Checking for libgif...
    ...GIF header available, building with GIF support.
    Checking for tiff...
    ...TIFF header available, building with TIFF support.
    Checking for libXpm...
    ...XPM header available, building with XPM support.
    checking for RECONVERTSTRING...
    ...RECONVERTSTRING is defined.
    Generating makefiles
            1 個のファイルをコピーしました。
            1 個のファイルをコピーしました。
            1 個のファイルをコピーしました。

    (中略)

    config.settings
    gmake.defs
    ..\leim\makefile.w32-in
            1 個のファイルをコピーしました。
            1 個のファイルをコピーしました。

    Emacs successfully configured.
    Run `make' to build, then run `make install' to install.
    上記のような表示がでればOK。
    なお、当然であるが configure.bat の行は prefix指定まで 一行である。注意して欲しい。

    6. そしてコンパイル。
    この環境ではmakeコマンドは、make.exe ではなく mingw32-make.exe であることに注意すること。以下の例ではボールドの文字が実行しているコマンドである。
    C:\work\emacs-23.1\nt>mingw32-make.exe bootstrap
    [Please ignore a syntax error on the next line - it is intentional]
    /usr/bin/sh: -c: line 0: unexpected EOF while looking for matching `"'
    /usr/bin/sh: -c: line 1: syntax error: unexpected end of file

    (中略)

    Checking c:/work/emacs-23.1/leim/quail/4Corner.el ...
    Saving file c:/work/emacs-23.1/leim/leim-list.el...
    Wrote c:/work/emacs-23.1/leim/leim-list.el
    Updating c:/work/emacs-23.1/leim/leim-list.el ... done
    "./../src/oo-spd/i386/emacs.exe" -batch --no-init-file --no-site-file --multibyt
    e --eval '(w32-append-code-lines "leim-list.el" "./leim-ext.el")'
    Saving file c:/work/emacs-23.1/leim/leim-list.el...
    Wrote c:/work/emacs-23.1/leim/leim-list.el
    mingw32-make.exe[2]: Leaving directory `C:/work/emacs-23.1/leim'
    mingw32-make.exe[1]: Leaving directory `C:/work/emacs-23.1/nt'

    C:\work\emacs-23.1\nt>mingw32-make.exe info
    [Please ignore a syntax error on the next line - it is intentional]
    /usr/bin/sh: -c: line 0: unexpected EOF while looking for matching `"'
    /usr/bin/sh: -c: line 1: syntax error: unexpected end of file

    (中略)

    mingw32-make.exe[1]: Entering directory `C:/work/emacs-23.1/doc/lispintro'
    mingw32-make.exe[1]: Nothing to be done for `info'.
    mingw32-make.exe[1]: Leaving directory `C:/work/emacs-23.1/doc/lispintro'

    C:\work\emacs-23.1\nt>mingw32-make.exe
    [Please ignore a syntax error on the next line - it is intentional]
    /usr/bin/sh: -c: line 0: unexpected EOF while looking for matching `"'
    /usr/bin/sh: -c: line 1: syntax error: unexpected end of file

    (中略)

    mingw32-make.exe   -C ../leim all
    [Please ignore a syntax error on the next line - it is intentional]
    /usr/bin/sh: -c: line 0: unexpected EOF while looking for matching `"'
    /usr/bin/sh: -c: line 1: syntax error: unexpected end of file
    mingw32-make.exe[1]: Entering directory `C:/work/emacs-23.1/leim'
    mingw32-make.exe[1]: Nothing to be done for `all'.
    mingw32-make.exe[1]: Leaving directory `C:/work/emacs-23.1/leim'
    7. インストールを行う。
    インストール先は configure.bat の --prefix で指定した場所である。この例では c:\work\emacs_bin がインストール先となる。
    C:\work\emacs-23.1\nt>mingw32-make.exe install
    [Please ignore a syntax error on the next line - it is intentional]
    /usr/bin/sh: -c: line 0: unexpected EOF while looking for matching `"'
    /usr/bin/sh: -c: line 1: syntax error: unexpected end of file

    (中略)

    mkdir "c:/work/emacs_bin/info"
    mkdir "c:/work/emacs_bin/lock"
    mkdir "c:/work/emacs_bin/data"
    mkdir "c:/work/emacs_bin/site-lisp"
    mkdir "c:/work/emacs_bin/etc/icons"
    if [ ! -s ../same-dir.tst ] ; then cp -f ../site-lisp/subdirs.el c:/work/emacs_b
    in/site-lisp ; fi
    if [ ! -s ../same-dir.tst ] ; then cp -rf ../etc c:/work/emacs_bin ; fi
    cp -rf icons c:/work/emacs_bin/etc
    if [ ! -s ../same-dir.tst ] ; then cp -rf ../info c:/work/emacs_bin ; fi
    if [ ! -s ../same-dir.tst ] ; then cp -f ../COPYING c:/work/emacs_bin ; fi
    cp -f ../COPYING c:/work/emacs_bin/bin
    rm ../same-dir.tst
    rm: cannot lstat `../same-dir.tst': No such file or directory
    mingw32-make.exe: [install] Error 1 (ignored)
    rm c:/work/emacs_bin/same-dir.tst
    8. 最後に画像表示に必要なDLL群をコピーする。
    前述までのステップで C:\work\emacs_bin\bin\runemacs.exe を実行すると Emacs は起動するが、以下のように画像が表示されない状態となる。(XP Mode内で実行した例)
    画像を表示するためには必要なDLLはすべて C:\MinGW\bin にあり、C:\work\emacs_bin\bin フォルダーにコピーしなければならない。今回コピーするDLLは次の9個である。
    jpeg62.dll libimage.dll libpng3.dll libpng12.dll libpng13.dll libtiff3.dll libungif4.dll xpm4.dll zlib1.dll
    なお、libimage.dll や libpng3/12/13.dll のどれかは必要ないかもしれない。しかし、私はどれが必要ないのか判断できなかったためにすべてコピーすることにした。
    必要のないDLLをご存じの方は是非教えていただきたいm(_ _)m

    DLLをコピーした後に実行すると以下のように画像が表示される。


    さて、以上で1つの目のステップである「パッチを当てたEmacsをWindows上でコンパイルする」が終わった。お疲れ様です。

    さて、次に説明する2つ目のステップ「少し快適に使うためのセッティング」が今回の重要な”少し快適”を実現するポイントなのだが、次回に説明することとする。(ちょっと疲れたので別の日に書くw)

    ちなみに、今回のビルドはXP Mode上で行ったので、ゲストOSのXPからホストOSのWindows 7に、生成したバイナリをコピーしなければならない。XP Mode上ではホストのドライブが \\tsclient\C (最後がドライブレター) で見えるので、C:\work\emacs_bin フォルダーをホストのお好みの場所にコピーする。
    そして、runemacs.exe を実行すると以下のように起動するだろう。

    では、また次回!

    Emacs (NTEmacs) 23.1 をWindows 7上で少し快適に使う - Part.2」(続き)