//===--- ModuleDependencyScanner.h - Import Swift modules --------*- C++ //-*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2020 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 // //===----------------------------------------------------------------------===// #include "swift/AST/ASTContext.h" #include "swift/AST/Identifier.h" #include "swift/AST/ModuleDependencies.h" #include "swift/Frontend/ModuleInterfaceLoader.h" #include "swift/Serialization/SerializedModuleLoader.h" #include "llvm/Support/ThreadPool.h" namespace swift { class DependencyTracker; } namespace swift { /// A dependency scanning worker which performs filesystem lookup /// of a named module dependency. class ModuleDependencyScanningWorker { public: ModuleDependencyScanningWorker( SwiftDependencyScanningService &globalScanningService, const CompilerInvocation &ScanCompilerInvocation, const SILOptions &SILOptions, ASTContext &ScanASTContext, DependencyTracker &DependencyTracker, DiagnosticEngine &diags); private: /// Retrieve the module dependencies for the module with the given name. ModuleDependencyVector scanFilesystemForModuleDependency(Identifier moduleName, const ModuleDependenciesCache &cache, bool isTestableImport = false); /// Retrieve the module dependencies for the Clang module with the given name. ModuleDependencyVector scanFilesystemForClangModuleDependency(Identifier moduleName, const ModuleDependenciesCache &cache); /// Retrieve the module dependencies for the Swift module with the given name. ModuleDependencyVector scanFilesystemForSwiftModuleDependency(Identifier moduleName, const ModuleDependenciesCache &cache); // Worker-specific instance of CompilerInvocation std::unique_ptr workerCompilerInvocation; // Worker-specific instance of ASTContext std::unique_ptr workerASTContext; // An AST delegate for interface scanning. std::unique_ptr scanningASTDelegate; // The Clang scanner tool used by this worker. clang::tooling::dependencies::DependencyScanningTool clangScanningTool; // Swift and Clang module loaders acting as scanners. std::unique_ptr swiftScannerModuleLoader; std::unique_ptr clangScannerModuleLoader; // Restrict access to the parent scanner class. friend class ModuleDependencyScanner; }; class ModuleDependencyScanner { public: ModuleDependencyScanner(SwiftDependencyScanningService &ScanningService, const CompilerInvocation &ScanCompilerInvocation, const SILOptions &SILOptions, ASTContext &ScanASTContext, DependencyTracker &DependencyTracker, DiagnosticEngine &diags, bool ParallelScan); /// Identify the scanner invocation's main module's dependencies llvm::ErrorOr getMainModuleDependencyInfo(ModuleDecl *mainModule); /// Resolve module dependencies of the given module, computing a full /// transitive closure dependency graph. std::vector getModuleDependencies(ModuleDependencyID moduleID, ModuleDependenciesCache &cache); /// Query the module dependency info for the Clang module with the given name. /// Explicit by-name lookups are useful for batch mode scanning. std::optional getNamedClangModuleDependencyInfo(StringRef moduleName, ModuleDependenciesCache &cache); /// Query the module dependency info for the Swift module with the given name. /// Explicit by-name lookups are useful for batch mode scanning. std::optional getNamedSwiftModuleDependencyInfo(StringRef moduleName, ModuleDependenciesCache &cache); private: /// Resolve the direct dependencies of the given module. std::vector resolveDirectModuleDependencies(ModuleDependencyID moduleID, ModuleDependenciesCache &cache); /// Resolve imported module names of a given module to concrete /// modules. If `ParallelScan` is enabled, this operation is multithreaded. void resolveImportDependencies(const ModuleDependencyID &moduleID, ModuleDependenciesCache &cache, ModuleDependencyIDSetVector &directDependencies); /// If a module has a bridging header or other header inputs, execute a dependency scan /// on it and record the dependencies. void resolveHeaderDependencies( const ModuleDependencyID &moduleID, ModuleDependenciesCache &cache, std::vector &allClangModules, llvm::StringSet<> &alreadyKnownModules, ModuleDependencyIDSetVector &directDependencies); /// Resolve all module dependencies comprised of Swift overlays /// of this module's Clang module dependencies. void resolveSwiftOverlayDependencies( const ModuleDependencyID &moduleID, const std::vector &clangDependencies, ModuleDependenciesCache &cache, ModuleDependencyIDSetVector &swiftOverlayDependencies, ModuleDependencyIDSetVector &directDependencies); /// Identify all cross-import overlay modules of the specified /// dependency set and apply an action for each. void discoverCrossImportOverlayDependencies( StringRef mainModuleName, ArrayRef allDependencies, ModuleDependenciesCache &cache, llvm::function_ref action); /// Perform an operation utilizing one of the Scanning workers /// available to this scanner. template auto withDependencyScanningWorker(Function &&F, Args &&...ArgList); Identifier getModuleImportIdentifier(StringRef moduleName); private: const CompilerInvocation &ScanCompilerInvocation; ASTContext &ScanASTContext; DiagnosticEngine &Diagnostics; /// The available pool of workers for filesystem module search unsigned NumThreads; std::list> Workers; llvm::StdThreadPool ScanningThreadPool; /// Protect worker access. std::mutex WorkersLock; }; } // namespace swift