//===-- llvm-libtool-darwin.cpp - a tool for creating libraries -----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// A utility for creating static and dynamic libraries for Darwin.
//
//===----------------------------------------------------------------------===//

#include "DependencyInfo.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Object/ArchiveWriter.h"
#include "llvm/Object/IRObjectFile.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/MachOUniversalWriter.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TextAPI/Architecture.h"
#include <map>
#include <type_traits>

using namespace llvm;
using namespace llvm::object;

class NewArchiveMemberList;
typedef std::map<uint64_t, NewArchiveMemberList> MembersPerArchitectureMap;

cl::OptionCategory LibtoolCategory("llvm-libtool-darwin Options");

static cl::opt<std::string> OutputFile("o", cl::desc("Specify output filename"),
                                       cl::value_desc("filename"),
                                       cl::cat(LibtoolCategory));

static cl::list<std::string> InputFiles(cl::Positional,
                                        cl::desc("<input files>"),
                                        cl::cat(LibtoolCategory));

static cl::opt<std::string>
    ArchType("arch_only",
             cl::desc("Specify architecture type for output library"),
             cl::value_desc("arch_type"), cl::cat(LibtoolCategory));

enum class Operation { None, Static };

static cl::opt<Operation> LibraryOperation(
    cl::desc("Library Type: "),
    cl::values(
        clEnumValN(Operation::Static, "static",
                   "Produce a statically linked library from the input files")),
    cl::init(Operation::None), cl::cat(LibtoolCategory));

static cl::opt<bool> DeterministicOption(
    "D", cl::desc("Use zero for timestamps and UIDs/GIDs (Default)"),
    cl::init(false), cl::cat(LibtoolCategory));

static cl::opt<bool>
    NonDeterministicOption("U", cl::desc("Use actual timestamps and UIDs/GIDs"),
                           cl::init(false), cl::cat(LibtoolCategory));

static cl::opt<std::string>
    FileList("filelist",
             cl::desc("Pass in file containing a list of filenames"),
             cl::value_desc("listfile[,dirname]"), cl::cat(LibtoolCategory));

static cl::list<std::string> Libraries(
    "l",
    cl::desc(
        "l<x> searches for the library libx.a in the library search path. If"
        " the string 'x' ends with '.o', then the library 'x' is searched for"
        " without prepending 'lib' or appending '.a'"),
    cl::Prefix, cl::cat(LibtoolCategory));

static cl::list<std::string> LibrarySearchDirs(
    "L",
    cl::desc(
        "L<dir> adds <dir> to the list of directories in which to search for"
        " libraries"),
    cl::Prefix, cl::cat(LibtoolCategory));

static cl::opt<std::string> DependencyInfoPath(
    "dependency_info",
    cl::desc("Write an Xcode dependency info file describing the dependencies "
             "of the created library"),
    cl::cat(LibtoolCategory));

static cl::opt<bool>
    VersionOption("V", cl::desc("Print the version number and exit"),
                  cl::cat(LibtoolCategory));

static cl::opt<bool> NoWarningForNoSymbols(
    "no_warning_for_no_symbols",
    cl::desc("Do not warn about files that have no symbols"),
    cl::cat(LibtoolCategory), cl::init(false));

static cl::opt<bool> WarningsAsErrors("warnings_as_errors",
                                      cl::desc("Treat warnings as errors"),
                                      cl::cat(LibtoolCategory),
                                      cl::init(false));

static cl::opt<std::string> IgnoredSyslibRoot("syslibroot", cl::Hidden);

static const std::array<std::string, 3> StandardSearchDirs{
    "/lib",
    "/usr/lib",
    "/usr/local/lib",
};

std::unique_ptr<DependencyInfo> GlobalDependencyInfo;

struct Config {
  bool Deterministic = true; // Updated by 'D' and 'U' modifiers.
  uint32_t ArchCPUType;
  uint32_t ArchCPUSubtype;
};

