koron / vim-kaoriya

Vim+kaoriya build system

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

配布物にdiff.exeを同梱してほしい

lamsh opened this issue · comments

現在配布されているvim74-kaoriya-win64-20160409.zipには,差分コマンドであるdiff.exeが含まれていません。そのため,:diffsplitコマンド任意のファイルの差分を表示させようとすると,以下のエラーメッセージが表示され,差分表示ができません

E97: 差分を作成できません

よろしければ,diff.exeの同梱を検討していただけませんでしょうか?理由は以下5点です。

  1. Windows版の公式の配布物(self-installing)にはdiff.exeが同梱されている。
  2. Windows版の公式の配布物で配布されているバイナリーファイルの閲覧で使用するxxd.exeはkaoriya版でも同梱されているにも関わらず,diff.exeは同梱されていないので,同梱物の方針が不整合となっている。
  3. 公式が提供する配布物を同梱しておくことで,公式との互換性を向上させられる。
  4. Windows標準の差分ツールfc.exeではvimdiffで使われるed形式を用意するのが困難。
  5. (私事で恐縮ですが)Vimで差分表示の機能を有効にするためだけに,diff.exeのインストールの許可を職場でもらうのはしのびないので,標準で同梱してもらえると同じような状況の人も助かるはず。

個人的な要望で恐縮ですが,よろしければご検討お願いします。

気持ちはわかります。
しかし良い diff が無くて放置している & だいたい msys2 を入れちゃうから困ってないという感じです。

@k-takata 公式配布物の diff.exe ってどこの使ってるんでしたっけ?

しかし良いdiff が無くて放置している & だいたい msys2 を入れちゃうから困ってないという感じです。

まあ,あんまり需要ありませんよねー。

ご参考までに,手元で確認してみましたが,公式に同梱されているdiff.exeはGNU diffutilsのもののようです。

C:\Users\senooken>where diff
C:\Program Files (x86)\vim\vim74\diff.exe

C:\Users\senooken>diff --version
diff - GNU diffutils version 2.7

参考リンク: vim-jp/issues#723

あと、:help E810 には以下のように書かれています。

The self-installing Vim for MS-Windows includes a diff program. If you don't
have it you might want to download a diff.exe. For example from
http://gnuwin32.sourceforge.net/packages/diffutils.htm.

The self-installing Vim for MS-Windows includes a diff program. If you don't
have it you might want to download a diff.exe. For example from
http://gnuwin32.sourceforge.net/packages/diffutils.htm.

上記URLから,BinariesとDependenciesをDLして解凍。その後,Dependenciesのlibiconv2.dlllibintl3.dllをBinariesのdiff.exeと同じ場所に配置すれば,Windows 10でもdiff.exeは実行できました。

ただ,公式の同梱物と違う箇所が5点ほどありました。

  1. diff.exeのバージョンが違う(公式:2.7,gnuwin32:2.8.7)
  2. dllの名前が違う(公式:libintl.dll,gnuwin32:libintl3.dll)
  3. 公式にはlibiconv2.dllは同梱されていないがdiff.exeは動作していた。
  4. diff.exeのファイルサイズが異なる(公式:67 KB,gnuwi32:147 KB)。
  5. gnuwin32ではdiff.exeの--versionオプションのメッセージが長い。
Y:\diffutils-2.8.7-1-bin\bin>diff.exe --version
diff (GNU diffutils) 2.8.7
Written by Paul Eggert, Mike Haertel, David Hayes,
Richard Stallman, and Len Tower.

Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

公式ではVimにdiff.exeを同梱するにあたって,不要な内容を削除するなど,改変していたのかもしれません。

gnuwin32のdiff.exelibiconv2.dlllibintl3.dllの3ファイルをkaoriyaのgvim.exeと同じ場所に配置すれば,:diffsplitがうまく実行できました。

gnuwin32のソースやコンパイルオプションを修正して,もともとkaoriya版に同梱されているiconv.dllintl.dllの関数を使うようにdiff.exeをコンパイルすれば,うまく動作するものができるかもしれません。少々手間ですが…

