From 0e12f2042e920d0f015fe21838b118e4eb7189ce Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Wed, 28 Feb 2024 16:35:22 -0800 Subject: [PATCH 1/2] [ScanDependency] Move binary module validation into scanner Improve swift dependency scanner by validating and selecting dependency module into scanner. This provides benefits that: * Build system does not need to schedule interface compilation task if the candidate module is picked, it can just use the candidate module directly. * There is no need for forwarding module in the explicit module build. Since the build system is coordinating the build, there is no need for the forwarding module in the module cache to avoid duplicated work, * This also correctly supports all the module loading modes in the dependency scanner. This is achieved by only adding validate and up-to-date binary module as the candidate module for swift interface module dependency. This allows caching build to construct the correct dependency in the CAS. If there is a candidate module for the interface module, dependency scanner will return a binary module dependency in the dependency graph. The legacy behavior is mostly preserved with a hidden frontend flag `-no-scanner-module-validation`, while the scanner output is mostly interchangeable with new scanner behavior with `prefer-interface` module loading mode except the candidate module will not be returned. rdar://123711823 --- include/swift/AST/ModuleDependencies.h | 6 + include/swift/AST/SearchPathOptions.h | 19 ++- include/swift/Option/FrontendOptions.td | 6 + .../Serialization/SerializedModuleLoader.h | 10 +- lib/AST/ModuleDependencies.cpp | 7 + .../ModuleDependencyScanner.cpp | 3 +- lib/DependencyScan/ScanDependencies.cpp | 139 ++++++++---------- lib/Frontend/CompilerInvocation.cpp | 28 +++- lib/Frontend/Frontend.cpp | 21 +-- lib/Frontend/ModuleInterfaceLoader.cpp | 44 ++++-- lib/Serialization/ScanningLoaders.cpp | 13 +- lib/Serialization/SerializedModuleLoader.cpp | 6 +- test/CAS/Xcc_args.swift | 5 +- test/CAS/cached_diagnostics.swift | 4 +- test/CAS/cross_import.swift | 2 +- test/CAS/index-store.swift | 2 +- test/CAS/module_deps.swift | 6 +- test/CAS/module_deps_include_tree.swift | 6 +- test/CAS/module_hash.swift | 4 +- test/CAS/plugin_cas.swift | 4 +- test/Frontend/module-alias-scan-deps.swift | 4 +- .../clang-args-transitive-availability.swift | 2 +- .../clang-session-transitive.swift | 2 +- .../extension-transitive-availability.swift | 2 +- .../infer-arch-from-file.swift | 2 +- .../FilterClangSearchPaths.swift | 2 +- test/ScanDependencies/ObjCStrict.swift | 2 +- test/ScanDependencies/batch_module_scan.swift | 2 +- test/ScanDependencies/bin_mod_import.swift | 4 +- .../blocklist-path-pass-down.swift | 2 +- .../bridging_header_dep_module_map.swift | 2 +- .../can_import_placeholder.swift | 4 +- test/ScanDependencies/clang-target.swift | 2 +- .../clang_auxiliary_module_framework.swift | 4 +- .../compiled_swift_modules.swift | 22 ++- test/ScanDependencies/direct_cc1_scan.swift | 4 +- .../eliminate_unused_vfs.swift | 2 +- .../explicit-swift-dependencies.swift | 2 +- .../header_deps_of_binary.swift | 2 +- .../include-sdk-in-command.swift | 2 +- ...module_deps_binary_dep_swift_overlay.swift | 2 +- .../module_deps_cache_reuse.swift | 4 +- .../module_deps_cross_import_overlay.swift | 4 +- ...module_deps_different_paths_no_reuse.swift | 4 +- .../module_deps_external.swift | 4 +- test/ScanDependencies/module_framework.swift | 4 +- test/ScanDependencies/module_load_mode.swift | 21 +++ .../no_cross_import_module_for_self.swift | 2 +- .../no_main_module_cross_import.swift | 2 +- test/ScanDependencies/package_interface.swift | 8 +- test/ScanDependencies/preserve_used_vfs.swift | 2 +- .../private_interface_candidate_module.swift | 2 +- .../separate_bridging_header_deps.swift | 2 +- test/ScanDependencies/testable-import.swift | 6 +- 54 files changed, 282 insertions(+), 190 deletions(-) create mode 100644 test/ScanDependencies/module_load_mode.swift diff --git a/include/swift/AST/ModuleDependencies.h b/include/swift/AST/ModuleDependencies.h index f5ca1ec99ae64..64a7a2cfe99d6 100644 --- a/include/swift/AST/ModuleDependencies.h +++ b/include/swift/AST/ModuleDependencies.h @@ -1115,6 +1115,12 @@ class ModuleDependenciesCache { std::optional findDependency(StringRef moduleName) const; + /// Look for known existing dependencies. + /// + /// \returns the cached result. + const ModuleDependencyInfo & + findKnownDependency(const ModuleDependencyID &moduleID) const; + /// Record dependencies for the given module. void recordDependency(StringRef moduleName, ModuleDependencyInfo dependencies); diff --git a/include/swift/AST/SearchPathOptions.h b/include/swift/AST/SearchPathOptions.h index 14ed706c67a95..dd7debcce1351 100644 --- a/include/swift/AST/SearchPathOptions.h +++ b/include/swift/AST/SearchPathOptions.h @@ -38,6 +38,15 @@ enum class ModuleSearchPathKind { RuntimeLibrary, }; +/// Specifies how to load modules when both a module interface and serialized +/// AST are present, or whether to disallow one format or the other altogether. +enum class ModuleLoadingMode { + PreferInterface, + PreferSerialized, + OnlyInterface, + OnlySerialized +}; + /// A single module search path that can come from different sources, e.g. /// framework search paths, import search path etc. class ModuleSearchPath : public llvm::RefCountedBase { @@ -499,6 +508,12 @@ class SearchPathOptions { /// original form. PathObfuscator DeserializedPathRecoverer; + /// Specify the module loading behavior of the compilation. + ModuleLoadingMode ModuleLoadMode = ModuleLoadingMode::PreferSerialized; + + /// Legacy scanner search behavior. + bool NoScannerModuleValidation = false; + /// Return all module search paths that (non-recursively) contain a file whose /// name is in \p Filenames. SmallVector @@ -546,7 +561,9 @@ class SearchPathOptions { RuntimeResourcePath, hash_combine_range(RuntimeLibraryImportPaths.begin(), RuntimeLibraryImportPaths.end()), - DisableModulesValidateSystemDependencies); + DisableModulesValidateSystemDependencies, + NoScannerModuleValidation, + ModuleLoadMode); } /// Return a hash code of any components from these options that should diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index bc4abcbd38ece..ed82e9cba1c5a 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -1348,4 +1348,10 @@ def disable_strict_concurrency_region_based_isolation : Flag<["-"], HelpText<"Disable region based isolation when running with strict concurrency enabled. Only enabled with asserts">, Flags<[HelpHidden]>; +def no_scanner_module_validation: Flag<["-"], "no-scanner-module-validation">, + HelpText<"Do not validate binary modules in scanner and delegate the validation to swift-frontend">; +def module_load_mode: Separate<["-"], "module-load-mode">, + MetaVarName<"only-interface|prefer-interface|prefer-serialized|only-serialized">, + HelpText<"Module loading mode">; + } // end let Flags = [FrontendOption, NoDriverOption, HelpHidden] diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h index a51f85d918c8c..5b08a71f9e783 100644 --- a/include/swift/Serialization/SerializedModuleLoader.h +++ b/include/swift/Serialization/SerializedModuleLoader.h @@ -16,6 +16,7 @@ #include "swift/AST/FileUnit.h" #include "swift/AST/Module.h" #include "swift/AST/ModuleLoader.h" +#include "swift/AST/SearchPathOptions.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrefixMapper.h" #include "llvm/TargetParser/Triple.h" @@ -28,15 +29,6 @@ namespace file_types { enum ID : uint8_t; } -/// Specifies how to load modules when both a module interface and serialized -/// AST are present, or whether to disallow one format or the other altogether. -enum class ModuleLoadingMode { - PreferInterface, - PreferSerialized, - OnlyInterface, - OnlySerialized -}; - /// How a dependency should be loaded. /// /// \sa getTransitiveLoadingBehavior diff --git a/lib/AST/ModuleDependencies.cpp b/lib/AST/ModuleDependencies.cpp index 18cf09ec2c065..b933181e48b0f 100644 --- a/lib/AST/ModuleDependencies.cpp +++ b/lib/AST/ModuleDependencies.cpp @@ -740,6 +740,13 @@ ModuleDependenciesCache::findDependency(StringRef moduleName) const { return std::nullopt; } +const ModuleDependencyInfo &ModuleDependenciesCache::findKnownDependency( + const ModuleDependencyID &moduleID) const { + auto dep = findDependency(moduleID); + assert(dep && "dependency unknown"); + return **dep; +} + bool ModuleDependenciesCache::hasDependency(const ModuleDependencyID &moduleID) const { return hasDependency(moduleID.ModuleName, moduleID.Kind); } diff --git a/lib/DependencyScan/ModuleDependencyScanner.cpp b/lib/DependencyScan/ModuleDependencyScanner.cpp index fe1461be18230..b75ea0393f19f 100644 --- a/lib/DependencyScan/ModuleDependencyScanner.cpp +++ b/lib/DependencyScan/ModuleDependencyScanner.cpp @@ -174,7 +174,8 @@ ModuleDependencyScanningWorker::ModuleDependencyScanningWorker( ScanASTContext, *static_cast( ScanASTContext.getModuleInterfaceChecker()), - &DependencyTracker, ModuleLoadingMode::OnlyInterface); + &DependencyTracker, + ScanCompilerInvocation.getSearchPathOptions().ModuleLoadMode); } ModuleDependencyVector diff --git a/lib/DependencyScan/ScanDependencies.cpp b/lib/DependencyScan/ScanDependencies.cpp index 841c4d12b257e..f8f6c3c0f082e 100644 --- a/lib/DependencyScan/ScanDependencies.cpp +++ b/lib/DependencyScan/ScanDependencies.cpp @@ -192,7 +192,7 @@ updateModuleCacheKey(ModuleDependencyInfo &depInfo, } static llvm::Error resolveExplicitModuleInputs( - ModuleDependencyID moduleID, const ModuleDependencyInfo &resolvingDepInfo, + ModuleDependencyID moduleID, const std::set &dependencies, ModuleDependenciesCache &cache, CompilerInstance &instance, std::optional> bridgingHeaderDeps) { @@ -200,6 +200,7 @@ static llvm::Error resolveExplicitModuleInputs( if (moduleID.Kind == ModuleDependencyKind::SwiftPlaceholder) return llvm::Error::success(); + auto &resolvingDepInfo = cache.findKnownDependency(moduleID); // If the dependency is already finalized, nothing needs to be done. if (resolvingDepInfo.isFinalized()) return llvm::Error::success(); @@ -242,13 +243,10 @@ static llvm::Error resolveExplicitModuleInputs( std::vector commandLine = resolvingDepInfo.getCommandline(); for (const auto &depModuleID : dependencies) { - const auto optionalDepInfo = - cache.findDependency(depModuleID); - assert(optionalDepInfo.has_value()); - const auto depInfo = optionalDepInfo.value(); + const auto &depInfo = cache.findKnownDependency(depModuleID); switch (depModuleID.Kind) { case swift::ModuleDependencyKind::SwiftInterface: { - auto interfaceDepDetails = depInfo->getAsSwiftInterfaceModule(); + auto interfaceDepDetails = depInfo.getAsSwiftInterfaceModule(); assert(interfaceDepDetails && "Expected Swift Interface dependency."); auto &path = interfaceDepDetails->moduleCacheKey.empty() ? interfaceDepDetails->moduleOutputPath @@ -257,7 +255,7 @@ static llvm::Error resolveExplicitModuleInputs( path); } break; case swift::ModuleDependencyKind::SwiftBinary: { - auto binaryDepDetails = depInfo->getAsSwiftBinaryModule(); + auto binaryDepDetails = depInfo.getAsSwiftBinaryModule(); assert(binaryDepDetails && "Expected Swift Binary Module dependency."); auto &path = binaryDepDetails->moduleCacheKey.empty() ? binaryDepDetails->compiledModulePath @@ -269,24 +267,23 @@ static llvm::Error resolveExplicitModuleInputs( // order to resolve the header's own header include directives. for (const auto &bridgingHeaderDepName : binaryDepDetails->headerModuleDependencies) { - auto optionalBridgingHeaderDepModuleInfo = cache.findDependency( + auto optionalBridgingHeaderDepModuleInfo = cache.findKnownDependency( {bridgingHeaderDepName, ModuleDependencyKind::Clang}); - assert(optionalDepInfo.has_value()); const auto bridgingHeaderDepModuleDetails = - optionalBridgingHeaderDepModuleInfo.value()->getAsClangModule(); + optionalBridgingHeaderDepModuleInfo.getAsClangModule(); commandLine.push_back( "-fmodule-map-file=" + remapPath(bridgingHeaderDepModuleDetails->moduleMapFile)); } } break; case swift::ModuleDependencyKind::SwiftPlaceholder: { - auto placeholderDetails = depInfo->getAsPlaceholderDependencyModule(); + auto placeholderDetails = depInfo.getAsPlaceholderDependencyModule(); assert(placeholderDetails && "Expected Swift Placeholder dependency."); commandLine.push_back("-swift-module-file=" + depModuleID.ModuleName + "=" + placeholderDetails->compiledModulePath); } break; case swift::ModuleDependencyKind::Clang: { - auto clangDepDetails = depInfo->getAsClangModule(); + auto clangDepDetails = depInfo.getAsClangModule(); assert(clangDepDetails && "Expected Clang Module dependency."); if (!resolvingDepInfo.isClangModule()) { commandLine.push_back("-Xcc"); @@ -303,13 +300,13 @@ static llvm::Error resolveExplicitModuleInputs( } // Only need to merge the CASFS from clang importer. - if (auto ID = depInfo->getCASFSRootID()) + if (auto ID = depInfo.getCASFSRootID()) rootIDs.push_back(*ID); - if (auto ID = depInfo->getClangIncludeTree()) + if (auto ID = depInfo.getClangIncludeTree()) includeTrees.push_back(*ID); } break; case swift::ModuleDependencyKind::SwiftSource: { - if (auto E = addBridgingHeaderDeps(*depInfo)) + if (auto E = addBridgingHeaderDeps(depInfo)) return E; break; } @@ -390,9 +387,8 @@ static llvm::Error resolveExplicitModuleInputs( std::vector newCommandLine = dependencyInfoCopy.getBridgingHeaderCommandline(); for (auto bridgingDep : *bridgingHeaderDeps) { - auto dep = cache.findDependency(bridgingDep); - assert(dep && "unknown clang dependency"); - auto *clangDep = (*dep)->getAsClangModule(); + auto &dep = cache.findKnownDependency(bridgingDep); + auto *clangDep = dep.getAsClangModule(); assert(clangDep && "wrong module dependency kind"); if (!clangDep->moduleCacheKey.empty()) { newCommandLine.push_back("-Xcc"); @@ -406,19 +402,11 @@ static llvm::Error resolveExplicitModuleInputs( dependencyInfoCopy.updateBridgingHeaderCommandLine(newCommandLine); } - if (resolvingDepInfo.isClangModule() || - resolvingDepInfo.isSwiftInterfaceModule()) { - // Compute and update module cache key. - auto Key = updateModuleCacheKey(dependencyInfoCopy, cache, CAS); - if (!Key) - return Key.takeError(); - } - - // For binary module, we need to make sure the lookup key is setup here in - // action cache. We just use the CASID of the binary module itself as key. - if (auto *binaryDep = dependencyInfoCopy.getAsSwiftBinaryModule()) { - auto Ref = - CASFS.getObjectRefForFileContent(binaryDep->compiledModulePath); + // Compute and update module cache key. + auto setupBinaryCacheKey = [&](StringRef path) -> llvm::Error { + // For binary module, we need to make sure the lookup key is setup here in + // action cache. We just use the CASID of the binary module itself as key. + auto Ref = CASFS.getObjectRefForFileContent(path); if (!Ref) return llvm::errorCodeToError(Ref.getError()); assert(*Ref && "Binary module should be loaded into CASFS already"); @@ -432,18 +420,36 @@ static llvm::Error resolveExplicitModuleInputs( if (auto E = instance.getActionCache().put(CAS.getID(**Ref), CAS.getID(*Result))) return E; + return llvm::Error::success(); + }; + + if (resolvingDepInfo.isClangModule() || + resolvingDepInfo.isSwiftInterfaceModule()) { + auto Key = updateModuleCacheKey(dependencyInfoCopy, cache, CAS); + if (!Key) + return Key.takeError(); + } else if (auto *binaryDep = dependencyInfoCopy.getAsSwiftBinaryModule()) { + if (auto E = setupBinaryCacheKey(binaryDep->compiledModulePath)) + return E; } } + dependencyInfoCopy.setIsFinalized(true); cache.updateDependency(moduleID, dependencyInfoCopy); return llvm::Error::success(); } -static llvm::Error pruneUnusedVFSOverlays( - ModuleDependencyID moduleID, const ModuleDependencyInfo &resolvingDepInfo, - const std::set &dependencies, - ModuleDependenciesCache &cache, CompilerInstance &instance) { +static llvm::Error +pruneUnusedVFSOverlays(ModuleDependencyID moduleID, + const std::set &dependencies, + ModuleDependenciesCache &cache, + CompilerInstance &instance) { + // Pruning of unused VFS overlay options for Clang dependencies + // is performed by the Clang dependency scanner. + if (moduleID.Kind == ModuleDependencyKind::Clang) + return llvm::Error::success(); + auto isVFSOverlayFlag = [](StringRef arg) { return arg == "-ivfsoverlay" || arg == "-vfsoverlay"; }; @@ -451,11 +457,7 @@ static llvm::Error pruneUnusedVFSOverlays( return arg == "-Xcc"; }; - // Pruning of unused VFS overlay options for Clang dependencies - // is performed by the Clang dependency scanner. - if (!resolvingDepInfo.isSwiftModule()) - return llvm::Error::success(); - + auto &resolvingDepInfo = cache.findKnownDependency(moduleID); // If this Swift dependency contains any VFS overlay paths, // then attempt to prune the ones not used by any of the Clang dependencies. if (!llvm::any_of(resolvingDepInfo.getCommandline(), @@ -469,10 +471,8 @@ static llvm::Error pruneUnusedVFSOverlays( // pruned by the Clang dependency scanner. llvm::StringSet<> usedVFSOverlayPaths; for (const auto &depModuleID : dependencies) { - const auto optionalDepInfo = cache.findDependency(depModuleID); - assert(optionalDepInfo.has_value()); - const auto depInfo = optionalDepInfo.value(); - if (auto clangDepDetails = depInfo->getAsClangModule()) { + const auto &depInfo = cache.findKnownDependency(depModuleID); + if (auto clangDepDetails = depInfo.getAsClangModule()) { const auto &depCommandLine = clangDepDetails->buildCommandLine; // true if the previous argument was the dash-option of an option pair bool getNext = false; @@ -1158,24 +1158,17 @@ generateFullDependencyGraph(const CompilerInstance &instance, for (size_t i = 0; i < allModules.size(); ++i) { const auto &module = allModules[i]; - // Grab the completed module dependencies. - auto moduleDepsQuery = cache.findDependency(module); - if (!moduleDepsQuery) { - llvm::report_fatal_error(Twine("Module Dependency Cache missing module") + - module.ModuleName); - } - - auto moduleDeps = *moduleDepsQuery; + auto &moduleDeps = cache.findKnownDependency(module); // Collect all the required pieces to build a ModuleInfo - auto swiftPlaceholderDeps = moduleDeps->getAsPlaceholderDependencyModule(); - auto swiftTextualDeps = moduleDeps->getAsSwiftInterfaceModule(); - auto swiftSourceDeps = moduleDeps->getAsSwiftSourceModule(); - auto swiftBinaryDeps = moduleDeps->getAsSwiftBinaryModule(); - auto clangDeps = moduleDeps->getAsClangModule(); + auto swiftPlaceholderDeps = moduleDeps.getAsPlaceholderDependencyModule(); + auto swiftTextualDeps = moduleDeps.getAsSwiftInterfaceModule(); + auto swiftSourceDeps = moduleDeps.getAsSwiftSourceModule(); + auto swiftBinaryDeps = moduleDeps.getAsSwiftBinaryModule(); + auto clangDeps = moduleDeps.getAsClangModule(); // ModulePath const char *modulePathSuffix = - moduleDeps->isSwiftModule() ? ".swiftmodule" : ".pcm"; + moduleDeps.isSwiftModule() ? ".swiftmodule" : ".pcm"; std::string modulePath; if (swiftTextualDeps) modulePath = swiftTextualDeps->moduleOutputPath; @@ -1196,10 +1189,8 @@ generateFullDependencyGraph(const CompilerInstance &instance, sourceFiles = clangDeps->fileDependencies; } - auto optionalDepInfo = cache.findDependency(module); - assert(optionalDepInfo.has_value() && "Missing dependency info during graph generation diagnosis."); - auto depInfo = optionalDepInfo.value(); - auto directDependencies = depInfo->getDirectModuleDependencies(); + auto &depInfo = cache.findKnownDependency(module); + auto directDependencies = depInfo.getDirectModuleDependencies(); // Generate a swiftscan_clang_details_t object based on the dependency kind auto getModuleDetails = [&]() -> swiftscan_module_details_t { @@ -1208,9 +1199,12 @@ generateFullDependencyGraph(const CompilerInstance &instance, swiftscan_string_ref_t moduleInterfacePath = create_clone(swiftTextualDeps->swiftInterfaceFile.c_str()); swiftscan_string_ref_t bridgingHeaderPath = - swiftTextualDeps->textualModuleDetails.bridgingHeaderFile.has_value() + swiftTextualDeps->textualModuleDetails.bridgingHeaderFile + .has_value() ? create_clone( - swiftTextualDeps->textualModuleDetails.bridgingHeaderFile.value().c_str()) + 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 @@ -1414,12 +1408,12 @@ computeTransitiveClosureOfExplicitDependencies( } static std::set computeBridgingHeaderTransitiveDependencies( - const ModuleDependencyInfo *dep, + const ModuleDependencyInfo &dep, const std::unordered_map> &transitiveClosures, const ModuleDependenciesCache &cache) { std::set result; - auto *sourceDep = dep->getAsSwiftSourceModule(); + auto *sourceDep = dep.getAsSwiftSourceModule(); if (!sourceDep) return result; @@ -1871,22 +1865,19 @@ static void resolveDependencyCommandLineArguments( // For main module or binary modules, no command-line to resolve. // For Clang modules, their dependencies are resolved by the clang Scanner // itself for us. - auto optionalDeps = cache.findDependency(modID); - assert(optionalDeps.has_value()); - auto deps = optionalDeps.value(); + auto &deps = cache.findKnownDependency(modID); std::optional> bridgingHeaderDeps; if (modID.Kind == ModuleDependencyKind::SwiftSource) bridgingHeaderDeps = computeBridgingHeaderTransitiveDependencies( deps, moduleTransitiveClosures, cache); - if (auto E = - resolveExplicitModuleInputs(modID, *deps, dependencyClosure, cache, - instance, bridgingHeaderDeps)) + if (auto E = resolveExplicitModuleInputs(modID, dependencyClosure, cache, + instance, bridgingHeaderDeps)) instance.getDiags().diagnose(SourceLoc(), diag::error_cas, toString(std::move(E))); - if (auto E = pruneUnusedVFSOverlays(modID, *deps, dependencyClosure, - cache, instance)) + if (auto E = + pruneUnusedVFSOverlays(modID, dependencyClosure, cache, instance)) instance.getDiags().diagnose(SourceLoc(), diag::error_cas, toString(std::move(E))); } diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 5d4526c2af1b7..929bfa39aac70 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1880,8 +1880,7 @@ static bool validateSwiftModuleFileArgumentAndAdd(const std::string &swiftModule return false; } -static bool ParseSearchPathArgs(SearchPathOptions &Opts, - ArgList &Args, +static bool ParseSearchPathArgs(SearchPathOptions &Opts, ArgList &Args, DiagnosticEngine &Diags, StringRef workingDirectory) { using namespace options; @@ -2016,6 +2015,31 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts, for (StringRef Opt : Args.getAllArgValues(OPT_scanner_prefix_map)) { Opts.ScannerPrefixMapper.push_back(Opt.str()); } + + Opts.NoScannerModuleValidation |= + Args.hasArg(OPT_no_scanner_module_validation); + + std::optional forceModuleLoadingMode; + if (auto *A = Args.getLastArg(OPT_module_load_mode)) + forceModuleLoadingMode = A->getValue(); + else if (auto Env = llvm::sys::Process::GetEnv("SWIFT_FORCE_MODULE_LOADING")) + forceModuleLoadingMode = Env; + if (forceModuleLoadingMode) { + if (*forceModuleLoadingMode == "prefer-interface" || + *forceModuleLoadingMode == "prefer-parseable") + Opts.ModuleLoadMode = ModuleLoadingMode::PreferInterface; + else if (*forceModuleLoadingMode == "prefer-serialized") + Opts.ModuleLoadMode = ModuleLoadingMode::PreferSerialized; + else if (*forceModuleLoadingMode == "only-interface" || + *forceModuleLoadingMode == "only-parseable") + Opts.ModuleLoadMode = ModuleLoadingMode::OnlyInterface; + else if (*forceModuleLoadingMode == "only-serialized") + Opts.ModuleLoadMode = ModuleLoadingMode::OnlySerialized; + else + Diags.diagnose(SourceLoc(), diag::unknown_forced_module_loading_mode, + *forceModuleLoadingMode); + } + // Opts.RuntimeIncludePath is set by calls to // setRuntimeIncludePath() or setMainExecutablePath(). // Opts.RuntimeImportPath is set by calls to diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index b3547658bf69e..47f79296c605c 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -709,26 +709,7 @@ bool CompilerInstance::setUpModuleLoaders() { enableLibraryEvolution, getDependencyTracker())); } - auto MLM = ModuleLoadingMode::PreferSerialized; - if (auto forceModuleLoadingMode = - llvm::sys::Process::GetEnv("SWIFT_FORCE_MODULE_LOADING")) { - if (*forceModuleLoadingMode == "prefer-interface" || - *forceModuleLoadingMode == "prefer-parseable") - MLM = ModuleLoadingMode::PreferInterface; - else if (*forceModuleLoadingMode == "prefer-serialized") - MLM = ModuleLoadingMode::PreferSerialized; - else if (*forceModuleLoadingMode == "only-interface" || - *forceModuleLoadingMode == "only-parseable") - MLM = ModuleLoadingMode::OnlyInterface; - else if (*forceModuleLoadingMode == "only-serialized") - MLM = ModuleLoadingMode::OnlySerialized; - else { - Diagnostics.diagnose(SourceLoc(), - diag::unknown_forced_module_loading_mode, - *forceModuleLoadingMode); - return true; - } - } + auto MLM = Invocation.getSearchPathOptions().ModuleLoadMode; auto IgnoreSourceInfoFile = Invocation.getFrontendOptions().IgnoreSwiftSourceInfo; if (Invocation.getLangOptions().EnableMemoryBufferImporter) { diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 27b187a2b75f7..1adce0d04c2c2 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -1372,7 +1372,8 @@ std::error_code ModuleInterfaceLoader::findModuleFilesInDirectory( } std::vector -ModuleInterfaceCheckerImpl::getCompiledModuleCandidatesForInterface(StringRef moduleName, StringRef interfacePath) { +ModuleInterfaceCheckerImpl::getCompiledModuleCandidatesForInterface( + StringRef moduleName, StringRef interfacePath) { // Derive .swiftmodule path from the .swiftinterface path. auto interfaceExt = file_types::getExtension(file_types::TY_SwiftModuleInterfaceFile); auto newExt = file_types::getExtension(file_types::TY_SwiftModuleFile); @@ -1392,17 +1393,32 @@ ModuleInterfaceCheckerImpl::getCompiledModuleCandidatesForInterface(StringRef mo ModuleInterfaceLoaderImpl Impl(Ctx, modulePath, interfacePath, moduleName, CacheDir, PrebuiltCacheDir, BackupInterfaceDir, - SourceLoc(), Opts, - RequiresOSSAModules, - nullptr, - ModuleLoadingMode::PreferSerialized); + SourceLoc(), Opts, RequiresOSSAModules, + nullptr, Ctx.SearchPathOpts.ModuleLoadMode); std::vector results; - auto pair = Impl.getCompiledModuleCandidates(); - // Add compiled module candidates only when they are non-empty. - if (!pair.first.empty()) - results.push_back(pair.first); - if (!pair.second.empty()) - results.push_back(pair.second); + std::string adjacentMod, prebuiltMod; + std::tie(adjacentMod, prebuiltMod) = Impl.getCompiledModuleCandidates(); + + auto validateModule = [&](StringRef modulePath) { + // Legacy behavior do not validate module. + if (Ctx.SearchPathOpts.NoScannerModuleValidation) + return true; + + // If we picked the other module already, no need to validate this one since + // it should not be used anyway. + if (!results.empty()) + return false; + SmallVector deps; + std::unique_ptr moduleBuffer; + return Impl.upToDateChecker.swiftModuleIsUpToDate( + modulePath, Impl.rebuildInfo, deps, moduleBuffer); + }; + + // Add compiled module candidates only when they are non-empty and up-to-date. + if (!adjacentMod.empty() && validateModule(adjacentMod)) + results.push_back(adjacentMod); + if (!prebuiltMod.empty() && validateModule(prebuiltMod)) + results.push_back(prebuiltMod); return results; } @@ -1862,6 +1878,12 @@ InterfaceSubContextDelegateImpl::InterfaceSubContextDelegateImpl( genericSubInvocation.getSearchPathOptions().PluginSearchOpts = searchPathOpts.PluginSearchOpts; + // Get module loading behavior options. + genericSubInvocation.getSearchPathOptions().NoScannerModuleValidation = + searchPathOpts.NoScannerModuleValidation; + genericSubInvocation.getSearchPathOptions().ModuleLoadMode = + searchPathOpts.ModuleLoadMode; + auto &subClangImporterOpts = genericSubInvocation.getClangImporterOptions(); // Respect the detailed-record preprocessor setting of the parent context. // This, and the "raw" clang module format it implicitly enables, are diff --git a/lib/Serialization/ScanningLoaders.cpp b/lib/Serialization/ScanningLoaders.cpp index a9dd8a9daba67..3cf6dec7769cb 100644 --- a/lib/Serialization/ScanningLoaders.cpp +++ b/lib/Serialization/ScanningLoaders.cpp @@ -152,8 +152,19 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath, std::string InPath = moduleInterfacePath.str(); auto compiledCandidates = getCompiledCandidates(Ctx, realModuleName.str(), InPath); - std::vector Args(BaseArgs.begin(), BaseArgs.end()); + if (!compiledCandidates.empty() && + !Ctx.SearchPathOpts.NoScannerModuleValidation) { + assert(compiledCandidates.size() == 1 && + "Should only have 1 candidate module"); + auto BinaryDep = scanModuleFile(compiledCandidates[0], isFramework); + if (!BinaryDep) + return BinaryDep.getError(); + + Result = *BinaryDep; + return std::error_code(); + } + std::vector Args(BaseArgs.begin(), BaseArgs.end()); // Add explicit Swift dependency compilation flags Args.push_back("-explicit-interface-module-build"); Args.push_back("-disable-implicit-swift-modules"); diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index 77bc1e1698fc4..e25d06e80a207 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -25,6 +25,7 @@ #include "swift/Basic/Version.h" #include "swift/Frontend/ModuleInterfaceLoader.h" #include "swift/Option/Options.h" +#include "swift/Serialization/Validation.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/ArgList.h" @@ -403,13 +404,16 @@ SerializedModuleLoaderBase::getImportsOfModule( llvm::StringSet<> importedModuleNames; std::string importedHeader = ""; - // Load the module file without validation. std::shared_ptr loadedModuleFile; serialization::ValidationInfo loadInfo = ModuleFileSharedCore::load( "", "", std::move(moduleBuf.get()), nullptr, nullptr, isFramework, isRequiredOSSAModules, SDKName, recoverer, loadedModuleFile); + // If failed to load, just ignore and return do not found. + if (loadInfo.status != serialization::Status::Valid) + return std::make_error_code(std::errc::no_such_file_or_directory); + for (const auto &dependency : loadedModuleFile->getDependencies()) { if (dependency.isHeader()) { assert(importedHeader.empty() && diff --git a/test/CAS/Xcc_args.swift b/test/CAS/Xcc_args.swift index 0ffbe0ace877d..498635f0a7fc5 100644 --- a/test/CAS/Xcc_args.swift +++ b/test/CAS/Xcc_args.swift @@ -5,14 +5,11 @@ // RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \ // RUN: %t/test.swift -o %t/deps.json -swift-version 5 -cache-compile-job -cas-path %t/cas -Xcc -D_VERSION=1 \ // RUN: -Xcc -fmodule-map-file=%t/include/module.modulemap -Xcc -ivfsoverlay -Xcc %t/empty.yaml \ -// RUN: -Xcc -I%t/empty.hmap +// RUN: -Xcc -I%t/empty.hmap -module-load-mode prefer-serialized // RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json clang:SwiftShims > %t/shims.cmd // RUN: %swift_frontend_plain @%t/shims.cmd -// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json Swift > %t/swift.cmd -// RUN: %swift_frontend_plain @%t/swift.cmd - // RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json clang:_Macro > %t/Macro.cmd // RUN: %swift_frontend_plain @%t/Macro.cmd diff --git a/test/CAS/cached_diagnostics.swift b/test/CAS/cached_diagnostics.swift index 3bb71963b33b7..8ac6bd000da2e 100644 --- a/test/CAS/cached_diagnostics.swift +++ b/test/CAS/cached_diagnostics.swift @@ -5,12 +5,10 @@ // RUN: %target-swift-frontend -scan-dependencies -module-name Test -O -import-objc-header %S/Inputs/objc.h \ // RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \ -// RUN: %s -o %t/deps.json -cache-compile-job -cas-path %t/cas +// RUN: %s -o %t/deps.json -cache-compile-job -cas-path %t/cas -module-load-mode prefer-serialized // RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json clang:SwiftShims > %t/shim.cmd // RUN: %swift_frontend_plain @%t/shim.cmd -// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json Swift > %t/swift.cmd -// RUN: %swift_frontend_plain @%t/swift.cmd // RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json bridgingHeader | tail -n +2 > %t/header.cmd // RUN: %target-swift-frontend @%t/header.cmd -disable-implicit-swift-modules %S/Inputs/objc.h -O -o %t/objc.pch 2>&1 | %FileCheck %s -check-prefix CHECK-BRIDGE diff --git a/test/CAS/cross_import.swift b/test/CAS/cross_import.swift index 9e34140953536..9abba2673f00a 100644 --- a/test/CAS/cross_import.swift +++ b/test/CAS/cross_import.swift @@ -15,7 +15,7 @@ // RUN: %target-swift-frontend -scan-dependencies -module-name Test -module-cache-path %t/clang-module-cache %t/main.swift \ // RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \ -// RUN: -o %t/deps.json -I %t -cache-compile-job -cas-path %t/cas -swift-version 5 -enable-cross-import-overlays +// RUN: -o %t/deps.json -I %t -cache-compile-job -cas-path %t/cas -swift-version 5 -enable-cross-import-overlays -module-load-mode prefer-interface // RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json A > %t/A.cmd // RUN: %swift_frontend_plain @%t/A.cmd diff --git a/test/CAS/index-store.swift b/test/CAS/index-store.swift index 5e39880edef21..421fa3e105ad7 100644 --- a/test/CAS/index-store.swift +++ b/test/CAS/index-store.swift @@ -7,7 +7,7 @@ // RUN: -emit-module-interface-path %t/A.swiftinterface \ // RUN: -o %t/A.swiftmodule -// RUN: %target-swift-frontend -scan-dependencies -module-name Test -O -module-cache-path %t/clang-module-cache \ +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-name Test -O -module-cache-path %t/clang-module-cache \ // RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \ // RUN: %t/test.swift -I %t -o %t/deps.json -cache-compile-job -cas-path %t/cas diff --git a/test/CAS/module_deps.swift b/test/CAS/module_deps.swift index be04d1236b09d..fd2957394c6df 100644 --- a/test/CAS/module_deps.swift +++ b/test/CAS/module_deps.swift @@ -4,7 +4,7 @@ // RUN: mkdir -p %t/clang-module-cache // RUN: mkdir -p %t/cas -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/../ScanDependencies/Inputs/CHeaders -I %S/../ScanDependencies/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/../ScanDependencies/Inputs/CHeaders/Bridging.h -swift-version 4 -cache-compile-job -cas-path %t/cas -no-clang-include-tree +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/../ScanDependencies/Inputs/CHeaders -I %S/../ScanDependencies/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/../ScanDependencies/Inputs/CHeaders/Bridging.h -swift-version 4 -cache-compile-job -cas-path %t/cas -no-clang-include-tree // Check the contents of the JSON output // RUN: %validate-json %t/deps.json &>/dev/null // RUN: %FileCheck -check-prefix CHECK -check-prefix CHECK_NO_CLANG_TARGET %s < %t/deps.json @@ -15,12 +15,12 @@ // Check the make-style dependencies file // RUN: %FileCheck %s -check-prefix CHECK-MAKE-DEPS < %t/deps.d -// 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/../ScanDependencies/Inputs/CHeaders -I %S/../ScanDependencies/Inputs/Swift -import-objc-header %S/../ScanDependencies/Inputs/CHeaders/Bridging.h -swift-version 4 -cache-compile-job -cas-path %t/cas -no-clang-include-tree +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -test-dependency-scan-cache-serialization -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/../ScanDependencies/Inputs/CHeaders -I %S/../ScanDependencies/Inputs/Swift -import-objc-header %S/../ScanDependencies/Inputs/CHeaders/Bridging.h -swift-version 4 -cache-compile-job -cas-path %t/cas -no-clang-include-tree // RUN: %validate-json %t/deps.json &>/dev/null // RUN: %FileCheck -check-prefix CHECK -check-prefix CHECK_NO_CLANG_TARGET %s < %t/deps.json // Ensure that scanning with `-clang-target` makes sure that Swift modules' respective PCM-dependency-build-argument sets do not contain target triples. -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps_clang_target.json -I %S/../ScanDependencies/Inputs/CHeaders -I %S/../ScanDependencies/Inputs/Swift -import-objc-header %S/../ScanDependencies/Inputs/CHeaders/Bridging.h -swift-version 4 -clang-target %target-cpu-apple-macosx10.14 -cache-compile-job -cas-path %t/cas -no-clang-include-tree +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s -o %t/deps_clang_target.json -I %S/../ScanDependencies/Inputs/CHeaders -I %S/../ScanDependencies/Inputs/Swift -import-objc-header %S/../ScanDependencies/Inputs/CHeaders/Bridging.h -swift-version 4 -clang-target %target-cpu-apple-macosx10.14 -cache-compile-job -cas-path %t/cas -no-clang-include-tree // Check the contents of the JSON output // RUN: %validate-json %t/deps_clang_target.json &>/dev/null // RUN: %FileCheck -check-prefix CHECK_CLANG_TARGET %s < %t/deps_clang_target.json diff --git a/test/CAS/module_deps_include_tree.swift b/test/CAS/module_deps_include_tree.swift index 8850132211a90..56022241bc106 100644 --- a/test/CAS/module_deps_include_tree.swift +++ b/test/CAS/module_deps_include_tree.swift @@ -4,7 +4,7 @@ // RUN: mkdir -p %t/clang-module-cache // RUN: mkdir -p %t/cas -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/../ScanDependencies/Inputs/CHeaders -I %S/../ScanDependencies/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/../ScanDependencies/Inputs/CHeaders/Bridging.h -swift-version 4 -cache-compile-job -cas-path %t/cas +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/../ScanDependencies/Inputs/CHeaders -I %S/../ScanDependencies/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/../ScanDependencies/Inputs/CHeaders/Bridging.h -swift-version 4 -cache-compile-job -cas-path %t/cas // Check the contents of the JSON output // RUN: %validate-json %t/deps.json &>/dev/null // RUN: %FileCheck -check-prefix CHECK -check-prefix CHECK_NO_CLANG_TARGET %s < %t/deps.json @@ -15,12 +15,12 @@ // Check the make-style dependencies file // RUN: %FileCheck %s -check-prefix CHECK-MAKE-DEPS < %t/deps.d -// 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/../ScanDependencies/Inputs/CHeaders -I %S/../ScanDependencies/Inputs/Swift -import-objc-header %S/../ScanDependencies/Inputs/CHeaders/Bridging.h -swift-version 4 -cache-compile-job -cas-path %t/cas +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -test-dependency-scan-cache-serialization -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/../ScanDependencies/Inputs/CHeaders -I %S/../ScanDependencies/Inputs/Swift -import-objc-header %S/../ScanDependencies/Inputs/CHeaders/Bridging.h -swift-version 4 -cache-compile-job -cas-path %t/cas // RUN: %validate-json %t/deps.json &>/dev/null // RUN: %FileCheck -check-prefix CHECK -check-prefix CHECK_NO_CLANG_TARGET %s < %t/deps.json // Ensure that scanning with `-clang-target` makes sure that Swift modules' respective PCM-dependency-build-argument sets do not contain target triples. -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps_clang_target.json -I %S/../ScanDependencies/Inputs/CHeaders -I %S/../ScanDependencies/Inputs/Swift -import-objc-header %S/../ScanDependencies/Inputs/CHeaders/Bridging.h -swift-version 4 -clang-target %target-cpu-apple-macosx10.14 -cache-compile-job -cas-path %t/cas +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s -o %t/deps_clang_target.json -I %S/../ScanDependencies/Inputs/CHeaders -I %S/../ScanDependencies/Inputs/Swift -import-objc-header %S/../ScanDependencies/Inputs/CHeaders/Bridging.h -swift-version 4 -clang-target %target-cpu-apple-macosx10.14 -cache-compile-job -cas-path %t/cas // Check the contents of the JSON output // RUN: %validate-json %t/deps_clang_target.json &>/dev/null // RUN: %FileCheck -check-prefix CHECK_CLANG_TARGET %s < %t/deps_clang_target.json diff --git a/test/CAS/module_hash.swift b/test/CAS/module_hash.swift index 2a8e0c250b9bd..4272bb24cb88f 100644 --- a/test/CAS/module_hash.swift +++ b/test/CAS/module_hash.swift @@ -1,9 +1,9 @@ // 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 -module-name Test +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s -o %t/deps.json -module-name Test -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps_cache.json -module-name Test \ +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s -o %t/deps_cache.json -module-name Test \ // RUN: -cache-compile-job -cas-path %t/cas // RUN: %{python} %S/Inputs/SwiftDepsExtractor.py %t/deps.json Swift modulePath > %t/path1 diff --git a/test/CAS/plugin_cas.swift b/test/CAS/plugin_cas.swift index 9a689b755e04b..a31f66b071f6f 100644 --- a/test/CAS/plugin_cas.swift +++ b/test/CAS/plugin_cas.swift @@ -4,7 +4,7 @@ // RUN: mkdir -p %t/clang-module-cache // RUN: mkdir -p %t/cas -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s \ +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s \ // RUN: -o %t/deps.json -I %S/../ScanDependencies/Inputs/CHeaders -I %S/../ScanDependencies/Inputs/Swift \ // RUN: -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/../ScanDependencies/Inputs/CHeaders/Bridging.h \ // RUN: -swift-version 4 -cache-compile-job \ @@ -23,7 +23,7 @@ // RUN: %FileCheck %s -check-prefix CHECK-MAKE-DEPS < %t/deps.d // Ensure that scanning with `-clang-target` makes sure that Swift modules' respective PCM-dependency-build-argument sets do not contain target triples. -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s \ +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s \ // RUN: -o %t/deps_clang_target.json -I %S/../ScanDependencies/Inputs/CHeaders \ // RUN: -I %S/../ScanDependencies/Inputs/Swift -import-objc-header %S/../ScanDependencies/Inputs/CHeaders/Bridging.h \ // RUN: -swift-version 4 -clang-target %target-cpu-apple-macosx10.14 -cache-compile-job \ diff --git a/test/Frontend/module-alias-scan-deps.swift b/test/Frontend/module-alias-scan-deps.swift index bf313ed52f280..a22c74411b0af 100644 --- a/test/Frontend/module-alias-scan-deps.swift +++ b/test/Frontend/module-alias-scan-deps.swift @@ -11,7 +11,7 @@ // RUN: test -f %t/AppleLogging.swiftmodule /// Scanned dependencies should contain real name AppleLogging -// RUN: %target-swift-frontend -scan-dependencies %t/FileLib.swift -module-alias XLogging=AppleLogging -I %t > %t/scandump.output +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface %t/FileLib.swift -module-alias XLogging=AppleLogging -I %t > %t/scandump.output // RUN: %validate-json %t/scandump.output | %FileCheck %s -check-prefix=CHECK-REAL-NAME // CHECK-REAL-NAME-NOT: "swiftPrebuiltExternal": "XLogging" // CHECK-REAL-NAME-NOT: "compiledModulePath":{{.*}}XLogging.swiftmodule", @@ -24,7 +24,7 @@ // RUN: test -f %t/AppleLoggingIF.swiftinterface /// Scanned dependencies should contain real name AppleLoggingIF -// RUN: %target-swift-frontend -scan-dependencies %t/FileLib.swift -module-alias XLogging=AppleLoggingIF -I %t > %t/scandumpIF.output +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface %t/FileLib.swift -module-alias XLogging=AppleLoggingIF -I %t > %t/scandumpIF.output // RUN: %validate-json %t/scandumpIF.output | %FileCheck %s -check-prefix=CHECK-REAL-NAME-IF // CHECK-REAL-NAME-IF-NOT: "swift": "XLogging" // CHECK-REAL-NAME-IF-NOT: "moduleInterfacePath":{{.*}}XLogging.swiftinterface diff --git a/test/ModuleInterface/clang-args-transitive-availability.swift b/test/ModuleInterface/clang-args-transitive-availability.swift index bdfb692fd3cee..dfc4df497cb38 100644 --- a/test/ModuleInterface/clang-args-transitive-availability.swift +++ b/test/ModuleInterface/clang-args-transitive-availability.swift @@ -5,7 +5,7 @@ // received the TANGERINE macro // RUN: %target-swift-frontend -typecheck -strict-implicit-module-context %s -I %S/Inputs/macro-only-module -Xcc -DTANGERINE=1 -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -// RUN: %target-swift-frontend -scan-dependencies -strict-implicit-module-context %s -o %t/deps.json -I %S/Inputs/macro-only-module -Xcc -DTANGERINE=1 -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -strict-implicit-module-context %s -o %t/deps.json -I %S/Inputs/macro-only-module -Xcc -DTANGERINE=1 -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import // RUN: %validate-json %t/deps.json &>/dev/null // RUN: %FileCheck %s < %t/deps.json diff --git a/test/ModuleInterface/clang-session-transitive.swift b/test/ModuleInterface/clang-session-transitive.swift index ae6ef6e6ef4df..8bf1cd8314245 100644 --- a/test/ModuleInterface/clang-session-transitive.swift +++ b/test/ModuleInterface/clang-session-transitive.swift @@ -4,7 +4,7 @@ // RUN: %target-build-swift -module-name TestModule -module-link-name TestModule %S/Inputs/TestModule.swift -enable-library-evolution -emit-module-interface -o %t/TestModule.swiftmodule -swift-version 5 -Xfrontend -disable-implicit-concurrency-module-import -Xfrontend -disable-implicit-string-processing-module-import -// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -I%t -validate-clang-modules-once -clang-build-session-file %t/Build.session -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import +// RUN: %target-swift-frontend -scan-dependencies -no-scanner-module-validation %s -o %t/deps.json -I%t -validate-clang-modules-once -clang-build-session-file %t/Build.session -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import // RUN: %validate-json %t/deps.json &>/dev/null // RUN: %FileCheck %s < %t/deps.json diff --git a/test/ModuleInterface/extension-transitive-availability.swift b/test/ModuleInterface/extension-transitive-availability.swift index 318986238f24a..a677fc4d6292c 100644 --- a/test/ModuleInterface/extension-transitive-availability.swift +++ b/test/ModuleInterface/extension-transitive-availability.swift @@ -3,7 +3,7 @@ // RUN: %target-swift-emit-module-interface(%t/ExtensionAvailable.swiftinterface) %S/Inputs/extension-available.swift -module-name ExtensionAvailable -I%t -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -I%t -application-extension -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import +// RUN: %target-swift-frontend -scan-dependencies -no-scanner-module-validation %s -o %t/deps.json -I%t -application-extension -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import // RUN: %validate-json %t/deps.json &>/dev/null // RUN: %FileCheck %s < %t/deps.json diff --git a/test/ModuleInterface/infer-arch-from-file.swift b/test/ModuleInterface/infer-arch-from-file.swift index ab1e409401a13..f75771843269c 100644 --- a/test/ModuleInterface/infer-arch-from-file.swift +++ b/test/ModuleInterface/infer-arch-from-file.swift @@ -5,7 +5,7 @@ import arm64 -// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -I %t -target arm64-apple-macos11.0 +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface %s -o %t/deps.json -I %t -target arm64-apple-macos11.0 // RUN: %validate-json %t/deps.json | %FileCheck %s // CHECK-NOT: arm64e-apple-macos11.0 diff --git a/test/ScanDependencies/FilterClangSearchPaths.swift b/test/ScanDependencies/FilterClangSearchPaths.swift index e8fdf399e224a..45563dd4c8506 100644 --- a/test/ScanDependencies/FilterClangSearchPaths.swift +++ b/test/ScanDependencies/FilterClangSearchPaths.swift @@ -1,7 +1,7 @@ // RUN: %empty-directory(%t) // RUN: %empty-directory(%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 -Xcc -fobjc-disable-direct-methods-for-testing -Xcc -I -Xcc /tmp/foo -Xcc -I/tmp/bar +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -Xcc -fobjc-disable-direct-methods-for-testing -Xcc -I -Xcc /tmp/foo -Xcc -I/tmp/bar // Check the contents of the JSON output // RUN: %validate-json %t/deps.json | %FileCheck %s diff --git a/test/ScanDependencies/ObjCStrict.swift b/test/ScanDependencies/ObjCStrict.swift index 5ba108d5fabed..c5764b7c7a1f1 100644 --- a/test/ScanDependencies/ObjCStrict.swift +++ b/test/ScanDependencies/ObjCStrict.swift @@ -1,7 +1,7 @@ // RUN: %empty-directory(%t) // RUN: %empty-directory(%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 -Xcc -fobjc-disable-direct-methods-for-testing +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -Xcc -fobjc-disable-direct-methods-for-testing // Check the contents of the JSON output // RUN: %validate-json %t/deps.json | %FileCheck %s diff --git a/test/ScanDependencies/batch_module_scan.swift b/test/ScanDependencies/batch_module_scan.swift index e276fda317883..6c4714e5612bc 100644 --- a/test/ScanDependencies/batch_module_scan.swift +++ b/test/ScanDependencies/batch_module_scan.swift @@ -14,7 +14,7 @@ // RUN: echo "\"output\": \"%/t/outputs/F.pcm.json\"" >> %/t/inputs/input.json // RUN: echo "}]" >> %/t/inputs/input.json -// 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 -batch-scan-input-file %/t/inputs/input.json +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -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 -batch-scan-input-file %/t/inputs/input.json // Check the contents of the JSON output // RUN: %validate-json %t/outputs/F.pcm.json | %FileCheck %s -check-prefix=CHECK-PCM diff --git a/test/ScanDependencies/bin_mod_import.swift b/test/ScanDependencies/bin_mod_import.swift index bf4ad63e4673f..79a04013891e8 100644 --- a/test/ScanDependencies/bin_mod_import.swift +++ b/test/ScanDependencies/bin_mod_import.swift @@ -7,11 +7,11 @@ import EWrapper // Step 1: Build a swift interface into a binary module // RUN: %target-swift-frontend -compile-module-from-interface %S/Inputs/Swift/EWrapper.swiftinterface -o %t/EWrapper.swiftmodule -I %t // Step 3: scan dependency should give us the binary module and a textual swift dependency from it -// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -I %t +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface %s -o %t/deps.json -I %t // RUN: %validate-json %t/deps.json | %FileCheck %s // Step 4: Ensure that round-trip serialization does not affect result -// RUN: %target-swift-frontend -scan-dependencies -test-dependency-scan-cache-serialization %s -o %t/deps.json -I %t +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -test-dependency-scan-cache-serialization %s -o %t/deps.json -I %t // RUN: %validate-json %t/deps.json | %FileCheck %s // CHECK: "modulePath": "{{.*}}EWrapper.swiftmodule" diff --git a/test/ScanDependencies/blocklist-path-pass-down.swift b/test/ScanDependencies/blocklist-path-pass-down.swift index 0136ddf9cefe7..bd7c40efb128c 100644 --- a/test/ScanDependencies/blocklist-path-pass-down.swift +++ b/test/ScanDependencies/blocklist-path-pass-down.swift @@ -14,7 +14,7 @@ // Run the scan -// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -F %t/Frameworks/ -sdk %t -blocklist-file %t/blocklist.yml +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface %s -o %t/deps.json -F %t/Frameworks/ -sdk %t -blocklist-file %t/blocklist.yml // RUN: %validate-json %t/deps.json | %FileCheck %s import E diff --git a/test/ScanDependencies/bridging_header_dep_module_map.swift b/test/ScanDependencies/bridging_header_dep_module_map.swift index ac17bfba27eb8..7c14b3e40afd9 100644 --- a/test/ScanDependencies/bridging_header_dep_module_map.swift +++ b/test/ScanDependencies/bridging_header_dep_module_map.swift @@ -20,7 +20,7 @@ // - Scan main module and ensure that the "FooClient" recipe includes the modulemap for Foo's briding header's module dependencies // but not other dependencies -// RUN: %target-swift-frontend -scan-dependencies %t/bridging_header_dep_module_map.swift -I %t/FooModuleDir -I %t/TestSwiftInterfaces -I %t/TestCHeaders -I %S/Inputs/CHeaders -o %t/deps.json +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface %t/bridging_header_dep_module_map.swift -I %t/FooModuleDir -I %t/TestSwiftInterfaces -I %t/TestCHeaders -I %S/Inputs/CHeaders -o %t/deps.json // RUN: %validate-json %t/deps.json | %FileCheck %s // Given the following dependency graph: diff --git a/test/ScanDependencies/can_import_placeholder.swift b/test/ScanDependencies/can_import_placeholder.swift index c7400bccc4611..9a42e2b9a04a2 100644 --- a/test/ScanDependencies/can_import_placeholder.swift +++ b/test/ScanDependencies/can_import_placeholder.swift @@ -10,11 +10,11 @@ // RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}]" >> %/t/inputs/map.json -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -placeholder-dependency-module-map-file %t/inputs/map.json -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: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s -placeholder-dependency-module-map-file %t/inputs/map.json -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: %validate-json %t/deps.json | %FileCheck %s // 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 -placeholder-dependency-module-map-file %t/inputs/map.json -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: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -test-dependency-scan-cache-serialization -module-cache-path %t/clang-module-cache %s -placeholder-dependency-module-map-file %t/inputs/map.json -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: %validate-json %t/deps.json | %FileCheck %s // REQUIRES: executable_test diff --git a/test/ScanDependencies/clang-target.swift b/test/ScanDependencies/clang-target.swift index 5bfaf3601b8cd..3c0170b80a251 100644 --- a/test/ScanDependencies/clang-target.swift +++ b/test/ScanDependencies/clang-target.swift @@ -12,7 +12,7 @@ // With -clang-target, we build one X.pcm // RUN: find %t.module-cache -name "X-*.pcm" | count 1 -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t.module-cache %s -o %t.deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -target %target-cpu-apple-macosx10.14 -clang-target %target-cpu-apple-macosx10.14 +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t.module-cache %s -o %t.deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -target %target-cpu-apple-macosx10.14 -clang-target %target-cpu-apple-macosx10.14 // RUN: %validate-json %t.deps.json | %FileCheck %s diff --git a/test/ScanDependencies/clang_auxiliary_module_framework.swift b/test/ScanDependencies/clang_auxiliary_module_framework.swift index 0c3448ce00c71..5154fdd85e5cb 100644 --- a/test/ScanDependencies/clang_auxiliary_module_framework.swift +++ b/test/ScanDependencies/clang_auxiliary_module_framework.swift @@ -1,11 +1,11 @@ // REQUIRES: OS=macosx // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -emit-dependencies -emit-dependencies-path %t/deps.d -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -F %S/Inputs/Frameworks -verify +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface %s -o %t/deps.json -emit-dependencies -emit-dependencies-path %t/deps.d -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -F %S/Inputs/Frameworks -verify // Check the contents of the JSON output // RUN: %validate-json %t/deps.json | %FileCheck %s // Ensure that round-trip serialization does not affect result -// RUN: %target-swift-frontend -scan-dependencies -test-dependency-scan-cache-serialization %s -o %t/deps.json -emit-dependencies -emit-dependencies-path %t/deps.d -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -F %S/Inputs/Frameworks -verify +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -test-dependency-scan-cache-serialization %s -o %t/deps.json -emit-dependencies -emit-dependencies-path %t/deps.d -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -F %S/Inputs/Frameworks -verify // RUN: %validate-json %t/deps.json | %FileCheck %s import WithAuxClangModule diff --git a/test/ScanDependencies/compiled_swift_modules.swift b/test/ScanDependencies/compiled_swift_modules.swift index d4bb2864dd23f..4ccda3f788fc1 100644 --- a/test/ScanDependencies/compiled_swift_modules.swift +++ b/test/ScanDependencies/compiled_swift_modules.swift @@ -8,32 +8,46 @@ import Foo // HAS_COMPILED: "compiledModuleCandidates": [ // HAS_COMPILED-NEXT: "{{.*}}Foo.swiftmodule{{.*}}.swiftmodule" +// HAS_BINARY: "swiftPrebuiltExternal": "Foo" + // HAS_NO_COMPILED-NOT: "{{.*}}Foo.swiftmodule{{.*}}.swiftmodule" // Step 1: build swift interface and swift module side by side // RUN: %target-swift-frontend -emit-module %t/Foo.swift -emit-module-path %t/Foo.swiftmodule/%target-swiftmodule-name -module-name Foo -emit-module-interface-path %t/Foo.swiftmodule/%target-swiftinterface-name // Step 2: scan dependency should give us the binary module adjacent to the interface file. -// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -I %t -emit-dependencies -emit-dependencies-path %t/deps.d +// RUN: %target-swift-frontend -scan-dependencies -no-scanner-module-validation %s -o %t/deps.json -I %t -emit-dependencies -emit-dependencies-path %t/deps.d // RUN: %validate-json %t/deps.json | %FileCheck %s -check-prefix=HAS_COMPILED +/// Check scanner picked binary dependency if not requesting raw scan output. +// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -I %t -emit-dependencies -emit-dependencies-path %t/deps.d +// RUN: %validate-json %t/deps.json | %FileCheck %s -check-prefix=HAS_BINARY + // Step 3: remove the adjacent module. // RUN: rm %t/Foo.swiftmodule/%target-swiftmodule-name // Step 4: scan dependency should give us the interface file. -// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -I %t -emit-dependencies -emit-dependencies-path %t/deps.d +// RUN: %target-swift-frontend -scan-dependencies -no-scanner-module-validation %s -o %t/deps.json -I %t -emit-dependencies -emit-dependencies-path %t/deps.d // RUN: %validate-json %t/deps.json | %FileCheck %s -check-prefix=HAS_NO_COMPILED // Step 4: build prebuilt module cache using the interface. // RUN: %target-swift-frontend -compile-module-from-interface -o %t/ResourceDir/%target-sdk-name/prebuilt-modules/Foo.swiftmodule/%target-swiftmodule-name -module-name Foo -disable-interface-lock %t/Foo.swiftmodule/%target-swiftinterface-name // Step 5: scan dependency now should give us the prebuilt module cache -// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -I %t -emit-dependencies -emit-dependencies-path %t/deps.d -sdk %t -prebuilt-module-cache-path %t/ResourceDir/%target-sdk-name/prebuilt-modules +// RUN: %target-swift-frontend -scan-dependencies -no-scanner-module-validation %s -o %t/deps.json -I %t -emit-dependencies -emit-dependencies-path %t/deps.d -sdk %t -prebuilt-module-cache-path %t/ResourceDir/%target-sdk-name/prebuilt-modules // RUN: %validate-json %t/deps.json | %FileCheck %s -check-prefix=HAS_COMPILED +/// Check scanner picked binary dependency if not requesting raw scan output. +// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -I %t -emit-dependencies -emit-dependencies-path %t/deps.d -sdk %t -prebuilt-module-cache-path %t/ResourceDir/%target-sdk-name/prebuilt-modules +// RUN: %validate-json %t/deps.json | %FileCheck %s -check-prefix=HAS_BINARY + // Step 6: update the interface file from where the prebuilt module cache was built. // RUN: touch %t/Foo.swiftmodule/%target-swiftinterface-name // Step 7: scan dependency should give us the prebuilt module file even though it's out-of-date. -// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -I %t -emit-dependencies -emit-dependencies-path %t/deps.d -sdk %t -prebuilt-module-cache-path %t/ResourceDir/%target-sdk-name/prebuilt-modules +// RUN: %target-swift-frontend -scan-dependencies -no-scanner-module-validation %s -o %t/deps.json -I %t -emit-dependencies -emit-dependencies-path %t/deps.d -sdk %t -prebuilt-module-cache-path %t/ResourceDir/%target-sdk-name/prebuilt-modules // RUN: %validate-json %t/deps.json | %FileCheck %s -check-prefix=HAS_COMPILED + +// Step 8: The new scanner behavior should not give use prebuilt module file because it is out-of-date. +// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -I %t -emit-dependencies -emit-dependencies-path %t/deps.d -sdk %t -prebuilt-module-cache-path %t/ResourceDir/%target-sdk-name/prebuilt-modules +// RUN: %validate-json %t/deps.json | %FileCheck %s -check-prefix=HAS_NO_COMPILED diff --git a/test/ScanDependencies/direct_cc1_scan.swift b/test/ScanDependencies/direct_cc1_scan.swift index 996fdec35832b..5888db7a9bd2f 100644 --- a/test/ScanDependencies/direct_cc1_scan.swift +++ b/test/ScanDependencies/direct_cc1_scan.swift @@ -7,13 +7,13 @@ // RUN: -emit-module-interface-path %t/A.swiftinterface \ // RUN: -o %t/A.swiftmodule -// RUN: %target-swift-frontend -scan-dependencies -o %t/deps.json -I %t \ +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -o %t/deps.json -I %t \ // RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \ // RUN: %t/test.swift -module-name Test -swift-version 5 // RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps.json A | %FileCheck %s --check-prefix CHECK-NO-DIRECT-CC1 // RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps.json Test | %FileCheck %s --allow-empty --check-prefix CHECK-NO-DIRECT-CC1 -// RUN: %target-swift-frontend -scan-dependencies -o %t/deps2.json -I %t \ +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -o %t/deps2.json -I %t \ // RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \ // RUN: -g -file-compilation-dir %t -Xcc -ferror-limit=1 \ // RUN: %t/test.swift -module-name Test -swift-version 5 -experimental-clang-importer-direct-cc1-scan diff --git a/test/ScanDependencies/eliminate_unused_vfs.swift b/test/ScanDependencies/eliminate_unused_vfs.swift index 7e5b88cff8ec2..dc2a9909595ec 100644 --- a/test/ScanDependencies/eliminate_unused_vfs.swift +++ b/test/ScanDependencies/eliminate_unused_vfs.swift @@ -6,7 +6,7 @@ // RUN: sed -e "s|OUT_DIR|%t/redirects|g" -e "s|IN_DIR|%S/Inputs/CHeaders|g" %t/overlay_template.yaml > %t/overlay.yaml -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/module-cache %t/test.swift -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -Xcc -ivfsoverlay -Xcc %t/overlay.yaml +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/module-cache %t/test.swift -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -Xcc -ivfsoverlay -Xcc %t/overlay.yaml // RUN: %validate-json %t/deps.json | %FileCheck %s //--- overlay_template.yaml diff --git a/test/ScanDependencies/explicit-swift-dependencies.swift b/test/ScanDependencies/explicit-swift-dependencies.swift index 746bf7f8416bf..e5a281caec5a0 100644 --- a/test/ScanDependencies/explicit-swift-dependencies.swift +++ b/test/ScanDependencies/explicit-swift-dependencies.swift @@ -1,7 +1,7 @@ // 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 +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -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: %validate-json %t/deps.json | %FileCheck %s diff --git a/test/ScanDependencies/header_deps_of_binary.swift b/test/ScanDependencies/header_deps_of_binary.swift index 20b43c3343925..d1c6e2b830ca8 100644 --- a/test/ScanDependencies/header_deps_of_binary.swift +++ b/test/ScanDependencies/header_deps_of_binary.swift @@ -23,7 +23,7 @@ // RUN: %target-swift-frontend -emit-module -emit-module-path %t/SwiftModules/Foo.swiftmodule %t/foo.swift -module-name Foo -import-objc-header %t/PCH/foo.pch -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -disable-implicit-swift-modules -explicit-swift-module-map-file %t/map.json // - Scan main module and ensure that the header dependencies point to .h and not .pch file -// RUN: %target-swift-frontend -scan-dependencies %t/header_deps_of_binary.swift -I %t/SwiftModules -I %S/Inputs/Swift -I %S/Inputs/CHeaders -o %t/deps.json +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface %t/header_deps_of_binary.swift -I %t/SwiftModules -I %S/Inputs/Swift -I %S/Inputs/CHeaders -o %t/deps.json // RUN: %validate-json %t/deps.json | %FileCheck %s // CHECK: "swift": "FooClient" diff --git a/test/ScanDependencies/include-sdk-in-command.swift b/test/ScanDependencies/include-sdk-in-command.swift index 1f1d96e1ec7bf..84512632a0b25 100644 --- a/test/ScanDependencies/include-sdk-in-command.swift +++ b/test/ScanDependencies/include-sdk-in-command.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -sdk %t/mysecretsdk.sdk +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface %s -o %t/deps.json -sdk %t/mysecretsdk.sdk // Check the contents of the JSON output // RUN: %validate-json %t/deps.json | %FileCheck %s diff --git a/test/ScanDependencies/module_deps_binary_dep_swift_overlay.swift b/test/ScanDependencies/module_deps_binary_dep_swift_overlay.swift index 75c70287c7cb1..8814a95ecfb3b 100644 --- a/test/ScanDependencies/module_deps_binary_dep_swift_overlay.swift +++ b/test/ScanDependencies/module_deps_binary_dep_swift_overlay.swift @@ -8,7 +8,7 @@ // RUN: %target-swift-frontend -emit-module -emit-module-path %t/DependencyModules/BinaryModuleDep.swiftmodule -module-cache-path %t/clang-module-cache %t/BinaryModuleDepSource.swift -module-name BinaryModuleDep -I %S/Inputs/CHeaders -I %S/Inputs/Swift // Scan the client and ensure both the Client and BinaryModuleDep modules have a Swift overlay dependency on 'F' as imported by 'ClangModuleWithOverlayedDep' -// 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 -I %t/DependencyModules +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -I %t/DependencyModules // Check the contents of the JSON output // RUN: %validate-json %t/deps.json | %FileCheck %s diff --git a/test/ScanDependencies/module_deps_cache_reuse.swift b/test/ScanDependencies/module_deps_cache_reuse.swift index 4012e5d406597..51718ede38662 100644 --- a/test/ScanDependencies/module_deps_cache_reuse.swift +++ b/test/ScanDependencies/module_deps_cache_reuse.swift @@ -2,10 +2,10 @@ // RUN: mkdir -p %t/clang-module-cache // Run the scanner once, emitting the serialized scanner cache -// RUN: %target-swift-frontend -scan-dependencies -Rdependency-scan-cache -serialize-dependency-scan-cache -dependency-scan-cache-path %t/cache.moddepcache -module-cache-path %t/clang-module-cache %s -o %t/deps_initial.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 2>&1 | %FileCheck %s -check-prefix CHECK-REMARK-SAVE +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -Rdependency-scan-cache -serialize-dependency-scan-cache -dependency-scan-cache-path %t/cache.moddepcache -module-cache-path %t/clang-module-cache %s -o %t/deps_initial.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 2>&1 | %FileCheck %s -check-prefix CHECK-REMARK-SAVE // Run the scanner again, but now re-using previously-serialized cache -// RUN: %target-swift-frontend -scan-dependencies -Rdependency-scan-cache -load-dependency-scan-cache -dependency-scan-cache-path %t/cache.moddepcache -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 2>&1 | %FileCheck %s -check-prefix CHECK-REMARK-LOAD +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -Rdependency-scan-cache -load-dependency-scan-cache -dependency-scan-cache-path %t/cache.moddepcache -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 2>&1 | %FileCheck %s -check-prefix CHECK-REMARK-LOAD // Check the contents of the JSON output // RUN: %validate-json %t/deps.json &>/dev/null diff --git a/test/ScanDependencies/module_deps_cross_import_overlay.swift b/test/ScanDependencies/module_deps_cross_import_overlay.swift index b7a047a3b7461..c5a663ca9a551 100644 --- a/test/ScanDependencies/module_deps_cross_import_overlay.swift +++ b/test/ScanDependencies/module_deps_cross_import_overlay.swift @@ -1,11 +1,11 @@ // 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 -I %S/Inputs/CHeaders/ExtraCModules -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 -module-name CrossImportTestModule +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -I %S/Inputs/CHeaders/ExtraCModules -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 -module-name CrossImportTestModule // Check the contents of the JSON output // RUN: %validate-json %t/deps.json | %FileCheck %s // 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 -I %S/Inputs/CHeaders/ExtraCModules -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 -module-name CrossImportTestModule +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -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 -I %S/Inputs/CHeaders/ExtraCModules -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 -module-name CrossImportTestModule // RUN: %validate-json %t/deps.json | %FileCheck %s // REQUIRES: executable_test diff --git a/test/ScanDependencies/module_deps_different_paths_no_reuse.swift b/test/ScanDependencies/module_deps_different_paths_no_reuse.swift index 9844160fe9e61..0afa3bab97918 100644 --- a/test/ScanDependencies/module_deps_different_paths_no_reuse.swift +++ b/test/ScanDependencies/module_deps_different_paths_no_reuse.swift @@ -4,12 +4,12 @@ // This test ensures that subsequent invocations of the dependency scanner that re-use previous cache state do not re-use cache entries that contain modules found outside of the current scanner invocation's search paths. // Run the scanner once, emitting the serialized scanner cache, with one set of search paths -// RUN: %target-swift-frontend -scan-dependencies -serialize-dependency-scan-cache -dependency-scan-cache-path %t/cache.moddepcache -module-cache-path %t/clang-module-cache %s -o %t/deps_initial.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -serialize-dependency-scan-cache -dependency-scan-cache-path %t/cache.moddepcache -module-cache-path %t/clang-module-cache %s -o %t/deps_initial.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 // RUN: %validate-json %t/deps_initial.json &>/dev/null // RUN: %FileCheck -input-file %t/deps_initial.json %s -check-prefix CHECK-INITIAL-SCAN // Run the scanner again, but now re-using previously-serialized cache and using a different search path for Swift modules -// RUN: %target-swift-frontend -scan-dependencies -load-dependency-scan-cache -dependency-scan-cache-path %t/cache.moddepcache -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/SwiftDifferent -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -load-dependency-scan-cache -dependency-scan-cache-path %t/cache.moddepcache -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/SwiftDifferent -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 // RUN: %validate-json %t/deps.json &>/dev/null // RUN: %FileCheck -input-file %t/deps.json %s -check-prefix CHECK-DIFFERENT diff --git a/test/ScanDependencies/module_deps_external.swift b/test/ScanDependencies/module_deps_external.swift index 515d7a33edcb7..37a61b6b349e4 100644 --- a/test/ScanDependencies/module_deps_external.swift +++ b/test/ScanDependencies/module_deps_external.swift @@ -10,7 +10,7 @@ // RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json // RUN: echo "}]" >> %/t/inputs/map.json -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -placeholder-dependency-module-map-file %t/inputs/map.json -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: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s -placeholder-dependency-module-map-file %t/inputs/map.json -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: %validate-json %t/deps.json | %FileCheck %s @@ -28,7 +28,7 @@ // RUN: %target-run %t/main %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 -placeholder-dependency-module-map-file %t/inputs/map.json -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -test-dependency-scan-cache-serialization -module-cache-path %t/clang-module-cache %s -placeholder-dependency-module-map-file %t/inputs/map.json -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 // RUN: %validate-json %t/deps.json | %FileCheck %s // REQUIRES: executable_test diff --git a/test/ScanDependencies/module_framework.swift b/test/ScanDependencies/module_framework.swift index 296ac57759690..2789c058fe21d 100644 --- a/test/ScanDependencies/module_framework.swift +++ b/test/ScanDependencies/module_framework.swift @@ -1,11 +1,11 @@ // REQUIRES: OS=macosx // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -emit-dependencies -emit-dependencies-path %t/deps.d -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -F %S/Inputs/Frameworks +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface %s -o %t/deps.json -emit-dependencies -emit-dependencies-path %t/deps.d -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -F %S/Inputs/Frameworks // Check the contents of the JSON output // RUN: %validate-json %t/deps.json | %FileCheck %s // Ensure that round-trip serialization does not affect result -// RUN: %target-swift-frontend -scan-dependencies -test-dependency-scan-cache-serialization %s -o %t/deps.json -emit-dependencies -emit-dependencies-path %t/deps.d -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -F %S/Inputs/Frameworks +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -test-dependency-scan-cache-serialization %s -o %t/deps.json -emit-dependencies -emit-dependencies-path %t/deps.d -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -F %S/Inputs/Frameworks // RUN: %validate-json %t/deps.json | %FileCheck %s import ScannerTestKit diff --git a/test/ScanDependencies/module_load_mode.swift b/test/ScanDependencies/module_load_mode.swift new file mode 100644 index 0000000000000..29ab5996dc185 --- /dev/null +++ b/test/ScanDependencies/module_load_mode.swift @@ -0,0 +1,21 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-swift-frontend -emit-module %t/Foo.swift -emit-module-path %t/Foo.swiftmodule/%target-swiftmodule-name -module-name Foo -emit-module-interface-path %t/Foo.swiftmodule/%target-swiftinterface-name -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib + +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode only-serialized \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \ +// RUN: %t/main.swift -I %t -o - | %FileCheck %s --check-prefix=SERIALIZED + +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode only-interface \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \ +// RUN: %t/main.swift -I %t -o - | %FileCheck %s --check-prefix=INTERFACE + +// SERIALIZED: "swiftPrebuiltExternal": "Foo" +// INTERFACE: "swift": "Foo" + +//--- main.swift +import Foo + +//--- Foo.swift +public func foo() {} diff --git a/test/ScanDependencies/no_cross_import_module_for_self.swift b/test/ScanDependencies/no_cross_import_module_for_self.swift index 4d34d97e1692c..042baf7ace9f6 100644 --- a/test/ScanDependencies/no_cross_import_module_for_self.swift +++ b/test/ScanDependencies/no_cross_import_module_for_self.swift @@ -1,6 +1,6 @@ // 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/CHeaders/ExtraCModules -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -swift-version 4 -module-name _cross_import_E +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/CHeaders/ExtraCModules -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -swift-version 4 -module-name _cross_import_E // Check the contents of the JSON output // RUN: %validate-json %t/deps.json | %FileCheck %s diff --git a/test/ScanDependencies/no_main_module_cross_import.swift b/test/ScanDependencies/no_main_module_cross_import.swift index a111f9737fe0c..4aa299a9d4ee5 100644 --- a/test/ScanDependencies/no_main_module_cross_import.swift +++ b/test/ScanDependencies/no_main_module_cross_import.swift @@ -1,6 +1,6 @@ // 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/CHeaders/ExtraCModules -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -swift-version 4 -module-name SubE +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/CHeaders/ExtraCModules -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -swift-version 4 -module-name SubE // Check the contents of the JSON output // RUN: %validate-json %t/deps.json | %FileCheck %s diff --git a/test/ScanDependencies/package_interface.swift b/test/ScanDependencies/package_interface.swift index 4688fa3575698..0d0f0b079cb8c 100644 --- a/test/ScanDependencies/package_interface.swift +++ b/test/ScanDependencies/package_interface.swift @@ -9,21 +9,21 @@ // RUN: -emit-private-module-interface-path %t/Bar.private.swiftinterface \ // RUN: -emit-package-module-interface-path %t/Bar.package.swiftinterface -// RUN: %target-swift-frontend -scan-dependencies -o %t/deps.json -I %t -experimental-package-interface-load \ +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -o %t/deps.json -I %t -experimental-package-interface-load \ // RUN: %t/Client.swift -module-name Client -package-name barpkg -swift-version 5 // RUN: %FileCheck %s --input-file=%t/deps.json --check-prefix CHECK --check-prefix CHECK-PACKAGE /// When package name doesn't match or not used, it should find private interface. -// RUN: %target-swift-frontend -scan-dependencies -o %t/deps2.json -I %t -experimental-package-interface-load \ +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -o %t/deps2.json -I %t -experimental-package-interface-load \ // RUN: %t/Client.swift -module-name Client -package-name foopkg -swift-version 5 // RUN: %FileCheck %s --input-file=%t/deps2.json --check-prefix CHECK --check-prefix CHECK-PRIVATE -// RUN: %target-swift-frontend -scan-dependencies -o %t/deps3.json -I %t -experimental-package-interface-load \ +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -o %t/deps3.json -I %t -experimental-package-interface-load \ // RUN: %t/Client.swift -module-name Client -swift-version 5 // RUN: %FileCheck %s --input-file=%t/deps3.json --check-prefix CHECK --check-prefix CHECK-PRIVATE /// If -experimental-package-interface-load is not used but in the same package, it should find the binary module -// RUN: %target-swift-frontend -scan-dependencies -I %t \ +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -I %t \ // RUN: %t/Client.swift -module-name Client -package-name barpkg -swift-version 5 | \ // RUN: %FileCheck %s --check-prefix CHECK-BINARY diff --git a/test/ScanDependencies/preserve_used_vfs.swift b/test/ScanDependencies/preserve_used_vfs.swift index 6efbe236b2a9f..d7348931bf4ec 100644 --- a/test/ScanDependencies/preserve_used_vfs.swift +++ b/test/ScanDependencies/preserve_used_vfs.swift @@ -6,7 +6,7 @@ // RUN: sed -e "s|OUT_DIR|%t/redirects|g" -e "s|IN_DIR|%S/Inputs/CHeaders|g" %t/overlay_template.yaml > %t/overlay.yaml -// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/module-cache %t/test.swift -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -Xcc -ivfsoverlay -Xcc %t/overlay.yaml +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/module-cache %t/test.swift -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -Xcc -ivfsoverlay -Xcc %t/overlay.yaml // RUN: %validate-json %t/deps.json | %FileCheck %s //--- redirects/RedirectedF.h diff --git a/test/ScanDependencies/private_interface_candidate_module.swift b/test/ScanDependencies/private_interface_candidate_module.swift index bf6752ee14555..41d9dd9013718 100644 --- a/test/ScanDependencies/private_interface_candidate_module.swift +++ b/test/ScanDependencies/private_interface_candidate_module.swift @@ -15,7 +15,7 @@ // RUN: %target-swift-frontend -emit-module -emit-module-path %t/Frameworks/E.framework/Modules/E.swiftmodule/%module-target-triple.swiftmodule -module-cache-path %t.module-cache %t/foo.swift -module-name E // Run the scan -// RUN: %target-swift-frontend -scan-dependencies %s -o %t/deps.json -F %t/Frameworks/ -sdk %t +// RUN: %target-swift-frontend -scan-dependencies -no-scanner-module-validation %s -o %t/deps.json -F %t/Frameworks/ -sdk %t // RUN: %validate-json %t/deps.json | %FileCheck %s import E diff --git a/test/ScanDependencies/separate_bridging_header_deps.swift b/test/ScanDependencies/separate_bridging_header_deps.swift index 69e5de969112b..f9c9ed02bc758 100644 --- a/test/ScanDependencies/separate_bridging_header_deps.swift +++ b/test/ScanDependencies/separate_bridging_header_deps.swift @@ -1,7 +1,7 @@ // 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 -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 5 // RUN: %validate-json %t/deps.json | %FileCheck %s import E diff --git a/test/ScanDependencies/testable-import.swift b/test/ScanDependencies/testable-import.swift index d2323cf9e3bf8..d6e57bd9c66c7 100644 --- a/test/ScanDependencies/testable-import.swift +++ b/test/ScanDependencies/testable-import.swift @@ -16,14 +16,14 @@ // RUN: -emit-module-interface-path %t/A.swiftinterface -enable-library-evolution -I %t -enable-testing \ // RUN: %t/A.swift -// RUN: %target-swift-frontend -scan-dependencies -module-name Test %t/test1.swift \ +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-name Test %t/test1.swift \ // RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib -enable-testing \ // RUN: -o %t/deps1.json -I %t -swift-version 5 // RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps1.json Test directDependencies | %FileCheck %s --check-prefix TEST1 // TEST1-DAG: "swiftPrebuiltExternal": "B" // TEST1-DAG: "swift": "C" -// RUN: %target-swift-frontend -scan-dependencies -module-name Test %t/test2.swift \ +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-name Test %t/test2.swift \ // RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib -enable-testing \ // RUN: -o %t/deps2.json -I %t -swift-version 5 // RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps2.json Test directDependencies | %FileCheck %s --check-prefix TEST2 @@ -36,7 +36,7 @@ // TEST2-A-DAG: "swift": "C" /// An indirect @testable import is still interface deps. -// RUN: %target-swift-frontend -scan-dependencies -module-name Test %t/test3.swift \ +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-name Test %t/test3.swift \ // RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib -enable-testing \ // RUN: -o %t/deps3.json -I %t -swift-version 5 // RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps3.json Test directDependencies | %FileCheck %s --check-prefix TEST3 From d4c90d6eeb4a2abbb86a19e8c808f8ba6928b488 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Thu, 4 Apr 2024 14:16:21 -0700 Subject: [PATCH 2/2] [DependencyScanning] Handle testable dependencies correctly Teach scanner to pick and choose binary modules correctly based on if it is testable import or not. Some situations that scanner need to be careful when testable is involved: * When it is a regular import, it should not import binary modules that are built with -enable-testing, it should prefer interfaces if that is available. * When testable import, it should only load binary module and it should make sure the internal imports from binary modules are actually required for testable import to work. If a testable import only find a regular binary module, dependency scanner currently will just preceed with such module and leave the diagnostics to swift-frontend, because the alternative (failed to find module) can be confusing to users. rdar://125914165 --- include/swift/AST/DiagnosticsSema.def | 3 + include/swift/Serialization/ScanningLoaders.h | 3 +- .../Serialization/SerializedModuleLoader.h | 15 ++- lib/Serialization/ScanningLoaders.cpp | 23 +++-- lib/Serialization/SerializedModuleLoader.cpp | 96 ++++++++++--------- .../testable-dependencies.swift | 78 +++++++++++++++ 6 files changed, 154 insertions(+), 64 deletions(-) create mode 100644 test/ScanDependencies/testable-dependencies.swift diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index b476269919b9e..b28a6828159f0 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -1193,6 +1193,9 @@ REMARK(module_api_import_aliases,none, "%select{, which reexports definition from %2|}3", (const Decl *, ModuleDecl *, ModuleDecl *, bool)) +REMARK(skip_module_invalid,none,"skip invalid swiftmodule: %0", (StringRef)) +REMARK(skip_module_testable,none,"skip swiftmodule built with '-enable-testing': %0", (StringRef)) + REMARK(macro_loaded,none, "loaded macro implementation module %0 from " "%select{shared library '%2'|executable '%2'|" diff --git a/include/swift/Serialization/ScanningLoaders.h b/include/swift/Serialization/ScanningLoaders.h index 12698ce2af8ce..d3419e1269233 100644 --- a/include/swift/Serialization/ScanningLoaders.h +++ b/include/swift/Serialization/ScanningLoaders.h @@ -34,7 +34,8 @@ class SwiftModuleScanner : public SerializedModuleLoaderBase { /// Scan the given interface file to determine dependencies. llvm::ErrorOr - scanInterfaceFile(Twine moduleInterfacePath, bool isFramework); + scanInterfaceFile(Twine moduleInterfacePath, bool isFramework, + bool isTestableImport); InterfaceSubContextDelegate &astDelegate; diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h index 5b08a71f9e783..fd13631f17342 100644 --- a/include/swift/Serialization/SerializedModuleLoader.h +++ b/include/swift/Serialization/SerializedModuleLoader.h @@ -24,6 +24,7 @@ namespace swift { class ModuleFile; class PathObfuscator; +class ModuleFileSharedCore; enum class ModuleLoadingBehavior; namespace file_types { enum ID : uint8_t; @@ -162,22 +163,18 @@ class SerializedModuleLoaderBase : public ModuleLoader { } /// Scan the given serialized module file to determine dependencies. - llvm::ErrorOr scanModuleFile(Twine modulePath, bool isFramework); + llvm::ErrorOr + scanModuleFile(Twine modulePath, bool isFramework, bool isTestableImport); struct BinaryModuleImports { llvm::StringSet<> moduleImports; std::string headerImport; }; - static llvm::ErrorOr - getImportsOfModule(Twine modulePath, + static BinaryModuleImports + getImportsOfModule(const ModuleFileSharedCore &loadedModule, ModuleLoadingBehavior transitiveBehavior, - bool isFramework, - bool isRequiredOSSAModules, - StringRef SDKName, - StringRef packageName, - llvm::vfs::FileSystem *fileSystem, - PathObfuscator &recoverer); + StringRef packageName); /// Load the module file into a buffer and also collect its module name. static std::unique_ptr diff --git a/lib/Serialization/ScanningLoaders.cpp b/lib/Serialization/ScanningLoaders.cpp index 3cf6dec7769cb..0bb53171a8c37 100644 --- a/lib/Serialization/ScanningLoaders.cpp +++ b/lib/Serialization/ScanningLoaders.cpp @@ -33,6 +33,7 @@ #include "llvm/Support/Threading.h" #include "llvm/Support/VirtualFileSystem.h" #include +#include using namespace swift; @@ -55,7 +56,8 @@ std::error_code SwiftModuleScanner::findModuleFilesInDirectory( if (LoadMode == ModuleLoadingMode::OnlySerialized || !InPath) { if (fs.exists(ModPath)) { // The module file will be loaded directly. - auto dependencies = scanModuleFile(ModPath, IsFramework); + auto dependencies = + scanModuleFile(ModPath, IsFramework, isTestableDependencyLookup); if (dependencies) { this->dependencies = std::move(dependencies.get()); return std::error_code(); @@ -66,7 +68,8 @@ std::error_code SwiftModuleScanner::findModuleFilesInDirectory( } assert(InPath); - auto dependencies = scanInterfaceFile(*InPath, IsFramework); + auto dependencies = + scanInterfaceFile(*InPath, IsFramework, isTestableDependencyLookup); if (dependencies) { this->dependencies = std::move(dependencies.get()); return std::error_code(); @@ -133,7 +136,7 @@ static std::vector getCompiledCandidates(ASTContext &ctx, llvm::ErrorOr SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath, - bool isFramework) { + bool isFramework, bool isTestableImport) { // Create a module filename. // FIXME: Query the module interface loader to determine an appropriate // name for the module, which includes an appropriate hash. @@ -156,12 +159,16 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath, !Ctx.SearchPathOpts.NoScannerModuleValidation) { assert(compiledCandidates.size() == 1 && "Should only have 1 candidate module"); - auto BinaryDep = scanModuleFile(compiledCandidates[0], isFramework); - if (!BinaryDep) - return BinaryDep.getError(); + auto BinaryDep = scanModuleFile(compiledCandidates[0], isFramework, + isTestableImport); + if (BinaryDep) { + Result = *BinaryDep; + return std::error_code(); + } - Result = *BinaryDep; - return std::error_code(); + // If return no such file, just fallback to use interface. + if (BinaryDep.getError() != std::errc::no_such_file_or_directory) + return BinaryDep.getError(); } std::vector Args(BaseArgs.begin(), BaseArgs.end()); diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index e25d06e80a207..2c607f409821a 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -392,29 +392,13 @@ std::error_code SerializedModuleLoaderBase::openModuleFile( return std::error_code(); } -llvm::ErrorOr +SerializedModuleLoaderBase::BinaryModuleImports SerializedModuleLoaderBase::getImportsOfModule( - Twine modulePath, ModuleLoadingBehavior transitiveBehavior, - bool isFramework, bool isRequiredOSSAModules, StringRef SDKName, - StringRef packageName, llvm::vfs::FileSystem *fileSystem, - PathObfuscator &recoverer) { - auto moduleBuf = fileSystem->getBufferForFile(modulePath); - if (!moduleBuf) - return moduleBuf.getError(); - + const ModuleFileSharedCore &loadedModuleFile, + ModuleLoadingBehavior transitiveBehavior, StringRef packageName) { llvm::StringSet<> importedModuleNames; std::string importedHeader = ""; - std::shared_ptr loadedModuleFile; - serialization::ValidationInfo loadInfo = ModuleFileSharedCore::load( - "", "", std::move(moduleBuf.get()), nullptr, nullptr, isFramework, - isRequiredOSSAModules, - SDKName, recoverer, loadedModuleFile); - - // If failed to load, just ignore and return do not found. - if (loadInfo.status != serialization::Status::Valid) - return std::make_error_code(std::errc::no_such_file_or_directory); - - for (const auto &dependency : loadedModuleFile->getDependencies()) { + for (const auto &dependency : loadedModuleFile.getDependencies()) { if (dependency.isHeader()) { assert(importedHeader.empty() && "Unexpected more than one header dependency"); @@ -423,11 +407,11 @@ SerializedModuleLoaderBase::getImportsOfModule( } ModuleLoadingBehavior dependencyTransitiveBehavior = - loadedModuleFile->getTransitiveLoadingBehavior( + loadedModuleFile.getTransitiveLoadingBehavior( dependency, /*debuggerMode*/ false, /*isPartialModule*/ false, packageName, - loadedModuleFile->isTestable()); + loadedModuleFile.isTestable()); if (dependencyTransitiveBehavior > transitiveBehavior) continue; @@ -441,41 +425,60 @@ SerializedModuleLoaderBase::getImportsOfModule( importedModuleNames.insert(moduleName); } - return SerializedModuleLoaderBase::BinaryModuleImports{importedModuleNames, importedHeader}; + return SerializedModuleLoaderBase::BinaryModuleImports{importedModuleNames, + importedHeader}; } llvm::ErrorOr -SerializedModuleLoaderBase::scanModuleFile(Twine modulePath, bool isFramework) { +SerializedModuleLoaderBase::scanModuleFile(Twine modulePath, bool isFramework, + bool isTestableImport) { const std::string moduleDocPath; const std::string sourceInfoPath; + + // Read and valid module. + auto moduleBuf = Ctx.SourceMgr.getFileSystem()->getBufferForFile(modulePath); + if (!moduleBuf) + return moduleBuf.getError(); + + std::shared_ptr loadedModuleFile; + serialization::ValidationInfo loadInfo = ModuleFileSharedCore::load( + "", "", std::move(moduleBuf.get()), nullptr, nullptr, isFramework, + isRequiredOSSAModules(), Ctx.LangOpts.SDKName, + Ctx.SearchPathOpts.DeserializedPathRecoverer, loadedModuleFile); + + if (!Ctx.SearchPathOpts.NoScannerModuleValidation) { + // If failed to load, just ignore and return do not found. + if (loadInfo.status != serialization::Status::Valid) { + if (Ctx.LangOpts.EnableModuleLoadingRemarks) + Ctx.Diags.diagnose(SourceLoc(), diag::skip_module_invalid, + modulePath.str()); + return std::make_error_code(std::errc::no_such_file_or_directory); + } + + if (loadedModuleFile->isTestable() && !isTestableImport) { + if (Ctx.LangOpts.EnableModuleLoadingRemarks) + Ctx.Diags.diagnose(SourceLoc(), diag::skip_module_testable, + modulePath.str()); + return std::make_error_code(std::errc::no_such_file_or_directory); + } + } + // Some transitive dependencies of binary modules are not required to be // imported during normal builds. // TODO: This is worth revisiting for debugger purposes where // loading the module is optional, and implementation-only imports // from modules with testing enabled where the dependency is // optional. - ModuleLoadingBehavior transitiveLoadingBehavior = - ModuleLoadingBehavior::Required; - auto binaryModuleImports = getImportsOfModule( - modulePath, transitiveLoadingBehavior, isFramework, - isRequiredOSSAModules(), - Ctx.LangOpts.SDKName, Ctx.LangOpts.PackageName, - Ctx.SourceMgr.getFileSystem().get(), - Ctx.SearchPathOpts.DeserializedPathRecoverer); - if (!binaryModuleImports) - return binaryModuleImports.getError(); + auto binaryModuleImports = + getImportsOfModule(*loadedModuleFile, ModuleLoadingBehavior::Required, + Ctx.LangOpts.PackageName); // Lookup optional imports of this module also - auto binaryModuleOptionalImports = getImportsOfModule( - modulePath, ModuleLoadingBehavior::Optional, isFramework, - isRequiredOSSAModules(), - Ctx.LangOpts.SDKName, Ctx.LangOpts.PackageName, - Ctx.SourceMgr.getFileSystem().get(), - Ctx.SearchPathOpts.DeserializedPathRecoverer); - if (!binaryModuleOptionalImports) - return binaryModuleImports.getError(); + auto binaryModuleOptionalImports = + getImportsOfModule(*loadedModuleFile, ModuleLoadingBehavior::Optional, + Ctx.LangOpts.PackageName); - auto importedModuleSet = binaryModuleImports.get().moduleImports; + auto importedModuleSet = binaryModuleImports.moduleImports; std::vector importedModuleNames; importedModuleNames.reserve(importedModuleSet.size()); llvm::transform(importedModuleSet.keys(), @@ -484,8 +487,8 @@ SerializedModuleLoaderBase::scanModuleFile(Twine modulePath, bool isFramework) { return N.str(); }); - auto importedHeader = binaryModuleImports.get().headerImport; - auto &importedOptionalModuleSet = binaryModuleOptionalImports.get().moduleImports; + auto importedHeader = binaryModuleImports.headerImport; + auto &importedOptionalModuleSet = binaryModuleOptionalImports.moduleImports; std::vector importedOptionalModuleNames; for (const auto optionalImportedModule : importedOptionalModuleSet.keys()) if (!importedModuleSet.contains(optionalImportedModule)) @@ -794,7 +797,8 @@ bool SerializedModuleLoaderBase::findModule( auto result = findModuleFilesInDirectory( moduleID, absoluteBaseName, moduleInterfacePath, moduleInterfaceSourcePath, moduleBuffer, moduleDocBuffer, - moduleSourceInfoBuffer, skipBuildingInterface, isFramework); + moduleSourceInfoBuffer, skipBuildingInterface, isFramework, + isTestableDependencyLookup); if (!result) return true; if (result == std::errc::not_supported) diff --git a/test/ScanDependencies/testable-dependencies.swift b/test/ScanDependencies/testable-dependencies.swift new file mode 100644 index 0000000000000..b16300be032e1 --- /dev/null +++ b/test/ScanDependencies/testable-dependencies.swift @@ -0,0 +1,78 @@ +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-swift-frontend -emit-module -module-name B -o %t/internal/B.swiftmodule -swift-version 5 \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \ +// RUN: -emit-module-interface-path %t/internal/B.swiftinterface -enable-library-evolution -I %t \ +// RUN: %t/B.swift + +// RUN: %target-swift-frontend -emit-module -module-name A -o %t/testable/A.swiftmodule -swift-version 5 \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \ +// RUN: -emit-module-interface-path %t/testable/A.swiftinterface -enable-library-evolution -I %t/internal -enable-testing \ +// RUN: %t/A.swift + +// RUN: %target-swift-frontend -emit-module -module-name A -o %t/regular/A.swiftmodule -swift-version 5 \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \ +// RUN: -emit-module-interface-path %t/regular/A.swiftinterface -enable-library-evolution -I %t/internal \ +// RUN: %t/A.swift + +/// Import testable build, should use interface. +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-serialized -module-name Test %t/main.swift \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \ +// RUN: -o %t/deps1.json -I %t/testable -swift-version 5 -Rmodule-loading 2>&1 | %FileCheck %s --check-prefix DIAG +// DIAG: remark: skip swiftmodule built with '-enable-testing' +// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps1.json Test directDependencies | %FileCheck %s --check-prefix TEST1 +// TEST1: "swift": "A" +// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps1.json A directDependencies | %FileCheck %s --check-prefix EMPTY --allow-empty +// EMPTY-NOT: B + +/// Import regular build, should use binary. +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-serialized -module-name Test %t/main.swift \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \ +// RUN: -o %t/deps2.json -I %t/regular -swift-version 5 -Rmodule-loading +// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps2.json Test directDependencies | %FileCheck %s --check-prefix TEST2 +// TEST2: "swiftPrebuiltExternal": "A" +// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps2.json swiftPrebuiltExternal:A directDependencies | %FileCheck %s --check-prefix EMPTY --allow-empty + +/// Testable import testable build, should use binary, even interface is preferred. +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-name Test %t/testable.swift \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib -enable-testing \ +// RUN: -o %t/deps3.json -I %t/testable -I %t/internal -swift-version 5 -Rmodule-loading +// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps3.json Test directDependencies | %FileCheck %s --check-prefix TEST3 +// TEST3: "swiftPrebuiltExternal": "A" +// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps3.json swiftPrebuiltExternal:A directDependencies | %FileCheck %s --check-prefix TEST3-A +// TEST3-A: "swift": "B" + +/// Testable import non-testable build without enable testing. +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-name Test %t/testable.swift \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \ +// RUN: -o %t/deps4.json -I %t/regular -swift-version 5 +// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps4.json Test directDependencies | %FileCheck %s --check-prefix TEST4 +// TEST4: "swiftPrebuiltExternal": "A" +// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps4.json swiftPrebuiltExternal:A directDependencies | %FileCheck %s --check-prefix EMPTY --allow-empty + +/// Testable import non-testable build enable testing, still succeed since swift-frontend can provide a better diagnostics when the module is actually imported. +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-name Test %t/testable.swift \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib -enable-testing \ +// RUN: -o %t/deps5.json -I %t/regular -swift-version 5 -Rmodule-loading + +/// Regular import a testable module with no interface, this is a dependency scanning error. +// RUN: rm %t/testable/A.swiftinterface +// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-name Test %t/main.swift \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib -enable-testing \ +// RUN: -o %t/deps6.json -I %t/testable -swift-version 5 -Rmodule-loading 2>&1 | %FileCheck %s --check-prefix ERROR +// ERROR: error: Unable to find module dependency: 'A' + +//--- main.swift +import A + +//--- testable.swift +@testable import A + +//--- A.swift +internal import B +@_spi(Testing) public func a() {} + +//--- B.swift +public func b() {} +