From e2555e235f867f3d7a0378e95a45109c8fd2dfbe Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Sat, 7 Feb 2015 15:28:54 -0800 Subject: Change target to output filenames --- .../protobuf/compiler/command_line_interface.cc | 69 +++++++++++++++------- .../protobuf/compiler/command_line_interface.h | 3 + .../compiler/command_line_interface_unittest.cc | 26 ++++++-- 3 files changed, 73 insertions(+), 25 deletions(-) (limited to 'src/google') diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index c8e60bc4..ddd58e2d 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -48,7 +48,6 @@ #include #include -#include #include #ifndef _SHARED_PTR_H #include @@ -254,6 +253,9 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { // format, unless one has already been written. void AddJarManifest(); + // Get name of all output files. + void GetOutputFilenames(vector* output_filenames); + // implements GeneratorContext -------------------------------------- io::ZeroCopyOutputStream* Open(const string& filename); io::ZeroCopyOutputStream* OpenForAppend(const string& filename); @@ -441,6 +443,14 @@ void CommandLineInterface::GeneratorContextImpl::AddJarManifest() { } } +void CommandLineInterface::GeneratorContextImpl::GetOutputFilenames( + vector* output_filenames) { + for (map::iterator iter = files_.begin(); + iter != files_.end(); ++iter) { + output_filenames->push_back(iter->first); + } +} + io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open( const string& filename) { return new MemoryOutputStream(this, filename, false); @@ -670,7 +680,6 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { // We construct a separate GeneratorContext for each output location. Note // that two code generators may output to the same location, in which case // they should share a single GeneratorContext so that OpenForInsert() works. - typedef hash_map GeneratorContextMap; GeneratorContextMap output_directories; // Generate output. @@ -717,16 +726,17 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } } - STLDeleteValues(&output_directories); - - if (!descriptor_set_name_.empty()) { - if (!WriteDescriptorSet(parsed_files)) { + if (!dependency_out_name_.empty()) { + if (!GenerateDependencyManifestFile(parsed_files, output_directories, + &source_tree)) { return 1; } } - if (!dependency_out_name_.empty()) { - if (!GenerateDependencyManifestFile(parsed_files, &source_tree)) { + STLDeleteValues(&output_directories); + + if (!descriptor_set_name_.empty()) { + if (!WriteDescriptorSet(parsed_files)) { return 1; } } @@ -878,6 +888,15 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { cerr << "Missing output directives." << endl; return PARSE_ARGUMENT_FAIL; } + if (mode_ != MODE_COMPILE && !dependency_out_name_.empty()) { + cerr << "Can only use --dependency_out=FILE when generating code." << endl; + return PARSE_ARGUMENT_FAIL; + } + if (!dependency_out_name_.empty() && input_files_.size() > 1) { + cerr << "Can only process one input file when using --dependency_out=FILE." + << endl; + return PARSE_ARGUMENT_FAIL; + } if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) { cerr << "--include_imports only makes sense when combined with " "--descriptor_set_out." << endl; @@ -1028,11 +1047,6 @@ CommandLineInterface::InterpretArgument(const string& name, cerr << name << " requires a non-empty value." << endl; return PARSE_ARGUMENT_FAIL; } - if (mode_ != MODE_COMPILE) { - cerr << "Cannot use --encode or --decode and --dependency_out=FILE at " - "the same time." << endl; - return PARSE_ARGUMENT_FAIL; - } dependency_out_name_ = value; } else if (name == "--include_imports") { @@ -1310,6 +1324,7 @@ bool CommandLineInterface::GenerateOutput( bool CommandLineInterface::GenerateDependencyManifestFile( const vector& parsed_files, + const GeneratorContextMap& output_directories, DiskSourceTree* source_tree) { FileDescriptorSet file_set; @@ -1321,6 +1336,18 @@ bool CommandLineInterface::GenerateDependencyManifestFile( file_set.mutable_file()); } + vector output_filenames; + for (GeneratorContextMap::const_iterator iter = output_directories.begin(); + iter != output_directories.end(); ++iter) { + const string& location = iter->first; + GeneratorContextImpl* directory = iter->second; + vector relative_output_filenames; + directory->GetOutputFilenames(&relative_output_filenames); + for (int i = 0; i < relative_output_filenames.size(); i++) { + output_filenames.push_back(location + relative_output_filenames[i]); + } + } + int fd; do { fd = open(dependency_out_name_.c_str(), @@ -1335,15 +1362,15 @@ bool CommandLineInterface::GenerateDependencyManifestFile( io::FileOutputStream out(fd); io::Printer printer(&out, '$'); - if (dependency_out_name_.compare(0, 1, "/") != 0) { - // Convert relative path to absolute path before print. - printer.Print("$working_directory$/$output_filename$:", - "working_directory", get_current_dir_name(), - "output_filename", dependency_out_name_); - } else { - printer.Print("$output_filename$:", - "output_filename", dependency_out_name_); + for (int i = 0; i < output_filenames.size(); i++) { + printer.Print(output_filenames[i].c_str()); + if (i == output_filenames.size() - 1) { + printer.Print(":"); + } else { + printer.Print(" \\\n"); + } } + for (int i = 0; i < file_set.file_size(); i++) { const FileDescriptorProto& file = file_set.file(i); const string& virtual_file = file.name(); diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index 1df53c4a..7e611c44 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -39,6 +39,7 @@ #define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__ #include +#include #include #include #include @@ -190,6 +191,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { class ErrorPrinter; class GeneratorContextImpl; class MemoryOutputStream; + typedef hash_map GeneratorContextMap; // Clear state from previous Run(). void Clear(); @@ -250,6 +252,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { // Implements the --dependency_out option bool GenerateDependencyManifestFile( const vector& parsed_files, + const GeneratorContextMap& output_directories, DiskSourceTree* source_tree); // Get all transitive dependencies of the given file (including the file diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index f298be75..9e02f729 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -959,6 +959,24 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) { EXPECT_TRUE(descriptor_set.file(1).has_source_code_info()); } +TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileGivenTwoInputs) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); + + Run("protocol_compiler --dependency_out=$tmpdir/manifest " + "--test_out=$tmpdir --proto_path=$tmpdir bar.proto foo.proto"); + + ExpectErrorText( + "Can only process one input file when using --dependency_out=FILE.\n"); +} + TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { CreateTempFile("foo.proto", "syntax = \"proto2\";\n" @@ -976,8 +994,8 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { ExpectNoErrors(); ExpectFileContent("manifest", - "$tmpdir/manifest: $tmpdir/foo.proto\\\n" - " $tmpdir/bar.proto"); + "$tmpdir/bar.proto.MockCodeGenerator.test_generator: " + "$tmpdir/foo.proto\\\n $tmpdir/bar.proto"); } TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForRelativePath) { @@ -1000,8 +1018,8 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForRelativePath) { ExpectNoErrors(); ExpectFileContent("manifest", - "$tmpdir/manifest: $tmpdir/foo.proto\\\n" - " $tmpdir/bar.proto"); + "$tmpdir/bar.proto.MockCodeGenerator.test_generator: " + "$tmpdir/foo.proto\\\n $tmpdir/bar.proto"); File::ChangeWorkingDirectory(current_working_directory); } -- cgit v1.2.3