From e9abc404df99ef85d3e25aaaccd4aa83e381b98f Mon Sep 17 00:00:00 2001 From: Feng Xiao Date: Thu, 21 May 2015 16:45:47 -0700 Subject: [PATCH] Add default import paths for descriptor.proto and other well-known types to protoc. Change-Id: I4afa295de4c8ed2a4cd0919cf84aedcd1327d9a5 --- .../compiler/command_line_interface.cc | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 567238aed1..8e0a0aa437 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -181,6 +181,68 @@ bool TryCreateParentDirectory(const string& prefix, const string& filename) { return true; } +// Get the absolute path of this protoc binary. +bool GetProtocAbsolutePath(string* path) { +#ifdef _WIN32 + char buffer[MAX_PATH]; + int len = GetModuleFileName(NULL, buffer, MAX_PATH); +#else + char buffer[PATH_MAX]; + int len = readlink("/proc/self/exe", buffer, PATH_MAX); +#endif + if (len > 0) { + path->assign(buffer, len); + return true; + } else { + return false; + } +} + +// Whether a path is where google/protobuf/descriptor.proto and other well-known +// type protos are installed. +bool IsInstalledProtoPath(const string& path) { + // Checking the descriptor.proto file should be good enough. + string file_path = path + "/google/protobuf/descriptor.proto"; + return access(file_path.c_str(), F_OK) != -1; +} + +// Add the paths where google/protobuf/descritor.proto and other well-known +// type protos are installed. +void AddDefaultProtoPaths(vector >* paths) { + // TODO(xiaofeng): The code currently only checks relative paths of where + // the protoc binary is installed. We probably should make it handle more + // cases than that. + string path; + if (!GetProtocAbsolutePath(&path)) { + return; + } + // Strip the binary name. + size_t pos = path.find_last_of("/\\"); + if (pos == string::npos || pos == 0) { + return; + } + path = path.substr(0, pos); + // Check the binary's directory. + if (IsInstalledProtoPath(path)) { + paths->push_back(pair("", path)); + return; + } + // Check if there is an include subdirectory. + if (IsInstalledProtoPath(path + "/include")) { + paths->push_back(pair("", path + "/include")); + return; + } + // Check if the upper level directory has an "include" subdirectory. + pos = path.find_last_of("/\\"); + if (pos == string::npos || pos == 0) { + return; + } + path = path.substr(0, pos); + if (IsInstalledProtoPath(path + "/include")) { + paths->push_back(pair("", path + "/include")); + return; + } +} } // namespace // A MultiFileErrorCollector that prints errors to stderr. @@ -644,6 +706,8 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { break; } + AddDefaultProtoPaths(&proto_path_); + // Set up the source tree. DiskSourceTree source_tree; for (int i = 0; i < proto_path_.size(); i++) {