1 //===-- MachOUtils.h - Mach-o specific helpers for dsymutil --------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "MachOUtils.h"
12 #include "llvm/Support/FileUtilities.h"
13 #include "llvm/Support/Program.h"
14 #include "llvm/Support/raw_ostream.h"
18 namespace MachOUtils {
20 std::string getArchName(StringRef Arch) {
21 if (Arch.startswith("thumb"))
22 return (llvm::Twine("arm") + Arch.drop_front(5)).str();
26 static bool runLipo(SmallVectorImpl<const char *> &Args) {
27 auto Path = sys::findProgramByName("lipo");
30 errs() << "error: lipo: " << Path.getError().message() << "\n";
36 sys::ExecuteAndWait(*Path, Args.data(), nullptr, nullptr, 0, 0, &ErrMsg);
38 errs() << "error: lipo: " << ErrMsg << "\n";
45 bool generateUniversalBinary(SmallVectorImpl<ArchAndFilename> &ArchFiles,
46 StringRef OutputFileName,
47 const LinkOptions &Options) {
48 // No need to merge one file into a universal fat binary. First, try
49 // to move it (rename) to the final location. If that fails because
50 // of cross-device link issues then copy and delete.
51 if (ArchFiles.size() == 1) {
52 StringRef From(ArchFiles.front().Path);
53 if (sys::fs::rename(From, OutputFileName)) {
54 if (std::error_code EC = sys::fs::copy_file(From, OutputFileName)) {
55 errs() << "error: while copying " << From << " to " << OutputFileName
56 << ": " << EC.message() << "\n";
59 sys::fs::remove(From);
64 SmallVector<const char *, 8> Args;
65 Args.push_back("lipo");
66 Args.push_back("-create");
68 for (auto &Thin : ArchFiles)
69 Args.push_back(Thin.Path.c_str());
71 // Align segments to match dsymutil-classic alignment
72 for (auto &Thin : ArchFiles) {
73 Thin.Arch = getArchName(Thin.Arch);
74 Args.push_back("-segalign");
75 Args.push_back(Thin.Arch.c_str());
79 Args.push_back("-output");
80 Args.push_back(OutputFileName.data());
81 Args.push_back(nullptr);
83 if (Options.Verbose) {
84 outs() << "Running lipo\n";
86 outs() << ' ' << ((Arg == nullptr) ? "\n" : Arg);
89 return Options.NoOutput ? true : runLipo(Args);