3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Windowsでiconv/dynなVimに読んで欲しいiconvのdllを探せない問題

Last updated at Posted at 2016-04-19

はじめに

しばらくアップデートしていなかったVimを新しいバージョンにしたのだが、自前でビルドしているiconv.dllを読まなくなってしまい、一部ファイルが編集できなくなってしまった。
このファイルを編集できなければ困るので結局前のバージョンに戻してしまったのだが、本日ようやく原因が分かったので共有する。

iconv.dllの読み込み順序

vim-jpのこのIssueによると、7.4.892時点では下記の順序で読むようになっているようだ。

  1. iconv.dll
  2. libiconv.dll
  3. libiconv2.dll
  4. 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.c
index 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.c
index 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から

  1. libiconv2.dll
  2. libiconv-2.dll
  3. iconv.dll
  4. 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によるビルド環境を整え、自前でビルドするようにした。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?