From: kholst Date: Wed, 16 Jan 2008 02:47:41 +0000 (+0000) Subject: thrift: Add -cpp_use_include_prefix flag to compiler X-Git-Tag: 0.2.0~1041 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=76f2c88edad82d3f6c0b7407295d9f7263394bdf;p=common%2Fthrift.git thrift: Add -cpp_use_include_prefix flag to compiler Summary: Adds a new flag to allow for a mode where #include statements in generated c++ will include path context information. For example, if my .thrift file includes "foo/bar/baz.thrift", the generated source files will contain #include statements like: #include "foo/bar/gen-cpp/baz_types.h" instead of just: #include "baz_types.h" -cpp_use_include_prefix is OFF by default. Reviewed By: dreiss Test Plan: Tested against multiple thrift input files both with and without the new flag. Revert: OK DiffCamp Revision: 5522 git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665431 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc index 620d09ef..7200b554 100644 --- a/compiler/cpp/src/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/generate/t_cpp_generator.cc @@ -54,7 +54,8 @@ void t_cpp_generator::init_generator() { const vector& includes = program_->get_includes(); for (size_t i = 0; i < includes.size(); ++i) { f_types_ << - "#include \"" << includes[i]->get_name() << "_types.h\"" << endl; + "#include \"" << get_include_prefix(*(includes[i])) << + includes[i]->get_name() << "_types.h\"" << endl; } f_types_ << endl; @@ -69,7 +70,8 @@ void t_cpp_generator::init_generator() { // Include the types file f_types_impl_ << - "#include \"" << program_name_ << "_types.h\"" << endl << + "#include \"" << get_include_prefix(*get_program()) << program_name_ << + "_types.h\"" << endl << endl; // If we are generating local reflection metadata, we need to include @@ -183,13 +185,15 @@ void t_cpp_generator::generate_consts(std::vector consts) { "#ifndef " << program_name_ << "_CONSTANTS_H" << endl << "#define " << program_name_ << "_CONSTANTS_H" << endl << endl << - "#include \"" << program_name_ << "_types.h\"" << endl << + "#include \"" << get_include_prefix(*get_program()) << program_name_ << + "_types.h\"" << endl << endl << ns_open_ << endl << endl; f_consts_impl << - "#include \"" << program_name_ << "_constants.h\"" << endl << + "#include \"" << get_include_prefix(*get_program()) << program_name_ << + "_constants.h\"" << endl << endl << ns_open_ << endl << endl; @@ -1014,11 +1018,14 @@ void t_cpp_generator::generate_service(t_service* tservice) { "#define " << svcname << "_H" << endl << endl << "#include " << endl << - "#include \"" << program_name_ << "_types.h\"" << endl; + "#include \"" << get_include_prefix(*get_program()) << program_name_ << + "_types.h\"" << endl; - if (tservice->get_extends() != NULL) { + t_service* extends_service = tservice->get_extends(); + if (extends_service != NULL) { f_header_ << - "#include \"" << tservice->get_extends()->get_name() << ".h\"" << endl; + "#include \"" << get_include_prefix(*(extends_service->get_program())) << + extends_service->get_name() << ".h\"" << endl; } f_header_ << @@ -1032,7 +1039,8 @@ void t_cpp_generator::generate_service(t_service* tservice) { f_service_ << autogen_comment(); f_service_ << - "#include \"" << svcname << ".h\"" << endl << + "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << + endl << endl << ns_open_ << endl << endl; @@ -2076,7 +2084,7 @@ void t_cpp_generator::generate_service_skeleton(t_service* tservice) { "// This autogenerated skeleton file illustrates how to build a server." << endl << "// You should copy it to another filename to avoid overwriting it." << endl << endl << - "#include \"" << svcname << ".h\"" << endl << + "#include \"" << get_include_prefix(*get_program()) << svcname << ".h\"" << endl << "#include " << endl << "#include " << endl << "#include " << endl << @@ -2867,3 +2875,19 @@ string t_cpp_generator::local_reflection_name(const char* prefix, t_type* ttype) return string() + "trlo_" + prefix + "_" + prog + "_" + name; } + +string t_cpp_generator::get_include_prefix(const t_program& program) const { + string include_prefix = program.get_include_prefix(); + if (!use_include_prefix_ || + (include_prefix.size() > 0 && include_prefix[0] == '/')) { + // if flag is turned off or this is absolute path, return empty prefix + return ""; + } + + string::size_type last_slash = string::npos; + if ((last_slash = include_prefix.rfind("/")) != string::npos) { + return include_prefix.substr(0, last_slash) + "/" + out_dir_base_ + "/"; + } + + return ""; +} diff --git a/compiler/cpp/src/generate/t_cpp_generator.h b/compiler/cpp/src/generate/t_cpp_generator.h index 574a7d29..4bc9783c 100644 --- a/compiler/cpp/src/generate/t_cpp_generator.h +++ b/compiler/cpp/src/generate/t_cpp_generator.h @@ -23,7 +23,8 @@ 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), + use_include_prefix_(false) { out_dir_base_ = "gen-cpp"; } @@ -163,13 +164,28 @@ class t_cpp_generator : public t_oop_generator { (ttype->is_base_type() && (((t_base_type*)ttype)->get_base() == t_base_type::TYPE_STRING)); } + void set_use_include_prefix(bool use_include_prefix) { + use_include_prefix_ = use_include_prefix; + } + private: + /** + * Returns the include prefix to use for a file generated by program, or the + * empty string if no include prefix should be used. + */ + std::string get_include_prefix(const t_program& program) const; /** * True iff we should generate local reflection metadata for TDenseProtocol. */ bool gen_dense_; + /** + * True iff we should use a path prefix in our #include statements for other + * thrift-generated header files. + */ + bool use_include_prefix_; + /** * Strings for namespace, computed once up front then used directly */ diff --git a/compiler/cpp/src/generate/t_generator.h b/compiler/cpp/src/generate/t_generator.h index 72ef1443..734e0338 100644 --- a/compiler/cpp/src/generate/t_generator.h +++ b/compiler/cpp/src/generate/t_generator.h @@ -38,6 +38,8 @@ class t_generator { */ void generate_program(); + const t_program* get_program() const { return program_; } + protected: /** diff --git a/compiler/cpp/src/main.cc b/compiler/cpp/src/main.cc index 131820a8..e0eb4b71 100644 --- a/compiler/cpp/src/main.cc +++ b/compiler/cpp/src/main.cc @@ -105,6 +105,12 @@ string g_curpath; */ vector g_incl_searchpath; +/** + * Should C++ include statements use path prefixes for other thrift-generated + * header files + */ +bool g_cpp_use_include_prefix = false; + /** * Global debug state */ @@ -613,6 +619,8 @@ void usage() { 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, " -cpp_use_include_prefix\n"); + fprintf(stderr, " Make C++ include statements use path prefixes\n"); fprintf(stderr, " -dense Generate metadata for TDenseProtocol (C++)\n"); fprintf(stderr, " -rest Generate PHP REST processors (with -php)\n"); fprintf(stderr, " -nowarn Suppress all compiler warnings (BAD!)\n"); @@ -832,6 +840,7 @@ void generate(t_program* program) { if (gen_cpp) { pverbose("Generating C++\n"); t_cpp_generator* cpp = new t_cpp_generator(program, gen_dense); + cpp->set_use_include_prefix(g_cpp_use_include_prefix); cpp->generate_program(); delete cpp; } @@ -933,7 +942,7 @@ void generate(t_program* program) { csharp->generate_program(); delete csharp; } - + if (dump_docs) { dump_docstrings(program); } @@ -1034,6 +1043,8 @@ int main(int argc, char** argv) { gen_st = true; } else if (strcmp(arg, "-csharp") == 0) { gen_csharp = true; + } else if (strcmp(arg, "-cpp_use_include_prefix") == 0) { + g_cpp_use_include_prefix = true; } else if (strcmp(arg, "-I") == 0) { // An argument of "-I\ asdf" is invalid and has unknown results arg = argv[++i]; @@ -1097,6 +1108,18 @@ int main(int argc, char** argv) { if (out_path.size()) { program->set_out_path(out_path); } + if (g_cpp_use_include_prefix) { + // infer this from the filename passed in + string input_filename = argv[i]; + string include_prefix; + + string::size_type last_slash = string::npos; + if ((last_slash = input_filename.rfind("/")) != string::npos) { + include_prefix = input_filename.substr(0, last_slash); + } + + program->set_include_prefix(include_prefix); + } // 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 62528e6f..7b369d66 100644 --- a/compiler/cpp/src/parse/t_program.h +++ b/compiler/cpp/src/parse/t_program.h @@ -70,6 +70,9 @@ class t_program : public t_doc { // Namespace const std::string& get_namespace() const { return namespace_; } + // Include prefix accessor + const std::string& get_include_prefix() const { return include_prefix_; } + // Accessors for program elements const std::vector& get_typedefs() const { return typedefs_; } const std::vector& get_enums() const { return enums_; } @@ -113,14 +116,35 @@ class t_program : public t_doc { // Includes - void add_include(std::string path) { - includes_.push_back(new t_program(path)); + void add_include(std::string path, std::string include_site) { + t_program* program = new t_program(path); + + // include prefix for this program is the site at which it was included + // (minus the filename) + std::string include_prefix; + std::string::size_type last_slash = std::string::npos; + if ((last_slash = include_site.rfind("/")) != std::string::npos) { + include_prefix = include_site.substr(0, last_slash); + } + + program->set_include_prefix(include_prefix); + includes_.push_back(program); } std::vector& get_includes() { return includes_; } + void set_include_prefix(std::string include_prefix) { + include_prefix_ = include_prefix; + + // this is intended to be a directory; add a trailing slash if necessary + int len = include_prefix_.size(); + if (len > 0 && include_prefix_[len - 1] != '/') { + include_prefix_ += '/'; + } + } + // Language specific namespace / packaging void set_cpp_namespace(std::string cpp_namespace) { @@ -236,6 +260,9 @@ class t_program : public t_doc { // Included programs std::vector includes_; + // Include prefix for this program, if any + std::string include_prefix_; + // Identifier lookup scope t_scope* scope_; diff --git a/compiler/cpp/src/thrifty.yy b/compiler/cpp/src/thrifty.yy index 5be19b36..2b099720 100644 --- a/compiler/cpp/src/thrifty.yy +++ b/compiler/cpp/src/thrifty.yy @@ -347,7 +347,7 @@ Include: if (g_parse_mode == INCLUDES) { std::string path = include_file(std::string($2)); if (!path.empty()) { - g_program->add_include(path); + g_program->add_include(path, std::string($2)); } } }