in cdk/extra/protobuf/protobuf-3.19.6/src/google/protobuf/compiler/command_line_interface.cc [964:1156]
int CommandLineInterface::Run(int argc, const char* const argv[]) {
Clear();
switch (ParseArguments(argc, argv)) {
case PARSE_ARGUMENT_DONE_AND_EXIT:
return 0;
case PARSE_ARGUMENT_FAIL:
return 1;
case PARSE_ARGUMENT_DONE_AND_CONTINUE:
break;
}
std::vector<const FileDescriptor*> parsed_files;
std::unique_ptr<DiskSourceTree> disk_source_tree;
std::unique_ptr<ErrorPrinter> error_collector;
std::unique_ptr<DescriptorPool> descriptor_pool;
// The SimpleDescriptorDatabases here are the constituents of the
// MergedDescriptorDatabase descriptor_set_in_database, so this vector is for
// managing their lifetimes. Its scope should match descriptor_set_in_database
std::vector<std::unique_ptr<SimpleDescriptorDatabase>>
databases_per_descriptor_set;
std::unique_ptr<MergedDescriptorDatabase> descriptor_set_in_database;
std::unique_ptr<SourceTreeDescriptorDatabase> source_tree_database;
// Any --descriptor_set_in FileDescriptorSet objects will be used as a
// fallback to input_files on command line, so create that db first.
if (!descriptor_set_in_names_.empty()) {
for (const std::string& name : descriptor_set_in_names_) {
std::unique_ptr<SimpleDescriptorDatabase> database_for_descriptor_set =
PopulateSingleSimpleDescriptorDatabase(name);
if (!database_for_descriptor_set) {
return EXIT_FAILURE;
}
databases_per_descriptor_set.push_back(
std::move(database_for_descriptor_set));
}
std::vector<DescriptorDatabase*> raw_databases_per_descriptor_set;
raw_databases_per_descriptor_set.reserve(
databases_per_descriptor_set.size());
for (const std::unique_ptr<SimpleDescriptorDatabase>& db :
databases_per_descriptor_set) {
raw_databases_per_descriptor_set.push_back(db.get());
}
descriptor_set_in_database.reset(
new MergedDescriptorDatabase(raw_databases_per_descriptor_set));
}
if (proto_path_.empty()) {
// If there are no --proto_path flags, then just look in the specified
// --descriptor_set_in files. But first, verify that the input files are
// there.
if (!VerifyInputFilesInDescriptors(descriptor_set_in_database.get())) {
return 1;
}
error_collector.reset(new ErrorPrinter(error_format_));
descriptor_pool.reset(new DescriptorPool(descriptor_set_in_database.get(),
error_collector.get()));
} else {
disk_source_tree.reset(new DiskSourceTree());
if (!InitializeDiskSourceTree(disk_source_tree.get(),
descriptor_set_in_database.get())) {
return 1;
}
error_collector.reset(
new ErrorPrinter(error_format_, disk_source_tree.get()));
source_tree_database.reset(new SourceTreeDescriptorDatabase(
disk_source_tree.get(), descriptor_set_in_database.get()));
source_tree_database->RecordErrorsTo(error_collector.get());
descriptor_pool.reset(new DescriptorPool(
source_tree_database.get(),
source_tree_database->GetValidationErrorCollector()));
}
descriptor_pool->EnforceWeakDependencies(true);
if (!ParseInputFiles(descriptor_pool.get(), disk_source_tree.get(),
&parsed_files)) {
return 1;
}
// 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.
GeneratorContextMap output_directories;
// Generate output.
if (mode_ == MODE_COMPILE) {
for (int i = 0; i < output_directives_.size(); i++) {
std::string output_location = output_directives_[i].output_location;
if (!HasSuffixString(output_location, ".zip") &&
!HasSuffixString(output_location, ".jar") &&
!HasSuffixString(output_location, ".srcjar")) {
AddTrailingSlash(&output_location);
}
auto& generator = output_directories[output_location];
if (!generator) {
// First time we've seen this output location.
generator.reset(new GeneratorContextImpl(parsed_files));
}
if (!GenerateOutput(parsed_files, output_directives_[i],
generator.get())) {
return 1;
}
}
}
// Write all output to disk.
for (const auto& pair : output_directories) {
const std::string& location = pair.first;
GeneratorContextImpl* directory = pair.second.get();
if (HasSuffixString(location, "/")) {
if (!directory->WriteAllToDisk(location)) {
return 1;
}
} else {
if (HasSuffixString(location, ".jar")) {
directory->AddJarManifest();
}
if (!directory->WriteAllToZip(location)) {
return 1;
}
}
}
if (!dependency_out_name_.empty()) {
GOOGLE_DCHECK(disk_source_tree.get());
if (!GenerateDependencyManifestFile(parsed_files, output_directories,
disk_source_tree.get())) {
return 1;
}
}
if (!descriptor_set_out_name_.empty()) {
if (!WriteDescriptorSet(parsed_files)) {
return 1;
}
}
if (mode_ == MODE_ENCODE || mode_ == MODE_DECODE) {
if (codec_type_.empty()) {
// HACK: Define an EmptyMessage type to use for decoding.
DescriptorPool pool;
FileDescriptorProto file;
file.set_name("empty_message.proto");
file.add_message_type()->set_name("EmptyMessage");
GOOGLE_CHECK(pool.BuildFile(file) != NULL);
codec_type_ = "EmptyMessage";
if (!EncodeOrDecode(&pool)) {
return 1;
}
} else {
if (!EncodeOrDecode(descriptor_pool.get())) {
return 1;
}
}
}
if (error_collector->FoundErrors() ||
(fatal_warnings_ && error_collector->FoundWarnings())) {
return 1;
}
if (mode_ == MODE_PRINT) {
switch (print_mode_) {
case PRINT_FREE_FIELDS:
for (int i = 0; i < parsed_files.size(); ++i) {
const FileDescriptor* fd = parsed_files[i];
for (int j = 0; j < fd->message_type_count(); ++j) {
PrintFreeFieldNumbers(fd->message_type(j));
}
}
break;
case PRINT_NONE:
GOOGLE_LOG(ERROR) << "If the code reaches here, it usually means a bug of "
"flag parsing in the CommandLineInterface.";
return 1;
// Do not add a default case.
}
}
return 0;
}