//===--- ToolChain.cpp - Collections of tools for one platform ------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 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/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; std::unique_ptr ToolChain::constructJob(const JobAction &JA, SmallVectorImpl &&inputs, std::unique_ptr output, const ActionList &inputActions, const llvm::opt::ArgList &args, const OutputInfo &OI) const { JobContext context{inputs, *output, inputActions, args, OI}; const char *executableName; llvm::opt::ArgStringList arguments; switch (JA.getKind()) { #define CASE(K) case Action::K: \ std::tie(executableName, arguments) = \ constructInvocation(cast(JA), context); \ break; CASE(CompileJob) CASE(BackendJob) CASE(MergeModuleJob) 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) == executableName) { executablePath = getDriver().getSwiftProgramPath().c_str(); } else { std::string relativePath = findProgramRelativeToSwift(executableName); if (!relativePath.empty()) { executablePath = args.MakeArgString(relativePath); } else { auto systemPath = llvm::sys::findProgramByName(executableName); if (systemPath) { executablePath = args.MakeArgString(systemPath.get()); } else { // For debugging purposes. executablePath = executableName; } } } return llvm::make_unique(JA, std::move(inputs), std::move(output), executablePath, std::move(arguments)); } 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 { llvm::SmallString<128> path{getDriver().getSwiftProgramPath()}; llvm::sys::path::remove_filename(path); auto result = llvm::sys::findProgramByName(executableName, {path}); if (result) return result.get(); return {}; } types::ID ToolChain::lookupTypeForExtension(StringRef Ext) const { return types::lookupTypeForExtension(Ext); }