static Expected<std::string> searchForFile(const Twine &FileName) {
  auto FindLib =
      [FileName](
          ArrayRef<std::string> SearchDirs) -> std::optional<std::string> {
    for (StringRef Dir : SearchDirs) {
      SmallString<128> Path;
      sys::path::append(Path, Dir, FileName);

      if (sys::fs::exists(Path))
        return std::string(Path);

      GlobalDependencyInfo->addMissingInput(Path);
    }
    return std::nullopt;
  };

  std::optional<std::string> Found = FindLib(LibrarySearchDirs);
  if (!Found)
    Found = FindLib(StandardSearchDirs);
  if (Found)
    return *Found;

  return createStringError(std::errc::invalid_argument,
                           "cannot locate file '%s'", FileName.str().c_str());
}

static Error processCommandLineLibraries() {
  for (StringRef BaseName : Libraries) {
    Expected<std::string> FullPath = searchForFile(
        BaseName.endswith(".o") ? BaseName.str() : "lib" + BaseName + ".a");
    if (!FullPath)
      return FullPath.takeError();
    InputFiles.push_back(FullPath.get());
  }

  return Error::success();
}

static Error processFileList() {
  StringRef FileName, DirName;
  std::tie(FileName, DirName) = StringRef(FileList).rsplit(",");

  ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
      MemoryBuffer::getFileOrSTDIN(FileName, /*IsText=*/false,
                                   /*RequiresNullTerminator=*/false);
  if (std::error_code EC = FileOrErr.getError())
    return createFileError(FileName, errorCodeToError(EC));
  const MemoryBuffer &Ref = *FileOrErr.get();

  line_iterator I(Ref, /*SkipBlanks=*/false);
  if (I.is_at_eof())
    return createStringError(std::errc::invalid_argument,
                             "file list file: '%s' is empty",
                             FileName.str().c_str());
  for (; !I.is_at_eof(); ++I) {
    StringRef Line = *I;
    if (Line.empty())
      return createStringError(std::errc::invalid_argument,
                               "file list file: '%s': filename cannot be empty",
                               FileName.str().c_str());

    SmallString<128> Path;
    if (!DirName.empty())
      sys::path::append(Path, DirName, Line);
    else
      sys::path::append(Path, Line);
    InputFiles.push_back(static_cast<std::string>(Path));
  }
  return Error::success();
}

static Error validateArchitectureName(StringRef ArchitectureName) {
  if (!MachOObjectFile::isValidArch(ArchitectureName)) {
    std::string Buf;
    raw_string_ostream OS(Buf);
    for (StringRef Arch : MachOObjectFile::getValidArchs())
      OS << Arch << " ";

    return createStringError(
        std::errc::invalid_argument,
        "invalid architecture '%s': valid architecture names are %s",
        ArchitectureName.str().c_str(), OS.str().c_str());
  }
  return Error::success();
}

static uint64_t getCPUID(uint32_t CPUType, uint32_t CPUSubtype) {
  switch (CPUType) {
  case MachO::CPU_TYPE_ARM:
  case MachO::CPU_TYPE_ARM64:
  case MachO::CPU_TYPE_ARM64_32:
  case MachO::CPU_TYPE_X86_64:
    // We consider CPUSubtype only for the above 4 CPUTypes to match cctools'
    // libtool behavior.
    return static_cast<uint64_t>(CPUType) << 32 | CPUSubtype;
  default:
    return CPUType;
  }
}

// MembersData is an organized collection of members.
struct MembersData {
  // MembersPerArchitectureMap is a mapping from CPU architecture to a list of
  // members.
  MembersPerArchitectureMap MembersPerArchitecture;
  std::vector<std::unique_ptr<MemoryBuffer>> FileBuffers;
};

