[dsymutil] Implement support for handling mach-o universal binaries as main input...
[oota-llvm.git] / tools / dsymutil / MachOUtils.cpp
1 //===-- MachOUtils.h - Mach-o specific helpers for dsymutil  --------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "MachOUtils.h"
11 #include "dsymutil.h"
12 #include "llvm/Support/FileUtilities.h"
13 #include "llvm/Support/Program.h"
14 #include "llvm/Support/raw_ostream.h"
15
16 namespace llvm {
17 namespace dsymutil {
18 namespace MachOUtils {
19
20 static bool runLipo(SmallVectorImpl<const char *> &Args) {
21   auto Path = sys::findProgramByName("lipo");
22
23   if (!Path) {
24     errs() << "error: lipo: " << Path.getError().message() << "\n";
25     return false;
26   }
27
28   std::string ErrMsg;
29   int result =
30       sys::ExecuteAndWait(*Path, Args.data(), nullptr, nullptr, 0, 0, &ErrMsg);
31   if (result) {
32     errs() << "error: lipo: " << ErrMsg << "\n";
33     return false;
34   }
35
36   return true;
37 }
38
39 bool generateUniversalBinary(SmallVectorImpl<ArchAndFilename> &ArchFiles,
40                              StringRef OutputFileName,
41                              const LinkOptions &Options) {
42   // No need to merge one file into a universal fat binary. First, try
43   // to move it (rename) to the final location. If that fails because
44   // of cross-device link issues then copy and delete.
45   if (ArchFiles.size() == 1) {
46     StringRef From(ArchFiles.front().Path);
47     if (sys::fs::rename(From, OutputFileName)) {
48       if (std::error_code EC = sys::fs::copy_file(From, OutputFileName)) {
49         errs() << "error: while copying " << From << " to " << OutputFileName
50                << ": " << EC.message() << "\n";
51         return false;
52       }
53       sys::fs::remove(From);
54     }
55     return true;
56   }
57
58   SmallVector<const char *, 8> Args;
59   Args.push_back("lipo");
60   Args.push_back("-create");
61
62   for (auto &Thin : ArchFiles)
63     Args.push_back(Thin.Path.c_str());
64
65   // Align segments to match dsymutil-classic alignment
66   for (auto &Thin : ArchFiles) {
67     Args.push_back("-segalign");
68     Args.push_back(Thin.Arch.c_str());
69     Args.push_back("20");
70   }
71
72   Args.push_back("-output");
73   Args.push_back(OutputFileName.data());
74   Args.push_back(nullptr);
75
76   if (Options.Verbose) {
77     outs() << "Running lipo\n";
78     for (auto Arg : Args)
79       outs() << ' ' << ((Arg == nullptr) ? "\n" : Arg);
80   }
81
82   return Options.NoOutput ? true : runLipo(Args);
83 }
84 }
85 }
86 }