もともとkaoriya版に同梱されているiconv.dllやintl.dllの関数を使うようにdiff.exeをコンパイルすれば,うまく動作するものができるかもしれません。少々手間ですが…

逆に、これができない限りは同梱配布はしたくない、というのが本音です。

で、もちろん手間ですので、今日までできていません。

公式同梱のdiff.exeは、libiconvもlibintlも無効化した状態でコンパイルされています。あとは、バージョン番号を見て分かるとおり、非常に古いです。(gnuwin32のもかなり古いですが。)
コンパイラはおそらくMinGWでしょう。

公式同梱のdiff.exeは、libiconvもlibintlも無効化した状態でコンパイルされています。

念の為PATHを無効化にして試してみましたが,本当ですね。ちょっと驚きました。

cd %USERPROFILE%\tmp
copy "C:\Program Files (x86)\Vim\vim74\diff.exe" .\
set PATH=
diff.exe --version

diff - GNU diffutils version 2.7

そうであれば,GNU diffutilsをMinGWでlibiconvとlibinitlを無効化にしてコンパイルできれば,同梱できるということでしょうか?
もしそれだけで(ソースの修正が不要で)できるのなら,コンパイル方法をちょっと調べて試してみましょうかね…

そうであれば,GNU diffutilsをMinGWでlibiconvとlibinitlを無効化にしてコンパイルできれば,同梱できるということでしょうか?

@lamsh いいえ。kaoriya版に同梱する条件は、
MSVC10 でコンパイルして msvcr10.dll にリンクするようにしたら、です。

@koron そうなのですね。CygwinとMSYSのMinGW以外のWindowsのビルド環境は一度も試したことがありません…できるかどうかわかりませんが、調べてみます。

MSVC10 でコンパイルして msvcr10.dll にリンクするようにしたら、です。

そこにこだわる理由は何でしょうか。公式同梱のdiff.exeはmsvcrt.dllにリンクしているので追加のdllは一切不要です。

GNU diffutilsのソースを落としてきてちょっと見てみましたが、automake/autoconfやGNU独自のgnulibなどに依存していて、VCでコンパイルしようというのは無謀ですね。

@k-takata

そこにこだわる理由は何でしょうか。

+kaoriya でやるから、です。
lib/dll/exe を全部 MS 純正のツールでビルドしてこその +kaoriya です。

libiconv も gettext もその他ライブラリ群も
+kaoirya の同梱物はすべてMSVCでコンパイルして来ているので
diff も難度は高いかもしれませんが無謀とまではいえないと考えています。

diffutils v2.7 では gnulib を含め、依存物が少ないので、やるならそこを起点にするのが良いでしょう。
もしかしたら v2.x くらいまでは同じ感じかもしれません。

なおそれようのレポジトリの clone は過去にやっていて、そのまま手付かずになってます。
https://github.com/koron/diffutils

気になって調べてみたら 2.8.7 までは gnulib ないですね。
https://github.com/koron/diffutils/tree/v2.8.7

見逃してた。 v2.8.6 でした。 2.8.7 は bootstrap で gnulib 使ってるぽい。

レポジトリ内に gnulib ってキーワードがまったく登場しないって意味だと、 2.8.4 まで。
2.8.6 は gnulib.mak を include している場所がある。

とりあえず https://github.com/koron/diffutils/tree/msvc/master/msvc において
v2.7 を MSVC14 でコンパイルするところまでは通しました。
必要なモジュールはほぼ揃えたつもりですが、まだ動いてはいません。
(違うファイルを入れても差分を出してくれない)

ここから実際に同梱に至るには

  1. とりあえず MSVC14 で現在の v2.7 を動くようにして
  2. v2.8.4 か v2.8.6 あたりまでアップグレード(もちろん動くこと前提)して
  3. その後 MSVC10 でコンパイルできるようにし
  4. もろもろコンパイルフラグを整える

ていう感じのフローになります。が、僕はココでいったん手を離すつもりなので
興味があったら続きをやってみてください。
あと近い将来、配布する Vim は VC14 でコンパイルするようにするつもりなので、
VC10 でコンパイルできるようにする 手順3 はやらなくても良いかもです。