// NewArchiveMemberList instances serve as collections of archive members and
// information about those members.
class NewArchiveMemberList {
  std::vector<NewArchiveMember> Members;
  // This vector contains the file that each NewArchiveMember from Members came
  // from. Therefore, it has the same size as Members.
  std::vector<StringRef> Files;

public:
  // Add a NewArchiveMember and the file it came from to the list.
  void push_back(NewArchiveMember &&Member, StringRef File) {
    Members.push_back(std::move(Member));
    Files.push_back(File);
  }

  ArrayRef<NewArchiveMember> getMembers() const { return Members; }

  ArrayRef<StringRef> getFiles() const { return Files; }

  static_assert(
      std::is_same<decltype(MembersData::MembersPerArchitecture)::mapped_type,
                   NewArchiveMemberList>(),
      "This test makes sure NewArchiveMemberList is used by MembersData since "
      "the following asserts test invariants required for MembersData.");
  static_assert(
      !std::is_copy_constructible_v<
          decltype(NewArchiveMemberList::Members)::value_type>,
      "MembersData::MembersPerArchitecture has a dependency on "
      "MembersData::FileBuffers so it should not be able to "
      "be copied on its own without FileBuffers. Unfortunately, "
      "is_copy_constructible does not detect whether the container (ie vector) "
      "of a non-copyable type is itself non-copyable so we have to test the "
      "actual type of the stored data (ie, value_type).");
  static_assert(
      !std::is_copy_assignable_v<
          decltype(NewArchiveMemberList::Members)::value_type>,
      "MembersData::MembersPerArchitecture has a dependency on "
      "MembersData::FileBuffers so it should not be able to "
      "be copied on its own without FileBuffers. Unfortunately, "
      "is_copy_constructible does not detect whether the container (ie vector) "
      "of a non-copyable type is itself non-copyable so we have to test the "
      "actual type of the stored data (ie, value_type).");
};

// MembersBuilder collects and organizes all members from the files provided by
// the user.
class MembersBuilder {
public:
  MembersBuilder(LLVMContext &LLVMCtx, const Config &C)
      : LLVMCtx(LLVMCtx), C(C) {}

  Expected<MembersData> build() {
    for (StringRef FileName : InputFiles)
      if (Error E = AddMember(*this, FileName)())
        return std::move(E);

    if (!ArchType.empty()) {
      uint64_t ArchCPUID = getCPUID(C.ArchCPUType, C.ArchCPUSubtype);
      if (Data.MembersPerArchitecture.find(ArchCPUID) ==
          Data.MembersPerArchitecture.end())
        return createStringError(std::errc::invalid_argument,
                                 "no library created (no object files in input "
                                 "files matching -arch_only %s)",
                                 ArchType.c_str());
    }
    return std::move(Data);
  }

private:
  class AddMember {
    MembersBuilder &Builder;
    StringRef FileName;

  public:
    AddMember(MembersBuilder &Builder, StringRef FileName)
        : Builder(Builder), FileName(FileName) {}

    Error operator()() {
      Expected<NewArchiveMember> NewMemberOrErr =
          NewArchiveMember::getFile(FileName, Builder.C.Deterministic);
      if (!NewMemberOrErr)
        return createFileError(FileName, NewMemberOrErr.takeError());
      auto &NewMember = *NewMemberOrErr;

      // For regular archives, use the basename of the object path for the
      // member name.
      NewMember.MemberName = sys::path::filename(NewMember.MemberName);
      file_magic Magic = identify_magic(NewMember.Buf->getBuffer());

      // Flatten archives.
      if (Magic == file_magic::archive)
        return addArchiveMembers(std::move(NewMember));

      // Flatten universal files.
      if (Magic == file_magic::macho_universal_binary)
        return addUniversalMembers(std::move(NewMember));

      // Bitcode files.
      if (Magic == file_magic::bitcode)
        return verifyAndAddIRObject(std::move(NewMember));

      return verifyAndAddMachOObject(std::move(NewMember));
    }

