1affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===- mcld.cpp -----------------------------------------------------------===//
2affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//
3affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//                     The MCLinker Project
4affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//
5affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// This file is distributed under the University of Illinois Open Source
6affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// License. See LICENSE.TXT for details.
7affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//
8affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
9cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
10affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <stdlib.h>
11affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <string>
12affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
13affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/ADT/SmallString.h>
14affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/CommandLine.h>
15affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/FileSystem.h>
16affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/Path.h>
17affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/raw_ostream.h>
18affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <llvm/Support/system_error.h>
19affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
20cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <mcld/Config/Config.h>
21cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
22affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <alone/Config/Config.h>
23affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <alone/Support/LinkerConfig.h>
24affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <alone/Support/Initialization.h>
25affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <alone/Support/TargetLinkerConfigs.h>
26affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <alone/Linker.h>
27affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
28affc150dc44fab1911775a49636d0ce85333b634Zonr Changusing namespace alone;
29affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
30affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
31affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// Compiler Options
32affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
33affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#ifdef TARGET_BUILD
34cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaostatic const std::string OptTargetTripe(DEFAULT_TARGET_TRIPLE_STRING);
35affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#else
36cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaostatic llvm::cl::opt<std::string>
37affc150dc44fab1911775a49636d0ce85333b634Zonr ChangOptTargetTriple("mtriple",
38cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                llvm::cl::desc("Specify the target triple (default: "
39cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                DEFAULT_TARGET_TRIPLE_STRING ")"),
40cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                llvm::cl::init(DEFAULT_TARGET_TRIPLE_STRING),
41cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                llvm::cl::value_desc("triple"));
42cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
43cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaostatic llvm::cl::alias OptTargetTripleC("C", llvm::cl::NotHidden,
44cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                        llvm::cl::desc("Alias for -mtriple"),
45cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                        llvm::cl::aliasopt(OptTargetTriple));
46affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#endif
47affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
48affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
49affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// Command Line Options
50affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// There are four kinds of command line options:
51affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//   1. input, (may be a file, such as -m and /tmp/XXXX.o.)
52affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//   2. scripting options, (represent a subset of link scripting language, such
53affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//      as --defsym.)
54affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//   3. and general options. (the rest of options)
55affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
56affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// General Options
57affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
58affc150dc44fab1911775a49636d0ce85333b634Zonr Changstatic llvm::cl::opt<std::string>
59affc150dc44fab1911775a49636d0ce85333b634Zonr ChangOptOutputFilename("o",
60affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                  llvm::cl::desc("Output filename"),
61affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                  llvm::cl::value_desc("filename"));
62affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
63affc150dc44fab1911775a49636d0ce85333b634Zonr Changstatic llvm::cl::opt<std::string>
64cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoOptSysRoot("sysroot", llvm::cl::desc("Use directory as the location of the "
65cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                     "sysroot, overriding the configure-time "
66cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                     "default."),
67affc150dc44fab1911775a49636d0ce85333b634Zonr Chang           llvm::cl::value_desc("directory"),
68affc150dc44fab1911775a49636d0ce85333b634Zonr Chang           llvm::cl::ValueRequired);
69affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
70affc150dc44fab1911775a49636d0ce85333b634Zonr Changstatic llvm::cl::list<std::string>
71affc150dc44fab1911775a49636d0ce85333b634Zonr ChangOptSearchDirList("L",
72affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                 llvm::cl::ZeroOrMore,
73cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                 llvm::cl::desc("Add path searchdir to the list of paths that "
74cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                "mcld will search for archive libraries and "
75cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                                "mcld control scripts."),
76affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                 llvm::cl::value_desc("searchdir"),
77affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                 llvm::cl::Prefix);
78affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
79affc150dc44fab1911775a49636d0ce85333b634Zonr Changstatic llvm::cl::opt<std::string>
80affc150dc44fab1911775a49636d0ce85333b634Zonr ChangOptSOName("soname",
81affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          llvm::cl::desc("Set internal name of shared library"),
82affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          llvm::cl::value_desc("name"));
83affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
84affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
85affc150dc44fab1911775a49636d0ce85333b634Zonr Changstatic llvm::cl::opt<bool>
86affc150dc44fab1911775a49636d0ce85333b634Zonr ChangOptShared("shared",
87affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          llvm::cl::desc("Create a shared library."),
88affc150dc44fab1911775a49636d0ce85333b634Zonr Chang          llvm::cl::init(false));
89affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
90cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaostatic llvm::cl::opt<bool>
91cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoOptBsymbolic("Bsymbolic",
92cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao             llvm::cl::desc("Bind references within the shared library."),
93cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao             llvm::cl::init(true));
94cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
95affc150dc44fab1911775a49636d0ce85333b634Zonr Changstatic llvm::cl::opt<std::string>
96affc150dc44fab1911775a49636d0ce85333b634Zonr ChangOptDyld("dynamic-linker",
97affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        llvm::cl::desc("Set the name of the dynamic linker."),
98affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        llvm::cl::value_desc("Program"));
99affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
100affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
101affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// Inputs
102affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
103affc150dc44fab1911775a49636d0ce85333b634Zonr Changstatic llvm::cl::list<std::string>
104affc150dc44fab1911775a49636d0ce85333b634Zonr ChangOptInputObjectFiles(llvm::cl::Positional,
105affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                    llvm::cl::desc("[input object files]"),
106cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                    llvm::cl::OneOrMore);
107affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
108affc150dc44fab1911775a49636d0ce85333b634Zonr Changstatic llvm::cl::list<std::string>
109affc150dc44fab1911775a49636d0ce85333b634Zonr ChangOptNameSpecList("l",
110affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                llvm::cl::ZeroOrMore,
111affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                llvm::cl::desc("Add the archive or object file specified by "
112affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                               "namespec to the list of files to link."),
113affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                llvm::cl::value_desc("namespec"),
114affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                llvm::cl::Prefix);
115affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
116affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
117affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// Scripting Options
118affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
119affc150dc44fab1911775a49636d0ce85333b634Zonr Changstatic llvm::cl::list<std::string>
120affc150dc44fab1911775a49636d0ce85333b634Zonr ChangOptWrapList("wrap",
121affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            llvm::cl::ZeroOrMore,
122affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            llvm::cl::desc("Use a wrap function fo symbol."),
123affc150dc44fab1911775a49636d0ce85333b634Zonr Chang            llvm::cl::value_desc("symbol"));
124affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
125cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaostatic llvm::cl::list<std::string>
126cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei LiaoOptPortableList("portable",
127cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                llvm::cl::ZeroOrMore,
128cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                llvm::cl::desc("Use a portable function to symbol."),
129cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                llvm::cl::value_desc("symbol"));
130cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
131affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
132affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// Helper Functions
133affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
134affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// Override "mcld -version"
135cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaostatic void MCLDVersionPrinter() {
136affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  llvm::raw_ostream &os = llvm::outs();
137affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  os << "mcld (The MCLinker Project, http://mclinker.googlecode.com/):\n"
138cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao     << "  version: "MCLD_VERSION"\n"
139affc150dc44fab1911775a49636d0ce85333b634Zonr Chang     << "  Default target: " << DEFAULT_TARGET_TRIPLE_STRING << "\n";
140affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
141affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  os << "\n";
142affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
143affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  os << "LLVM (http://llvm.org/):\n";
144cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
145affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return;
146affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
147affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
148affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#define DEFAULT_OUTPUT_PATH "a.out"
149affc150dc44fab1911775a49636d0ce85333b634Zonr Changstatic inline
150cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaostd::string DetermineOutputFilename(const std::string &pOutputPath) {
151affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!pOutputPath.empty()) {
152affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return pOutputPath;
153affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
154affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
155affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // User does't specify the value to -o
156affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (OptInputObjectFiles.size() > 1) {
157affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    llvm::errs() << "Use " DEFAULT_OUTPUT_PATH " for output file!\n";
158affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return DEFAULT_OUTPUT_PATH;
159affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
160affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
161affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // There's only one input file
162affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  const std::string &input_path = OptInputObjectFiles[0];
163affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  llvm::SmallString<200> output_path(input_path);
164affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
165affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  llvm::error_code err = llvm::sys::fs::make_absolute(output_path);
166affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (llvm::errc::success != err) {
167affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    llvm::errs() << "Failed to determine the absolute path of `" << input_path
168affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                 << "'! (detail: " << err.message() << ")\n";
169affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return "";
170affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
171affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
172affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  llvm::sys::path::remove_filename(output_path);
173affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  llvm::sys::path::append(output_path, "a.out");
174affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
175affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return output_path.c_str();
176affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
177affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
178affc150dc44fab1911775a49636d0ce85333b634Zonr Changstatic inline
179cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaobool ConfigLinker(Linker &pLinker, const std::string &pOutputFilename) {
180affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  LinkerConfig* config = NULL;
181affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
182affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#ifdef TARGET_BUILD
183affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  config = new (std::nothrow) DefaultLinkerConfig();
184affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#else
185affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  config = new (std::nothrow) LinkerConfig(OptTargetTriple);
186affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#endif
187affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (config == NULL) {
188affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    llvm::errs() << "Out of memory when create the linker configuration!\n";
189affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
190affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
191affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
192cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // Setup the configuration accroding to the command line options.
193cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
194cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // 1. Set up soname.
195cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (!OptSOName.empty()) {
196affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    config->setSOName(OptSOName);
197cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  } else {
198affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    config->setSOName(pOutputFilename);
199cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  }
200affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
201cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // 2. If given, set up sysroot.
202cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (!OptSysRoot.empty()) {
203affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    config->setSysRoot(OptSysRoot);
204cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  }
205affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
206cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // 3. If given, set up dynamic linker path.
207cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  if (!OptDyld.empty()) {
208affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    config->setDyld(OptDyld);
209cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  }
210affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
211cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // 4. If given, set up wrapped symbols.
212cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  llvm::cl::list<std::string>::iterator wrap, wrap_end = OptWrapList.end();
213cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  for (wrap = OptWrapList.begin(); wrap != wrap_end; ++wrap) {
214affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    config->addWrap(*wrap);
215cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  }
216cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
217cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // 5. If given, set up portable symbols.
218cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  llvm::cl::list<std::string>::iterator portable, portable_end = OptPortableList.end();
219cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  for (portable = OptPortableList.begin(); portable != portable_end; ++portable) {
220cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    config->addPortable(*portable);
221cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  }
222affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
223cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // 6. if given, set up search directories.
224cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  llvm::cl::list<std::string>::iterator sdir, sdir_end = OptSearchDirList.end();
225cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  for (sdir = OptSearchDirList.begin(); sdir != sdir_end; ++sdir) {
226affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    config->addSearchDir(*sdir);
227cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  }
228affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
229cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // set up default search directories
230cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  config->addSearchDir("=/lib");
231cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  config->addSearchDir("=/usr/lib");
232cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
233cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // 7. Set up output's type.
234cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  config->setShared(OptShared);
235affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
236cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // 8. Set up -Bsymbolic.
237cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  config->setBsymbolic(OptBsymbolic);
238cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
239cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  Linker::ErrorCode result = pLinker.config(*config);
240affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (Linker::kSuccess != result) {
241affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    llvm::errs() << "Failed to configure the linker! (detail: "
242cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                 << Linker::GetErrorString(result) << ")\n";
243affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
244affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
245affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
246affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
247affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
248affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
249affc150dc44fab1911775a49636d0ce85333b634Zonr Changstatic inline
250cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaobool PrepareInputOutput(Linker &pLinker, const std::string &pOutputPath) {
251cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // -----  Set output  ----- //
252cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
253cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // FIXME: Current MCLinker requires one to set up output before inputs. The
254cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // constraint will be relaxed in the furture.
255affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  Linker::ErrorCode result = pLinker.setOutput(pOutputPath);
256affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
257affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (Linker::kSuccess != result) {
258affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    llvm::errs() << "Failed to open the output file! (detail: "
259affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                 << pOutputPath << ": "
260affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                 << Linker::GetErrorString(result) << ")\n";
261affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
262affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
263affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
264cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // -----  Set inputs  ----- //
265cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  llvm::cl::list<std::string>::iterator file_it = OptInputObjectFiles.begin();
266cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  llvm::cl::list<std::string>::iterator lib_it  = OptNameSpecList.begin();
267affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
268cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  llvm::cl::list<std::string>::iterator file_begin = OptInputObjectFiles.begin();
269cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  llvm::cl::list<std::string>::iterator lib_begin = OptNameSpecList.begin();
270cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  llvm::cl::list<std::string>::iterator file_end = OptInputObjectFiles.end();
271cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  llvm::cl::list<std::string>::iterator lib_end = OptNameSpecList.end();
272affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
273cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  unsigned lib_pos = 0, file_pos = 0;
274affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  while (true) {
275cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    if (lib_it != lib_end) {
276cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      lib_pos = OptNameSpecList.getPosition(lib_it - lib_begin);
277cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    } else {
278cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      lib_pos = 0;
279cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    }
280cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
281cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    if (file_it != file_end) {
282cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      file_pos = OptInputObjectFiles.getPosition(file_it - file_begin);
283cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    } else {
284cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      file_pos = 0;
285cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    }
286cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
287cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    if ((file_pos != 0) && ((lib_pos == 0) || (file_pos < lib_pos))) {
288cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      result = pLinker.addObject(*file_it);
289affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      if (Linker::kSuccess != result) {
290cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        llvm::errs() << "Failed to open the input file! (detail: " << *file_it
291cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                     << ": " << Linker::GetErrorString(result) << ")\n";
292affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        return false;
293affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
294cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      ++file_it;
295cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    } else if ((lib_pos != 0) && ((file_pos == 0) || (lib_pos < file_pos))) {
296cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      result = pLinker.addNameSpec(*lib_it);
297affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      if (Linker::kSuccess != result) {
298cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao        llvm::errs() << "Failed to open the namespec! (detail: " << *lib_it
299cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao                     << ": " << Linker::GetErrorString(result) << ")\n";
300affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        return false;
301affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
302cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      ++lib_it;
303cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    } else {
304affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      break; // we're done with the list
305cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    }
306affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
307affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
308affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
309affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
310affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
311cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaostatic inline bool LinkFiles(Linker &pLinker) {
312affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  Linker::ErrorCode result = pLinker.link();
313affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (Linker::kSuccess != result) {
314affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    llvm::errs() << "Failed to linking! (detail: "
315affc150dc44fab1911775a49636d0ce85333b634Zonr Chang                 << Linker::GetErrorString(result) << "\n";
316affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return false;
317affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
318affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
319affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
320affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
321cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liaoint main(int argc, char** argv) {
322affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  llvm::cl::SetVersionPrinter(MCLDVersionPrinter);
323affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  llvm::cl::ParseCommandLineOptions(argc, argv);
324affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  init::Initialize();
325affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
326affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  std::string OutputFilename = DetermineOutputFilename(OptOutputFilename);
327affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (OutputFilename.empty()) {
328affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return EXIT_FAILURE;
329affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
330affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
331affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  Linker linker;
332affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!ConfigLinker(linker, OutputFilename)) {
333affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return EXIT_FAILURE;
334affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
335affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
336affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!PrepareInputOutput(linker, OutputFilename)) {
337affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return EXIT_FAILURE;
338affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
339affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
340affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (!LinkFiles(linker)) {
341affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return EXIT_FAILURE;
342affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
343cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
344affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return EXIT_SUCCESS;
345affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
346affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
347