あと近い将来、配布する Vim は VC14 でコンパイルするようにするつもりなので、

完全に別件ですが、現状RubyがVC14ではビルドできないので、if_rubyを有効にするのはちょっと面倒です。(ま、VC12でconfig.hを生成して、ちょっと書き換えれば動くのは確認できましたが。)

@koron コンパイルうまくできたのですね!お疲れさまでした。

月曜日の夜からこちらでも作業に取り組んでいたのですが,要領が悪くて昨日ようやくdiffutilsのビルドに着手できたところでした…。
こちらのページの手順を元にWindows 10にMSVC10一式をインストールしました。

Autotoolsの利用を念頭に置かれたパッケージをMSVC環境でビルドする方法が思いつかなかったので,よいか悪いかはわかりませんが以下のフローでビルドを試していました。

  1. Visual Studioのコマンドプロンプトを起動。
  2. MSYS2のC:/msys64/usr/binにPATHを追加設定。
  3. MSYS2のbashをコマンドプロンプトから起動。
  4. CC="cl.exe -nologo" ./configureのコマンドでMakefileを作成。
  5. 適宜コンパイルエラーを潰す。

この方法だと,diffutils 2.8.1(2.8.4はconfigure自体がない)はconfigureでエラーが出てダメでした(散々試してv2.8系でのautotoolsを使ったMSVCでのコンパイルは断念)。
2.7だけconfigureは成功しました(makeはまだうまくいっていないが,頑張れば解決できそうなエラー内容)。

https://github.com/koron/diffutils/tree/msvc/master/msvc を拝見させていただいたのですが,自分でMakefileを書かれたのですね。
早速MSVC10で試してみましたが,当然ながらMSVC14じゃないとだめみたいですね…。

regex.c
c:\msys64\home\senooken\local\src\diffutils-kaoriya\msvc\src\regex_internal.h(43) : fatal error C1083: Cannot open include file: 'stdbool.h': No such file or directory
strcasecmp.c

興味があるので,Makefileautotoolsの両方の方法でもう少し続きをやってみます。

ここから実際に同梱に至るには

  1. とりあえず MSVC14 で現在の v2.7 を動くようにして
  2. v2.8.4 か v2.8.6 あたりまでアップグレード(もちろん動くこと前提)して

MSVCでコンパイルして正常に動作するものがまだないので,あまりハードルをあげずに,同梱するバージョンはひとまず公式と同じv2.7でいいのではないでしょうか…

v2.8系は以下2点の懸念があります。

  1. v2.8.4とv2.8.6はGNUのソース配布元で配布されていないので,これらのバージョンでのビルドはあまり考えられていなさそう。
  2. autotoolsの対応状況と,v2.7->v2.8の間が8年空いており,v2.8系のビルドは難しそう。

個人的に,公式が未だにdiffutils v2.7を同梱しているのはこうした問題があるからなのかなと思いました。
もちろんうまくコンパイルできるならv2.8のほうがよいのですけど…。

1か月ほど挑戦してみようと思います。

VC14 を使った理由には、正式にフリーで入手可能 であり参加しやすい点と、
C99以降への対応度が高い点があげられます。
特に後者は VC10 でやると瑣末な問題で時間を食うことになるでしょう。
また、VC10 への対応は VC14 で動いてからやっても済むことで、
僕や @k-takata さんがさんざんやって得意とするところでもあります。

autotools で VC はそもそも諦めたほうが良いです。
仮にできたとしても autotools を動かすために必要な手順(=ドキュメント)が多くなるので、
その意味でも手間が増えてしまいます。
私のほうで Makefile を書いてしまったのは
autotools でハマるのを避けてもらうためでもあります。

なるほど。
最初にMSVC10でのビルドを条件に挙げられていたので素直にMSVC10を使っていたのですが、MSVC14からMSVC10へ移植できるのですね。

教えていただいた通り、autotoolsはやめて、MSVC14で挑戦してみます。
ありがとうございます。