  private:
    // Check that a file's architecture [FileCPUType, FileCPUSubtype]
    // matches the architecture specified under -arch_only flag.
    bool acceptFileArch(uint32_t FileCPUType, uint32_t FileCPUSubtype) {
      if (Builder.C.ArchCPUType != FileCPUType)
        return false;

      switch (Builder.C.ArchCPUType) {
      case MachO::CPU_TYPE_ARM:
      case MachO::CPU_TYPE_ARM64_32:
      case MachO::CPU_TYPE_X86_64:
        return Builder.C.ArchCPUSubtype == FileCPUSubtype;

      case MachO::CPU_TYPE_ARM64:
        if (Builder.C.ArchCPUSubtype == MachO::CPU_SUBTYPE_ARM64_ALL)
          return FileCPUSubtype == MachO::CPU_SUBTYPE_ARM64_ALL ||
                 FileCPUSubtype == MachO::CPU_SUBTYPE_ARM64_V8;
        else
          return Builder.C.ArchCPUSubtype == FileCPUSubtype;

      default:
        return true;
      }
    }

    Error verifyAndAddMachOObject(NewArchiveMember Member) {
      auto MBRef = Member.Buf->getMemBufferRef();
      Expected<std::unique_ptr<object::ObjectFile>> ObjOrErr =
          object::ObjectFile::createObjectFile(MBRef);

      // Throw error if not a valid object file.
      if (!ObjOrErr)
        return createFileError(Member.MemberName, ObjOrErr.takeError());

      // Throw error if not in Mach-O format.
      if (!isa<object::MachOObjectFile>(**ObjOrErr))
        return createStringError(std::errc::invalid_argument,
                                 "'%s': format not supported",
                                 Member.MemberName.data());

      auto *O = cast<MachOObjectFile>(ObjOrErr->get());
      uint32_t FileCPUType, FileCPUSubtype;
      std::tie(FileCPUType, FileCPUSubtype) = MachO::getCPUTypeFromArchitecture(
          MachO::getArchitectureFromName(O->getArchTriple().getArchName()));

      // If -arch_only is specified then skip this file if it doesn't match
      // the architecture specified.
      if (!ArchType.empty() && !acceptFileArch(FileCPUType, FileCPUSubtype)) {
        return Error::success();
      }

      if (!NoWarningForNoSymbols && O->symbols().empty()) {
        Error E = createFileError(
            Member.MemberName,
            createStringError(std::errc::invalid_argument,
                              "has no symbols for architecture %s",
                              O->getArchTriple().getArchName().str().c_str()));

        if (WarningsAsErrors)
          return E;
        WithColor::defaultWarningHandler(std::move(E));
      }

      uint64_t FileCPUID = getCPUID(FileCPUType, FileCPUSubtype);
      Builder.Data.MembersPerArchitecture[FileCPUID].push_back(
          std::move(Member), FileName);
      return Error::success();
    }

    Error verifyAndAddIRObject(NewArchiveMember Member) {
      auto MBRef = Member.Buf->getMemBufferRef();
      Expected<std::unique_ptr<object::IRObjectFile>> IROrErr =
          object::IRObjectFile::create(MBRef, Builder.LLVMCtx);

      // Throw error if not a valid IR object file.
      if (!IROrErr)
        return createFileError(Member.MemberName, IROrErr.takeError());

      Triple TT = Triple(IROrErr->get()->getTargetTriple());

      Expected<uint32_t> FileCPUTypeOrErr = MachO::getCPUType(TT);
      if (!FileCPUTypeOrErr)
        return FileCPUTypeOrErr.takeError();

      Expected<uint32_t> FileCPUSubTypeOrErr = MachO::getCPUSubType(TT);
      if (!FileCPUSubTypeOrErr)
        return FileCPUSubTypeOrErr.takeError();

      // If -arch_only is specified then skip this file if it doesn't match
      // the architecture specified.
      if (!ArchType.empty() &&
          !acceptFileArch(*FileCPUTypeOrErr, *FileCPUSubTypeOrErr)) {
        return Error::success();
      }

      uint64_t FileCPUID = getCPUID(*FileCPUTypeOrErr, *FileCPUSubTypeOrErr);
      Builder.Data.MembersPerArchitecture[FileCPUID].push_back(
          std::move(Member), FileName);
      return Error::success();
    }

