Cygwinでbayonをコンパイルした時のメモ

概要

環境

$ uname -srv
CYGWIN_NT-5.1 1.7.9(0.237/5/3) 2011-03-29 10:10

$ g++ -v
(略)
gcc version 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)

$ pwd
/cygdrive/c/home/src/bayon-0.1.0

作業ログ(失敗とその対処)

# google-sparsehash 1.10はインストール済み
$ ./configure --prefix=/usr/local
(略)
$ make
g++ -c -I. -I/usr/local/include/bayon -I/cygdrive/c/home/include -I/usr/local/include -D_GNU_S
OURCE=1 -DHAVE_CONFIG_H -Wall -fPIC -O3 bayon.cc
bayon.cc:1: warning: -fPIC ignored for target (all code is position independent)
/usr/local/include/google/sparsehash/hashtable-common.h: In member function `SizeType sh_hashtable_settings<Key, HashFunc, SizeType, HT_MIN_BUCKETS>::hash(const Key&) const [with Key = std::string, HashFunc = __gnu_cxx::hash<std::string>, SizeType = size_t, int HT_MIN_BUCKETS = 4]':
/usr/local/include/google/sparsehash/densehashtable.h:1213:   instantiated from `typename Alloc::rebind<Value>::other::size_type google::dense_hashtable<Value, Key, HashFcn, ExtractKey, SetKey, EqualKey, Alloc>::hash(const Key&) const [with Value = std::pair<const std::string, double>, Key = std::string, HashFcn = __gnu_cxx::hash<std::string>, ExtractKey = google::dense_hash_map<std::string, double, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, google::libc_allocator_with_realloc<std::pair<const std::string, double> > >::SelectKey, SetKey = google::dense_hash_map<std::string, double, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, google::libc_allocator_with_realloc<std::pair<const std::string, double> > >::SetKey, EqualKey = std::equal_to<std::string>, Alloc = google::libc_allocator_with_realloc<std::pair<const std::string, double> >]'
/usr/local/include/google/sparsehash/densehashtable.h:812:   instantiated from `std::pair<typename Alloc::rebind<Value>::other::size_type, typename Alloc::rebind<Value>::other::size_type> google::dense_hashtable<Value, Key, HashFcn, ExtractKey, SetKey, EqualKey, Alloc>::find_position(const Key&) const [with Value = std::pair<const std::string, double>, Key = std::string, HashFcn = __gnu_cxx::hash<std::string>, ExtractKey = google::dense_hash_map<std::string, double, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, google::libc_allocator_with_realloc<std::pair<const std::string, double> > >::SelectKey, SetKey = google::dense_hash_map<std::string, double, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, google::libc_allocator_with_realloc<std::pair<const std::string, double> > >::SetKey, EqualKey = std::equal_to<std::string>, Alloc = google::libc_allocator_with_realloc<std::pair<const std::string, double> >]'
/usr/local/include/google/sparsehash/densehashtable.h:968:   instantiated from `Value& google::dense_hashtable<Value, Key, HashFcn, ExtractKey, SetKey, EqualKey, Alloc>::find_or_insert(const Key&) [with DefaultValue = google::dense_hash_map<std::string, double, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, google::libc_allocator_with_realloc<std::pair<const std::string, double> > >::DefaultValue, Value = std::pair<const std::string, double>, Key = std::string, HashFcn = __gnu_cxx::hash<std::string>, ExtractKey = google::dense_hash_map<std::string, double, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, google::libc_allocator_with_realloc<std::pair<const std::string, double> > >::SelectKey, SetKey = google::dense_hash_map<std::string, double, __gnu_cxx::hash<std::string>, std::equal_to<std::string>, google::libc_allocator_with_realloc<std::pair<const std::string, double> > >::SetKey, EqualKey = std::equal_to<std::string>, Alloc = google::libc_allocator_with_realloc<std::pair<const std::string, double> >]'
/usr/local/include/google/dense_hash_map:270:   instantiated from `T& google::dense_hash_map<Key, T, HashFcn, EqualKey, Alloc>::operator[](const typename google::dense_hashtable<std::pair<const _Key, _Tp>, Key, HashFcn, google::dense_hash_map<Key, T, HashFcn, EqualKey, Alloc>::SelectKey, google::dense_hash_map<Key, T, HashFcn, EqualKey, Alloc>::SetKey, EqualKey, Alloc>::key_type&) [with Key = std::string, T = double, HashFcn = __gnu_cxx::hash<std::string>, EqualKey = std::equal_to<std::string>, Alloc = google::libc_allocator_with_realloc<std::pair<const std::string, double> >]'
/usr/local/include/google/dense_hash_map:270:   instantiated from `T& google::dense_hash_map<Key, T, HashFcn, EqualKey, Alloc>::operator[](const typename google::dense_hashtable<std::pair<const _Key, _Tp>, Key, HashFcn, google::dense_hash_map<Key, T, HashFcn, EqualKey, Alloc>::SelectKey, google::dense_hash_map<Key, T, HashFcn, EqualKey, Alloc>::SetKey, EqualKey, Alloc>::key_type&) [with Key = std::string, T = double, HashFcn = __gnu_cxx::hash<std::string>, EqualKey = std::equal_to<std::string>, Alloc = google::libc_allocator_with_realloc<std::pair<const std::string, double> >]'
bayon.cc:272:   instantiated from here
/usr/local/include/google/sparsehash/hashtable-common.h:65: error: `operator()' is not a member of `__gnu_cxx::hash<std::string>'
make: *** [bayon.o] Error 1

