| //===--- ToolChain.cpp - Collections of tools for one platform ------------===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See http://swift.org/LICENSE.txt for license information |
| // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| /// \file This file defines the base implementation of the ToolChain class. |
| /// The platform-specific subclasses are implemented in ToolChains.cpp. |
| /// For organizational purposes, the platform-independent logic for |
| /// constructing job invocations is also located in ToolChains.cpp. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "swift/Driver/ToolChain.h" |
| #include "swift/Driver/Compilation.h" |
| #include "swift/Driver/Driver.h" |
| #include "swift/Driver/Job.h" |
| #include "llvm/Option/ArgList.h" |
| #include "llvm/Support/FileSystem.h" |
| #include "llvm/Support/Path.h" |
| #include "llvm/Support/Program.h" |
| #include "llvm/ADT/STLExtras.h" |
| |
| using namespace swift; |
| using namespace swift::driver; |
| using namespace llvm::opt; |
| |
| const char * const ToolChain::SWIFT_EXECUTABLE_NAME; |
| |
| ToolChain::JobContext::JobContext(Compilation &C, |
| ArrayRef<const Job *> Inputs, |
| ArrayRef<const Action *> InputActions, |
| const CommandOutput &Output, |
| const OutputInfo &OI) |
| : C(C), Inputs(Inputs), InputActions(InputActions), Output(Output), |
| OI(OI), Args(C.getArgs()) {} |
| |
| ArrayRef<InputPair> ToolChain::JobContext::getTopLevelInputFiles() const { |
| return C.getInputFiles(); |
| } |
| const char *ToolChain::JobContext::getAllSourcesPath() const { |
| return C.getAllSourcesPath(); |
| } |
| |
| const char * |
| ToolChain::JobContext::getTemporaryFilePath(const llvm::Twine &name, |
| StringRef suffix) const { |
| SmallString<128> buffer; |
| std::error_code EC = |
| llvm::sys::fs::createTemporaryFile(name, suffix, buffer); |
| if (EC) { |
| // FIXME: This should not take down the entire process. |
| llvm::report_fatal_error("unable to create temporary file for filelist"); |
| } |
| |
| C.addTemporaryFile(buffer.str()); |
| // We can't just reference the data in the TemporaryFiles vector because |
| // that could theoretically get copied to a new address. |
| return C.getArgs().MakeArgString(buffer.str()); |
| } |
| |
| std::unique_ptr<Job> |
| ToolChain::constructJob(const JobAction &JA, |
| Compilation &C, |
| SmallVectorImpl<const Job *> &&inputs, |
| const ActionList &inputActions, |
| std::unique_ptr<CommandOutput> output, |
| const OutputInfo &OI) const { |
| JobContext context{C, inputs, inputActions, *output, OI}; |
| |
| auto invocationInfo = [&]() -> InvocationInfo { |
| switch (JA.getKind()) { |
| #define CASE(K) case Action::K: \ |
| return constructInvocation(cast<K##Action>(JA), context); |
| CASE(CompileJob) |
| CASE(InterpretJob) |
| CASE(BackendJob) |
| CASE(MergeModuleJob) |
| CASE(ModuleWrapJob) |
| CASE(LinkJob) |
| CASE(GenerateDSYMJob) |
| CASE(AutolinkExtractJob) |
| CASE(REPLJob) |
| #undef CASE |
| case Action::Input: |
| llvm_unreachable("not a JobAction"); |
| } |
| }(); |
| |
| // Special-case the Swift frontend. |
| const char *executablePath = nullptr; |
| if (StringRef(SWIFT_EXECUTABLE_NAME) == invocationInfo.ExecutableName) { |
| executablePath = getDriver().getSwiftProgramPath().c_str(); |
| } else { |
| std::string relativePath = |
| findProgramRelativeToSwift(invocationInfo.ExecutableName); |
| if (!relativePath.empty()) { |
| executablePath = C.getArgs().MakeArgString(relativePath); |
| } else { |
| auto systemPath = |
| llvm::sys::findProgramByName(invocationInfo.ExecutableName); |
| if (systemPath) { |
| executablePath = C.getArgs().MakeArgString(systemPath.get()); |
| } else { |
| // For debugging purposes. |
| executablePath = invocationInfo.ExecutableName; |
| } |
| } |
| } |
| |
| return llvm::make_unique<Job>(JA, std::move(inputs), std::move(output), |
| executablePath, |
| std::move(invocationInfo.Arguments), |
| std::move(invocationInfo.ExtraEnvironment), |
| std::move(invocationInfo.FilelistInfo)); |
| } |
| |
| std::string |
| ToolChain::findProgramRelativeToSwift(StringRef executableName) const { |
| auto insertionResult = |
| ProgramLookupCache.insert(std::make_pair(executableName, "")); |
| if (insertionResult.second) { |
| std::string path = findProgramRelativeToSwiftImpl(executableName); |
| insertionResult.first->setValue(std::move(path)); |
| } |
| return insertionResult.first->getValue(); |
| } |
| |
| std::string |
| ToolChain::findProgramRelativeToSwiftImpl(StringRef executableName) const { |
| StringRef swiftPath = getDriver().getSwiftProgramPath(); |
| StringRef swiftBinDir = llvm::sys::path::parent_path(swiftPath); |
| |
| auto result = llvm::sys::findProgramByName(executableName, {swiftBinDir}); |
| if (result) |
| return result.get(); |
| return {}; |
| } |
| |
| types::ID ToolChain::lookupTypeForExtension(StringRef Ext) const { |
| return types::lookupTypeForExtension(Ext); |
| } |