    Error addChildMember(const object::Archive::Child &M) {
      Expected<NewArchiveMember> NewMemberOrErr =
          NewArchiveMember::getOldMember(M, Builder.C.Deterministic);
      if (!NewMemberOrErr)
        return NewMemberOrErr.takeError();
      auto &NewMember = *NewMemberOrErr;

      file_magic Magic = identify_magic(NewMember.Buf->getBuffer());

      if (Magic == file_magic::bitcode)
        return verifyAndAddIRObject(std::move(NewMember));

      return verifyAndAddMachOObject(std::move(NewMember));
    }

    Error processArchive(object::Archive &Lib) {
      Error Err = Error::success();
      for (const object::Archive::Child &Child : Lib.children(Err))
        if (Error E = addChildMember(Child))
          return createFileError(FileName, std::move(E));
      if (Err)
        return createFileError(FileName, std::move(Err));

      return Error::success();
    }

    Error addArchiveMembers(NewArchiveMember NewMember) {
      Expected<std::unique_ptr<Archive>> LibOrErr =
          object::Archive::create(NewMember.Buf->getMemBufferRef());
      if (!LibOrErr)
        return createFileError(FileName, LibOrErr.takeError());

      if (Error E = processArchive(**LibOrErr))
        return E;

      // Update vector FileBuffers with the MemoryBuffers to transfer
      // ownership.
      Builder.Data.FileBuffers.push_back(std::move(NewMember.Buf));
      return Error::success();
    }

    Error addUniversalMembers(NewArchiveMember NewMember) {
      Expected<std::unique_ptr<MachOUniversalBinary>> BinaryOrErr =
          MachOUniversalBinary::create(NewMember.Buf->getMemBufferRef());
      if (!BinaryOrErr)
        return createFileError(FileName, BinaryOrErr.takeError());

      auto *UO = BinaryOrErr->get();
      for (const MachOUniversalBinary::ObjectForArch &O : UO->objects()) {

        Expected<std::unique_ptr<MachOObjectFile>> MachOObjOrErr =
            O.getAsObjectFile();
        if (MachOObjOrErr) {
          NewArchiveMember NewMember =
              NewArchiveMember(MachOObjOrErr->get()->getMemoryBufferRef());
          NewMember.MemberName = sys::path::filename(NewMember.MemberName);

          if (Error E = verifyAndAddMachOObject(std::move(NewMember)))
            return E;
          continue;
        }

        Expected<std::unique_ptr<IRObjectFile>> IRObjectOrError =
            O.getAsIRObject(Builder.LLVMCtx);
        if (IRObjectOrError) {
          // A universal file member can be a MachOObjectFile, an IRObject or an
          // Archive. In case we can successfully cast the member as an
          // IRObject, it is safe to throw away the error generated due to
          // casting the object as a MachOObjectFile.
          consumeError(MachOObjOrErr.takeError());

          NewArchiveMember NewMember =
              NewArchiveMember(IRObjectOrError->get()->getMemoryBufferRef());
          NewMember.MemberName = sys::path::filename(NewMember.MemberName);

          if (Error E = verifyAndAddIRObject(std::move(NewMember)))
            return E;
          continue;
        }

        Expected<std::unique_ptr<Archive>> ArchiveOrError = O.getAsArchive();
        if (ArchiveOrError) {
          // A universal file member can be a MachOObjectFile, an IRObject or an
          // Archive. In case we can successfully cast the member as an Archive,
          // it is safe to throw away the error generated due to casting the
          // object as a MachOObjectFile.
          consumeError(MachOObjOrErr.takeError());
          consumeError(IRObjectOrError.takeError());

          if (Error E = processArchive(**ArchiveOrError))
            return E;
          continue;
        }

        Error CombinedError = joinErrors(
            ArchiveOrError.takeError(),
            joinErrors(IRObjectOrError.takeError(), MachOObjOrErr.takeError()));
        return createFileError(FileName, std::move(CombinedError));
      }

      // Update vector FileBuffers with the MemoryBuffers to transfer
      // ownership.
      Builder.Data.FileBuffers.push_back(std::move(NewMember.Buf));
      return Error::success();
    }
  };