Google Code Archive - Long-term storage for Google Code Project Hosting.によれば、 __gnu_cxx::hashがstd:stringをサポートしてないのが原因。

bayonのutil.hでは

/* hash function of string key for __gnu_cxx::hash_map */
#if (defined(_WIN32) || !defined(HAVE_GOOGLE_DENSE_HASH_MAP)) && defined(HAVE_EXT_HASH_MAP)
namespace __gnu_cxx {
  template<> struct hash<std::string> {
    size_t operator() (const std::string &x) const {
      return hash<const char *>()(x.c_str());
    }
  };

となってるので、対策はされてるもののCygwinのことは考慮されてない模様。
条件部を

 /* hash function of string key for __gnu_cxx::hash_map */
-#if (defined(_WIN32) || !defined(HAVE_GOOGLE_DENSE_HASH_MAP)) && defined(HAVE_EXT_HASH_MAP)
+#if 1 || (defined(_WIN32) || !defined(HAVE_GOOGLE_DENSE_HASH_MAP)) && defined(HAVE_EXT_HASH_MAP)
 namespace __gnu_cxx {

として対処した(ひどいが、もっとましなやりかたを思いつかなかった……)。

で、ふたたびmakeする。

$ make
LD_RUN_PATH=.:/lib:/usr/lib:/usr/local/lib:/cygdrive/c/home/lib:/usr/local/lib:/usr/local/lib g++ -Wall -fPIC -O3 -o bayon bayon.o -L. -L/usr/local/lib -L/cygdrive/c/home/lib -L/usr/local/lib  -lbayon
bayon.o:bayon.cc:(.text+0x7c70): undefined reference to `bayon::Classifier::VECID_EMPTY_KEY'
bayon.o:bayon.cc:(.text+0x7c82): undefined reference to `bayon::Classifier::VECID_EMPTY_KEY'
collect2: ld returned 1 exit status
make: *** [bayon] Error 1

これは、classifier.hの

   Classifier() {
    init_hash_map(VECID_EMPTY_KEY, vectors_);
    init_hash_map(VECID_EMPTY_KEY, inverted_index_);

が悪さしてる(なぜだ……)ので、定数を展開する。

   Classifier() {
-    init_hash_map(VECID_EMPTY_KEY, vectors_);
-    init_hash_map(VECID_EMPTY_KEY, inverted_index_);
+    // VECID_EMPTY_KEY = -1
+    init_hash_map(-1, vectors_);
+    init_hash_map(-1, inverted_index_);
   }

で、とりあえずコンパイルは通ったのでインストールしてみる(googletest導入法調べてないのでテストは割愛……)

$ make install

チュートリアルのサンプルを動かしてみる

$ bayon -n 3 -p data/test2.tsv
1       田村    0.987737        小島    0.987737
2       青柳    0.928262        阿佐田  0.928262
3       三輪    0.922401        古川    0.922401

エス!!!

(おわり)