From: David Reiss Date: Fri, 11 Jan 2008 20:59:03 +0000 (+0000) Subject: Thrift: MinGW port. X-Git-Tag: 0.2.0~1052 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=204420fa56d93adb59ac9fe339bb25e8d9b13fb2;p=common%2Fthrift.git Thrift: MinGW port. Summary: Todd Berman from imeem has contributed a patch that allows the Thrift compiler to be built with MinGW and run on Windows. Reviewed By: mcslee Test Plan: Built the compiler from scratch on Linux. If my changes messed up the MinGW build, I'm sure Todd will yell at me. Revert Plan: ok git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665420 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CONTRIBUTORS b/CONTRIBUTORS index c8665588..51345981 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -11,6 +11,9 @@ Dave Simpson Igor Afanasyev -Perl HttpClient and bugfixes +Todd Berman +- MinGW port of the compiler. + ---------------- Release 20070917 ---------------- diff --git a/compiler/cpp/Makefile.am b/compiler/cpp/Makefile.am index 921a6a9a..2c0368c0 100644 --- a/compiler/cpp/Makefile.am +++ b/compiler/cpp/Makefile.am @@ -23,6 +23,7 @@ thrift_SOURCES = src/thrifty.yy \ src/generate/t_st_generator.cc \ src/globals.h \ src/main.h \ + src/platform.h \ src/md5.h \ src/parse/t_doc.h \ src/parse/t_type.h \ diff --git a/compiler/cpp/src/generate/t_cocoa_generator.cc b/compiler/cpp/src/generate/t_cocoa_generator.cc index fc853658..1356c355 100644 --- a/compiler/cpp/src/generate/t_cocoa_generator.cc +++ b/compiler/cpp/src/generate/t_cocoa_generator.cc @@ -8,6 +8,7 @@ #include #include #include "t_cocoa_generator.h" +#include "platform.h" using namespace std; /** @@ -16,7 +17,7 @@ using namespace std; */ void t_cocoa_generator::init_generator() { // Make output directory - mkdir(get_out_dir().c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + MKDIR(get_out_dir().c_str()); cocoa_prefix_ = program_->get_cocoa_prefix(); // we have a .h header file... diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc index c4654263..620d09ef 100644 --- a/compiler/cpp/src/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/generate/t_cpp_generator.cc @@ -10,6 +10,7 @@ #include #include #include "t_cpp_generator.h" +#include "platform.h" using namespace std; /** @@ -20,7 +21,7 @@ using namespace std; */ void t_cpp_generator::init_generator() { // Make output directory - mkdir(get_out_dir().c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + MKDIR(get_out_dir().c_str()); // Make output file string f_types_name = get_out_dir()+program_name_+"_types.h"; @@ -462,7 +463,7 @@ void t_cpp_generator::generate_struct_definition(ofstream& out, // Isset struct has boolean fields, but only for non-required fields. bool has_nonrequired_fields = false; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - if ((*m_iter)->get_req() != t_field::REQUIRED) + if ((*m_iter)->get_req() != t_field::T_REQUIRED) has_nonrequired_fields = true; } @@ -476,7 +477,7 @@ void t_cpp_generator::generate_struct_definition(ofstream& out, "__isset() : "; bool first = true; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - if ((*m_iter)->get_req() == t_field::REQUIRED) { + if ((*m_iter)->get_req() == t_field::T_REQUIRED) { continue; } if (first) { @@ -491,7 +492,7 @@ void t_cpp_generator::generate_struct_definition(ofstream& out, out << " {}" << endl; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - if ((*m_iter)->get_req() != t_field::REQUIRED) { + if ((*m_iter)->get_req() != t_field::T_REQUIRED) { indent(out) << "bool " << (*m_iter)->get_name() << ";" << endl; } @@ -513,7 +514,7 @@ void t_cpp_generator::generate_struct_definition(ofstream& out, for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { // Most existing Thrift code does not use isset or optional/required, // so we treat "default" fields as required. - if ((*m_iter)->get_req() != t_field::OPTIONAL) { + if ((*m_iter)->get_req() != t_field::T_OPTIONAL) { out << indent() << "if (!(" << (*m_iter)->get_name() << " == rhs." << (*m_iter)->get_name() << "))" << endl << @@ -638,7 +639,7 @@ void t_cpp_generator::generate_local_reflection(std::ofstream& out, indent_up(); for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { indent(out) << "{ " << (*m_iter)->get_key() << ", " << - (((*m_iter)->get_req() == t_field::OPTIONAL) ? "true" : "false") << + (((*m_iter)->get_req() == t_field::T_OPTIONAL) ? "true" : "false") << " }," << endl; } // Zero for the T_STOP marker. @@ -751,7 +752,7 @@ void t_cpp_generator::generate_struct_reader(ofstream& out, // Required variables aren't in __isset, so we need tmp vars to check them. for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if ((*f_iter)->get_req() == t_field::REQUIRED) + if ((*f_iter)->get_req() == t_field::T_REQUIRED) indent(out) << "bool isset_" << (*f_iter)->get_name() << " = false;" << endl; } out << endl; @@ -788,7 +789,7 @@ void t_cpp_generator::generate_struct_reader(ofstream& out, indent_up(); const char *isset_prefix = - ((*f_iter)->get_req() != t_field::REQUIRED) ? "this->__isset." : "isset_"; + ((*f_iter)->get_req() != t_field::T_REQUIRED) ? "this->__isset." : "isset_"; #if 0 // This code throws an exception if the same field is encountered twice. @@ -842,7 +843,7 @@ void t_cpp_generator::generate_struct_reader(ofstream& out, // there might possibly be a chance of continuing. out << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if ((*f_iter)->get_req() == t_field::REQUIRED) + if ((*f_iter)->get_req() == t_field::T_REQUIRED) out << indent() << "if (!isset_" << (*f_iter)->get_name() << ')' << endl << indent() << " throw TProtocolException(TProtocolException::INVALID_DATA);" << endl; @@ -878,7 +879,7 @@ void t_cpp_generator::generate_struct_writer(ofstream& out, indent(out) << "xfer += oprot->writeStructBegin(\"" << name << "\");" << endl; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if ((*f_iter)->get_req() == t_field::OPTIONAL) { + if ((*f_iter)->get_req() == t_field::T_OPTIONAL) { indent(out) << "if (this->__isset." << (*f_iter)->get_name() << ") {" << endl; indent_up(); } @@ -897,7 +898,7 @@ void t_cpp_generator::generate_struct_writer(ofstream& out, // Write field closer indent(out) << "xfer += oprot->writeFieldEnd();" << endl; - if ((*f_iter)->get_req() == t_field::OPTIONAL) { + if ((*f_iter)->get_req() == t_field::T_OPTIONAL) { indent_down(); indent(out) << '}' << endl; } diff --git a/compiler/cpp/src/generate/t_erl_generator.cc b/compiler/cpp/src/generate/t_erl_generator.cc index 44683cd5..02d73614 100644 --- a/compiler/cpp/src/generate/t_erl_generator.cc +++ b/compiler/cpp/src/generate/t_erl_generator.cc @@ -9,6 +9,7 @@ #include #include #include "t_erl_generator.h" +#include "platform.h" using namespace std; @@ -20,7 +21,7 @@ using namespace std; */ void t_erl_generator::init_generator() { // Make output directory - mkdir(get_out_dir().c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + MKDIR(get_out_dir().c_str()); // setup export lines export_lines_first_ = true; diff --git a/compiler/cpp/src/generate/t_hs_generator.cc b/compiler/cpp/src/generate/t_hs_generator.cc index 8746ba4f..6ef7a953 100644 --- a/compiler/cpp/src/generate/t_hs_generator.cc +++ b/compiler/cpp/src/generate/t_hs_generator.cc @@ -9,6 +9,7 @@ #include #include #include "t_hs_generator.h" +#include "platform.h" using namespace std; /* @@ -72,7 +73,7 @@ void t_hs_generator::generate_program() { */ void t_hs_generator::init_generator() { // Make output directory - mkdir(get_out_dir().c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + MKDIR(get_out_dir().c_str()); // Make output file diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc index e0a1be2b..cd4b873d 100644 --- a/compiler/cpp/src/generate/t_java_generator.cc +++ b/compiler/cpp/src/generate/t_java_generator.cc @@ -8,6 +8,7 @@ #include #include #include "t_java_generator.h" +#include "platform.h" using namespace std; /** @@ -18,7 +19,7 @@ using namespace std; */ void t_java_generator::init_generator() { // Make output directory - mkdir(get_out_dir().c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + MKDIR(get_out_dir().c_str()); package_name_ = program_->get_java_package(); string dir = package_name_; @@ -26,12 +27,12 @@ void t_java_generator::init_generator() { string::size_type loc; while ((loc = dir.find(".")) != string::npos) { subdir = subdir + "/" + dir.substr(0, loc); - mkdir(subdir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + MKDIR(subdir.c_str()); dir = dir.substr(loc+1); } if (dir.size() > 0) { subdir = subdir + "/" + dir; - mkdir(subdir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + MKDIR(subdir.c_str()); } package_dir_ = subdir; @@ -565,7 +566,7 @@ void t_java_generator::generate_java_struct_writer(ofstream& out, indent() << "if (this." << (*f_iter)->get_name() << " != null) {" << endl; indent_up(); } - bool optional = bean_style_ && (*f_iter)->get_req() == t_field::OPTIONAL; + bool optional = bean_style_ && (*f_iter)->get_req() == t_field::T_OPTIONAL; if (optional) { out << indent() << "if (this.__isset." << (*f_iter)->get_name() << ") {" << endl; diff --git a/compiler/cpp/src/generate/t_ocaml_generator.cc b/compiler/cpp/src/generate/t_ocaml_generator.cc index 8bf64570..f4f5c4ad 100644 --- a/compiler/cpp/src/generate/t_ocaml_generator.cc +++ b/compiler/cpp/src/generate/t_ocaml_generator.cc @@ -9,6 +9,7 @@ #include #include #include "t_ocaml_generator.h" +#include "platform.h" using namespace std; /* @@ -72,7 +73,7 @@ void t_ocaml_generator::generate_program() { */ void t_ocaml_generator::init_generator() { // Make output directory - mkdir(get_out_dir().c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + MKDIR(get_out_dir().c_str()); // Make output file string f_types_name = get_out_dir()+program_name_+"_types.ml"; diff --git a/compiler/cpp/src/generate/t_perl_generator.cc b/compiler/cpp/src/generate/t_perl_generator.cc index ee6b5b4f..fe554185 100644 --- a/compiler/cpp/src/generate/t_perl_generator.cc +++ b/compiler/cpp/src/generate/t_perl_generator.cc @@ -8,6 +8,7 @@ #include #include #include "t_perl_generator.h" +#include "platform.h" using namespace std; /** @@ -18,13 +19,13 @@ using namespace std; */ void t_perl_generator::init_generator() { // Make output directory - mkdir(get_out_dir().c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + MKDIR(get_out_dir().c_str()); string outdir = get_out_dir(); std::string ns = program_->get_perl_package(); if (ns.length() > 0) { outdir += ns + "/"; - mkdir(outdir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + MKDIR(outdir.c_str()); } // Make output file diff --git a/compiler/cpp/src/generate/t_php_generator.cc b/compiler/cpp/src/generate/t_php_generator.cc index 5b3c979f..1f4ed1fc 100644 --- a/compiler/cpp/src/generate/t_php_generator.cc +++ b/compiler/cpp/src/generate/t_php_generator.cc @@ -8,6 +8,7 @@ #include #include #include "t_php_generator.h" +#include "platform.h" using namespace std; /** @@ -18,7 +19,7 @@ using namespace std; */ void t_php_generator::init_generator() { // Make output directory - mkdir(get_out_dir().c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + MKDIR(get_out_dir().c_str()); // Make output file string f_types_name = get_out_dir()+program_name_+"_types.php"; diff --git a/compiler/cpp/src/generate/t_py_generator.cc b/compiler/cpp/src/generate/t_py_generator.cc index 7f3507f1..ca192ceb 100644 --- a/compiler/cpp/src/generate/t_py_generator.cc +++ b/compiler/cpp/src/generate/t_py_generator.cc @@ -10,6 +10,7 @@ #include #include #include "t_py_generator.h" +#include "platform.h" using namespace std; /** @@ -24,7 +25,7 @@ void t_py_generator::init_generator() { package_dir_ = get_out_dir(); while (true) { // TODO: Do better error checking here. - mkdir(package_dir_.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + MKDIR(package_dir_.c_str()); std::ofstream init_py((package_dir_+"/__init__.py").c_str()); init_py.close(); if (module.empty()) { @@ -1030,13 +1031,16 @@ void t_py_generator::generate_service_remote(t_service* tservice) { // Make file executable, love that bitwise OR action chmod(f_remote_name.c_str(), - S_IRUSR | - S_IWUSR | - S_IXUSR | - S_IRGRP | - S_IXGRP | - S_IROTH | - S_IXOTH); + S_IRUSR + | S_IWUSR + | S_IXUSR +#ifndef MINGW + | S_IRGRP + | S_IXGRP + | S_IROTH + | S_IXOTH +#endif + ); } /** diff --git a/compiler/cpp/src/generate/t_rb_generator.cc b/compiler/cpp/src/generate/t_rb_generator.cc index 59f25de2..56690e8a 100644 --- a/compiler/cpp/src/generate/t_rb_generator.cc +++ b/compiler/cpp/src/generate/t_rb_generator.cc @@ -9,6 +9,7 @@ #include #include #include "t_rb_generator.h" +#include "platform.h" using namespace std; /** @@ -19,7 +20,7 @@ using namespace std; */ void t_rb_generator::init_generator() { // Make output directory - mkdir(get_out_dir().c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + MKDIR(get_out_dir().c_str()); // Make output file string f_types_name = get_out_dir()+program_name_+"_types.rb"; diff --git a/compiler/cpp/src/generate/t_st_generator.cc b/compiler/cpp/src/generate/t_st_generator.cc index c8456bc8..fa7d851c 100644 --- a/compiler/cpp/src/generate/t_st_generator.cc +++ b/compiler/cpp/src/generate/t_st_generator.cc @@ -11,6 +11,7 @@ #include #include #include "t_st_generator.h" +#include "platform.h" using namespace std; /** @@ -21,7 +22,7 @@ using namespace std; */ void t_st_generator::init_generator() { // Make output directory - mkdir(T_ST_DIR, S_IREAD | S_IWRITE | S_IEXEC); + MKDIR(T_ST_DIR); temporary_var = 0; @@ -560,7 +561,7 @@ string t_st_generator::struct_writer(t_struct *tstruct, string sname) { indent_up(); for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { - bool optional = (*fld_iter)->get_req() == t_field::OPTIONAL; + bool optional = (*fld_iter)->get_req() == t_field::T_OPTIONAL; string fname = (*fld_iter)->get_name(); string accessor = sname + " " + sanitize(fname); diff --git a/compiler/cpp/src/generate/t_xsd_generator.cc b/compiler/cpp/src/generate/t_xsd_generator.cc index 04645d2e..7bab56d1 100644 --- a/compiler/cpp/src/generate/t_xsd_generator.cc +++ b/compiler/cpp/src/generate/t_xsd_generator.cc @@ -8,11 +8,12 @@ #include #include #include "t_xsd_generator.h" +#include "platform.h" using namespace std; void t_xsd_generator::init_generator() { // Make output directory - mkdir(get_out_dir().c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + MKDIR(get_out_dir().c_str()); // Make output file string f_php_name = get_out_dir()+program_->get_name()+"_xsd.php"; diff --git a/compiler/cpp/src/main.cc b/compiler/cpp/src/main.cc index ac5fa04c..48774314 100644 --- a/compiler/cpp/src/main.cc +++ b/compiler/cpp/src/main.cc @@ -23,6 +23,11 @@ #include #include +#ifdef MINGW +# include /* for GetFullPathName */ +# include +#endif + // Careful: must include globals first for extern definitions #include "globals.h" @@ -154,6 +159,28 @@ bool gen_cocoa = false; bool gen_st = false; bool gen_recurse = false; +/** + * MinGW doesn't have realpath, so use fallback implementation in that case, + * otherwise this just calls through to realpath + */ +char *saferealpath(const char *path, char *resolved_path) { +#ifdef MINGW + char buf[MAX_PATH]; + char* basename; + DWORD len = GetFullPathName(path, MAX_PATH, buf, &basename); + if (len == 0 || len > MAX_PATH - 1){ + strcpy(resolved_path, path); + } else { + CharLowerBuff(buf, len); + strcpy(resolved_path, buf); + } + return resolved_path; +#else + return realpath(path, resolved_path); +#endif +} + + /** * Report an error to the user. This is called yyerror for historical * reasons (lex and yacc expect the error reporting routine to be called @@ -276,7 +303,7 @@ string include_file(string filename) { if (filename[0] == '/') { // Realpath! char rp[PATH_MAX]; - if (realpath(filename.c_str(), rp) == NULL) { + if (saferealpath(filename.c_str(), rp) == NULL) { pwarning(0, "Cannot open include file %s\n", filename.c_str()); return std::string(); } @@ -298,7 +325,7 @@ string include_file(string filename) { // Realpath! char rp[PATH_MAX]; - if (realpath(sfilename.c_str(), rp) == NULL) { + if (saferealpath(sfilename.c_str(), rp) == NULL) { continue; } @@ -754,7 +781,7 @@ void parse(t_program* program, t_program* parent_program) { parse(*iter, program); } - // Parse the program the file + // Parse the program file g_parse_mode = PROGRAM; g_program = program; g_scope = program->scope(); @@ -1011,6 +1038,16 @@ int main(int argc, char** argv) { usage(); } out_path = arg; + +#ifdef MINGW + //strip out trailing \ on Windows + int last = out_path.length()-1; + if (out_path[last] == '\\') + { + out_path.erase(last); + } +#endif + struct stat sb; if (stat(out_path.c_str(), &sb) < 0) { fprintf(stderr, "Output directory %s is unusable: %s\n", out_path.c_str(), strerror(errno)); @@ -1038,8 +1075,8 @@ int main(int argc, char** argv) { // Real-pathify it char rp[PATH_MAX]; - if (realpath(argv[i], rp) == NULL) { - failure("Could not open input file: %s", argv[i]); + if (saferealpath(argv[i], rp) == NULL) { + failure("Could not open input file with realpath: %s", argv[i]); } string input_file(rp); diff --git a/compiler/cpp/src/parse/t_field.h b/compiler/cpp/src/parse/t_field.h index 35ee1a2f..fb882a96 100644 --- a/compiler/cpp/src/parse/t_field.h +++ b/compiler/cpp/src/parse/t_field.h @@ -34,7 +34,7 @@ class t_field { type_(type), name_(name), key_(key), - req_(OPT_IN_REQ_OUT), + req_(T_OPT_IN_REQ_OUT), value_(NULL), xsd_optional_(false), xsd_nillable_(false), @@ -55,9 +55,9 @@ class t_field { } enum e_req { - REQUIRED, - OPTIONAL, - OPT_IN_REQ_OUT + T_REQUIRED, + T_OPTIONAL, + T_OPT_IN_REQ_OUT, }; void set_req(e_req req) { @@ -117,7 +117,7 @@ class t_field { // but it does the same thing. std::string get_fingerprint_material() const { return boost::lexical_cast(key_) + ":" + - (req_ == OPTIONAL ? "opt-" : "") + + ((req_ == T_OPTIONAL) ? "opt-" : "") + type_->get_fingerprint_material(); } diff --git a/compiler/cpp/src/platform.h b/compiler/cpp/src/platform.h new file mode 100644 index 00000000..df64e9a3 --- /dev/null +++ b/compiler/cpp/src/platform.h @@ -0,0 +1,22 @@ +// Distributed under the Thrift Software License +// +// See accompanying file LICENSE or visit the Thrift site at: +// http://developers.facebook.com/thrift/ + +/** + * define for mkdir,since the method signature + * is different for the non-POSIX MinGW + */ + +#ifdef MINGW +#include +#else +#include +#include +#endif + +#if defined MINGW +#define MKDIR(x) mkdir(x) +#else +#define MKDIR(x) mkdir(x, S_IRWXU | S_IRWXG | S_IRWXO) +#endif diff --git a/compiler/cpp/src/thrifty.yy b/compiler/cpp/src/thrifty.yy index e46d0ef7..9475adf5 100644 --- a/compiler/cpp/src/thrifty.yy +++ b/compiler/cpp/src/thrifty.yy @@ -825,9 +825,9 @@ FieldRequiredness: if (g_parse_mode == PROGRAM) { pwarning(1, "required keyword is ignored in argument lists.\n"); } - $$ = t_field::OPT_IN_REQ_OUT; + $$ = t_field::T_OPT_IN_REQ_OUT; } else { - $$ = t_field::REQUIRED; + $$ = t_field::T_REQUIRED; } } | tok_optional @@ -836,14 +836,14 @@ FieldRequiredness: if (g_parse_mode == PROGRAM) { pwarning(1, "optional keyword is ignored in argument lists.\n"); } - $$ = t_field::OPT_IN_REQ_OUT; + $$ = t_field::T_OPT_IN_REQ_OUT; } else { - $$ = t_field::OPTIONAL; + $$ = t_field::T_OPTIONAL; } } | { - $$ = t_field::OPT_IN_REQ_OUT; + $$ = t_field::T_OPT_IN_REQ_OUT; } FieldValue: