@@ -486,6 +486,7 @@ void FileGenerator::GenerateFile(io::Printer* p, GeneratedFileType file_type,
486486 /* for_bundled_proto = */ is_bundled_proto_);
487487 const std::string header_extension (kHeaderExtension );
488488
489+ absl::flat_hash_set<const FileDescriptor*> file_imports;
489490 switch (file_type) {
490491 case GeneratedFileType::kHeader :
491492 // Generated files bundled with the library get minimal imports,
@@ -500,35 +501,50 @@ void FileGenerator::GenerateFile(io::Printer* p, GeneratedFileType file_type,
500501 if (HeadersUseForwardDeclarations ()) {
501502 // #import any headers for "public imports" in the proto file.
502503 for (int i = 0 ; i < file_->public_dependency_count (); i++) {
503- import_writer. AddFile (file_->public_dependency (i), header_extension );
504+ file_imports. insert (file_->public_dependency (i));
504505 }
506+ } else if (generation_options_.generate_minimal_imports ) {
507+ DetermineNeededDeps (&file_imports, PublicDepsHandling::kForceInclude );
505508 } else {
506509 for (int i = 0 ; i < file_->dependency_count (); i++) {
507- import_writer. AddFile (file_->dependency (i), header_extension );
510+ file_imports. insert (file_->dependency (i));
508511 }
509512 }
510513 break ;
511514 case GeneratedFileType::kSource :
512515 import_writer.AddRuntimeImport (" GPBProtocolBuffers_RuntimeSupport.h" );
513516 import_writer.AddFile (file_, header_extension);
514517 if (HeadersUseForwardDeclarations ()) {
515- // #import the headers for anything that a plain dependency of this
516- // proto file (that means they were just an include, not a "public"
517- // include).
518- absl::flat_hash_set<std::string> public_import_names;
519- for (int i = 0 ; i < file_->public_dependency_count (); i++) {
520- public_import_names.insert (file_->public_dependency (i)->name ());
521- }
522- for (int i = 0 ; i < file_->dependency_count (); i++) {
523- const FileDescriptor* dep = file_->dependency (i);
524- if (!public_import_names.contains (dep->name ())) {
525- import_writer.AddFile (dep, header_extension);
518+ if (generation_options_.generate_minimal_imports ) {
519+ DetermineNeededDeps (&file_imports, PublicDepsHandling::kExclude );
520+ } else {
521+ // #import the headers for anything that a plain dependency of this
522+ // proto file (that means they were just an include, not a "public"
523+ // include).
524+ absl::flat_hash_set<std::string> public_import_names;
525+ for (int i = 0 ; i < file_->public_dependency_count (); i++) {
526+ public_import_names.insert (file_->public_dependency (i)->name ());
527+ }
528+ for (int i = 0 ; i < file_->dependency_count (); i++) {
529+ const FileDescriptor* dep = file_->dependency (i);
530+ if (!public_import_names.contains (dep->name ())) {
531+ file_imports.insert (dep);
532+ }
526533 }
527534 }
528535 }
529536 break ;
530537 }
531538
539+ if (!file_imports.empty ()) {
540+ for (int i = 0 ; i < file_->dependency_count (); i++) {
541+ const FileDescriptor* dep = file_->dependency (i);
542+ if (file_imports.contains (dep)) {
543+ import_writer.AddFile (file_->dependency (i), header_extension);
544+ }
545+ }
546+ }
547+
532548 for (const auto & dep : file_options.extra_files_to_import ) {
533549 import_writer.AddFile (dep, header_extension);
534550 }
@@ -752,6 +768,34 @@ void FileGenerator::EmitFileDescription(io::Printer* p) const {
752768 p->Emit (" \n " );
753769}
754770
771+ void FileGenerator::DetermineNeededDeps (
772+ absl::flat_hash_set<const FileDescriptor*>* deps,
773+ PublicDepsHandling public_deps_handling) const {
774+ // This logic captures the deps that are needed for types thus removing the
775+ // ones that are only deps because they provide the definitions for custom
776+ // options. If protoc gets something like "import options" then this logic can
777+ // go away as the non "import options" deps would be the ones needed.
778+
779+ if (public_deps_handling == PublicDepsHandling::kForceInclude ) {
780+ for (int i = 0 ; i < file_->public_dependency_count (); i++) {
781+ deps->insert (file_->public_dependency (i));
782+ }
783+ }
784+
785+ for (const auto & generator : message_generators_) {
786+ generator->DetermineNeededFiles (deps);
787+ }
788+ for (const auto & generator : extension_generators_) {
789+ generator->DetermineNeededFiles (deps);
790+ }
791+
792+ if (public_deps_handling == PublicDepsHandling::kExclude ) {
793+ for (int i = 0 ; i < file_->public_dependency_count (); i++) {
794+ deps->erase (file_);
795+ }
796+ }
797+ }
798+
755799} // namespace objectivec
756800} // namespace compiler
757801} // namespace protobuf
0 commit comments