diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 652ce04495..d8ffc57a3e 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -2215,6 +2215,12 @@ bool CommandLineInterface::GenerateDependencyManifestFile( output_filenames.push_back(descriptor_set_out_name_); } + // Some consumers consider first output as the "primary output" (ninja) + // If this doesn't match their primary output it ignores the manifest. + // The unordered map for output_directories means we can't guarantee the order of files. + // Sorting here makes the "primary output" can be whichever is first alphabetically + std::sort(output_filenames.begin(), output_filenames.end()); + int fd; do { fd = open(dependency_out_name_.c_str(), diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index b2cf3d5d10..f82710fe9d 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -1779,6 +1779,41 @@ TEST_F(CommandLineInterfaceTest, "$tmpdir/bar.pb: " "$tmpdir/foo.proto\\\n $tmpdir/bar.proto"); } + +TEST_F(CommandLineInterfaceTest, + DependencyManifestFileIsOrderedByFilePath) { + 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_a " + "--test_out=$tmpdir " + "--descriptor_set_out=$tmpdir/a.pb --proto_path=$tmpdir bar.proto"); + + ExpectNoErrors(); + + ExpectFileContent("manifest_a", + "$tmpdir/a.pb \\\n" + "$tmpdir/bar.proto.MockCodeGenerator.test_generator: " + "$tmpdir/foo.proto\\\n $tmpdir/bar.proto"); + + Run("protocol_compiler --dependency_out=$tmpdir/manifest_z " + "--test_out=$tmpdir " + "--descriptor_set_out=$tmpdir/z.pb --proto_path=$tmpdir bar.proto"); + + ExpectNoErrors(); + + ExpectFileContent("manifest_z", + "$tmpdir/bar.proto.MockCodeGenerator.test_generator \\\n" + "$tmpdir/z.pb: " + "$tmpdir/foo.proto\\\n $tmpdir/bar.proto"); +} #endif // !_WIN32 TEST_F(CommandLineInterfaceTest, TestArgumentFile) {