2015年3月27日金曜日

[cygwin] cygwin版のgitコマンドでサーバーとの通信に失敗する問題の対処

cygwin上でgitコマンドを使用しているのですが、ある環境でのみgit pull/pushで以下のようなエラーが発生する問題に遭遇しました。調子よく動作している別の環境との比較で原因が判明したので、同じ問題にハマってしまった人向けに情報を残しておきます。

問題の現象:

問題の環境ではgit pull/pushを実行すると、以下のようなエラーが出力されていました。
% git pull origin master
fatal: 'pull' appears to be a git command, but we were not
able to execute it. Maybe git-pull is broken?

% git push origin master
fatal: Full write to remote helper failed: Broken pipe

解決方法:

この問題はPATH環境変数の設定によって発生します。cygwinのバイナリが格納されているディレクトリ(C:\cygwin64\bin)がユーザー環境変数にしか定義されていない状態だと、このエラーになります。以下のいずれかの設定に変更することで問題を解決できます。

  1. cygwinのシェルスクリプトでpath環境変数の先頭に/usr/binを追加する
    • cygwinをインストールしたデフォルト環境ではこの状態になっています。自分はcabalコマンドがcygwin上で実行できるよう、このデフォルト設定を無効にしていました。
  2. ユーザー環境変数ではなく、システム環境変数のPATHにcygwinディレクトリを追加する
    • 推測ですが、システムプロセスとして/usr/bin以下のコマンドを実行しているのだと思われます。パスの順序は変わらないのに、ユーザー環境変数のPATHにcygwinディレクトリを記述していると、問題の現象が発生しています。

備考:

2015年3月25日水曜日