最初にMSVC10でのビルドを条件に挙げられていた

その点については本当に申し訳ないです。

今すぐに配布するならば msvcr10.dll とリンクしたいので VC10 にしたいのは間違いありません。
しかし他にも解決しなきゃいけない重要な問題がある中で、
最初のハードルがそれだと高過ぎると考えました。
あわせてこういうカスタムな Makefile を書くのは、
僕が慣れているのでやってしまったというわけです。

なので VC14 で、場合によっては プラス VS2015 Community/デバッガ を使って、
なるべく楽に、より重要な問題へ取り組んでもらえたらな、との判断です。

ご親切にどうもありがとうございます。

まあ、ここまでお膳立てされても、うまくできるかどうかはわからないのですが、ちょっとやってみます。
諦めるときはこちらでまた連絡させていただきます。
よろしくお願いします。

VCとgccは、コマンドのオプションが全く違うので、autotoolsを使うのはかなり難しいと思います。
ちなみに、libffiは VC + autotools でビルドするようになっているのですが、オプションを変換するための専用スクリプトを用意しています。
参考: http://qiita.com/k-takata/items/23a64846c75039c6e9b3

はい。VCとgccとでオプションなど違うのはわかっています。

しかし、いきなり自分でMakefileを作るのは難しいです。
なので、一旦configureでコンパイルの順番や依存関係、オプション、マクロやsedなどの処理などが盛り込まれたMakefileを作り、これをベースにして、VCと合わない部分を適宜修正すれば楽にできるかなと考えました。

雛形を作っていただいたので、autotoolsは使わずにMSVCのツールだけでやるようにします。

すみません…連絡が遅くなりました。少し進展があったのでお知らせします。

cl.exeのオプション-Ziでデバッグ情報を埋め込んでも,gdbからは利用できず,デバッグするにはVisualStudioを使わないとだめのようだったのですが,使い方がよくわからないので,結局printfデバッグで原因を探ることにしました。

kaoriyaさんのリポジトリをforkしてdiff.exeが動作するように修正しました。
https://github.com/lamsh/diffutils/

diff.cで2つのファイルが同じかどうかの条件分岐がうまくいっていない箇所があったので修正しました。
これで,ファイルの差分は取れるようになりました。ただし,ディレクトリの差分はうまくとれません。

修正には,GnuWin32のdiffutilsのソースを参考にしてファイルの修正が必要な箇所(diff.cとsystem.h)をそのまま使いました。
http://gnuwin32.sourceforge.net/packages/diffutils.htm

ディレクトリの差分は少し修正が多くなりそうです。
diff.cの1000行目付近のdiff_dirs関数がうまくいっておらず,この内部のdir_sort関数のexcluded_filename関数があまり実装されていない(exclude変数など)のが原因のようです。GnuWin32では,構造体を新しく定義して使っているので,これに合わせるなら修正が少し多くなります。
https://github.com/lamsh/diffutils/blob/msvc/master/src/diff.c#L118

GnuWin32のソースをまるごと使えば,ちまちま修正しなくてもそのまま使えるんじゃないかともちょっと思っています。

引き続き取り組んでみます。

@lamsh 単品のファイルの差分は取れるようになったとのことで、おつかれさま&ありがとうございます!
まずはそこまでのPRを作ってもらえませんか? レビューしてマージしてしまいたいです。

@koron わかりました。
今晩プルリクエスト送らせていただきます。

ディレクトリの差分がとれない問題について対応してみました。

@koron プルリクエストを送りましたので,お時間のあるときにでもご確認お願いしますね。
Fix error for directory diff. by lamsh · Pull Request #2 · koron/diffutils

後で対応の経過を辿れるように,先日のファイル単品の差分修正のプルリクエストのURLを以下にも掲載しておきます。
Fix checking whether arguments are same file. by lamsh · Pull Request #1 · koron/diffutils

早速ダウンロードして動作に問題ないことを確認しました。
モチベーションのあがらない作業にも関わらず,ご対応いただきありがとうございました!