kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/cxx/indexer/textproto/textproto_indexer_main.cc (about) 1 /* 2 * Copyright 2019 The Kythe Authors. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <fcntl.h> 18 19 #include <fstream> 20 #include <functional> 21 #include <iostream> 22 23 #include "absl/flags/flag.h" 24 #include "absl/flags/parse.h" 25 #include "absl/flags/usage.h" 26 #include "absl/log/check.h" 27 #include "absl/log/log.h" 28 #include "absl/status/status.h" 29 #include "absl/status/statusor.h" 30 #include "google/protobuf/io/zero_copy_stream_impl.h" 31 #include "kythe/cxx/common/indexing/KytheCachingOutput.h" 32 #include "kythe/cxx/common/indexing/KytheGraphRecorder.h" 33 #include "kythe/cxx/common/init.h" 34 #include "kythe/cxx/common/kzip_reader.h" 35 #include "kythe/cxx/indexer/textproto/analyzer.h" 36 #include "kythe/cxx/indexer/textproto/plugin_registry.h" 37 #include "kythe/proto/analysis.pb.h" 38 #include "kythe/proto/buildinfo.pb.h" 39 40 ABSL_FLAG(std::string, o, "-", "Output filename."); 41 ABSL_FLAG(bool, flush_after_each_entry, true, 42 "Flush output after writing each entry."); 43 ABSL_FLAG(std::string, index_file, "", "Path to a KZip file to index."); 44 45 namespace kythe { 46 namespace lang_textproto { 47 namespace { 48 /// Callback function to process a single compilation unit. 49 using CompilationVisitCallback = std::function<void( 50 const proto::CompilationUnit&, std::vector<proto::FileData> file_data)>; 51 52 /// \brief Reads all compilations from a .kzip file into memory. 53 /// \param path The path from which the file should be read. 54 /// \param visit Callback function called for each compiliation unit within 55 /// the kzip. 56 // TODO(justbuchanan): Refactor so that this function is shared with the cxx 57 // indexer. It was initially copied from cxx/indexer/frontend.cc. 58 void DecodeKzipFile(const std::string& path, 59 const CompilationVisitCallback& visit) { 60 // This forces the BuildDetails proto descriptor to be added to the pool so 61 // we can deserialize it. 62 proto::BuildDetails needed_for_proto_deserialization; 63 64 absl::StatusOr<IndexReader> reader = kythe::KzipReader::Open(path); 65 CHECK(reader.ok()) << "Couldn't open kzip from " << path << ": " 66 << reader.status(); 67 bool compilation_read = false; 68 auto status = reader->Scan([&](absl::string_view digest) { 69 std::vector<proto::FileData> virtual_files; 70 auto compilation = reader->ReadUnit(digest); 71 CHECK(compilation.ok()) << compilation.status(); 72 for (const auto& file : compilation->unit().required_input()) { 73 auto content = reader->ReadFile(file.info().digest()); 74 CHECK(content.ok()) << "Unable to read file with digest: " 75 << file.info().digest() << ": " << content.status(); 76 proto::FileData file_data; 77 file_data.set_content(*content); 78 file_data.mutable_info()->set_path(file.info().path()); 79 file_data.mutable_info()->set_digest(file.info().digest()); 80 virtual_files.push_back(std::move(file_data)); 81 } 82 83 visit(compilation->unit(), std::move(virtual_files)); 84 85 compilation_read = true; 86 return true; 87 }); 88 CHECK(status.ok()) << status; 89 CHECK(compilation_read) << "Missing compilation in " << path; 90 } 91 92 int main(int argc, char* argv[]) { 93 kythe::InitializeProgram(argv[0]); 94 absl::SetProgramUsageMessage( 95 R"(Command-line frontend for the Kythe Textproto indexer. 96 97 Example: 98 indexer -o foo.bin --index_file foo.kzip")"); 99 absl::ParseCommandLine(argc, argv); 100 101 CHECK(!absl::GetFlag(FLAGS_index_file).empty()) 102 << "Please provide a kzip file path to --index_file."; 103 104 std::string output = absl::GetFlag(FLAGS_o); 105 int write_fd = STDOUT_FILENO; 106 if (output != "-") { 107 // TODO: do we need all these flags? 108 write_fd = ::open(output.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 109 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 110 CHECK(write_fd != -1) << "Can't open output file"; 111 } 112 113 google::protobuf::io::FileOutputStream raw_output(write_fd); 114 raw_output.SetCloseOnDelete(true); 115 FileOutputStream kythe_output(&raw_output); 116 kythe_output.set_flush_after_each_entry( 117 absl::GetFlag(FLAGS_flush_after_each_entry)); 118 KytheGraphRecorder recorder(&kythe_output); 119 120 DecodeKzipFile(absl::GetFlag(FLAGS_index_file), 121 [&](const proto::CompilationUnit& unit, 122 std::vector<proto::FileData> file_data) { 123 absl::Status status = lang_textproto::AnalyzeCompilationUnit( 124 kythe::lang_textproto::LoadRegisteredPlugins, unit, 125 file_data, &recorder); 126 CHECK(status.ok()) << status; 127 }); 128 129 return 0; 130 } 131 132 } // namespace 133 } // namespace lang_textproto 134 } // namespace kythe 135 136 int main(int argc, char* argv[]) { kythe::lang_textproto::main(argc, argv); }