はじめに
しばらくアップデートしていなかったVimを新しいバージョンにしたのだが、自前でビルドしているiconv.dll
を読まなくなってしまい、一部ファイルが編集できなくなってしまった。
このファイルを編集できなければ困るので結局前のバージョンに戻してしまったのだが、本日ようやく原因が分かったので共有する。
iconv.dll
の読み込み順序
vim-jpのこのIssueによると、7.4.892時点では下記の順序で読むようになっているようだ。
- iconv.dll
- libiconv.dll
- libiconv2.dll
- libiconv-2.dll
香り屋版Vimにはiconv.dll
として同梱されていたため、自前でビルドしたiconvも同様にiconv.dll
という名前にしてVimに読ませていた。
この読み込み順序はsrc/mbyte.cに書いており、7.4.892のパッチを見るとこのように実装されている。
diff --git a/src/mbyte.c b/src/mbyte.cindex 75559b0..6046d7d 100644--- a/src/mbyte.c+++ b/src/mbyte.c@@ -4400,7 +4400,9 @@ static HINSTANCE hMsvcrtDLL = 0;
# ifndef DYNAMIC_ICONV_DLL
# define DYNAMIC_ICONV_DLL "iconv.dll"
-# define DYNAMIC_ICONV_DLL_ALT "libiconv.dll"+# define DYNAMIC_ICONV_DLL_ALT1 "libiconv.dll"+# define DYNAMIC_ICONV_DLL_ALT2 "libiconv2.dll"+# define DYNAMIC_ICONV_DLL_ALT3 "libiconv-2.dll"
# endif
# ifndef DYNAMIC_MSVCRT_DLL
# define DYNAMIC_MSVCRT_DLL "msvcrt.dll"
@@ -4456,9 +4458,16 @@ iconv_enabled(verbose)
{
if (hIconvDLL != 0 && hMsvcrtDLL != 0)
return TRUE;
++ /* The iconv DLL file goes under different names, try them all. */
hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL);
- if (hIconvDLL == 0) /* sometimes it's called libiconv.dll */- hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL_ALT);+ if (hIconvDLL == 0)+ hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL_ALT1);+ if (hIconvDLL == 0)+ hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL_ALT2);+ if (hIconvDLL == 0)+ hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL_ALT3);+
if (hIconvDLL != 0)
hMsvcrtDLL = vimLoadLib(DYNAMIC_MSVCRT_DLL);
if (hIconvDLL == 0 || hMsvcrtDLL == 0)
ではどこかでこの順序が変わってしまったのだろうとパッチを順番に見ていくと、7.4.1165で以下のように変更されているのを見つけた。
diff --git a/src/mbyte.c b/src/mbyte.cindex edca9a7..0e4b7e4 100644--- a/src/mbyte.c+++ b/src/mbyte.c@@ -4392,21 +4392,21 @@ iconv_string(vcp, str, slen, unconvlenp, resultlenp)
* Dynamically load the "iconv.dll" on Win32.
*/
-#ifndef DYNAMIC_ICONV /* just generating prototypes */-# define HINSTANCE int-#endif+# ifndef DYNAMIC_ICONV /* must be generating prototypes */+# define HINSTANCE int+# endif
static HINSTANCE hIconvDLL = 0;
static HINSTANCE hMsvcrtDLL = 0;
-# ifndef DYNAMIC_ICONV_DLL-# define DYNAMIC_ICONV_DLL "iconv.dll"-# define DYNAMIC_ICONV_DLL_ALT1 "libiconv.dll"-# define DYNAMIC_ICONV_DLL_ALT2 "libiconv2.dll"-# define DYNAMIC_ICONV_DLL_ALT3 "libiconv-2.dll"-# endif-# ifndef DYNAMIC_MSVCRT_DLL-# define DYNAMIC_MSVCRT_DLL "msvcrt.dll"-# endif+# ifndef DYNAMIC_ICONV_DLL+# define DYNAMIC_ICONV_DLL "iconv.dll"+# define DYNAMIC_ICONV_DLL_ALT1 "libiconv.dll"+# define DYNAMIC_ICONV_DLL_ALT2 "libiconv2.dll"+# define DYNAMIC_ICONV_DLL_ALT3 "libiconv-2.dll"+# endif+# ifndef DYNAMIC_MSVCRT_DLL+# define DYNAMIC_MSVCRT_DLL "msvcrt.dll"+# endif
/*
* Get the address of 'funcname' which is imported by 'hInst' DLL.
@@ -4459,14 +4459,22 @@ iconv_enabled(verbose)
if (hIconvDLL != 0 && hMsvcrtDLL != 0)
return TRUE;
- /* The iconv DLL file goes under different names, try them all. */- hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL);- if (hIconvDLL == 0)- hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL_ALT1);+ /* The iconv DLL file goes under different names, try them all.+ * Do the "2" version first, it's newer. */+#ifdef DYNAMIC_ICONV_DLL_ALT2
if (hIconvDLL == 0)
hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL_ALT2);
+#endif+#ifdef DYNAMIC_ICONV_DLL_ALT3
if (hIconvDLL == 0)
hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL_ALT3);
+#endif+ if (hIconvDLL == 0)+ hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL);+#ifdef DYNAMIC_ICONV_DLL_ALT1+ if (hIconvDLL == 0)+ hIconvDLL = vimLoadLib(DYNAMIC_ICONV_DLL_ALT1);+#endif
if (hIconvDLL != 0)
hMsvcrtDLL = vimLoadLib(DYNAMIC_MSVCRT_DLL);
パッチにもあるように7.4.1165から
- libiconv2.dll
- libiconv-2.dll
- iconv.dll
- libiconv.dll
の順序で読み込むように変更されたようだ。
調べてみると昔にインストールした何か由来のlibiconv2.dll
を真っ先に見つけて読むようになっていた。
自前ビルド版のiconvのdllをlibiconv2.dll
としてvim.exe
と同一ディレクトリに配置してやることで本来読んで欲しいiconvのdllを読ませることに成功した。
追記
古いiconv.dll
を削除すると
コンピューターに iconv.dll がないため、プログラムを開始できません。この問題を解決するには、プログラムを再インストールしてみてください
というエラーが出るようになった。
どうもintl.dll
等がiconv.dll
がある前提となっており、libiconv2.dll
だけでは立ち上がらないようだ。
仕方がないのでlibiconv2.dll
のハードリンクをiconv.dll
という名前で作成すること解決とした。
蛇足
香り屋版Vimの配布方法がgithubのreleasesを使う方法に変更されるようだ。
こちらのProxyではAmazon AWSとの通信を問答無用で遮断されてしまうので、今後新バージョンをダウンロードできなくなってしまった。
仕方がないのでMinGW-w64によるビルド環境を整え、自前でビルドするようにした。