| //===--- ToolChain.h - Collections of tools for one platform ----*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_DRIVER_TOOLCHAIN_H |
| #define SWIFT_DRIVER_TOOLCHAIN_H |
| |
| #include "swift/Basic/FileTypes.h" |
| #include "swift/Basic/LLVM.h" |
| #include "swift/Driver/Action.h" |
| #include "swift/Driver/Job.h" |
| #include "swift/Option/Options.h" |
| #include "llvm/ADT/Triple.h" |
| #include "llvm/Option/Option.h" |
| |
| #include <memory> |
| |
| namespace swift { |
| namespace driver { |
| class CommandOutput; |
| class Compilation; |
| class Driver; |
| class Job; |
| class OutputInfo; |
| |
| /// A ToolChain is responsible for turning abstract Actions into concrete, |
| /// runnable Jobs. |
| /// |
| /// The primary purpose of a ToolChain is built around the |
| /// \c constructInvocation family of methods. This is a set of callbacks |
| /// following the Visitor pattern for the various JobAction subclasses, which |
| /// returns an executable name and arguments for the Job to be run. The base |
| /// ToolChain knows how to perform most operations, but some (like linking) |
| /// require platform-specific knowledge, provided in subclasses. |
| class ToolChain { |
| const Driver &D; |
| const llvm::Triple Triple; |
| mutable llvm::StringMap<std::string> ProgramLookupCache; |
| |
| protected: |
| ToolChain(const Driver &D, const llvm::Triple &T) : D(D), Triple(T) {} |
| |
| /// A special name used to identify the Swift executable itself. |
| constexpr static const char *const SWIFT_EXECUTABLE_NAME = "swift"; |
| |
| /// Packs together the supplementary information about the job being created. |
| class JobContext { |
| private: |
| Compilation &C; |
| |
| public: |
| ArrayRef<const Job *> Inputs; |
| ArrayRef<const Action *> InputActions; |
| const CommandOutput &Output; |
| const OutputInfo &OI; |
| |
| /// The arguments to the driver. Can also be used to create new strings with |
| /// the same lifetime. |
| /// |
| /// This just caches C.getArgs(). |
| const llvm::opt::ArgList &Args; |
| |
| public: |
| JobContext(Compilation &C, ArrayRef<const Job *> Inputs, |
| ArrayRef<const Action *> InputActions, |
| const CommandOutput &Output, const OutputInfo &OI); |
| |
| /// Forwards to Compilation::getInputFiles. |
| ArrayRef<InputPair> getTopLevelInputFiles() const; |
| |
| /// Forwards to Compilation::getAllSourcesPath. |
| const char *getAllSourcesPath() const; |
| |
| /// Creates a new temporary file for use by a job. |
| /// |
| /// The returned string already has its lifetime extended to match other |
| /// arguments. |
| const char *getTemporaryFilePath(const llvm::Twine &name, |
| StringRef suffix = "") const; |
| |
| /// For frontend, merge-module, and link invocations. |
| bool shouldUseInputFileList() const; |
| |
| bool shouldUsePrimaryInputFileListInFrontendInvocation() const; |
| |
| bool shouldUseMainOutputFileListInFrontendInvocation() const; |
| |
| bool shouldUseSupplementaryOutputFileMapInFrontendInvocation() const; |
| |
| /// Reify the existing behavior that SingleCompile compile actions do not |
| /// filter, but batch-mode and single-file compilations do. Some clients are |
| /// relying on this (i.e., they pass inputs that don't have ".swift" as an |
| /// extension.) It would be nice to eliminate this distinction someday. |
| bool shouldFilterFrontendInputsByType() const; |
| |
| const char *computeFrontendModeForCompile() const; |
| |
| void addFrontendInputAndOutputArguments( |
| llvm::opt::ArgStringList &Arguments, |
| std::vector<FilelistInfo> &FilelistInfos) const; |
| |
| private: |
| void addFrontendCommandLineInputArguments( |
| bool mayHavePrimaryInputs, bool useFileList, bool usePrimaryFileList, |
| bool filterByType, llvm::opt::ArgStringList &arguments) const; |
| void addFrontendSupplementaryOutputArguments( |
| llvm::opt::ArgStringList &arguments) const; |
| }; |
| |
| /// Packs together information chosen by toolchains to create jobs. |
| struct InvocationInfo { |
| const char *ExecutableName; |
| llvm::opt::ArgStringList Arguments; |
| std::vector<std::pair<const char *, const char *>> ExtraEnvironment; |
| std::vector<FilelistInfo> FilelistInfos; |
| |
| // Not all platforms and jobs support the use of response files, so assume |
| // "false" by default. If the executable specified in the InvocationInfo |
| // constructor supports response files, this can be overridden and set to |
| // "true". |
| bool allowsResponseFiles = false; |
| |
| InvocationInfo(const char *name, llvm::opt::ArgStringList args = {}, |
| decltype(ExtraEnvironment) extraEnv = {}) |
| : ExecutableName(name), Arguments(std::move(args)), |
| ExtraEnvironment(std::move(extraEnv)) {} |
| }; |
| |
| virtual InvocationInfo constructInvocation(const CompileJobAction &job, |
| const JobContext &context) const; |
| virtual InvocationInfo constructInvocation(const InterpretJobAction &job, |
| const JobContext &context) const; |
| virtual InvocationInfo constructInvocation(const BackendJobAction &job, |
| const JobContext &context) const; |
| virtual InvocationInfo constructInvocation(const MergeModuleJobAction &job, |
| const JobContext &context) const; |
| virtual InvocationInfo constructInvocation(const ModuleWrapJobAction &job, |
| const JobContext &context) const; |
| |
| virtual InvocationInfo constructInvocation(const REPLJobAction &job, |
| const JobContext &context) const; |
| |
| virtual InvocationInfo constructInvocation(const GenerateDSYMJobAction &job, |
| const JobContext &context) const; |
| virtual InvocationInfo |
| constructInvocation(const VerifyDebugInfoJobAction &job, |
| const JobContext &context) const; |
| virtual InvocationInfo constructInvocation(const GeneratePCHJobAction &job, |
| const JobContext &context) const; |
| virtual InvocationInfo |
| constructInvocation(const AutolinkExtractJobAction &job, |
| const JobContext &context) const; |
| virtual InvocationInfo constructInvocation(const LinkJobAction &job, |
| const JobContext &context) const; |
| |
| /// Searches for the given executable in appropriate paths relative to the |
| /// Swift binary. |
| /// |
| /// This method caches its results. |
| /// |
| /// \sa findProgramRelativeToSwiftImpl |
| std::string findProgramRelativeToSwift(StringRef name) const; |
| |
| /// An override point for platform-specific subclasses to customize how to |
| /// do relative searches for programs. |
| /// |
| /// This method is invoked by findProgramRelativeToSwift(). |
| virtual std::string findProgramRelativeToSwiftImpl(StringRef name) const; |
| |
| void addInputsOfType(llvm::opt::ArgStringList &Arguments, |
| ArrayRef<const Action *> Inputs, |
| file_types::ID InputType, |
| const char *PrefixArgument = nullptr) const; |
| |
| void addInputsOfType(llvm::opt::ArgStringList &Arguments, |
| ArrayRef<const Job *> Jobs, |
| const llvm::opt::ArgList &Args, file_types::ID InputType, |
| const char *PrefixArgument = nullptr) const; |
| |
| void addPrimaryInputsOfType(llvm::opt::ArgStringList &Arguments, |
| ArrayRef<const Job *> Jobs, |
| const llvm::opt::ArgList &Args, |
| file_types::ID InputType, |
| const char *PrefixArgument = nullptr) const; |
| |
| /// Get the runtime library link path, which is platform-specific and found |
| /// relative to the compiler. |
| void getRuntimeLibraryPath(SmallVectorImpl<char> &runtimeLibPath, |
| const llvm::opt::ArgList &args, bool shared) const; |
| |
| void addPathEnvironmentVariableIfNeeded(Job::EnvironmentVector &env, |
| const char *name, |
| const char *separator, |
| options::ID optionID, |
| const llvm::opt::ArgList &args, |
| StringRef extraEntry = "") const; |
| |
| /// Specific toolchains should override this to provide additional conditions |
| /// under which the compiler invocation should be written into debug info. For |
| /// example, Darwin does this if the RC_DEBUG_OPTIONS environment variable is |
| /// set to match the behavior of Clang. |
| virtual bool shouldStoreInvocationInDebugInfo() const { return false; } |
| |
| public: |
| virtual ~ToolChain() = default; |
| |
| const Driver &getDriver() const { return D; } |
| const llvm::Triple &getTriple() const { return Triple; } |
| |
| /// Construct a Job for the action \p JA, taking the given information into |
| /// account. |
| /// |
| /// This method dispatches to the various \c constructInvocation methods, |
| /// which may be overridden by platform-specific subclasses. |
| std::unique_ptr<Job> constructJob(const JobAction &JA, Compilation &C, |
| SmallVectorImpl<const Job *> &&inputs, |
| ArrayRef<const Action *> inputActions, |
| std::unique_ptr<CommandOutput> output, |
| const OutputInfo &OI) const; |
| |
| /// Return true iff the input \c Job \p A is an acceptable candidate for |
| /// batching together into a BatchJob, via a call to \c |
| /// constructBatchJob. This is true when the \c Job is a built from a \c |
| /// CompileJobAction in a \c Compilation \p C running in \c |
| /// OutputInfo::Mode::StandardCompile output mode, with a single \c TY_Swift |
| /// \c InputAction. |
| bool jobIsBatchable(const Compilation &C, const Job *A) const; |
| |
| /// Equivalence relation that holds iff the two input Jobs \p A and \p B are |
| /// acceptable candidates for combining together into a \c BatchJob, via a |
| /// call to \c constructBatchJob. This is true when each job independently |
| /// satisfies \c jobIsBatchable, and the two jobs have identical executables, |
| /// output types and environments (i.e. they are identical aside from their |
| /// inputs). |
| bool jobsAreBatchCombinable(const Compilation &C, const Job *A, |
| const Job *B) const; |
| |
| /// Construct a \c BatchJob that subsumes the work of a set of Jobs. Any pair |
| /// of elements in \p Jobs are assumed to satisfy the equivalence relation \c |
| /// jobsAreBatchCombinable, i.e. they should all be "the same" job in in all |
| /// ways other than their choices of inputs. The provided \p NextQuasiPID |
| /// should be a negative number that persists between calls; this method will |
| /// decrement it to assign quasi-PIDs to each of the \p Jobs passed. |
| std::unique_ptr<Job> constructBatchJob(ArrayRef<const Job *> Jobs, |
| int64_t &NextQuasiPID, |
| Compilation &C) const; |
| |
| /// Return the default language type to use for the given extension. |
| /// If the extension is empty or is otherwise not recognized, return |
| /// the invalid type \c TY_INVALID. |
| file_types::ID lookupTypeForExtension(StringRef Ext) const; |
| |
| /// Copies the path for the directory clang libraries would be stored in on |
| /// the current toolchain. |
| void getClangLibraryPath(const llvm::opt::ArgList &Args, |
| SmallString<128> &LibPath) const; |
| |
| /// Returns the name the clang library for a given sanitizer would have on |
| /// the current toolchain. |
| /// |
| /// \param Sanitizer Sanitizer name. |
| /// \param shared Whether the library is shared |
| virtual std::string sanitizerRuntimeLibName(StringRef Sanitizer, |
| bool shared = true) const = 0; |
| |
| /// Returns whether a given sanitizer exists for the current toolchain. |
| /// |
| /// \param sanitizer Sanitizer name. |
| /// \param shared Whether the library is shared |
| bool sanitizerRuntimeLibExists(const llvm::opt::ArgList &args, |
| StringRef sanitizer, bool shared = true) const; |
| |
| /// Adds a runtime library to the arguments list for linking. |
| /// |
| /// \param LibName The library name |
| /// \param Arguments The arguments list to append to |
| void addLinkRuntimeLib(const llvm::opt::ArgList &Args, |
| llvm::opt::ArgStringList &Arguments, |
| StringRef LibName) const; |
| }; |
| } // end namespace driver |
| } // end namespace swift |
| |
| #endif |