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); }