おはようございます。来年の4月からは小学生になる長男は、園の近所の小学校から学芸会に招待され、小学校を見学してきました。卒園生もその小学校には通っており、ひさしぶりに、小学生になったお兄さん、お姉さんにもあえた様でした。@kjunichiです。
背景
WindowsでPlv8を自前でビルドを試みていた。 諸事情によりMinGWとMSVCを行ったり来たりして作業していた。
stream関連を使おうとするとエラーが出る
1点目は、fstream関連を使おうとするとエラーが出る。
$ g++ -Wall -O2 -std=c++11 -fno-rtti -I. -I./ -IC:/msys64/home/kjw_j/local/pg96/include/POSTGR~1/server -IC:/msys64/home/kjw_j/local/pg96/include/POSTGR~1/internal -IC:/msys64/home/kjw_j/local/pg96/include/POSTGR~1/server/port/win32 -I/C/Users/kjw_j/Documents/work/build/v8 -I/C/Users/kjw_j/Documents/work/build/v8/include -o ch1 ch1.cc
In file included from ch1.cc:9:0:
C:/msys64/mingw64/include/c++/7.2.0/fstream:297:54: error: macro "open" requires 3 arguments, but only 2 given
open(const char* __s, ios_base::openmode __mode);
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:307:61: error: macro "open" requires 3 arguments, but only 2 given
open(const std::string& __s, ios_base::openmode __mode)
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:308:40: error: macro "open" requires 3 arguments, but only 2 given
{ return open(__s.c_str(), __mode); }
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:499:24: error: macro "open" requires 3 arguments, but only 2 given
this->open(__s, __mode);
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:516:24: error: macro "open" requires 3 arguments, but only 2 given
this->open(__s, __mode);
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:595:69: error: macro "open" requires 3 arguments, but only 2 given
open(const char* __s, ios_base::openmode __mode = ios_base::in)
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:597:49: error: macro "open" requires 3 arguments, but only 2 given
if (!_M_filebuf.open(__s, __mode | ios_base::in))
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:615:76: error: macro "open" requires 3 arguments, but only 2 given
open(const std::string& __s, ios_base::openmode __mode = ios_base::in)
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:617:49: error: macro "open" requires 3 arguments, but only 2 given
if (!_M_filebuf.open(__s, __mode | ios_base::in))
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:702:24: error: macro "open" requires 3 arguments, but only 2 given
this->open(__s, __mode);
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:720:24: error: macro "open" requires 3 arguments, but only 2 given
this->open(__s, __mode);
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:800:64: error: macro "open" requires 3 arguments, but only 2 given
ios_base::openmode __mode = ios_base::out | ios_base::trunc)
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:802:50: error: macro "open" requires 3 arguments, but only 2 given
if (!_M_filebuf.open(__s, __mode | ios_base::out))
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:821:64: error: macro "open" requires 3 arguments, but only 2 given
ios_base::openmode __mode = ios_base::out | ios_base::trunc)
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:823:50: error: macro "open" requires 3 arguments, but only 2 given
if (!_M_filebuf.open(__s, __mode | ios_base::out))
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:907:24: error: macro "open" requires 3 arguments, but only 2 given
this->open(__s, __mode);
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:922:24: error: macro "open" requires 3 arguments, but only 2 given
this->open(__s, __mode);
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:1002:61: error: macro "open" requires 3 arguments, but only 2 given
ios_base::openmode __mode = ios_base::in | ios_base::out)
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:1004:34: error: macro "open" requires 3 arguments, but only 2 given
if (!_M_filebuf.open(__s, __mode))
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:1023:61: error: macro "open" requires 3 arguments, but only 2 given
ios_base::openmode __mode = ios_base::in | ios_base::out)
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:1025:34: error: macro "open" requires 3 arguments, but only 2 given
if (!_M_filebuf.open(__s, __mode))
^
In file included from C:/msys64/mingw64/include/c++/7.2.0/fstream:1081:0,
from ch1.cc:9:
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:179:52: error: macro "open" requires 3 arguments, but only 2 given
open(const char* __s, ios_base::openmode __mode)
^
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:184:28: error: macro "open" requires 3 arguments, but only 2 given
_M_file.open(__s, __mode);
^
In file included from ch1.cc:9:0:
C:/msys64/mingw64/include/c++/7.2.0/fstream:308:43: error: expected ';' at end of member declaration
{ return open(__s.c_str(), __mode); }
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:308:43: error: redeclaration of 'std::basic_filebuf<_CharT, _Traits>::__filebuf_type* std::basic_filebuf<_CharT, _Traits>::open'
C:/msys64/mingw64/include/c++/7.2.0/fstream:297:7: note: previous declaration 'std::basic_filebuf<_CharT, _Traits>::__filebuf_type* std::basic_filebuf<_CharT, _Traits>::open'
open(const char* __s, ios_base::openmode __mode);
^~~~
C:/msys64/mingw64/include/c++/7.2.0/fstream:308:9: error: expected primary-expression before 'return'
{ return open(__s.c_str(), __mode); }
^~~~~~
C:/msys64/mingw64/include/c++/7.2.0/fstream:308:9: error: expected '}' before 'return'
C:/msys64/mingw64/include/c++/7.2.0/fstream:308:9: error: expected ';' before 'return'
C:/msys64/mingw64/include/c++/7.2.0/fstream:603:7: error: variable or field 'open' declared void
}
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:603:7: error: expected ';' at end of member declaration
C:/msys64/mingw64/include/c++/7.2.0/fstream:623:7: error: variable or field 'open' declared void
}
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:623:7: error: expected ';' at end of member declaration
C:/msys64/mingw64/include/c++/7.2.0/fstream:808:7: error: variable or field 'open' declared void
}
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:808:7: error: expected ';' at end of member declaration
C:/msys64/mingw64/include/c++/7.2.0/fstream:829:7: error: variable or field 'open' declared void
}
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:829:7: error: expected ';' at end of member declaration
C:/msys64/mingw64/include/c++/7.2.0/fstream:1010:7: error: variable or field 'open' declared void
}
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:1010:7: error: expected ';' at end of member declaration
C:/msys64/mingw64/include/c++/7.2.0/fstream:1031:7: error: variable or field 'open' declared void
}
^
C:/msys64/mingw64/include/c++/7.2.0/fstream:1031:7: error: expected ';' at end of member declaration
In file included from C:/msys64/mingw64/include/c++/7.2.0/fstream:1081:0,
from ch1.cc:9:
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:179:5: error: 'std::basic_filebuf<_CharT, _Traits>::__filebuf_type* std::basic_filebuf<_CharT, _Traits>::open' is not a static data member of 'class std::basic_filebuf<_CharT, _Traits>'
open(const char* __s, ios_base::openmode __mode)
^~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:179:5: error: template definition of non-template 'std::basic_filebuf<_CharT, _Traits>::__filebuf_type* std::basic_filebuf<_CharT, _Traits>::open'
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:181:22: error: expected primary-expression before '*' token
__filebuf_type *__ret = 0;
^
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:181:23: error: '__ret' was not declared in this scope
__filebuf_type *__ret = 0;
^~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:181:23: note: suggested alternative: '_creat'
__filebuf_type *__ret = 0;
^~~~~
_creat
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:181:32: error: expected '}' before ';' token
__filebuf_type *__ret = 0;
^
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:182:7: error: expected unqualified-id before 'if'
if (!this->is_open())
^~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:207:7: error: expected unqualified-id before 'return'
return __ret;
^~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:211:14: error: expected nested-name-specifier before 'basic_filebuf'
typename basic_filebuf<_CharT, _Traits>::__filebuf_type*
^~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:211:27: error: expected initializer before '<' token
typename basic_filebuf<_CharT, _Traits>::__filebuf_type*
^
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:261:5: error: 'streamsize' does not name a type; did you mean 'HeapSize'?
streamsize
^~~~~~~~~~
HeapSize
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:287:14: error: expected nested-name-specifier before 'basic_filebuf'
typename basic_filebuf<_CharT, _Traits>::int_type
^~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:287:27: error: expected initializer before '<' token
typename basic_filebuf<_CharT, _Traits>::int_type
^
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:446:14: error: expected nested-name-specifier before 'basic_filebuf'
typename basic_filebuf<_CharT, _Traits>::int_type
^~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:446:27: error: expected initializer before '<' token
typename basic_filebuf<_CharT, _Traits>::int_type
^
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:505:14: error: expected nested-name-specifier before 'basic_filebuf'
typename basic_filebuf<_CharT, _Traits>::int_type
^~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:505:27: error: expected initializer before '<' token
typename basic_filebuf<_CharT, _Traits>::int_type
^
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:571:18: error: expected initializer before '<' token
basic_filebuf<_CharT, _Traits>::
^
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:633:5: error: 'streamsize' does not name a type; did you mean 'HeapSize'?
streamsize
^~~~~~~~~~
HeapSize
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:721:5: error: 'streamsize' does not name a type; did you mean 'HeapSize'?
streamsize
^~~~~~~~~~
HeapSize
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:769:14: error: expected nested-name-specifier before 'basic_filebuf'
typename basic_filebuf<_CharT, _Traits>::__streambuf_type*
^~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:769:27: error: expected initializer before '<' token
typename basic_filebuf<_CharT, _Traits>::__streambuf_type*
^
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:798:14: error: expected nested-name-specifier before 'basic_filebuf'
typename basic_filebuf<_CharT, _Traits>::pos_type
^~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:798:27: error: expected initializer before '<' token
typename basic_filebuf<_CharT, _Traits>::pos_type
^
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:858:14: error: expected nested-name-specifier before 'basic_filebuf'
typename basic_filebuf<_CharT, _Traits>::pos_type
^~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:858:27: error: expected initializer before '<' token
typename basic_filebuf<_CharT, _Traits>::pos_type
^
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:873:14: error: expected nested-name-specifier before 'basic_filebuf'
typename basic_filebuf<_CharT, _Traits>::pos_type
^~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:873:27: error: expected initializer before '<' token
typename basic_filebuf<_CharT, _Traits>::pos_type
^
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:899:22: error: expected initializer before '<' token
int basic_filebuf<_CharT, _Traits>::
^
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:918:18: error: expected initializer before '<' token
basic_filebuf<_CharT, _Traits>::
^
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:979:18: error: expected initializer before '<' token
basic_filebuf<_CharT, _Traits>::
^
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:996:18: error: expected initializer before '<' token
basic_filebuf<_CharT, _Traits>::
^
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1053:25: error: 'basic_filebuf' is not a class template
extern template class basic_filebuf<char>;
^~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1053:25: error: explicit instantiation of non-template type 'basic_filebuf'
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1054:25: error: 'basic_ifstream' is not a class template
extern template class basic_ifstream<char>;
^~~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1054:25: error: explicit instantiation of non-template type 'basic_ifstream'
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1055:25: error: 'basic_ofstream' is not a class template
extern template class basic_ofstream<char>;
^~~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1055:25: error: explicit instantiation of non-template type 'basic_ofstream'
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1056:25: error: 'basic_fstream' is not a class template
extern template class basic_fstream<char>;
^~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1056:25: error: explicit instantiation of non-template type 'basic_fstream'
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1059:25: error: 'basic_filebuf' is not a class template
extern template class basic_filebuf<wchar_t>;
^~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1059:25: error: explicit instantiation of non-template type 'basic_filebuf'
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1060:25: error: 'basic_ifstream' is not a class template
extern template class basic_ifstream<wchar_t>;
^~~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1060:25: error: explicit instantiation of non-template type 'basic_ifstream'
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1061:25: error: 'basic_ofstream' is not a class template
extern template class basic_ofstream<wchar_t>;
^~~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1061:25: error: explicit instantiation of non-template type 'basic_ofstream'
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1062:25: error: 'basic_fstream' is not a class template
extern template class basic_fstream<wchar_t>;
^~~~~~~~~~~~~
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1062:25: error: explicit instantiation of non-template type 'basic_fstream'
C:/msys64/mingw64/include/c++/7.2.0/bits/fstream.tcc:1067:1: error: expected declaration before '}' token
} // namespace std
^
当初、Mingwのg++を疑い、pacmanコマンドをググって更新したが、エラーが出たまま。
仕方がないので、ミニマムケースを調査した。
#include <fstream>
int main(){return 0;}
こちらはOK。g++がはずれ版という訳では無さそう。
次に、イマイチビルド方法も良く理解できずビルドしたV8が悪さしてないかを 確認。
#include <v8.h>
#include <fstream>
int main(){return 0;}
ビルドコマンドは
gcc -Wall -O2 -std=c++11 -fno-rtti -I. -I./ \ -I/C/Users/kjunichi/Documents/work/build/v8 \ -I/C/Users/kjunichi/Documents/work/build/v8/include \ -v test2.cc
こちらもOK
#include <v8.h>
#include <vector>
#include <string>
extern "C" {
#include "postgres.h"
}
#include <fstream>
int main(){return 0;}
今度は、PostgreSQLのヘッダディレクトリもインクルードパスに追加して、 結構ゴツいコマンドにw
gcc -Wall -O2 -std=c++11 -fno-rtti -I. -I./ \ -IC:/msys64/home/kjw_j/local/pg96/include/POSTGR~1/server \ -IC:/msys64/home/kjw_j/local/pg96/include/POSTGR~1/internal \ -IC:/msys64/home/kjw_j/local/pg96/include/POSTGR~1/server/port/win32 \ -I/C/Users/kjunichi/Documents/work/build/v8 \ -I/C/Users/kjunichi/Documents/work/build/v8/include \ -v test3.cc
これがNGでした。
ということで、PostgreSQLが何かやってることが原因と分かりました。
さらに調査を進めると、postgres.h配下にopenが定義してあり、それが、今回のエラーの原因となっている ことが分かりました。
PostgreSQL/9.6/include/server/port.h 289:#define open(a,b,c) pgwin32_open(a,b,c)
ここで、Windowsプラットフォームの場合、PostgreSQLが用意したopen関数をマクロで定義していおり、 これがビルドの通らない原因となっていました。
対処しては、PostgreSQLのヘッダ内でopenをマクロで定義しているから、これを出たところで、
undefするという方法をとりました。
#include "plv8_config.h"
#include <v8.h>
#include <vector>
#include <string>
extern "C" {
#include "postgres.h"
}
#undef open
#include <fstream>
int main(){return 0;}
これで、g++から怒られなくなりました。
generic-msvc.hでエラーになる
C:\Program Files\PostgreSQL\9.6\include\server\port/atomics/generic-msvc.h(79): error C2664: '__int64 _InterlockedCom pareExchange64(volatile __int64 *,__int64,__int64)': 引数 1 を 'volatile uint64 *' から 'volatile __int64 *' へ変換でき ません。 [C:\U sers\kjw_j\Documents\work\plv8msvccheck\libplv8.vcxproj] C:\Program Files\PostgreSQL\9.6\include\server\port/atomics/generic-msvc.h(93): error C2664: '__int64 _InterlockedExc hangeAdd64(volatile __int64 *,__int64)': 引数 1 を 'volatile uint64 *' から 'volatile __int64 *' へ変換できません。 [C:\ Users\kjw_j\D ocuments\work\plv8msvccheck\libplv8.vcxproj] C:\Program Files\PostgreSQL\9.6\include\server\port/atomics/generic-msvc.h(79): error C2664: '__int64 _InterlockedCom pareExchange64(volatile __int64 *,__int64,__int64)': 引数 1 を 'volatile uint64 *' から 'volatile __int64 *' へ変換でき ません。 [C:\U sers\kjw_j\Documents\work\plv8msvccheck\libplv8.vcxproj] C:\Program Files\PostgreSQL\9.6\include\server\port/atomics/generic-msvc.h(93): error C2664: '__int64 _InterlockedExc hangeAdd64(volatile __int64 *,__int64)': 引数 1 を 'volatile uint64 *' から 'volatile __int64 *' へ変換できません。 [C:\ Users\kjw_j\D ocuments\work\plv8msvccheck\libplv8.vcxproj]
これはgccだと通らないヘッダの為、MSVC環境で作業していて発生しました。
こちらは、cl.exeのエラーをよく読めば、書いてある通りだが、 Windows側のAPIへ渡すポインタがsingned int型なのに、PostgreSQL側からはunsigned int型を 渡している為、Cでは問題にならないが、C++では型の符号あり・なしも明確に区別しているようで、これに 抵触してコンパイラーがエラーを出していました。
以下の様の問題の箇所をキャストをつけて修正
static inline bool pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 *expected, uint64 newval) { bool ret; uint64 current; current = _InterlockedCompareExchange64((int64 *)&ptr->value, newval, *expected); ret = current == *expected; *expected = current; return ret; }
#define PG_HAVE_ATOMIC_FETCH_ADD_U64 static inline uint64 pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_) { return _InterlockedExchangeAdd64((int64 *)&ptr->value, add_); }
まとめ
PostgreSQLの機能拡張をWindowsでC++も組み合わせると、
- open関数をマクロでPostgreSQL独自のopen関数に置き換えているので、そのままでは、C++のfstream系の処理が利用できない。
- 符号の有無のチェックが厳格になり、MSVCでは、generic-msvc.hでエラーになる。