[windows][haskell] bzlibパッケージ利用時にHSbzlib-0.5.0.5.o: unknown symbol `fileno'となる問題の対処

Haskellでは、bzip2で圧縮されたデータを解凍(もちろん逆に圧縮も)できるbzlibパッケージが提供されています。

ところが、自分の環境(Windows 8.1+Haslell Platform 2014.2.0.0)でbzlibパッケージをインポートするサンプルプログラムをビルド・実行しようとすると、以下のようなエラーになってしまいました。
> runghc examples/bunzip2.hs       
bunzipz2.hs: C:\Users\XXX\AppData\Roaming\cabal\x86_64-windows-ghc-7.8.3\bzlib-0.5.0.5\HSbzlib-0.5.0.5.o: unknown symbol `fileno'                      
bunzip2.hs: bunzip2.hs: unable to load package `bzlib-0.5.0.5'            

ネット上の情報を漁ってみたのですが同じ問題に遭遇している人はいなさそう・・・。ということで、自力で調べてみました。以下、分かったことと回避方法をまとめておきます。


問題の原因:

  • 詳細は「調査の内容」に記しましたが、bzlibが内部で呼び出しているfileno()とfdopen()が定義されているmingwのlibmoldname.aがリンクされないのが原因のようです。

問題の回避方法

  • libmoldname.aをリンクする修正が正しいのですが、その方法が分からなかったため、bzlibのコードに手をいれてileno()とfdopen()を呼ばないバージョンをビルドし、それで正規のパッケージを置き換えることで、bzlibが利用できるようになりました。以下、その手順です。
    1. cabalのpackageがダウンロードされているディレクトリに移動する
    2. % cd C:\Users\XXX\AppData\Roaming\cabal\packages\hackage.haskell.org\bzlib\0.5.0.5
      
    3. bzlib-0.5.0.5.tar.gzを展開する
    4. % tar xzf bzlib-0.5.0.5.tar.gz
      
    5. このパッチをDLしてbzlib.patchという名前で保存し、適用する
    6. % patch -p1 < bzlib.patch
      
    7. パッチを含んだアーカイブでオリジナルのbzlib-0.5.0.5.tar.gzを置き換える
    8. % tar czf bzlib-0.5.0.5.tar.gz bzlib-0.5.0.5/
      
    9. bzlibパッケージをreinstallする
    10. % cabal install bzlib --reinstall
      

調査の内容:

  • 自分の環境にcygwinとHaskell付属のmingwの両方が存在しているが原因かと思ったがそうではないらしい。
    • mingwのライブラリにもfilenoがちゃんと用意されている。
    • mingw環境においてここのfilenoのサンプルがビルドでき、動作しているため
      • > gcc fileno.cpp
  • mingw環境の確認
    • filenoを利用するC言語版サンプルをビルドしてmapファイルを出力したところ、filenoはlibmoldname.aというライブラリの定義をリンクしていることが分かった。
      • gcc -Wl,-Map=a.map -g fileno.cpp
      •  .text          0x0000000000402c10        0x8 c:/program files/haskell platform/2014.2.0.0/mingw/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x86_64-w64-mingw32/lib/../lib/libmoldname.a(dnvzs00026.o)
                        0x0000000000402c10                fileno
        
  • bzlib-0.5.0.5をローカル環境でビルドしてその内容を確認
    • filenoがunknown symbolとなっているのは以下の2つのオブジェクトファイル
      • bzlib-0.5.0.5/dist/build/cbits/bzlib.o
      • bzlib-0.5.0.5/dist/build/cbits/HSbzlib-0.5.0.5.o
    • 上記オブジェクトファイルで同じくunknown symbolになっているfopen, fread, fwrite, fcloseといった関数はlibmoldname.aとは別のlibmsvcrt.aにアーカイブされている。
      • a.mapより
      •  .text          0x0000000000402c70        0x8 c:/program files/haskell platform/2014.2.0.0/mingw/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x86_64-w64-mingw32/lib/../lib/libmsvcrt.a(dnhvs00971.o)
                        0x0000000000402c70                fopen
         .text          0x0000000000402c78        0x8 c:/program files/haskell platform/2014.2.0.0/mingw/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x86_64-w64-mingw32/lib/../lib/libmsvcrt.a(dnhvs00979.o)
                        0x0000000000402c78                fread
        
        
  • windows版のみcabal buildでパッケージをビルドする際に、filenoの解決に必要なlibmoldname.aのリンクが漏れているのでは?
    • 試しに、libmoldname.aを削除してcabal buildをビルドしてみたところ、リンクエラーになりました。ということは、パッケージビルド時にはlibmoldname.aをリンクしようとしていることになります。・・・ハズレ。
    • Resolving dependencies...
      Configuring bzlib-0.5.0.5...
      Building bzlib-0.5.0.5...
      Preprocessing library bzlib-0.5.0.5...
      c:/program files/haskell platform/2014.2.0.0/mingw/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lmoldname
      c:/program files/haskell platform/2014.2.0.0/mingw/bin/../lib/gcc/x86_64-w64-mingw32/4.6.3/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lmoldname
      collect2: ld returned 1 exit status
      linking dist\build\Codec\Compression\BZip\Stream_hsc_make.o failed (exit code 1)
      
      command was: C:\Program Files\Haskell Platform\2014.2.0.0\mingw\bin\gcc.exe dist\build\Codec\Compression\BZip\Stream_hsc_make.o dist\build\Codec\Compression\BZip\Stream_hsc_utils.o -o dist\build\Codec\Compression\BZip\Stream_hsc_make.exe -LC:\Users\XXX\AppData\Roaming\cabal\x86_64-windows-ghc-7.8.3\bytestring-0.10.4.1 -LC:\Program Files\Haskell Platform\2014.2.0.0\lib\deepseq-1.3.0.2 -LC:\Program Files\Haskell Platform\2014.2.0.0\lib\array-0.5.0.0 -LC:\Program Files\Haskell Platform\2014.2.0.0\lib\base-4.7.0.1 -lwsock32 -luser32 -lshell32 -LC:\Program Files\Haskell Platform\2014.2.0.0\lib\integer-gmp-0.5.1.0 -LC:\Program Files\Haskell Platform\2014.2.0.0\lib\ghc-prim-0.3.1.0 -LC:\Program Files\Haskell Platform\2014.2.0.0\lib/rts-1.0 -lm -lwsock32 -lgdi32 -lwinmm
      
  • パッケージビルド時ではなく、パッケージを利用するコードをコンパイルして実行ファイルを生成するときにlibmodulename.aがリンクされていないようです。
    • これはどこの設定に書かれているのか・・・?
      
      

備考:

  • 冒頭に書いたとおり、本来ならば適切にlibmoldname.aをリンクするように修正するのが正しい解決方法なのですが、bzlibパッケージの中にそのような見つからず、どこを変えれば良いか分かりませんでした・・・。orz 。どこを修正すればリンクライブラリを追加できるか知っている方、是非ご教示ください。 m(_ _)m 
  • unknown symbolとなるfilenoとfdopenはbzlib-0.5.0.5/cbits/bzlib.cの中で呼び出しています。コードを確認したところどちらも環境によってはundefされており、呼び出さなくても問題はないことを確認しました。
  • なお、Linux, Mac環境上ではこの問題は発生しません。問題なく利用できています。

参考:

2015年3月12日木曜日

[windows][haskell] cabal installでWin32File.hsc:34:19: fatal error: Share.h: No such file or directoryというエラーが出たときの対処方法

Windows 8.1+Haslell Platform 2014.2.0.0環境でcabal installを実行したところ、以下のようなエラーに遭遇しました。

問題の現象:

Preprocessing library streaming-commons-0.1.9.1...
Win32File.hsc:34:19: fatal error: Share.h: No such file or directory
compilation terminated.
compiling dist\build\System\Win32File_hsc_make.c failed (exit code 1)

問題の原因:

ネットの情報によると、これはcygwin環境とmingw環境が混在している場合に発生するようです。Haskell Platformはmingwに依存しているのですが、cygwinがインストールされているとcabal installから実行されるgccその他の挙動がmingwのものと異なってしまい、エラーとなります。

問題の解決方法:

cygwin付属のバイナリでなく、mingw付属のバイナリが利用されるようにPATHの記述を変更することで、この問題が発生しなくなります。PATH環境変数の中にあるcygwin環境のディレクトリを"C:\Program Files\Haskell Platform\2014.2.0.0\mingw\bin"というディレクトリよりも後ろに記載するように修正してください。

参考: