diff --git a/include/swift-c/DependencyScan/DependencyScan.h b/include/swift-c/DependencyScan/DependencyScan.h index 4de2a6ea95104..c08a6fb7482c3 100644 --- a/include/swift-c/DependencyScan/DependencyScan.h +++ b/include/swift-c/DependencyScan/DependencyScan.h @@ -150,6 +150,10 @@ swiftscan_swift_textual_detail_get_context_hash( SWIFTSCAN_PUBLIC bool swiftscan_swift_textual_detail_get_is_framework( swiftscan_module_details_t details); +SWIFTSCAN_PUBLIC swiftscan_string_set_t * +swiftscan_swift_textual_detail_get_swift_overlay_dependencies( + swiftscan_module_details_t details); + //=== Swift Binary Module Details query APIs ------------------------------===// SWIFTSCAN_PUBLIC swiftscan_string_ref_t diff --git a/include/swift/AST/ModuleDependencies.h b/include/swift/AST/ModuleDependencies.h index dbe76a9220e12..d5be234dc5194 100644 --- a/include/swift/AST/ModuleDependencies.h +++ b/include/swift/AST/ModuleDependencies.h @@ -137,6 +137,10 @@ struct CommonSwiftTextualModuleDependencyDetails { /// (Clang) modules on which the bridging header depends. std::vector bridgingModuleDependencies; + + /// Dependencies comprised of Swift overlay modules of direct and + /// transitive Clang dependencies. + std::vector swiftOverlayDependencies; }; /// Describes the dependencies of a Swift module described by an Swift interface file. @@ -450,12 +454,26 @@ class ModuleDependencyInfo { } /// Resolve a dependency's set of `imports` with qualified Module IDs - void resolveDependencies(const std::vector &dependencyIDs) { + void resolveDependencies(const ArrayRef dependencyIDs) { assert(!storage->resolved && "Resolving an already-resolved dependency"); storage->resolved = true; storage->resolvedModuleDependencies.assign(dependencyIDs.begin(), dependencyIDs.end()); } + /// Set this module's set of Swift Overlay dependencies + void setOverlayDependencies(const ArrayRef dependencyIDs) { + assert(isSwiftSourceModule() || isSwiftInterfaceModule()); + CommonSwiftTextualModuleDependencyDetails *textualModuleDetails; + if (auto sourceDetailsStorage = dyn_cast(storage.get())) { + textualModuleDetails = &sourceDetailsStorage->textualModuleDetails; + } else if (auto interfaceDetailsStorage = dyn_cast(storage.get())) { + textualModuleDetails = &interfaceDetailsStorage->textualModuleDetails; + } else { + llvm_unreachable("Unknown kind of dependency module info."); + } + textualModuleDetails->swiftOverlayDependencies.assign(dependencyIDs.begin(), dependencyIDs.end()); + } + void updateCommandLine(const std::vector &newCommandLine) { assert(isSwiftInterfaceModule() && "Can only update command line on Swift interface dependency"); cast(storage.get())->updateCommandLine(newCommandLine); @@ -762,7 +780,12 @@ class ModuleDependenciesCache { /// Resolve a dependency module's set of imports /// to a kind-qualified set of module IDs. void resolveDependencyImports(ModuleDependencyID moduleID, - const std::vector &dependencyIDs); + const ArrayRef dependencyIDs); + + /// Resolve a dependency module's set of Swift module dependencies + /// that are Swift overlays of Clang module dependencies. + void setSwiftOverlayDependencues(ModuleDependencyID moduleID, + const ArrayRef dependencyIDs); StringRef getMainModuleName() const { return mainScanModuleName; diff --git a/include/swift/DependencyScan/DependencyScanImpl.h b/include/swift/DependencyScan/DependencyScanImpl.h index 2f9046a09d80f..dd0463e502e44 100644 --- a/include/swift/DependencyScan/DependencyScanImpl.h +++ b/include/swift/DependencyScan/DependencyScanImpl.h @@ -79,6 +79,10 @@ typedef struct { /// (Clang) modules on which the bridging header depends. swiftscan_string_set_t *bridging_module_dependencies; + /// (Swift) module dependencies by means of being overlays of + /// Clang module dependencies + swiftscan_string_set_t *swift_overlay_module_dependencies; + /// Options to the compile command required to build this module interface swiftscan_string_set_t *command_line; diff --git a/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h b/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h index 254c985fbc85b..bad67c1e43bf1 100644 --- a/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h +++ b/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h @@ -41,7 +41,7 @@ using llvm::BCVBR; const unsigned char MODULE_DEPENDENCY_CACHE_FORMAT_SIGNATURE[] = {'I', 'M', 'D','C'}; const unsigned MODULE_DEPENDENCY_CACHE_FORMAT_VERSION_MAJOR = 4; /// Increment this on every change. -const unsigned MODULE_DEPENDENCY_CACHE_FORMAT_VERSION_MINOR = 0; +const unsigned MODULE_DEPENDENCY_CACHE_FORMAT_VERSION_MINOR = 1; /// Various identifiers in this format will rely on having their strings mapped /// using this ID. @@ -139,7 +139,8 @@ using SwiftInterfaceModuleDetailsLayout = FileIDField, // bridgingHeaderFile FileIDArrayIDField, // sourceFiles FileIDArrayIDField, // bridgingSourceFiles - FileIDArrayIDField // bridgingModuleDependencies + FileIDArrayIDField, // bridgingModuleDependencies + DependencyIDArrayIDField // swiftOverlayDependencies >; using SwiftSourceModuleDetailsLayout = @@ -148,7 +149,8 @@ using SwiftSourceModuleDetailsLayout = FileIDField, // bridgingHeaderFile FileIDArrayIDField, // sourceFiles FileIDArrayIDField, // bridgingSourceFiles - FileIDArrayIDField // bridgingModuleDependencies + FileIDArrayIDField, // bridgingModuleDependencies + DependencyIDArrayIDField // swiftOverlayDependencies >; using SwiftBinaryModuleDetailsLayout = diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 7742e73b74cac..cf6c7110870ce 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -1286,6 +1286,10 @@ def disable_clang_target : Flag<["-"], "disable-clang-target">, Flags<[NewDriverOnlyOption]>, HelpText<"Disable a separately specified target triple for Clang instance to use">; +def explain_module_dependency : Separate<["-"], "explain-module-dependency">, + Flags<[NewDriverOnlyOption]>, + HelpText<"Emit remark/notes describing why compilaiton may depend on a module with a given name.">; + def min_inlining_target_version : Separate<["-"], "target-min-inlining-version">, Flags<[FrontendOption, ModuleInterfaceOptionIgnorable]>, HelpText<"Require inlinable code with no '@available' attribute to back-deploy " diff --git a/lib/AST/ModuleDependencies.cpp b/lib/AST/ModuleDependencies.cpp index 55485c38320e3..a9f5435d05d34 100644 --- a/lib/AST/ModuleDependencies.cpp +++ b/lib/AST/ModuleDependencies.cpp @@ -447,7 +447,7 @@ void ModuleDependenciesCache::updateDependency( } void ModuleDependenciesCache::resolveDependencyImports(ModuleDependencyID moduleID, - const std::vector &dependencyIDs) { + const ArrayRef dependencyIDs) { auto optionalDependencyInfo = findDependency(moduleID.first, moduleID.second); assert(optionalDependencyInfo.has_value() && "Resolving unknown dependency"); // Copy the existing info to a mutable one we can then replace it with, after resolving its dependencies. @@ -455,3 +455,13 @@ void ModuleDependenciesCache::resolveDependencyImports(ModuleDependencyID module dependencyInfo.resolveDependencies(dependencyIDs); updateDependency(moduleID, dependencyInfo); } + +void ModuleDependenciesCache::setSwiftOverlayDependencues(ModuleDependencyID moduleID, + const ArrayRef dependencyIDs) { + auto optionalDependencyInfo = findDependency(moduleID.first, moduleID.second); + assert(optionalDependencyInfo.has_value() && "Resolving unknown dependency"); + // Copy the existing info to a mutable one we can then replace it with, after setting its overlay dependencies. + auto dependencyInfo = *(optionalDependencyInfo.value()); + dependencyInfo.setOverlayDependencies(dependencyIDs); + updateDependency(moduleID, dependencyInfo); +} diff --git a/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp b/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp index 075666ddc5dbc..6cf39b6fb96b9 100644 --- a/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp +++ b/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp @@ -238,12 +238,14 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi unsigned outputPathFileID, interfaceFileID, compiledModuleCandidatesArrayID, buildCommandLineArrayID, extraPCMArgsArrayID, contextHashID, isFramework, bridgingHeaderFileID, sourceFilesArrayID, - bridgingSourceFilesArrayID, bridgingModuleDependenciesArrayID; + bridgingSourceFilesArrayID, bridgingModuleDependenciesArrayID, + overlayDependencyIDArrayID; SwiftInterfaceModuleDetailsLayout::readRecord( Scratch, outputPathFileID, interfaceFileID, compiledModuleCandidatesArrayID, buildCommandLineArrayID, extraPCMArgsArrayID, contextHashID, isFramework, bridgingHeaderFileID, sourceFilesArrayID, - bridgingSourceFilesArrayID, bridgingModuleDependenciesArrayID); + bridgingSourceFilesArrayID, bridgingModuleDependenciesArrayID, + overlayDependencyIDArrayID); auto outputModulePath = getIdentifier(outputPathFileID); if (!outputModulePath) @@ -320,6 +322,12 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi for (const auto &mod : *bridgingModuleDeps) moduleDep.addBridgingModuleDependency(mod, alreadyAdded); + // Add Swift overlay dependencies + auto overlayModuleDependencyIDs = getModuleDependencyIDArray(overlayDependencyIDArrayID); + if (!overlayModuleDependencyIDs.has_value()) + llvm::report_fatal_error("Bad overlay dependencies: no qualified dependencies"); + moduleDep.setOverlayDependencies(overlayModuleDependencyIDs.value()); + cache.recordDependency(currentModuleName, std::move(moduleDep), getContextHash()); hasCurrentModule = false; @@ -336,11 +344,12 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi "Unexpected context hash on MODULE_NODE corresponding to a " "SWIFT_SOURCE_MODULE_DETAILS_NODE record"); unsigned extraPCMArgsArrayID, bridgingHeaderFileID, sourceFilesArrayID, - bridgingSourceFilesArrayID, bridgingModuleDependenciesArrayID; + bridgingSourceFilesArrayID, bridgingModuleDependenciesArrayID, + overlayDependencyIDArrayID; SwiftSourceModuleDetailsLayout::readRecord( Scratch, extraPCMArgsArrayID, bridgingHeaderFileID, sourceFilesArrayID, bridgingSourceFilesArrayID, - bridgingModuleDependenciesArrayID); + bridgingModuleDependenciesArrayID, overlayDependencyIDArrayID); auto extraPCMArgs = getStringArray(extraPCMArgsArrayID); if (!extraPCMArgs) @@ -387,6 +396,12 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi for (const auto &mod : *bridgingModuleDeps) moduleDep.addBridgingModuleDependency(mod, alreadyAdded); + // Add Swift overlay dependencies + auto overlayModuleDependencyIDs = getModuleDependencyIDArray(overlayDependencyIDArrayID); + if (!overlayModuleDependencyIDs.has_value()) + llvm::report_fatal_error("Bad overlay dependencies: no qualified dependencies"); + moduleDep.setOverlayDependencies(overlayModuleDependencyIDs.value()); + cache.recordDependency(currentModuleName, std::move(moduleDep), getContextHash()); hasCurrentModule = false; @@ -631,6 +646,7 @@ enum ModuleIdentifierArrayKind : uint8_t { SourceFiles, BridgingSourceFiles, BridgingModuleDependencies, + SwiftOverlayDependencyIDs, NonPathCommandLine, FileDependencies, CapturedPCMArgs, @@ -846,7 +862,8 @@ void ModuleDependenciesCacheSerializer::writeModuleInfo(ModuleDependencyID modul bridgingHeaderFileId, getArrayID(moduleID, ModuleIdentifierArrayKind::SourceFiles), getArrayID(moduleID, ModuleIdentifierArrayKind::BridgingSourceFiles), - getArrayID(moduleID, ModuleIdentifierArrayKind::BridgingModuleDependencies)); + getArrayID(moduleID, ModuleIdentifierArrayKind::BridgingModuleDependencies), + getArrayID(moduleID, ModuleIdentifierArrayKind::SwiftOverlayDependencyIDs)); break; } case swift::ModuleDependencyKind::SwiftSource: { @@ -865,7 +882,8 @@ void ModuleDependenciesCacheSerializer::writeModuleInfo(ModuleDependencyID modul bridgingHeaderFileId, getArrayID(moduleID, ModuleIdentifierArrayKind::SourceFiles), getArrayID(moduleID, ModuleIdentifierArrayKind::BridgingSourceFiles), - getArrayID(moduleID, ModuleIdentifierArrayKind::BridgingModuleDependencies)); + getArrayID(moduleID, ModuleIdentifierArrayKind::BridgingModuleDependencies), + getArrayID(moduleID, ModuleIdentifierArrayKind::SwiftOverlayDependencyIDs)); break; } case swift::ModuleDependencyKind::SwiftBinary: { @@ -996,9 +1014,8 @@ void ModuleDependenciesCacheSerializer::collectStringsAndArrays( for (auto &contextHash : cache.getAllContextHashes()) { addIdentifier(contextHash); for (auto &moduleID : cache.getAllModules(contextHash)) { - auto optionalDependencyInfo = cache.findDependency(moduleID.first, - moduleID.second, - contextHash); + auto optionalDependencyInfo = + cache.findDependency(moduleID.first, moduleID.second, contextHash); assert(optionalDependencyInfo.has_value() && "Expected dependency info."); auto dependencyInfo = optionalDependencyInfo.value(); // Add the module's name @@ -1006,83 +1023,94 @@ void ModuleDependenciesCacheSerializer::collectStringsAndArrays( // Add the module's dependencies addStringArray(moduleID, ModuleIdentifierArrayKind::DependencyImports, dependencyInfo->getModuleImports()); - addDependencyIDArray(moduleID, ModuleIdentifierArrayKind::QualifiedModuleDependencyIDs, - dependencyInfo->getModuleDependencies()); + addDependencyIDArray( + moduleID, ModuleIdentifierArrayKind::QualifiedModuleDependencyIDs, + dependencyInfo->getModuleDependencies()); // Add the dependency-kind-specific data switch (dependencyInfo->getKind()) { - case swift::ModuleDependencyKind::SwiftInterface: { - auto swiftTextDeps = dependencyInfo->getAsSwiftInterfaceModule(); - assert(swiftTextDeps); - addIdentifier(swiftTextDeps->moduleOutputPath); - addIdentifier(swiftTextDeps->swiftInterfaceFile); - addStringArray(moduleID, - ModuleIdentifierArrayKind::CompiledModuleCandidates, - swiftTextDeps->compiledModuleCandidates); - addStringArray(moduleID, ModuleIdentifierArrayKind::BuildCommandLine, - swiftTextDeps->buildCommandLine); - addStringArray(moduleID, ModuleIdentifierArrayKind::ExtraPCMArgs, - swiftTextDeps->textualModuleDetails.extraPCMArgs); - addIdentifier(swiftTextDeps->contextHash); - if (swiftTextDeps->textualModuleDetails.bridgingHeaderFile.has_value()) - addIdentifier(swiftTextDeps->textualModuleDetails.bridgingHeaderFile - .value()); - addStringArray(moduleID, ModuleIdentifierArrayKind::SourceFiles, - std::vector()); - addStringArray(moduleID, ModuleIdentifierArrayKind::BridgingSourceFiles, - swiftTextDeps->textualModuleDetails.bridgingSourceFiles); - addStringArray( - moduleID, ModuleIdentifierArrayKind::BridgingModuleDependencies, - swiftTextDeps->textualModuleDetails.bridgingModuleDependencies); - break; - } - case swift::ModuleDependencyKind::SwiftBinary: { - auto swiftBinDeps = dependencyInfo->getAsSwiftBinaryModule(); - assert(swiftBinDeps); - addIdentifier(swiftBinDeps->compiledModulePath); - addIdentifier(swiftBinDeps->moduleDocPath); - addIdentifier(swiftBinDeps->sourceInfoPath); - break; - } - case swift::ModuleDependencyKind::SwiftPlaceholder: { - auto swiftPHDeps = dependencyInfo->getAsPlaceholderDependencyModule(); - assert(swiftPHDeps); - addIdentifier(swiftPHDeps->compiledModulePath); - addIdentifier(swiftPHDeps->moduleDocPath); - addIdentifier(swiftPHDeps->sourceInfoPath); - break; - } - case swift::ModuleDependencyKind::SwiftSource: { - auto swiftSourceDeps = dependencyInfo->getAsSwiftSourceModule(); - assert(swiftSourceDeps); - addStringArray(moduleID, ModuleIdentifierArrayKind::ExtraPCMArgs, - swiftSourceDeps->textualModuleDetails.extraPCMArgs); - if (swiftSourceDeps->textualModuleDetails.bridgingHeaderFile.has_value()) - addIdentifier(swiftSourceDeps->textualModuleDetails.bridgingHeaderFile.value()); - addStringArray(moduleID, ModuleIdentifierArrayKind::SourceFiles, - swiftSourceDeps->sourceFiles); - addStringArray(moduleID, ModuleIdentifierArrayKind::BridgingSourceFiles, - swiftSourceDeps->textualModuleDetails.bridgingSourceFiles); - addStringArray(moduleID, ModuleIdentifierArrayKind::BridgingModuleDependencies, - swiftSourceDeps->textualModuleDetails.bridgingModuleDependencies); - break; - } - case swift::ModuleDependencyKind::Clang: { - auto clangDeps = dependencyInfo->getAsClangModule(); - assert(clangDeps); - addIdentifier(clangDeps->pcmOutputPath); - addIdentifier(clangDeps->moduleMapFile); - addIdentifier(clangDeps->contextHash); - addStringArray(moduleID, ModuleIdentifierArrayKind::NonPathCommandLine, - clangDeps->nonPathCommandLine); - addStringArray(moduleID, ModuleIdentifierArrayKind::FileDependencies, - clangDeps->fileDependencies); - addStringArray(moduleID, ModuleIdentifierArrayKind::CapturedPCMArgs, - clangDeps->capturedPCMArgs); - break; - } - default: - llvm_unreachable("Unhandled dependency kind."); + case swift::ModuleDependencyKind::SwiftInterface: { + auto swiftTextDeps = dependencyInfo->getAsSwiftInterfaceModule(); + assert(swiftTextDeps); + addIdentifier(swiftTextDeps->moduleOutputPath); + addIdentifier(swiftTextDeps->swiftInterfaceFile); + addStringArray(moduleID, + ModuleIdentifierArrayKind::CompiledModuleCandidates, + swiftTextDeps->compiledModuleCandidates); + addStringArray(moduleID, ModuleIdentifierArrayKind::BuildCommandLine, + swiftTextDeps->buildCommandLine); + addStringArray(moduleID, ModuleIdentifierArrayKind::ExtraPCMArgs, + swiftTextDeps->textualModuleDetails.extraPCMArgs); + addIdentifier(swiftTextDeps->contextHash); + if (swiftTextDeps->textualModuleDetails.bridgingHeaderFile.has_value()) + addIdentifier( + swiftTextDeps->textualModuleDetails.bridgingHeaderFile.value()); + addStringArray(moduleID, ModuleIdentifierArrayKind::SourceFiles, + std::vector()); + addStringArray(moduleID, ModuleIdentifierArrayKind::BridgingSourceFiles, + swiftTextDeps->textualModuleDetails.bridgingSourceFiles); + addStringArray( + moduleID, ModuleIdentifierArrayKind::BridgingModuleDependencies, + swiftTextDeps->textualModuleDetails.bridgingModuleDependencies); + addDependencyIDArray( + moduleID, ModuleIdentifierArrayKind::SwiftOverlayDependencyIDs, + swiftTextDeps->textualModuleDetails.swiftOverlayDependencies); + break; + } + case swift::ModuleDependencyKind::SwiftBinary: { + auto swiftBinDeps = dependencyInfo->getAsSwiftBinaryModule(); + assert(swiftBinDeps); + addIdentifier(swiftBinDeps->compiledModulePath); + addIdentifier(swiftBinDeps->moduleDocPath); + addIdentifier(swiftBinDeps->sourceInfoPath); + break; + } + case swift::ModuleDependencyKind::SwiftPlaceholder: { + auto swiftPHDeps = dependencyInfo->getAsPlaceholderDependencyModule(); + assert(swiftPHDeps); + addIdentifier(swiftPHDeps->compiledModulePath); + addIdentifier(swiftPHDeps->moduleDocPath); + addIdentifier(swiftPHDeps->sourceInfoPath); + break; + } + case swift::ModuleDependencyKind::SwiftSource: { + auto swiftSourceDeps = dependencyInfo->getAsSwiftSourceModule(); + assert(swiftSourceDeps); + addStringArray(moduleID, ModuleIdentifierArrayKind::ExtraPCMArgs, + swiftSourceDeps->textualModuleDetails.extraPCMArgs); + if (swiftSourceDeps->textualModuleDetails.bridgingHeaderFile + .has_value()) + addIdentifier( + swiftSourceDeps->textualModuleDetails.bridgingHeaderFile.value()); + addStringArray(moduleID, ModuleIdentifierArrayKind::SourceFiles, + swiftSourceDeps->sourceFiles); + addStringArray( + moduleID, ModuleIdentifierArrayKind::BridgingSourceFiles, + swiftSourceDeps->textualModuleDetails.bridgingSourceFiles); + addStringArray( + moduleID, ModuleIdentifierArrayKind::BridgingModuleDependencies, + swiftSourceDeps->textualModuleDetails.bridgingModuleDependencies); + addDependencyIDArray( + moduleID, ModuleIdentifierArrayKind::SwiftOverlayDependencyIDs, + swiftSourceDeps->textualModuleDetails.swiftOverlayDependencies); + break; + } + case swift::ModuleDependencyKind::Clang: { + auto clangDeps = dependencyInfo->getAsClangModule(); + assert(clangDeps); + addIdentifier(clangDeps->pcmOutputPath); + addIdentifier(clangDeps->moduleMapFile); + addIdentifier(clangDeps->contextHash); + addStringArray(moduleID, ModuleIdentifierArrayKind::NonPathCommandLine, + clangDeps->nonPathCommandLine); + addStringArray(moduleID, ModuleIdentifierArrayKind::FileDependencies, + clangDeps->fileDependencies); + addStringArray(moduleID, ModuleIdentifierArrayKind::CapturedPCMArgs, + clangDeps->capturedPCMArgs); + break; + } + default: + llvm_unreachable("Unhandled dependency kind."); } } } diff --git a/lib/DependencyScan/ScanDependencies.cpp b/lib/DependencyScan/ScanDependencies.cpp index c33272c39c49f..9d94da4e784dd 100644 --- a/lib/DependencyScan/ScanDependencies.cpp +++ b/lib/DependencyScan/ScanDependencies.cpp @@ -306,7 +306,7 @@ resolveExplicitModuleInputs(ModuleDependencyID moduleID, } /// Resolve the direct dependencies of the given module. -static ArrayRef +static std::vector resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleID, ModuleDependenciesCache &cache, InterfaceSubContextDelegate &ASTDelegate) { @@ -326,7 +326,8 @@ resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleI auto isSwift = isSwiftInterfaceOrSource || knownDependencies->isSwiftBinaryModule(); // Find the dependencies of every module this module directly depends on. - ModuleDependencyIDSetVector result; + ModuleDependencyIDSetVector directDependencies; + ModuleDependencyIDSetVector swiftOverlayDependencies; for (auto dependsOn : knownDependencies->getModuleImports()) { // Figure out what kind of module we need. bool onlyClangModule = !isSwift || moduleID.first == dependsOn; @@ -335,14 +336,14 @@ resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleI if (onlyClangModule) { if (auto found = ctx.getClangModuleDependencies(dependsOn, cache, ASTDelegate)) - result.insert({dependsOn, ModuleDependencyKind::Clang}); + directDependencies.insert({dependsOn, ModuleDependencyKind::Clang}); } else { if (auto found = ctx.getModuleDependencies(dependsOn, cache, ASTDelegate, /* optionalDependencyLookup */ false, isTestable, moduleID)) - result.insert({dependsOn, found.value()->getKind()}); + directDependencies.insert({dependsOn, found.value()->getKind()}); } } @@ -355,7 +356,7 @@ resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleI /* optionalDependencyLookup */ true, /* isTestableDependency */ false, moduleID)) - result.insert({optionallyDependsOn, found.value()->getKind()}); + directDependencies.insert({optionallyDependsOn, found.value()->getKind()}); } if (isSwiftInterfaceOrSource) { @@ -385,7 +386,9 @@ resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleI assert(bridgingModuleDependencies); for (const auto &clangDep : *bridgingModuleDependencies) { - result.insert({clangDep, ModuleDependencyKind::Clang}); + /// TODO: separate this out of here as well into a separate entry in + /// `CommonSwiftTextualModuleDependencyDetails` + directDependencies.insert({clangDep, ModuleDependencyKind::Clang}); findAllImportedClangModules(ctx, clangDep, cache, allClangModules, knownModules); } @@ -393,7 +396,7 @@ resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleI } // Find all of the Clang modules this Swift module depends on. - for (const auto &dep : result) { + for (const auto &dep : directDependencies) { if (dep.second != ModuleDependencyKind::Clang) continue; @@ -406,15 +409,26 @@ resolveDirectDependencies(CompilerInstance &instance, ModuleDependencyID moduleI for (const auto &clangDep : allClangModules) { if (auto found = ctx.getSwiftModuleDependencies(clangDep, cache, ASTDelegate)) { - if (clangDep != moduleID.first) - result.insert({clangDep, found.value()->getKind()}); + if (clangDep != moduleID.first) { + swiftOverlayDependencies.insert({clangDep, found.value()->getKind()}); + // FIXME: Once all clients know to fetch these dependencies from + // `swiftOverlayDependencies`, the goal is to no longer have them in + // `directDependencies` so the following will need to go away. + directDependencies.insert({clangDep, found.value()->getKind()}); + } } } } // Resolve the dependnecy info - cache.resolveDependencyImports(moduleID, result.takeVector()); - return cache.findDependency(moduleID.first, moduleID.second).value()->getModuleDependencies(); + cache.resolveDependencyImports(moduleID, directDependencies.getArrayRef()); + // Resolve swift Overlay dependencies + if (!swiftOverlayDependencies.empty()) + cache.setSwiftOverlayDependencues(moduleID, swiftOverlayDependencies.getArrayRef()); + + ModuleDependencyIDSetVector result = directDependencies; + result.insert(swiftOverlayDependencies.begin(), swiftOverlayDependencies.end()); + return result.takeVector(); } static void discoverCrossImportOverlayDependencies( @@ -665,11 +679,12 @@ void writeJSONSingleField(llvm::raw_ostream &out, StringRef fieldName, out << "\n"; } -void writeDirectDependencies(llvm::raw_ostream &out, - const swiftscan_string_set_t *dependencies, - unsigned indentLevel, bool trailingComma) { +void writeDependencies(llvm::raw_ostream &out, + const swiftscan_string_set_t *dependencies, + std::string dependenciesKind, + unsigned indentLevel, bool trailingComma) { out.indent(indentLevel * 2); - out << "\"directDependencies\": "; + out << "\"" + dependenciesKind + "\": "; out << "[\n"; for (size_t i = 0; i < dependencies->count; ++i) { @@ -783,8 +798,9 @@ static void writeJSON(llvm::raw_ostream &out, // Direct dependencies. if (swiftTextualDeps || swiftBinaryDeps || clangDeps) - writeDirectDependencies(out, directDependencies, 3, - /*trailingComma=*/true); + writeDependencies(out, directDependencies, + "directDependencies", 3, + /*trailingComma=*/true); // Swift and Clang-specific details. out.indent(3 * 2); out << "\"details\": {\n"; @@ -836,6 +852,9 @@ static void writeJSON(llvm::raw_ostream &out, bool hasBridgingHeaderPath = swiftTextualDeps->bridging_header_path.data && get_C_string(swiftTextualDeps->bridging_header_path)[0] != '\0'; + bool hasOverlayDependencies = + swiftTextualDeps->swift_overlay_module_dependencies && + swiftTextualDeps->swift_overlay_module_dependencies->count > 0; bool commaAfterFramework = swiftTextualDeps->extra_pcm_args->count != 0 || hasBridgingHeaderPath; @@ -871,7 +890,12 @@ static void writeJSON(llvm::raw_ostream &out, swiftTextualDeps->bridging_module_dependencies, 6, /*trailingComma=*/false); out.indent(5 * 2); - out << "}\n"; + out << (hasOverlayDependencies ? "},\n" : "}\n"); + } + if (hasOverlayDependencies) { + writeDependencies(out, swiftTextualDeps->swift_overlay_module_dependencies, + "swiftOverlayDependencies", 5, + /*trailingComma=*/true); } } else if (swiftPlaceholderDeps) { out << "\"swiftPlaceholder\": {\n"; @@ -972,6 +996,33 @@ static bool writeJSONToOutput(DiagnosticEngine &diags, }); } +static void bridgeDependencyIDs(const ArrayRef dependencies, + std::vector &bridgedDependencyNames) { + for (const auto &dep : dependencies) { + std::string dependencyKindAndName; + switch (dep.second) { + case ModuleDependencyKind::SwiftInterface: + case ModuleDependencyKind::SwiftSource: + dependencyKindAndName = "swiftTextual"; + break; + case ModuleDependencyKind::SwiftBinary: + dependencyKindAndName = "swiftBinary"; + break; + case ModuleDependencyKind::SwiftPlaceholder: + dependencyKindAndName = "swiftPlaceholder"; + break; + case ModuleDependencyKind::Clang: + dependencyKindAndName = "clang"; + break; + default: + llvm_unreachable("Unhandled dependency kind."); + } + dependencyKindAndName += ":"; + dependencyKindAndName += dep.first; + bridgedDependencyNames.push_back(dependencyKindAndName); + } +} + static swiftscan_dependency_graph_t generateFullDependencyGraph(CompilerInstance &instance, ModuleDependenciesCache &cache, @@ -1043,8 +1094,11 @@ generateFullDependencyGraph(CompilerInstance &instance, ? create_clone( swiftTextualDeps->textualModuleDetails.bridgingHeaderFile.value().c_str()) : create_null(); - details->kind = SWIFTSCAN_DEPENDENCY_INFO_SWIFT_TEXTUAL; + // Create an overlay dependencies set according to the output format + std::vector bridgedOverlayDependencyNames; + bridgeDependencyIDs(swiftTextualDeps->textualModuleDetails.swiftOverlayDependencies, + bridgedOverlayDependencyNames); details->swift_textual_details = { moduleInterfacePath, @@ -1052,6 +1106,7 @@ generateFullDependencyGraph(CompilerInstance &instance, bridgingHeaderPath, create_set(swiftTextualDeps->textualModuleDetails.bridgingSourceFiles), create_set(swiftTextualDeps->textualModuleDetails.bridgingModuleDependencies), + create_set(bridgedOverlayDependencyNames), create_set(swiftTextualDeps->buildCommandLine), create_set(swiftTextualDeps->textualModuleDetails.extraPCMArgs), create_clone(swiftTextualDeps->contextHash.c_str()), @@ -1063,15 +1118,19 @@ generateFullDependencyGraph(CompilerInstance &instance, ? create_clone( swiftSourceDeps->textualModuleDetails.bridgingHeaderFile.value().c_str()) : create_null(); - // TODO: Once the clients are taught about the new dependency kind, - // switch to using a bespoke kind here. details->kind = SWIFTSCAN_DEPENDENCY_INFO_SWIFT_TEXTUAL; + // Create an overlay dependencies set according to the output format + std::vector bridgedOverlayDependencyNames; + bridgeDependencyIDs(swiftSourceDeps->textualModuleDetails.swiftOverlayDependencies, + bridgedOverlayDependencyNames); + details->swift_textual_details = { moduleInterfacePath, create_empty_set(), bridgingHeaderPath, create_set(swiftSourceDeps->textualModuleDetails.bridgingSourceFiles), create_set(swiftSourceDeps->textualModuleDetails.bridgingModuleDependencies), + create_set(bridgedOverlayDependencyNames), create_empty_set(), create_set(swiftSourceDeps->textualModuleDetails.extraPCMArgs), /*contextHash*/create_null(), @@ -1113,30 +1172,7 @@ generateFullDependencyGraph(CompilerInstance &instance, // Create a direct dependencies set according to the output format std::vector bridgedDependencyNames; - for (const auto &dep : directDependencies) { - std::string dependencyKindAndName; - switch (dep.second) { - case ModuleDependencyKind::SwiftInterface: - case ModuleDependencyKind::SwiftSource: - dependencyKindAndName = "swiftTextual"; - break; - case ModuleDependencyKind::SwiftBinary: - dependencyKindAndName = "swiftBinary"; - break; - case ModuleDependencyKind::SwiftPlaceholder: - dependencyKindAndName = "swiftPlaceholder"; - break; - case ModuleDependencyKind::Clang: - dependencyKindAndName = "clang"; - break; - default: - llvm_unreachable("Unhandled dependency kind."); - } - dependencyKindAndName += ":"; - dependencyKindAndName += dep.first; - bridgedDependencyNames.push_back(dependencyKindAndName); - } - + bridgeDependencyIDs(directDependencies, bridgedDependencyNames); moduleInfo->direct_dependencies = create_set(bridgedDependencyNames); moduleInfo->details = getModuleDetails(); } diff --git a/test/ScanDependencies/Inputs/ModuleDependencyGraph.swift b/test/ScanDependencies/Inputs/ModuleDependencyGraph.swift index 4ac30644f59e8..faf8912f7507b 100644 --- a/test/ScanDependencies/Inputs/ModuleDependencyGraph.swift +++ b/test/ScanDependencies/Inputs/ModuleDependencyGraph.swift @@ -86,12 +86,6 @@ struct SwiftModuleDetails: Codable { /// The paths of potentially ready-to-use compiled modules for the interface. var compiledModuleCandidates: [String]? - /// The bridging header, if any. - var bridgingHeaderPath: String? - - /// The source files referenced by the bridging header. - var bridgingSourceFiles: [String]? = [] - /// Options to the compile command var commandLine: [String]? = [] @@ -102,6 +96,12 @@ struct SwiftModuleDetails: Codable { /// A flag to indicate whether or not this module is a framework. var isFramework: Bool + + /// The bridging header info, if any. + var bridgingHeader: BridgingHeader? + + /// A set of Swift Overlays of Clang Module Dependencies + var swiftOverlayDependencies: [ModuleDependencyId]? } /// Details specific to Swift placeholder dependencies. diff --git a/test/ScanDependencies/module_deps_swift_overlay.swift b/test/ScanDependencies/module_deps_swift_overlay.swift new file mode 100644 index 0000000000000..dc80bf07c7fbd --- /dev/null +++ b/test/ScanDependencies/module_deps_swift_overlay.swift @@ -0,0 +1,20 @@ +// RUN: %empty-directory(%t) +// RUN: mkdir -p %t/clang-module-cache +// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 +// Check the contents of the JSON output +// RUN: %FileCheck %s < %t/deps.json + +// Ensure that round-trip serialization does not affect result +// RUN: %target-swift-frontend -scan-dependencies -test-dependency-scan-cache-serialization -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 +// RUN: %FileCheck %s < %t/deps.json + +// REQUIRES: executable_test +// REQUIRES: objc_interop + +import E + +// CHECK: "swiftOverlayDependencies": [ +// CHECK-NEXT: { +// CHECK-NEXT: "swift": "F" +// CHECK-NEXT: } +// CHECK-NEXT: ] diff --git a/tools/libSwiftScan/libSwiftScan.cpp b/tools/libSwiftScan/libSwiftScan.cpp index c8bc786fd9085..23c5b697ef26c 100644 --- a/tools/libSwiftScan/libSwiftScan.cpp +++ b/tools/libSwiftScan/libSwiftScan.cpp @@ -291,6 +291,11 @@ bool swiftscan_swift_textual_detail_get_is_framework( return details->swift_textual_details.is_framework; } +swiftscan_string_set_t *swiftscan_swift_textual_detail_get_swift_overlay_dependencies( + swiftscan_module_details_t details) { + return details->swift_textual_details.swift_overlay_module_dependencies; +} + //=== Swift Binary Module Details query APIs ------------------------------===// swiftscan_string_ref_t swiftscan_swift_binary_detail_get_compiled_module_path( diff --git a/tools/libSwiftScan/libSwiftScan.exports b/tools/libSwiftScan/libSwiftScan.exports index abfcc6c820607..4b940c96ea5f2 100644 --- a/tools/libSwiftScan/libSwiftScan.exports +++ b/tools/libSwiftScan/libSwiftScan.exports @@ -15,6 +15,7 @@ swiftscan_swift_textual_detail_get_command_line swiftscan_swift_textual_detail_get_extra_pcm_args swiftscan_swift_textual_detail_get_context_hash swiftscan_swift_textual_detail_get_is_framework +swiftscan_swift_textual_detail_get_swift_overlay_dependencies swiftscan_swift_binary_detail_get_compiled_module_path swiftscan_swift_binary_detail_get_module_doc_path swiftscan_swift_binary_detail_get_module_source_info_path