  MembersData Data;
  LLVMContext &LLVMCtx;
  const Config &C;
};

static Expected<SmallVector<Slice, 2>>
buildSlices(LLVMContext &LLVMCtx,
            ArrayRef<OwningBinary<Archive>> OutputBinaries) {
  SmallVector<Slice, 2> Slices;

  for (const auto &OB : OutputBinaries) {
    const Archive &A = *OB.getBinary();
    Expected<Slice> ArchiveSlice = Slice::create(A, &LLVMCtx);
    if (!ArchiveSlice)
      return ArchiveSlice.takeError();
    Slices.push_back(*ArchiveSlice);
  }
  return Slices;
}

static Error
checkForDuplicates(const MembersPerArchitectureMap &MembersPerArch) {
  for (const auto &M : MembersPerArch) {
    ArrayRef<NewArchiveMember> Members = M.second.getMembers();
    ArrayRef<StringRef> Files = M.second.getFiles();
    StringMap<std::vector<StringRef>> MembersToFiles;
    for (auto Iterators = std::make_pair(Members.begin(), Files.begin());
         Iterators.first != Members.end();
         ++Iterators.first, ++Iterators.second) {
      assert(Iterators.second != Files.end() &&
             "Files should be the same size as Members.");
      MembersToFiles[Iterators.first->MemberName].push_back(*Iterators.second);
    }

    std::string ErrorData;
    raw_string_ostream ErrorStream(ErrorData);
    for (const auto &MemberToFile : MembersToFiles) {
      if (MemberToFile.getValue().size() > 1) {
        ErrorStream << "file '" << MemberToFile.getKey().str()
                    << "' was specified multiple times.\n";

        for (StringRef OriginalFile : MemberToFile.getValue())
          ErrorStream << "in: " << OriginalFile.str() << '\n';

        ErrorStream << '\n';
      }
    }

    ErrorStream.flush();
    if (ErrorData.size() > 0)
      return createStringError(std::errc::invalid_argument, ErrorData.c_str());
  }
  return Error::success();
}

static Error createStaticLibrary(LLVMContext &LLVMCtx, const Config &C) {
  MembersBuilder Builder(LLVMCtx, C);
  auto DataOrError = Builder.build();
  if (auto Error = DataOrError.takeError())
    return Error;

  const auto &NewMembers = DataOrError->MembersPerArchitecture;

  if (Error E = checkForDuplicates(NewMembers)) {
    if (WarningsAsErrors)
      return E;
    WithColor::defaultWarningHandler(std::move(E));
  }

  if (NewMembers.size() == 1)
    return writeArchive(OutputFile, NewMembers.begin()->second.getMembers(),
                        /*WriteSymtab=*/true,
                        /*Kind=*/object::Archive::K_DARWIN, C.Deterministic,
                        /*Thin=*/false);

  SmallVector<OwningBinary<Archive>, 2> OutputBinaries;
  for (const std::pair<const uint64_t, NewArchiveMemberList> &M : NewMembers) {
    Expected<std::unique_ptr<MemoryBuffer>> OutputBufferOrErr =
        writeArchiveToBuffer(M.second.getMembers(),
                             /*WriteSymtab=*/true,
                             /*Kind=*/object::Archive::K_DARWIN,
                             C.Deterministic,
                             /*Thin=*/false);
    if (!OutputBufferOrErr)
      return OutputBufferOrErr.takeError();
    std::unique_ptr<MemoryBuffer> &OutputBuffer = OutputBufferOrErr.get();

    Expected<std::unique_ptr<Archive>> ArchiveOrError =
        Archive::create(OutputBuffer->getMemBufferRef());
    if (!ArchiveOrError)
      return ArchiveOrError.takeError();
    std::unique_ptr<Archive> &A = ArchiveOrError.get();

    OutputBinaries.push_back(
        OwningBinary<Archive>(std::move(A), std::move(OutputBuffer)));
  }

  Expected<SmallVector<Slice, 2>> Slices = buildSlices(LLVMCtx, OutputBinaries);
  if (!Slices)
    return Slices.takeError();

  llvm::stable_sort(*Slices);
  return writeUniversalBinary(*Slices, OutputFile);
}

