@@ -121,9 +121,12 @@ using google::protobuf::io::win32::setmode;
121121using google::protobuf::io::win32::write;
122122#endif
123123
124- static const char * kDefaultDirectDependenciesViolationMsg =
124+ constexpr absl::string_view kDefaultDirectDependenciesViolationMsg =
125125 " File is imported but not declared in --direct_dependencies: %s" ;
126126
127+ constexpr absl::string_view kDefaultOptionDependenciesViolationMsg =
128+ " File is option imported but not declared in --option_dependencies: %s" ;
129+
127130// Returns true if the text begins with a Windows-style absolute path, starting
128131// with a drive letter. Example: "C:\foo".
129132static bool StartsWithWindowsAbsolutePath (absl::string_view text) {
@@ -958,7 +961,9 @@ const char* const CommandLineInterface::kPathSeparator = ":";
958961
959962CommandLineInterface::CommandLineInterface ()
960963 : direct_dependencies_violation_msg_(
961- kDefaultDirectDependenciesViolationMsg ) {}
964+ kDefaultDirectDependenciesViolationMsg ),
965+ option_dependencies_violation_msg_ (
966+ kDefaultOptionDependenciesViolationMsg ) {}
962967
963968CommandLineInterface::~CommandLineInterface () = default ;
964969
@@ -1645,6 +1650,26 @@ bool CommandLineInterface::ParseInputFiles(
16451650 break ;
16461651 }
16471652 }
1653+
1654+ // Enforce --option_dependencies.
1655+ if (option_dependencies_explicitly_set_) {
1656+ bool indirect_option_imports = false ;
1657+ for (int i = 0 ; i < parsed_file->option_dependency_count (); ++i) {
1658+ if (option_dependencies_.find (parsed_file->option_dependency_name (i)) ==
1659+ option_dependencies_.end ()) {
1660+ indirect_option_imports = true ;
1661+ std::cerr << parsed_file->name () << " : "
1662+ << absl::StrReplaceAll (
1663+ option_dependencies_violation_msg_,
1664+ {{" %s" , parsed_file->option_dependency_name (i)}})
1665+ << std::endl;
1666+ }
1667+ }
1668+ if (indirect_option_imports) {
1669+ result = false ;
1670+ break ;
1671+ }
1672+ }
16481673 }
16491674 descriptor_pool->ClearDirectInputFiles ();
16501675 return result;
@@ -1657,7 +1682,11 @@ void CommandLineInterface::Clear() {
16571682 proto_path_.clear ();
16581683 input_files_.clear ();
16591684 direct_dependencies_.clear ();
1660- direct_dependencies_violation_msg_ = kDefaultDirectDependenciesViolationMsg ;
1685+ direct_dependencies_violation_msg_ =
1686+ std::string (kDefaultDirectDependenciesViolationMsg );
1687+ option_dependencies_.clear ();
1688+ option_dependencies_violation_msg_ =
1689+ std::string (kDefaultOptionDependenciesViolationMsg );
16611690 output_directives_.clear ();
16621691 codec_type_.clear ();
16631692 descriptor_set_in_names_.clear ();
@@ -2139,7 +2168,23 @@ CommandLineInterface::InterpretArgument(const std::string& name,
21392168
21402169 } else if (name == " --direct_dependencies_violation_msg" ) {
21412170 direct_dependencies_violation_msg_ = value;
2171+ } else if (name == " --option_dependencies" ) {
2172+ if (option_dependencies_explicitly_set_) {
2173+ std::cerr << name
2174+ << " may only be passed once. To specify multiple "
2175+ " option dependencies, pass them all as a single "
2176+ " parameter separated by ':'."
2177+ << std::endl;
2178+ return PARSE_ARGUMENT_FAIL;
2179+ }
21422180
2181+ option_dependencies_explicitly_set_ = true ;
2182+ std::vector<std::string> direct =
2183+ absl::StrSplit (value, ' :' , absl::SkipEmpty ());
2184+ ABSL_DCHECK (option_dependencies_.empty ());
2185+ option_dependencies_.insert (direct.begin (), direct.end ());
2186+ } else if (name == " --option_dependencies_violation_msg" ) {
2187+ option_dependencies_violation_msg_ = value;
21432188 } else if (name == " --descriptor_set_in" ) {
21442189 if (!descriptor_set_in_names_.empty ()) {
21452190 std::cerr << name
@@ -2520,7 +2565,13 @@ Parse PROTO_FILES and generate output based on the options given:
25202565 are counted as occupied fields numbers.
25212566 --enable_codegen_trace Enables tracing which parts of protoc are
25222567 responsible for what codegen output. Not supported
2523- by all backends or on all platforms.)" ;
2568+ by all backends or on all platforms.
2569+ --direct_dependencies A colon delimited list of imports that are
2570+ allowed to be used in "import"
2571+ declarations, when explictily provided.
2572+ --option_dependencies A colon delimited list of imports that are
2573+ allowed to be used in "import option"
2574+ declarations, when explicitly provided.)" ;
25242575 std::cout << R"(
25252576 --notices Show notice file and exit.)" ;
25262577 if (!plugin_prefix_.empty ()) {
0 commit comments