| //===-- api_notes.cpp - API Notes Driver ----------------------------------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// This file provides conversion between the YAML (source) and binary forms |
| /// of API notes. |
| /// |
| //===----------------------------------------------------------------------===// |
| #include "clang/APINotes/APINotesYAMLCompiler.h" |
| #include "llvm/Support/CommandLine.h" |
| #include "llvm/Support/FileSystem.h" |
| #include "llvm/Support/MemoryBuffer.h" |
| #include "llvm/Support/raw_ostream.h" |
| #include "llvm/Support/PrettyStackTrace.h" |
| #include "llvm/Support/Signals.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/StringMap.h" |
| #include "llvm/ADT/Triple.h" |
| |
| using namespace llvm; |
| namespace api_notes = clang::api_notes; |
| |
| int cc1apinotes_main(ArrayRef<const char *> Argv, const char *Argv0, |
| void *MainAddr) { |
| |
| // Mark all our options with this category, everything else (except for |
| // -version and -help) will be hidden. |
| static cl::OptionCategory APINotesCategory("API Notes options"); |
| |
| static cl::opt<api_notes::ActionType> |
| Action(cl::desc("Mode:"), cl::init(api_notes::ActionType::None), |
| cl::values( |
| clEnumValN(api_notes::ActionType::YAMLToBinary, |
| "yaml-to-binary", |
| "Convert YAML to binary format"), |
| clEnumValN(api_notes::ActionType::BinaryToYAML, |
| "binary-to-yaml", |
| "Convert binary format to YAML"), |
| clEnumValN(api_notes::ActionType::Dump, |
| "dump", |
| "Parse and dump the output")), |
| cl::cat(APINotesCategory)); |
| |
| static cl::opt<std::string> |
| InputFilename(cl::Positional, cl::desc("<input file>"), |
| cl::Required, cl::cat(APINotesCategory)); |
| |
| static cl::opt<std::string> |
| Target("target", cl::desc("Generate binary format for the given target"), |
| cl::cat(APINotesCategory)); |
| |
| static cl::opt<std::string> |
| OutputFilename("o", cl::desc("Output file name"), cl::cat(APINotesCategory)); |
| |
| cl::HideUnrelatedOptions(APINotesCategory); |
| |
| SmallVector<const char *, 4> Args; |
| Args.push_back(Argv0); |
| Args.append(Argv.begin(), Argv.end()); |
| cl::ParseCommandLineOptions(Args.size(), |
| Args.data(), |
| "Clang API Notes Tool\n"); |
| |
| if (Action == clang::api_notes::ActionType::None) { |
| errs() << "action required\n"; |
| cl::PrintHelpMessage(); |
| return 1; |
| } |
| |
| auto fileBufOrErr = MemoryBuffer::getFile(InputFilename); |
| if (std::error_code EC = fileBufOrErr.getError()) { |
| llvm::errs() << "\n Could not open input file: " + EC.message() << '\n'; |
| return true; |
| } |
| StringRef input = fileBufOrErr.get()->getBuffer(); |
| |
| switch (Action) { |
| case api_notes::ActionType::None: |
| llvm_unreachable("handled above"); |
| |
| case api_notes::ActionType::YAMLToBinary: { |
| if (OutputFilename.empty()) { |
| errs() << "output file is required\n"; |
| cl::PrintHelpMessage(); |
| return 1; |
| } |
| |
| api_notes::OSType targetOS = api_notes::OSType::Absent; |
| // TODO: Check that we've specified the target. |
| if (!Target.empty()) { |
| llvm::Triple target(llvm::Triple::normalize(Target)); |
| switch (target.getOS()) { |
| case llvm::Triple::Darwin: |
| case llvm::Triple::MacOSX: |
| targetOS = api_notes::OSType::OSX; |
| break; |
| case llvm::Triple::IOS: |
| targetOS = api_notes::OSType::IOS; |
| break; |
| case llvm::Triple::WatchOS: |
| targetOS = api_notes::OSType::WatchOS; |
| break; |
| case llvm::Triple::TvOS: |
| targetOS = api_notes::OSType::TvOS; |
| break; |
| default: |
| errs() << "target is not supported\n"; |
| return 1; |
| } |
| } |
| std::error_code EC; |
| llvm::raw_fd_ostream os(OutputFilename, EC, |
| llvm::sys::fs::OpenFlags::F_None); |
| |
| if (api_notes::compileAPINotes(input, /*sourceFile=*/nullptr, os, targetOS)) |
| return 1; |
| |
| os.flush(); |
| |
| return os.has_error(); |
| } |
| |
| case api_notes::ActionType::BinaryToYAML: { |
| if (OutputFilename.empty()) { |
| errs() << "output file required\n"; |
| cl::PrintHelpMessage(); |
| return 1; |
| } |
| |
| std::error_code EC; |
| llvm::raw_fd_ostream os(OutputFilename, EC, |
| llvm::sys::fs::OpenFlags::F_None); |
| |
| if (api_notes::decompileAPINotes(std::move(fileBufOrErr.get()), os)) |
| return 1; |
| |
| os.flush(); |
| |
| return os.has_error(); |
| } |
| |
| case api_notes::ActionType::Dump: |
| return api_notes::parseAndDumpAPINotes(input); |
| } |
| |
| return 1; |
| } |
| |