static Expected<Config> parseCommandLine(int Argc, char **Argv) {
  Config C;
  cl::ParseCommandLineOptions(Argc, Argv, "llvm-libtool-darwin\n");

  if (LibraryOperation == Operation::None) {
    if (!VersionOption) {
      std::string Error;
      raw_string_ostream Stream(Error);
      LibraryOperation.error("must be specified", "", Stream);
      return createStringError(std::errc::invalid_argument, Error.c_str());
    }
    return C;
  }

  GlobalDependencyInfo =
      DependencyInfoPath.empty()
          ? std::make_unique<DummyDependencyInfo>()
          : std::make_unique<DependencyInfo>(DependencyInfoPath);

  if (OutputFile.empty()) {
    std::string Error;
    raw_string_ostream Stream(Error);
    OutputFile.error("must be specified", "o", Stream);
    return createStringError(std::errc::invalid_argument, Error.c_str());
  }

  if (DeterministicOption && NonDeterministicOption)
    return createStringError(std::errc::invalid_argument,
                             "cannot specify both -D and -U flags");
  else if (NonDeterministicOption)
    C.Deterministic = false;

  if (!Libraries.empty())
    if (Error E = processCommandLineLibraries())
      return std::move(E);

  if (!FileList.empty())
    if (Error E = processFileList())
      return std::move(E);

  if (InputFiles.empty())
    return createStringError(std::errc::invalid_argument,
                             "no input files specified");

  if (ArchType.getNumOccurrences()) {
    if (Error E = validateArchitectureName(ArchType))
      return std::move(E);

    std::tie(C.ArchCPUType, C.ArchCPUSubtype) =
        MachO::getCPUTypeFromArchitecture(
            MachO::getArchitectureFromName(ArchType));
  }

  GlobalDependencyInfo->write("llvm-libtool-darwin " LLVM_VERSION_STRING,
                              InputFiles, OutputFile);

  return C;
}

int main(int Argc, char **Argv) {
  InitLLVM X(Argc, Argv);
  cl::HideUnrelatedOptions({&LibtoolCategory, &getColorCategory()});
  Expected<Config> ConfigOrErr = parseCommandLine(Argc, Argv);
  if (!ConfigOrErr) {
    WithColor::defaultErrorHandler(ConfigOrErr.takeError());
    return EXIT_FAILURE;
  }

  if (VersionOption)
    cl::PrintVersionMessage();

  llvm::InitializeAllTargetInfos();
  llvm::InitializeAllTargetMCs();
  llvm::InitializeAllAsmParsers();

  LLVMContext LLVMCtx;
  Config C = *ConfigOrErr;
  switch (LibraryOperation) {
  case Operation::None:
    break;
  case Operation::Static:
    if (Error E = createStaticLibrary(LLVMCtx, C)) {
      WithColor::defaultErrorHandler(std::move(E));
      return EXIT_FAILURE;
    }
    break;
  }
}
