From 65b7075b5aa64c139ad59a3db35ddddda6a2203f Mon Sep 17 00:00:00 2001 From: dweatherford Date: Wed, 31 Oct 2007 02:18:14 +0000 Subject: [PATCH] [thrift] Output dir selection + updated TSCons Summary: Allows setting the output directory via the new '-o dir' cmdline option. TSCons is updated to use this to put the output in the right place no matter the cwd, so doing dependent builds from different directories won't break. Reviewed By: martin Test Plan: mkdir /tmp/honk; thrift -cpp -java -javabean -php -phpi -py -rb -xsd -perl -erl -ocaml -hs -cocoa -o /tmp/honk Tablet.thrift Revert: svn git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665311 13f79535-47bb-0310-9956-ffa450edef68 --- .../cpp/src/generate/t_cocoa_generator.cc | 6 ++--- compiler/cpp/src/generate/t_cocoa_generator.h | 7 +++-- compiler/cpp/src/generate/t_cpp_generator.cc | 16 ++++++------ compiler/cpp/src/generate/t_cpp_generator.h | 8 +++--- compiler/cpp/src/generate/t_erl_generator.cc | 12 ++++----- compiler/cpp/src/generate/t_erl_generator.h | 3 +-- compiler/cpp/src/generate/t_generator.h | 12 +++++++++ compiler/cpp/src/generate/t_hs_generator.cc | 12 ++++----- compiler/cpp/src/generate/t_hs_generator.h | 7 ++--- compiler/cpp/src/generate/t_java_generator.cc | 5 ++-- compiler/cpp/src/generate/t_java_generator.h | 10 +++---- .../cpp/src/generate/t_ocaml_generator.cc | 12 ++++----- compiler/cpp/src/generate/t_ocaml_generator.h | 6 ++--- compiler/cpp/src/generate/t_perl_generator.cc | 12 ++++----- compiler/cpp/src/generate/t_perl_generator.h | 8 ++---- compiler/cpp/src/generate/t_php_generator.cc | 8 +++--- compiler/cpp/src/generate/t_php_generator.h | 11 +------- compiler/cpp/src/generate/t_py_generator.cc | 2 +- compiler/cpp/src/generate/t_py_generator.h | 6 ++--- compiler/cpp/src/generate/t_rb_generator.cc | 8 +++--- compiler/cpp/src/generate/t_rb_generator.h | 7 ++--- compiler/cpp/src/generate/t_xsd_generator.cc | 6 ++--- compiler/cpp/src/generate/t_xsd_generator.h | 7 +++-- compiler/cpp/src/main.cc | 26 +++++++++++++++++++ compiler/cpp/src/parse/t_program.h | 21 +++++++++++++-- lib/py/src/TSCons.py | 4 ++- 26 files changed, 142 insertions(+), 100 deletions(-) diff --git a/compiler/cpp/src/generate/t_cocoa_generator.cc b/compiler/cpp/src/generate/t_cocoa_generator.cc index fe28a7a3..728cd492 100644 --- a/compiler/cpp/src/generate/t_cocoa_generator.cc +++ b/compiler/cpp/src/generate/t_cocoa_generator.cc @@ -16,12 +16,12 @@ using namespace std; */ void t_cocoa_generator::init_generator() { // Make output directory - mkdir(T_COCOA_DIR, S_IREAD | S_IWRITE | S_IEXEC); + mkdir(get_out_dir().c_str(), S_IREAD | S_IWRITE | S_IEXEC); cocoa_prefix_ = program_->get_cocoa_prefix(); // we have a .h header file... string f_header_name = program_name_+".h"; - string f_header_fullname = string(T_COCOA_DIR)+"/"+f_header_name; + string f_header_fullname = get_out_dir()+f_header_name; f_header_.open(f_header_fullname.c_str()); f_header_ << @@ -33,7 +33,7 @@ void t_cocoa_generator::init_generator() { cocoa_thrift_imports(); // ...and a .m implementation file - string f_impl_name = string(T_COCOA_DIR)+"/"+program_name_+".m"; + string f_impl_name = get_out_dir()+program_name_+".m"; f_impl_.open(f_impl_name.c_str()); f_impl_ << diff --git a/compiler/cpp/src/generate/t_cocoa_generator.h b/compiler/cpp/src/generate/t_cocoa_generator.h index b34ba8b5..9ceac31c 100644 --- a/compiler/cpp/src/generate/t_cocoa_generator.h +++ b/compiler/cpp/src/generate/t_cocoa_generator.h @@ -14,9 +14,6 @@ #include "t_oop_generator.h" -// TODO(mcslee: Paramaterize the output dir -#define T_COCOA_DIR "gen-cocoa" - /** * Objective-C code generator. * @@ -26,7 +23,9 @@ class t_cocoa_generator : public t_oop_generator { public: t_cocoa_generator(t_program* program) : - t_oop_generator(program) {} + t_oop_generator(program) { + out_dir_base_ = "gen-cocoa"; + } /** * Init and close methods diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc index d5f2baf8..34823206 100644 --- a/compiler/cpp/src/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/generate/t_cpp_generator.cc @@ -20,13 +20,13 @@ using namespace std; */ void t_cpp_generator::init_generator() { // Make output directory - mkdir(T_CPP_DIR, S_IREAD | S_IWRITE | S_IEXEC); + mkdir(get_out_dir().c_str(), S_IREAD | S_IWRITE | S_IEXEC); // Make output file - string f_types_name = string(T_CPP_DIR)+"/"+program_name_+"_types.h"; + string f_types_name = get_out_dir()+program_name_+"_types.h"; f_types_.open(f_types_name.c_str()); - string f_types_impl_name = string(T_CPP_DIR)+"/"+program_name_+"_types.cpp"; + string f_types_impl_name = get_out_dir()+program_name_+"_types.cpp"; f_types_impl_.open(f_types_impl_name.c_str()); // Print header @@ -163,11 +163,11 @@ void t_cpp_generator::generate_enum(t_enum* tenum) { * Generates a class that holds all the constants. */ void t_cpp_generator::generate_consts(std::vector consts) { - string f_consts_name = string(T_CPP_DIR)+"/"+program_name_+"_constants.h"; + string f_consts_name = get_out_dir()+program_name_+"_constants.h"; ofstream f_consts; f_consts.open(f_consts_name.c_str()); - string f_consts_impl_name = string(T_CPP_DIR)+"/"+program_name_+"_constants.cpp"; + string f_consts_impl_name = get_out_dir()+program_name_+"_constants.cpp"; ofstream f_consts_impl; f_consts_impl.open(f_consts_impl_name.c_str()); @@ -1002,7 +1002,7 @@ void t_cpp_generator::generate_service(t_service* tservice) { string svcname = tservice->get_name(); // Make output files - string f_header_name = string(T_CPP_DIR)+"/"+svcname+".h"; + string f_header_name = get_out_dir()+svcname+".h"; f_header_.open(f_header_name.c_str()); // Print header file includes @@ -1026,7 +1026,7 @@ void t_cpp_generator::generate_service(t_service* tservice) { endl; // Service implementation file includes - string f_service_name = string(T_CPP_DIR)+"/"+svcname+".cpp"; + string f_service_name = get_out_dir()+svcname+".cpp"; f_service_.open(f_service_name.c_str()); f_service_ << autogen_comment(); @@ -2065,7 +2065,7 @@ void t_cpp_generator::generate_service_skeleton(t_service* tservice) { string svcname = tservice->get_name(); // Service implementation file includes - string f_skeleton_name = string(T_CPP_DIR)+"/"+svcname+"_server.skeleton.cpp"; + string f_skeleton_name = get_out_dir()+svcname+"_server.skeleton.cpp"; string ns = namespace_prefix(tservice->get_program()->get_cpp_namespace()); diff --git a/compiler/cpp/src/generate/t_cpp_generator.h b/compiler/cpp/src/generate/t_cpp_generator.h index 008140a2..574a7d29 100644 --- a/compiler/cpp/src/generate/t_cpp_generator.h +++ b/compiler/cpp/src/generate/t_cpp_generator.h @@ -14,9 +14,6 @@ #include "t_oop_generator.h" -// TODO(mcslee): Paramaterize the output dir -#define T_CPP_DIR "gen-cpp" - /** * C++ code generator. This is legitimacy incarnate. * @@ -26,7 +23,10 @@ class t_cpp_generator : public t_oop_generator { public: t_cpp_generator(t_program* program, bool gen_dense) : t_oop_generator(program), - gen_dense_(gen_dense) {} + gen_dense_(gen_dense) { + + out_dir_base_ = "gen-cpp"; + } /** * Init and close methods diff --git a/compiler/cpp/src/generate/t_erl_generator.cc b/compiler/cpp/src/generate/t_erl_generator.cc index 6e5f9989..c070b767 100644 --- a/compiler/cpp/src/generate/t_erl_generator.cc +++ b/compiler/cpp/src/generate/t_erl_generator.cc @@ -20,15 +20,15 @@ using namespace std; */ void t_erl_generator::init_generator() { // Make output directory - mkdir(T_ERL_DIR, S_IREAD | S_IWRITE | S_IEXEC); + mkdir(get_out_dir().c_str(), S_IREAD | S_IWRITE | S_IEXEC); // setup export lines export_lines_first_ = true; export_types_lines_first_ = true; // types files - string f_types_name = string(T_ERL_DIR)+"/"+program_name_+"_types.erl"; - string f_types_hrl_name = string(T_ERL_DIR)+"/"+program_name_+"_types.hrl"; + string f_types_name = get_out_dir()+program_name_+"_types.erl"; + string f_types_hrl_name = get_out_dir()+program_name_+"_types.hrl"; f_types_file_.open(f_types_name.c_str()); f_types_hrl_file_.open(f_types_hrl_name.c_str()); @@ -47,7 +47,7 @@ void t_erl_generator::init_generator() { f_types_hrl_file_ << render_includes() << endl; // consts file - string f_consts_name = string(T_ERL_DIR)+"/"+program_name_+"_constants.hrl"; + string f_consts_name = get_out_dir()+program_name_+"_constants.hrl"; f_consts_.open(f_consts_name.c_str()); f_consts_ << @@ -511,8 +511,8 @@ void t_erl_generator::generate_service(t_service* tservice) { // ...awesome service_name_[0] = tolower(service_name_[0]); - string f_service_hrl_name = string(T_ERL_DIR)+"/"+service_name_+"_thrift.hrl"; - string f_service_name = string(T_ERL_DIR)+"/"+service_name_+"_thrift.erl"; + string f_service_hrl_name = get_out_dir()+service_name_+"_thrift.hrl"; + string f_service_name = get_out_dir()+service_name_+"_thrift.erl"; f_service_file_.open(f_service_name.c_str()); f_service_hrl_.open(f_service_hrl_name.c_str()); diff --git a/compiler/cpp/src/generate/t_erl_generator.h b/compiler/cpp/src/generate/t_erl_generator.h index cf2c87bc..831bb214 100644 --- a/compiler/cpp/src/generate/t_erl_generator.h +++ b/compiler/cpp/src/generate/t_erl_generator.h @@ -8,8 +8,6 @@ #include "t_oop_generator.h" -#define T_ERL_DIR "gen-erl" - /** * Erlang code generator. * @@ -22,6 +20,7 @@ class t_erl_generator : public t_oop_generator { { program_name_[0] = tolower(program_name_[0]); service_name_[0] = tolower(service_name_[0]); + out_dir_base_ = "gen-erl"; } /** diff --git a/compiler/cpp/src/generate/t_generator.h b/compiler/cpp/src/generate/t_generator.h index beea968d..8452f1f4 100644 --- a/compiler/cpp/src/generate/t_generator.h +++ b/compiler/cpp/src/generate/t_generator.h @@ -78,6 +78,13 @@ class t_generator { return tservice->get_name(); } + /** + * Get the current output directory + */ + virtual std::string get_out_dir() const { + return program_->get_out_path() + out_dir_base_ + "/"; + } + /** * Creates a unique temporary variable name, which is just "name" with a * number appended to it (i.e. name35) @@ -159,6 +166,11 @@ class t_generator { */ std::string service_name_; + /** + * Output type-specifc directory name ("gen-*") + */ + std::string out_dir_base_; + private: /** * Current code indentation level diff --git a/compiler/cpp/src/generate/t_hs_generator.cc b/compiler/cpp/src/generate/t_hs_generator.cc index 920b453b..03d62a4b 100644 --- a/compiler/cpp/src/generate/t_hs_generator.cc +++ b/compiler/cpp/src/generate/t_hs_generator.cc @@ -72,15 +72,15 @@ void t_hs_generator::generate_program() { */ void t_hs_generator::init_generator() { // Make output directory - mkdir(T_HS_DIR, S_IREAD | S_IWRITE | S_IEXEC); + mkdir(get_out_dir().c_str(), S_IREAD | S_IWRITE | S_IEXEC); // Make output file string pname = capitalize(program_name_); - string f_types_name = string(T_HS_DIR)+"/"+pname+"_Types.hs"; + string f_types_name = get_out_dir()+pname+"_Types.hs"; f_types_.open(f_types_name.c_str()); - string f_consts_name = string(T_HS_DIR)+"/"+pname+"_Consts.hs"; + string f_consts_name = get_out_dir()+pname+"_Consts.hs"; f_consts_.open(f_consts_name.c_str()); // Print header @@ -509,7 +509,7 @@ void t_hs_generator::generate_hs_struct_writer(ofstream& out, * @param tservice The service definition */ void t_hs_generator::generate_service(t_service* tservice) { - string f_service_name = string(T_HS_DIR)+"/"+capitalize(service_name_)+".hs"; + string f_service_name = get_out_dir()+capitalize(service_name_)+".hs"; f_service_.open(f_service_name.c_str()); f_service_ << @@ -586,7 +586,7 @@ void t_hs_generator::generate_hs_function_helpers(t_function* tfunction) { * @param tservice The service to generate a header definition for */ void t_hs_generator::generate_service_interface(t_service* tservice) { - string f_iface_name = string(T_HS_DIR)+"/"+capitalize(service_name_)+"_Iface.hs"; + string f_iface_name = get_out_dir()+capitalize(service_name_)+"_Iface.hs"; f_iface_.open(f_iface_name.c_str()); indent(f_iface_) << "module " << capitalize(service_name_) << "_Iface where" << endl; @@ -623,7 +623,7 @@ void t_hs_generator::generate_service_interface(t_service* tservice) { * @param tservice The service to generate a server for. */ void t_hs_generator::generate_service_client(t_service* tservice) { - string f_client_name = string(T_HS_DIR)+"/"+capitalize(service_name_)+"_Client.hs"; + string f_client_name = get_out_dir()+capitalize(service_name_)+"_Client.hs"; f_client_.open(f_client_name.c_str()); vector functions = tservice->get_functions(); diff --git a/compiler/cpp/src/generate/t_hs_generator.h b/compiler/cpp/src/generate/t_hs_generator.h index 41a59b12..bae507ba 100644 --- a/compiler/cpp/src/generate/t_hs_generator.h +++ b/compiler/cpp/src/generate/t_hs_generator.h @@ -14,8 +14,6 @@ #include "t_oop_generator.h" -#define T_HS_DIR "gen-hs" - /** * Haskell code generator. * @@ -24,7 +22,10 @@ class t_hs_generator : public t_oop_generator { public: t_hs_generator(t_program* program) : - t_oop_generator(program) {} + t_oop_generator(program) { + + out_dir_base_ = "gen-hs"; + } /** * Init and close methods diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc index 0bfab75d..a6d2c4a6 100644 --- a/compiler/cpp/src/generate/t_java_generator.cc +++ b/compiler/cpp/src/generate/t_java_generator.cc @@ -18,12 +18,11 @@ using namespace std; */ void t_java_generator::init_generator() { // Make output directory - const char* java_dir = bean_style_ ? T_JAVABEAN_DIR : T_JAVA_DIR; - mkdir(java_dir, S_IREAD | S_IWRITE | S_IEXEC); + mkdir(get_out_dir().c_str(), S_IREAD | S_IWRITE | S_IEXEC); package_name_ = program_->get_java_package(); string dir = package_name_; - string subdir = java_dir; + string subdir = get_out_dir(); string::size_type loc; while ((loc = dir.find(".")) != string::npos) { subdir = subdir + "/" + dir.substr(0, loc); diff --git a/compiler/cpp/src/generate/t_java_generator.h b/compiler/cpp/src/generate/t_java_generator.h index 913b0f9f..d3b85d5d 100644 --- a/compiler/cpp/src/generate/t_java_generator.h +++ b/compiler/cpp/src/generate/t_java_generator.h @@ -14,10 +14,6 @@ #include "t_oop_generator.h" -// TODO(mcslee: Paramaterize the output dir -#define T_JAVA_DIR "gen-java" -#define T_JAVABEAN_DIR "gen-javabean" - /** * Java code generator. * @@ -27,7 +23,11 @@ class t_java_generator : public t_oop_generator { public: t_java_generator(t_program* program, bool bean_style=false) : t_oop_generator(program), - bean_style_(bean_style) {} + bean_style_(bean_style) { + + out_dir_base_ = (bean_style_ ? "gen-javabean" : "gen-java"); + } + /** * Init and close methods diff --git a/compiler/cpp/src/generate/t_ocaml_generator.cc b/compiler/cpp/src/generate/t_ocaml_generator.cc index 0a5f97b0..7bfe4fd6 100644 --- a/compiler/cpp/src/generate/t_ocaml_generator.cc +++ b/compiler/cpp/src/generate/t_ocaml_generator.cc @@ -72,15 +72,15 @@ void t_ocaml_generator::generate_program() { */ void t_ocaml_generator::init_generator() { // Make output directory - mkdir(T_OCAML_DIR, S_IREAD | S_IWRITE | S_IEXEC); + mkdir(get_out_dir().c_str(), S_IREAD | S_IWRITE | S_IEXEC); // Make output file - string f_types_name = string(T_OCAML_DIR)+"/"+program_name_+"_types.ml"; + string f_types_name = get_out_dir()+program_name_+"_types.ml"; f_types_.open(f_types_name.c_str()); - string f_types_i_name = string(T_OCAML_DIR)+"/"+program_name_+"_types.mli"; + string f_types_i_name = get_out_dir()+program_name_+"_types.mli"; f_types_i_.open(f_types_i_name.c_str()); - string f_consts_name = string(T_OCAML_DIR)+"/"+program_name_+"_consts.ml"; + string f_consts_name = get_out_dir()+program_name_+"_consts.ml"; f_consts_.open(f_consts_name.c_str()); // Print header @@ -557,9 +557,9 @@ void t_ocaml_generator::generate_ocaml_struct_writer(ofstream& out, * @param tservice The service definition */ void t_ocaml_generator::generate_service(t_service* tservice) { - string f_service_name = string(T_OCAML_DIR)+"/"+capitalize(service_name_)+".ml"; + string f_service_name = get_out_dir()+capitalize(service_name_)+".ml"; f_service_.open(f_service_name.c_str()); - string f_service_i_name = string(T_OCAML_DIR)+"/"+capitalize(service_name_)+".mli"; + string f_service_i_name = get_out_dir()+capitalize(service_name_)+".mli"; f_service_i_.open(f_service_i_name.c_str()); f_service_ << diff --git a/compiler/cpp/src/generate/t_ocaml_generator.h b/compiler/cpp/src/generate/t_ocaml_generator.h index 1ea9b2f2..331cf224 100644 --- a/compiler/cpp/src/generate/t_ocaml_generator.h +++ b/compiler/cpp/src/generate/t_ocaml_generator.h @@ -14,8 +14,6 @@ #include "t_oop_generator.h" -#define T_OCAML_DIR "gen-ocaml" - /** * OCaml code generator. * @@ -24,7 +22,9 @@ class t_ocaml_generator : public t_oop_generator { public: t_ocaml_generator(t_program* program) : - t_oop_generator(program) {} + t_oop_generator(program) { + out_dir_base_ = "gen-ocaml"; + } /** * Init and close methods diff --git a/compiler/cpp/src/generate/t_perl_generator.cc b/compiler/cpp/src/generate/t_perl_generator.cc index 76a44438..edec0106 100644 --- a/compiler/cpp/src/generate/t_perl_generator.cc +++ b/compiler/cpp/src/generate/t_perl_generator.cc @@ -18,19 +18,19 @@ using namespace std; */ void t_perl_generator::init_generator() { // Make output directory - mkdir(T_PERL_DIR, S_IREAD | S_IWRITE | S_IEXEC); + mkdir(get_out_dir().c_str(), S_IREAD | S_IWRITE | S_IEXEC); - string outdir(T_PERL_DIR); + string outdir = get_out_dir(); std::string ns = program_->get_perl_package(); if (ns.length() > 0) { - outdir += "/" + ns; + outdir += ns + "/"; mkdir(outdir.c_str(), S_IREAD | S_IWRITE | S_IEXEC); } // Make output file - string f_types_name = outdir+"/Types.pm"; + string f_types_name = outdir+"Types.pm"; f_types_.open(f_types_name.c_str()); - string f_consts_name = outdir+"/Constants.pm"; + string f_consts_name = outdir+"Constants.pm"; f_consts_.open(f_consts_name.c_str()); // Print header @@ -465,7 +465,7 @@ void t_perl_generator::generate_perl_struct_writer(ofstream& out, * @param tservice The service definition */ void t_perl_generator::generate_service(t_service* tservice) { - string f_service_name = string(T_PERL_DIR)+"/"+service_name_+".pm"; + string f_service_name = get_out_dir()+service_name_+".pm"; f_service_.open(f_service_name.c_str()); f_service_ << diff --git a/compiler/cpp/src/generate/t_perl_generator.h b/compiler/cpp/src/generate/t_perl_generator.h index a0235439..dcb2e5e3 100644 --- a/compiler/cpp/src/generate/t_perl_generator.h +++ b/compiler/cpp/src/generate/t_perl_generator.h @@ -23,7 +23,8 @@ class t_perl_generator : public t_oop_generator { public: t_perl_generator(t_program* program) : t_oop_generator(program) { - T_PERL_DIR = "gen-perl"; + + out_dir_base_ = "gen-perl"; } /** @@ -147,11 +148,6 @@ class t_perl_generator : public t_oop_generator { private: - /** - * Output directory - */ - char* T_PERL_DIR; - /** * File streams */ diff --git a/compiler/cpp/src/generate/t_php_generator.cc b/compiler/cpp/src/generate/t_php_generator.cc index 2f478faf..0a680a56 100644 --- a/compiler/cpp/src/generate/t_php_generator.cc +++ b/compiler/cpp/src/generate/t_php_generator.cc @@ -18,12 +18,12 @@ using namespace std; */ void t_php_generator::init_generator() { // Make output directory - mkdir(T_PHP_DIR, S_IREAD | S_IWRITE | S_IEXEC); + mkdir(get_out_dir().c_str(), S_IREAD | S_IWRITE | S_IEXEC); // Make output file - string f_types_name = string(T_PHP_DIR)+"/"+program_name_+"_types.php"; + string f_types_name = get_out_dir()+program_name_+"_types.php"; f_types_.open(f_types_name.c_str()); - string f_consts_name = string(T_PHP_DIR)+"/"+program_name_+"_constants.php"; + string f_consts_name = get_out_dir()+program_name_+"_constants.php"; f_consts_.open(f_consts_name.c_str()); // Print header @@ -552,7 +552,7 @@ void t_php_generator::generate_php_struct_writer(ofstream& out, * @param tservice The service definition */ void t_php_generator::generate_service(t_service* tservice) { - string f_service_name = string(T_PHP_DIR)+"/"+service_name_+".php"; + string f_service_name = get_out_dir()+service_name_+".php"; f_service_.open(f_service_name.c_str()); f_service_ << diff --git a/compiler/cpp/src/generate/t_php_generator.h b/compiler/cpp/src/generate/t_php_generator.h index 16aac870..1f2e2584 100644 --- a/compiler/cpp/src/generate/t_php_generator.h +++ b/compiler/cpp/src/generate/t_php_generator.h @@ -25,11 +25,7 @@ class t_php_generator : public t_oop_generator { t_oop_generator(program), binary_inline_(binary_inline), rest_(rest) { - if (binary_inline_) { - T_PHP_DIR = "gen-phpi"; - } else { - T_PHP_DIR = "gen-php"; - } + out_dir_base_ = (binary_inline_ ? "gen-phpi" : "gen-php"); } /** @@ -145,11 +141,6 @@ class t_php_generator : public t_oop_generator { private: - /** - * Output directory - */ - char* T_PHP_DIR; - /** * File streams */ diff --git a/compiler/cpp/src/generate/t_py_generator.cc b/compiler/cpp/src/generate/t_py_generator.cc index 84330583..3dd38928 100644 --- a/compiler/cpp/src/generate/t_py_generator.cc +++ b/compiler/cpp/src/generate/t_py_generator.cc @@ -21,7 +21,7 @@ using namespace std; void t_py_generator::init_generator() { // Make output directory string module = get_real_py_module(program_); - package_dir_ = T_PY_DIR; + package_dir_ = get_out_dir(); while (true) { // TODO: Do better error checking here. mkdir(package_dir_.c_str(), S_IREAD | S_IWRITE | S_IEXEC); diff --git a/compiler/cpp/src/generate/t_py_generator.h b/compiler/cpp/src/generate/t_py_generator.h index 723745fe..c2eed8d0 100644 --- a/compiler/cpp/src/generate/t_py_generator.h +++ b/compiler/cpp/src/generate/t_py_generator.h @@ -14,8 +14,6 @@ #include "t_generator.h" -#define T_PY_DIR "gen-py" - /** * Python code generator. * @@ -24,7 +22,9 @@ class t_py_generator : public t_generator { public: t_py_generator(t_program* program) : - t_generator(program) {} + t_generator(program) { + out_dir_base_ = "gen-py"; + } /** * Init and close methods diff --git a/compiler/cpp/src/generate/t_rb_generator.cc b/compiler/cpp/src/generate/t_rb_generator.cc index 9e3cd3c7..b68ef301 100644 --- a/compiler/cpp/src/generate/t_rb_generator.cc +++ b/compiler/cpp/src/generate/t_rb_generator.cc @@ -19,13 +19,13 @@ using namespace std; */ void t_rb_generator::init_generator() { // Make output directory - mkdir(T_RB_DIR, S_IREAD | S_IWRITE | S_IEXEC); + mkdir(get_out_dir().c_str(), S_IREAD | S_IWRITE | S_IEXEC); // Make output file - string f_types_name = string(T_RB_DIR)+"/"+program_name_+"_types.rb"; + string f_types_name = get_out_dir()+program_name_+"_types.rb"; f_types_.open(f_types_name.c_str()); - string f_consts_name = string(T_RB_DIR)+"/"+program_name_+"_constants.rb"; + string f_consts_name = get_out_dir()+program_name_+"_constants.rb"; f_consts_.open(f_consts_name.c_str()); // Print header @@ -380,7 +380,7 @@ void t_rb_generator::end_namespace(std::ofstream& out, vector modul * @param tservice The service definition */ void t_rb_generator::generate_service(t_service* tservice) { - string f_service_name = string(T_RB_DIR)+"/"+service_name_+".rb"; + string f_service_name = get_out_dir()+service_name_+".rb"; f_service_.open(f_service_name.c_str()); f_service_ << diff --git a/compiler/cpp/src/generate/t_rb_generator.h b/compiler/cpp/src/generate/t_rb_generator.h index 0c7524f9..d5b8abcd 100644 --- a/compiler/cpp/src/generate/t_rb_generator.h +++ b/compiler/cpp/src/generate/t_rb_generator.h @@ -15,8 +15,6 @@ #include "t_oop_generator.h" -#define T_RB_DIR "gen-rb" - /** * Ruby code generator. * @@ -25,7 +23,10 @@ class t_rb_generator : public t_oop_generator { public: t_rb_generator(t_program* program) : - t_oop_generator(program) {} + t_oop_generator(program) { + + out_dir_base_ = "gen-rb"; + } /** * Init and close methods diff --git a/compiler/cpp/src/generate/t_xsd_generator.cc b/compiler/cpp/src/generate/t_xsd_generator.cc index 3f0b8f9a..09100486 100644 --- a/compiler/cpp/src/generate/t_xsd_generator.cc +++ b/compiler/cpp/src/generate/t_xsd_generator.cc @@ -12,10 +12,10 @@ using namespace std; void t_xsd_generator::init_generator() { // Make output directory - mkdir(T_XSD_DIR, S_IREAD | S_IWRITE | S_IEXEC); + mkdir(get_out_dir().c_str(), S_IREAD | S_IWRITE | S_IEXEC); // Make output file - string f_php_name = string(T_XSD_DIR)+"/"+program_->get_name()+"_xsd.php"; + string f_php_name = get_out_dir()+program_->get_name()+"_xsd.php"; f_php_.open(f_php_name.c_str()); f_php_ << @@ -170,7 +170,7 @@ void t_xsd_generator::generate_element(ostream& out, void t_xsd_generator::generate_service(t_service* tservice) { // Make output file - string f_xsd_name = string(T_XSD_DIR)+"/"+tservice->get_name()+".xsd"; + string f_xsd_name = get_out_dir()+tservice->get_name()+".xsd"; f_xsd_.open(f_xsd_name.c_str()); string ns = program_->get_xsd_namespace(); diff --git a/compiler/cpp/src/generate/t_xsd_generator.h b/compiler/cpp/src/generate/t_xsd_generator.h index aa5623fe..31d9f60a 100644 --- a/compiler/cpp/src/generate/t_xsd_generator.h +++ b/compiler/cpp/src/generate/t_xsd_generator.h @@ -12,9 +12,6 @@ #include #include "t_generator.h" -// TODO(mcslee): Paramaterize the output dir -#define T_XSD_DIR "gen-xsd" - /** * XSD generator, creates an XSD for the base types etc. * @@ -23,7 +20,9 @@ class t_xsd_generator : public t_generator { public: t_xsd_generator(t_program* program) : - t_generator(program) {} + t_generator(program) { + out_dir_base_ = "gen-xsd"; + } virtual ~t_xsd_generator() {} diff --git a/compiler/cpp/src/main.cc b/compiler/cpp/src/main.cc index 00780557..468a7b06 100644 --- a/compiler/cpp/src/main.cc +++ b/compiler/cpp/src/main.cc @@ -21,6 +21,7 @@ #include #include #include +#include // Careful: must include globals first for extern definitions #include "globals.h" @@ -566,6 +567,8 @@ void usage() { fprintf(stderr, " -ocaml Generate OCaml output files\n"); fprintf(stderr, " -hs Generate Haskell output files\n"); fprintf(stderr, " -cocoa Generate Cocoa/Objective-C output files\n"); + fprintf(stderr, " -o dir Set the output directory for gen-* packages\n"); + fprintf(stderr, " (default: current directory)\n"); fprintf(stderr, " -I dir Add a directory to the list of directories\n"); fprintf(stderr, " searched for include directives\n"); fprintf(stderr, " -dense Generate metadata for TDenseProtocol (C++)\n"); @@ -770,6 +773,9 @@ void generate(t_program* program) { if (gen_recurse) { const vector& includes = program->get_includes(); for (size_t i = 0; i < includes.size(); ++i) { + // Propogate output path from parent to child programs + includes[i]->set_out_path(program->get_out_path()); + generate(includes[i]); } } @@ -889,6 +895,7 @@ void generate(t_program* program) { */ int main(int argc, char** argv) { int i; + std::string out_path; // Setup time string time_t now = time(NULL); @@ -960,6 +967,22 @@ int main(int argc, char** argv) { usage(); } g_incl_searchpath.push_back(arg); + } else if (strcmp(arg, "-o") == 0) { + arg = argv[++i]; + if (arg == NULL) { + fprintf(stderr, "-o: missing output directory"); + usage(); + } + out_path = arg; + 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)); + return -1; + } + if (! S_ISDIR(sb.st_mode)) { + fprintf(stderr, "Output directory %s exists but is not a directory\n", out_path.c_str()); + return -1; + } } else { fprintf(stderr, "!!! Unrecognized option: %s\n", arg); usage(); @@ -985,6 +1008,9 @@ int main(int argc, char** argv) { // Instance of the global parse tree t_program* program = new t_program(input_file); + if (out_path.size()) { + program->set_out_path(out_path); + } // Initialize global types g_type_void = new t_base_type("void", t_base_type::TYPE_VOID); diff --git a/compiler/cpp/src/parse/t_program.h b/compiler/cpp/src/parse/t_program.h index f7516a35..224c9d5c 100644 --- a/compiler/cpp/src/parse/t_program.h +++ b/compiler/cpp/src/parse/t_program.h @@ -46,12 +46,14 @@ class t_program : public t_doc { public: t_program(std::string path, std::string name) : path_(path), - name_(name) { + name_(name), + out_path_("./") { scope_ = new t_scope(); } t_program(std::string path) : - path_(path) { + path_(path), + out_path_("./") { name_ = program_name(path); scope_ = new t_scope(); } @@ -59,6 +61,9 @@ class t_program : public t_doc { // Path accessor const std::string& get_path() const { return path_; } + // Output path accessor + const std::string& get_out_path() const { return out_path_; } + // Name accessor const std::string& get_name() const { return name_; } @@ -84,6 +89,15 @@ class t_program : public t_doc { // Programs to include const std::vector& get_includes() const { return includes_; } + void set_out_path(std::string out_path) { + out_path_ = out_path; + // Ensure that it ends with a trailing '/' (or '\' for windows machines) + char c = out_path_.at(out_path_.size() - 1); + if (!(c == '/' || c == '\\')) { + out_path_.push_back('/'); + } + } + // Scoping and namespacing void set_namespace(std::string name) { namespace_ = name; @@ -186,6 +200,9 @@ class t_program : public t_doc { // Name std::string name_; + // Output directory + std::string out_path_; + // Namespace std::string namespace_; diff --git a/lib/py/src/TSCons.py b/lib/py/src/TSCons.py index 20490332..ac992faf 100644 --- a/lib/py/src/TSCons.py +++ b/lib/py/src/TSCons.py @@ -6,10 +6,12 @@ # See accompanying file LICENSE or visit the Thrift site at: # http://developers.facebook.com/thrift/ +from os import path from SCons.Builder import Builder def scons_env(env, add=''): - lstr = 'thrift --cpp ' + add + ' $SOURCE' + opath = path.dirname(path.abspath('$TARGET')) + lstr = 'thrift --cpp -o ' + opath + ' ' + add + ' $SOURCE' cppbuild = Builder(action = lstr) env.Append(BUILDERS = {'ThriftCpp' : cppbuild}) -- 2.17.1