diff --git a/include/swift-c/DependencyScan/DependencyScan.h b/include/swift-c/DependencyScan/DependencyScan.h index b278bb0f066..44ad31db6bf 100644 --- a/include/swift-c/DependencyScan/DependencyScan.h +++ b/include/swift-c/DependencyScan/DependencyScan.h @@ -25,7 +25,7 @@ /// SWIFTSCAN_VERSION_MINOR should increase when there are API additions. /// SWIFTSCAN_VERSION_MAJOR is intended for "major" source/ABI breaking changes. #define SWIFTSCAN_VERSION_MAJOR 2 -#define SWIFTSCAN_VERSION_MINOR 0 +#define SWIFTSCAN_VERSION_MINOR 1 SWIFTSCAN_BEGIN_DECLS @@ -222,6 +222,14 @@ SWIFTSCAN_PUBLIC swiftscan_string_ref_t swiftscan_swift_textual_detail_get_user_module_version( swiftscan_module_details_t details); +SWIFTSCAN_PUBLIC swiftscan_string_ref_t +swiftscan_swift_textual_detail_get_chained_bridging_header_path( + swiftscan_module_details_t details); + +SWIFTSCAN_PUBLIC swiftscan_string_ref_t +swiftscan_swift_textual_detail_get_chained_bridging_header_content( + swiftscan_module_details_t details); + //=== Swift Binary Module Details query APIs ------------------------------===// SWIFTSCAN_PUBLIC swiftscan_string_ref_t diff --git a/include/swift/AST/ModuleDependencies.h b/include/swift/AST/ModuleDependencies.h index e19bd9fcb59..fda9aeedbd7 100644 --- a/include/swift/AST/ModuleDependencies.h +++ b/include/swift/AST/ModuleDependencies.h @@ -30,11 +30,13 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringSet.h" +#include "llvm/CAS/ActionCache.h" #include "llvm/CAS/CASProvidingFileSystem.h" #include "llvm/CAS/CASReference.h" #include "llvm/CAS/CachingOnDiskFileSystem.h" #include "llvm/CAS/ObjectStore.h" #include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Mutex.h" #include "llvm/Support/PrefixMapper.h" #include "llvm/Support/VirtualFileSystem.h" @@ -338,6 +340,12 @@ public: /// The Swift frontend invocation arguments to build bridging header. std::vector bridgingHeaderBuildCommandLine; + /// The chained bridging header path if used. + std::string chainedBridgingHeaderPath; + + /// The chained bridging header source buffer if used. + std::string chainedBridgingHeaderContent; + SwiftSourceModuleDependenciesStorage( StringRef RootID, ArrayRef buildCommandLine, ArrayRef moduleImports, @@ -354,6 +362,7 @@ public: return new SwiftSourceModuleDependenciesStorage(*this); } + static bool classof(const ModuleDependencyInfoStorageBase *base) { return base->dependencyKind == ModuleDependencyKind::SwiftSource; } @@ -370,6 +379,11 @@ public: void addTestableImport(ImportPath::Module module) { testableImports.insert(module.front().Item.str()); } + + void setChainedBridgingHeaderBuffer(StringRef path, StringRef buffer) { + chainedBridgingHeaderPath = path.str(); + chainedBridgingHeaderContent = buffer.str(); + } }; /// Describes the dependencies of a pre-built Swift module (with no @@ -769,11 +783,11 @@ public: setLinkLibraries(const ArrayRef linkLibraries) { storage->linkLibraries.assign(linkLibraries.begin(), linkLibraries.end()); } - + const ArrayRef getAuxiliaryFiles() const { return storage->auxiliaryFiles; } - + void setAuxiliaryFiles(const ArrayRef auxiliaryFiles) { storage->auxiliaryFiles.assign(auxiliaryFiles.begin(), auxiliaryFiles.end()); @@ -961,11 +975,14 @@ public: void addSourceFile(StringRef sourceFile); /// Add source files that the header input depends on. - void addHeaderSourceFile(StringRef bridgingSourceFile); + void setHeaderSourceFiles(const std::vector &sourceFiles); /// Add bridging header include tree. void addBridgingHeaderIncludeTree(StringRef ID); + /// Set the chained bridging header buffer. + void setChainedBridgingHeaderBuffer(StringRef path, StringRef buffer); + /// Collect a map from a secondary module name to a list of cross-import /// overlays, when this current module serves as the primary module. llvm::StringMap> @@ -1025,8 +1042,9 @@ class SwiftDependencyScanningService { /// If use clang include tree. bool UseClangIncludeTree = false; - /// CAS ObjectStore Instance. + /// CAS Instance. std::shared_ptr CAS; + std::shared_ptr ActionCache; /// File prefix mapper. std::unique_ptr Mapper; @@ -1182,11 +1200,11 @@ public: /// Query all dependencies ModuleDependencyIDSetVector getAllDependencies(const ModuleDependencyID &moduleID) const; - + /// Query all Clang module dependencies. ModuleDependencyIDSetVector getClangDependencies(const ModuleDependencyID &moduleID) const; - + /// Query all directly-imported Swift dependencies llvm::ArrayRef getImportedSwiftDependencies(const ModuleDependencyID &moduleID) const; diff --git a/include/swift/AST/SearchPathOptions.h b/include/swift/AST/SearchPathOptions.h index 9886803debb..ff697f5ef49 100644 --- a/include/swift/AST/SearchPathOptions.h +++ b/include/swift/AST/SearchPathOptions.h @@ -577,6 +577,9 @@ public: /// "in-package", must not require package-only module dependencies. bool ResolveInPackageModuleDependencies = false; + /// Enable auto bridging header chaining. + bool BridgingHeaderChaining = false; + /// Return all module search paths that (non-recursively) contain a file whose /// name is in \p Filenames. SmallVector diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index f607b4562a0..ead4cf7c8d3 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -201,7 +201,7 @@ namespace swift { /// Maximum number of typo corrections we are allowed to perform. /// This is disabled by default until we can get typo-correction working within acceptable performance bounds. unsigned TypoCorrectionLimit = 0; - + /// Should access control be respected? bool EnableAccessControl = true; @@ -260,7 +260,7 @@ namespace swift { /// Emit a remark when indexing a system module. bool EnableIndexingSystemModuleRemarks = false; - + /// Emit a remark on early exit in explicit interface build bool EnableSkipExplicitInterfaceModuleBuildRemarks = false; @@ -684,7 +684,7 @@ namespace swift { void clearAllPlatformConditionValues() { PlatformConditionValues.clear(); } - + /// Returns the value for the given platform condition or an empty string. StringRef getPlatformConditionValue(PlatformConditionKind Kind) const; @@ -864,7 +864,7 @@ namespace swift { /// 4.2 GHz Intel Core i7. /// (It's arbitrary, but will keep the compiler from taking too much time.) unsigned SwitchCheckingInvocationThreshold = 200000; - + /// If true, the time it takes to type-check each function will be dumped /// to llvm::errs(). bool DebugTimeFunctionBodies = false; @@ -908,7 +908,7 @@ namespace swift { /// Enable experimental operator designated types feature. bool EnableOperatorDesignatedTypes = false; - + /// Disable constraint system performance hacks. bool DisableConstraintSolverPerformanceHacks = false; @@ -956,6 +956,9 @@ namespace swift { /// The bridging header or PCH that will be imported. std::string BridgingHeader; + /// The bridging header PCH file. + std::string BridgingHeaderPCH; + /// When automatically generating a precompiled header from the bridging /// header, place it in this directory. std::string PrecompiledHeaderOutputDir; @@ -1077,6 +1080,9 @@ namespace swift { /// compilation source targets. std::vector getReducedExtraArgsForSwiftModuleDependency() const; + + /// Get PCH input path. Return empty string if there is no PCH input. + std::string getPCHInputPath() const; }; } // end namespace swift diff --git a/include/swift/ClangImporter/ClangImporter.h b/include/swift/ClangImporter/ClangImporter.h index 07a264819e9..d03ab411a82 100644 --- a/include/swift/ClangImporter/ClangImporter.h +++ b/include/swift/ClangImporter/ClangImporter.h @@ -508,6 +508,8 @@ public: /// information will be augmented with information about the given /// textual header inputs. /// + /// \param headerPath the path to the header to be scanned. + /// /// \param clangScanningTool The clang dependency scanner. /// /// \param cache The module dependencies cache to update, with information @@ -515,7 +517,8 @@ public: /// /// \returns \c true if an error occurred, \c false otherwise bool getHeaderDependencies( - ModuleDependencyID moduleID, + ModuleDependencyID moduleID, std::optional headerPath, + std::optional sourceBuffer, clang::tooling::dependencies::DependencyScanningTool &clangScanningTool, ModuleDependenciesCache &cache, ModuleDependencyIDSetVector &headerClangModuleDependencies, @@ -677,6 +680,11 @@ public: const clang::TypedefType *getTypeDefForCXXCFOptionsDefinition( const clang::Decl *candidateDecl) override; + /// Create cache key for embedded bridging header. + static llvm::Expected + createEmbeddedBridgingHeaderCacheKey( + llvm::cas::ObjectStore &CAS, llvm::cas::ObjectRef ChainedPCHIncludeTree); + SourceLoc importSourceLocation(clang::SourceLocation loc) override; }; diff --git a/include/swift/DependencyScan/DependencyScanImpl.h b/include/swift/DependencyScan/DependencyScanImpl.h index e0e15024b01..8a4e181b33d 100644 --- a/include/swift/DependencyScan/DependencyScanImpl.h +++ b/include/swift/DependencyScan/DependencyScanImpl.h @@ -130,6 +130,13 @@ typedef struct { /// User module version swiftscan_string_ref_t user_module_version; + + /// Chained bridging header path. + swiftscan_string_ref_t chained_bridging_header_path; + + /// Chained bridging header content. + swiftscan_string_ref_t chained_bridging_header_content; + } swiftscan_swift_textual_details_t; /// Swift modules with only a binary module file. diff --git a/include/swift/DependencyScan/ModuleDependencyScanner.h b/include/swift/DependencyScan/ModuleDependencyScanner.h index 00130597f72..2ca1b6542a7 100644 --- a/include/swift/DependencyScan/ModuleDependencyScanner.h +++ b/include/swift/DependencyScan/ModuleDependencyScanner.h @@ -16,6 +16,7 @@ #include "swift/AST/ModuleDependencies.h" #include "swift/Frontend/ModuleInterfaceLoader.h" #include "swift/Serialization/SerializedModuleLoader.h" +#include "llvm/CAS/CASReference.h" #include "llvm/Support/ThreadPool.h" namespace swift { @@ -48,6 +49,11 @@ private: llvm::PrefixMapper *prefixMapper, bool isTestableImport = false); + /// Store cache entry for include tree. + llvm::Error + createCacheKeyForEmbeddedHeader(std::string embeddedHeaderIncludeTree, + std::string chainedHeaderIncludeTree); + // Worker-specific instance of CompilerInvocation std::unique_ptr workerCompilerInvocation; // Worker-specific instance of ASTContext @@ -59,6 +65,9 @@ private: // Swift and Clang module loaders acting as scanners. std::unique_ptr swiftScannerModuleLoader; std::unique_ptr clangScannerModuleLoader; + // CAS instance. + std::shared_ptr CAS; + std::shared_ptr ActionCache; // Restrict access to the parent scanner class. friend class ModuleDependencyScanner; }; @@ -116,10 +125,9 @@ private: resolveAllClangModuleDependencies(ArrayRef swiftModules, ModuleDependenciesCache &cache, ModuleDependencyIDSetVector &discoveredClangModules); - void - resolveHeaderDependencies(ArrayRef swiftModules, - ModuleDependenciesCache &cache, - ModuleDependencyIDSetVector &discoveredHeaderDependencyClangModules); + void resolveHeaderDependencies( + ArrayRef swiftModules, ModuleDependenciesCache &cache, + ModuleDependencyIDSetVector &discoveredHeaderDependencyClangModules); void resolveSwiftOverlayDependencies(ArrayRef swiftModules, ModuleDependenciesCache &cache, @@ -151,6 +159,12 @@ private: ModuleDependenciesCache &cache, llvm::function_ref action); + /// Performance BridgingHeader Chaining. + llvm::Error + performBridgingHeaderChaining(const ModuleDependencyID &rootModuleID, + ModuleDependenciesCache &cache, + ModuleDependencyIDSetVector &allModules); + /// Perform an operation utilizing one of the Scanning workers /// available to this scanner. template diff --git a/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h b/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h index c9f1ca0d507..3ef6326be1c 100644 --- a/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h +++ b/include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h @@ -233,7 +233,9 @@ using SwiftSourceModuleDetailsLayout = IdentifierIDField, // CASFileSystemRootID IdentifierIDField, // bridgingHeaderIncludeTree FlagIDArrayIDField, // buildCommandLine - FlagIDArrayIDField // bridgingHeaderBuildCommandLine + FlagIDArrayIDField, // bridgingHeaderBuildCommandLine + IdentifierIDField, // chainedBridgingHeaderPath + IdentifierIDField // chainedBridgingHeaderContent >; using SwiftBinaryModuleDetailsLayout = diff --git a/include/swift/Frontend/CompileJobCacheKey.h b/include/swift/Frontend/CompileJobCacheKey.h index bc119a35f5e..f32208f3a55 100644 --- a/include/swift/Frontend/CompileJobCacheKey.h +++ b/include/swift/Frontend/CompileJobCacheKey.h @@ -21,6 +21,7 @@ #include "swift/AST/DiagnosticEngine.h" #include "swift/Basic/FileTypes.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/CAS/CASReference.h" #include "llvm/CAS/ObjectStore.h" #include "llvm/Support/Error.h" #include "llvm/Support/raw_ostream.h" @@ -49,6 +50,7 @@ createCompileJobCacheKeyForOutput(llvm::cas::ObjectStore &CAS, llvm::Error printCompileJobCacheKey(llvm::cas::ObjectStore &CAS, llvm::cas::ObjectRef Key, llvm::raw_ostream &os); + } // namespace swift #endif diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index 23d1a330cdb..1c6f0c1e516 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -54,6 +54,9 @@ public: /// An Objective-C header to import and make implicitly visible. std::string ImplicitObjCHeaderPath; + /// An Objective-C pch to import and make implicitly visible. + std::string ImplicitObjCPCHPath; + /// The map of aliases and real names of imported or referenced modules. llvm::StringMap ModuleAliasMap; @@ -374,6 +377,12 @@ public: /// Emit remarks indicating use of the serialized module dependency scanning cache. bool EmitDependencyScannerCacheRemarks = false; + /// The path at which the dependency scanner can write generated files. + std::string ScannerOutputDir; + + /// If the scanner output is written directly to the disk for debugging. + bool WriteScannerOutput = false; + /// Whether the dependency scanner invocation should resolve imports /// to filesystem modules in parallel. bool ParallelDependencyScan = true; diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index 7a005271a3b..a8c4fe84b3b 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -171,12 +171,12 @@ def verify_generic_signatures : Separate<["-"], "verify-generic-signatures">, def show_diagnostics_after_fatal : Flag<["-"], "show-diagnostics-after-fatal">, HelpText<"Keep emitting subsequent diagnostics after a fatal error">; - + def enable_cross_import_overlays : Flag<["-"], "enable-cross-import-overlays">, HelpText<"Automatically import declared cross-import overlays.">; def disable_cross_import_overlays : Flag<["-"], "disable-cross-import-overlays">, HelpText<"Do not automatically import declared cross-import overlays.">; - + def enable_testable_attr_requires_testable_module : Flag<["-"], "enable-testable-attr-requires-testable-module">, HelpText<"Enable checking of @testable">; @@ -196,7 +196,7 @@ def enable_target_os_checking : def disable_target_os_checking : Flag<["-"], "disable-target-os-checking">, HelpText<"Disable checking the target OS of serialized modules">; - + def crosscheck_unqualified_lookup : Flag<["-"], "crosscheck-unqualified-lookup">, HelpText<"Compare legacy DeclContext- to ASTScope-based unqualified name lookup (for debugging)">; @@ -384,9 +384,9 @@ def public_autolink_library : // HIDDEN FLAGS let Flags = [FrontendOption, NoDriverOption, HelpHidden] in { -def enable_experimental_swift_based_closure_specialization : +def enable_experimental_swift_based_closure_specialization : Flag<["-"], "experimental-swift-based-closure-specialization">, - HelpText<"Use the experimental Swift based closure-specialization optimization pass instead of the existing C++ one">; + HelpText<"Use the experimental Swift based closure-specialization optimization pass instead of the existing C++ one">; def checked_async_objc_bridging : Joined<["-"], "checked-async-objc-bridging=">, HelpText<"Control whether checked continuations are used when bridging " @@ -898,7 +898,7 @@ def disable_concrete_type_metadata_mangled_name_accessors : Flag<["-"], "disable def disable_standard_substitutions_in_reflection_mangling : Flag<["-"], "disable-standard-substitutions-in-reflection-mangling">, HelpText<"Disable referencing stdlib symbols via mangled names in reflection mangling">, Flags<[FrontendOption, HelpHidden]>; - + def playground : Flag<["-"], "playground">, HelpText<"Apply the playground semantics and transformation">; @@ -938,13 +938,13 @@ def sil_unroll_threshold : Separate<["-"], "sil-unroll-threshold">, def sil_verify_all : Flag<["-"], "sil-verify-all">, HelpText<"Verify SIL after each transform">; - + def sil_verify_none : Flag<["-"], "sil-verify-none">, HelpText<"Completely disable SIL verification">; def sil_ownership_verify_all : Flag<["-"], "sil-ownership-verify-all">, HelpText<"Verify ownership after each transform">; - + def verify_all_substitution_maps : Flag<["-"], "verify-all-substitution-maps">, HelpText<"Verify all SubstitutionMaps on construction">; @@ -1163,7 +1163,7 @@ def disable_interface_lockfile : Flag<["-"], "disable-interface-lock">, def bridging_header_directory_for_print: Separate<["-"], "bridging-header-directory-for-print">, MetaVarName<"">, HelpText<"Directory for bridging header to be printed in compatibility header">; -def entry_point_function_name: Separate<["-"], "entry-point-function-name">, MetaVarName<"">, +def entry_point_function_name: Separate<["-"], "entry-point-function-name">, MetaVarName<"">, HelpText<"Name of the entry point function">; def target_sdk_version : Separate<["-"], "target-sdk-version">, @@ -1450,6 +1450,12 @@ def module_load_mode: Separate<["-"], "module-load-mode">, MetaVarName<"only-interface|prefer-interface|prefer-serialized|only-serialized">, HelpText<"Module loading mode">; +def scanner_output_dir: Separate<["-"], "scanner-output-dir">, + HelpText<"Directory for generated files from swift dependency scanner">; +def scanner_debug_write_output: Flag<["-"], "scanner-debug-write-output">, + HelpText<"Write generated output from scanner for debugging purpose">, + Flags<[HelpHidden]>; + def platform_availability_inheritance_map_path : Separate<["-"], "platform-availability-inheritance-map-path">, MetaVarName<"">, HelpText<"Path of the platform inheritance platform map">; diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index a682d371a1d..df804fa591f 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -173,12 +173,12 @@ def verify_incremental_dependencies : Flag<["-"], "verify-incremental-dependencies">, Flags<[FrontendOption, HelpHidden]>, HelpText<"Enable the dependency verifier for each frontend job">; - + def strict_implicit_module_context : Flag<["-"], "strict-implicit-module-context">, Flags<[FrontendOption, HelpHidden]>, HelpText<"Enable the strict forwarding of compilation context to downstream implicit module dependencies">; - + def no_strict_implicit_module_context : Flag<["-"], "no-strict-implicit-module-context">, Flags<[FrontendOption, HelpHidden]>, @@ -315,7 +315,7 @@ def tools_directory : Separate<["-"], "tools-directory">, def D : JoinedOrSeparate<["-"], "D">, Flags<[FrontendOption]>, HelpText<"Marks a conditional compilation flag as true">; - + def e : Separate<["-"], "e">, Flags<[NewDriverOnlyOption]>, HelpText<"Executes a line of code provided on the command line">; @@ -353,11 +353,21 @@ def import_objc_header : Separate<["-"], "import-objc-header">, def import_bridging_header : Separate<["-"], "import-bridging-header">, Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>, Alias; +def import_pch : Separate<["-"], "import-pch">, + Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>, + HelpText<"Import bridging header PCH file">; def pch_output_dir: Separate<["-"], "pch-output-dir">, Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>, HelpText<"Directory to persist automatically created precompiled bridging headers">; +def auto_bridging_header_chaining: Flag<["-"], "auto-bridging-header-chaining">, + Flags<[FrontendOption, HelpHidden]>, + HelpText<"Automatically chaining all the bridging headers">; +def no_auto_bridging_header_chaining: Flag<["-"], "no-auto-bridging-header-chaining">, + Flags<[FrontendOption, HelpHidden]>, + HelpText<"Do not automatically chaining all the bridging headers">; + // FIXME: Unhide this once it doesn't depend on an output file map. def incremental : Flag<["-"], "incremental">, Flags<[NoInteractiveOption, HelpHidden, DoesNotAffectIncrementalBuild]>, @@ -2176,7 +2186,7 @@ def external_plugin_path : Separate<["-"], "external-plugin-path">, Group, HelpText<"Add directory to the plugin search path with a plugin server executable">, MetaVarName<"#">; - + def cas_backend: Flag<["-"], "cas-backend">, Flags<[FrontendOption, NoDriverOption]>, HelpText<"Enable using CASBackend for object file output">; diff --git a/include/swift/Serialization/SerializationOptions.h b/include/swift/Serialization/SerializationOptions.h index c94caf69ae6..269ea577373 100644 --- a/include/swift/Serialization/SerializationOptions.h +++ b/include/swift/Serialization/SerializationOptions.h @@ -45,6 +45,9 @@ public: StringRef GroupInfoPath; StringRef ImportedHeader; + StringRef ImportedPCHPath; + bool SerializeBridgingHeader = false; + bool SerializeEmptyBridgingHeader = false; StringRef ModuleLinkName; StringRef ModuleInterface; std::vector ExtraClangOptions; diff --git a/include/swift/Serialization/SerializedModuleLoader.h b/include/swift/Serialization/SerializedModuleLoader.h index e7a40b1cad1..072b2e009fd 100644 --- a/include/swift/Serialization/SerializedModuleLoader.h +++ b/include/swift/Serialization/SerializedModuleLoader.h @@ -436,7 +436,7 @@ public: getFilenameForPrivateDecl(const Decl *decl) const override; virtual TypeDecl *lookupLocalType(StringRef MangledName) const override; - + virtual OpaqueTypeDecl * lookupOpaqueResultType(StringRef MangledName) override; @@ -583,6 +583,11 @@ bool extractCompilerFlagsFromInterface( /// Extract the user module version number from an interface file. llvm::VersionTuple extractUserModuleVersionFromInterface(StringRef moduleInterfacePath); + +/// Extract embedded bridging header from binary module. +std::string +extractEmbeddedBridgingHeaderContent(std::unique_ptr file, + ASTContext &Context); } // end namespace swift #endif diff --git a/lib/AST/ModuleDependencies.cpp b/lib/AST/ModuleDependencies.cpp index 444da5301af..11bd72ee3ae 100644 --- a/lib/AST/ModuleDependencies.cpp +++ b/lib/AST/ModuleDependencies.cpp @@ -391,26 +391,25 @@ void ModuleDependencyInfo::addBridgingHeader(StringRef bridgingHeader) { } /// Add source files that the bridging header depends on. -void ModuleDependencyInfo::addHeaderSourceFile(StringRef bridgingSourceFile) { +void ModuleDependencyInfo::setHeaderSourceFiles( + const std::vector &files) { switch (getKind()) { case swift::ModuleDependencyKind::SwiftInterface: { auto swiftInterfaceStorage = cast(storage.get()); - swiftInterfaceStorage->textualModuleDetails.bridgingSourceFiles.push_back( - bridgingSourceFile.str()); + swiftInterfaceStorage->textualModuleDetails.bridgingSourceFiles = files; break; } case swift::ModuleDependencyKind::SwiftSource: { auto swiftSourceStorage = cast(storage.get()); - swiftSourceStorage->textualModuleDetails.bridgingSourceFiles.push_back( - bridgingSourceFile.str()); + swiftSourceStorage->textualModuleDetails.bridgingSourceFiles = files; break; } case swift::ModuleDependencyKind::SwiftBinary: { auto swiftBinaryStorage = cast(storage.get()); - swiftBinaryStorage->headerSourceFiles.push_back(bridgingSourceFile.str()); + swiftBinaryStorage->headerSourceFiles = files; break; } default: @@ -439,6 +438,20 @@ void ModuleDependencyInfo::addBridgingHeaderIncludeTree(StringRef ID) { } } +void ModuleDependencyInfo::setChainedBridgingHeaderBuffer(StringRef path, + StringRef buffer) { + switch (getKind()) { + case swift::ModuleDependencyKind::SwiftSource: { + auto swiftSourceStorage = + cast(storage.get()); + swiftSourceStorage->setChainedBridgingHeaderBuffer(path, buffer); + break; + } + default: + llvm_unreachable("Unexpected dependency kind"); + } +} + void ModuleDependencyInfo::addSourceFile(StringRef sourceFile) { switch (getKind()) { case swift::ModuleDependencyKind::SwiftSource: { @@ -678,6 +691,7 @@ bool SwiftDependencyScanningService::setupCachingDependencyScanningService( // Setup CAS. CASOpts = Instance.getInvocation().getCASOptions().CASOpts; CAS = Instance.getSharedCASInstance(); + ActionCache = Instance.getSharedCacheInstance(); auto CachingFS = llvm::cas::createCachingOnDiskFileSystem(Instance.getObjectStore()); @@ -771,14 +785,14 @@ ModuleDependenciesCache::findDependency( } return std::nullopt; } - + assert(kind.has_value() && "Expected dependencies kind for lookup."); std::optional optionalDep = std::nullopt; const auto &map = getDependenciesMap(kind.value()); auto known = map.find(moduleName); if (known != map.end()) optionalDep = &(known->second); - + // During a scan, only produce the cached source module info for the current // module under scan. if (optionalDep.has_value()) { @@ -899,7 +913,6 @@ void ModuleDependenciesCache::setHeaderClangDependencies(ModuleDependencyID moduleID, const ArrayRef dependencyIDs) { auto dependencyInfo = findKnownDependency(moduleID); - assert(dependencyInfo.getHeaderClangDependencies().empty()); #ifndef NDEBUG for (const auto &depID : dependencyIDs) assert(depID.Kind == ModuleDependencyKind::Clang); diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp index dcb6697a21c..ee44d01eb7c 100644 --- a/lib/Basic/LangOptions.cpp +++ b/lib/Basic/LangOptions.cpp @@ -18,6 +18,7 @@ #include "swift/Basic/LangOptions.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/Basic/Feature.h" +#include "swift/Basic/FileTypes.h" #include "swift/Basic/Platform.h" #include "swift/Basic/PlaygroundOption.h" #include "swift/Basic/Range.h" @@ -818,3 +819,14 @@ ClangImporterOptions::getReducedExtraArgsForSwiftModuleDependency() const { return filtered_args; } + +std::string ClangImporterOptions::getPCHInputPath() const { + if (!BridgingHeaderPCH.empty()) + return BridgingHeaderPCH; + + if (llvm::sys::path::extension(BridgingHeader) + .ends_with(file_types::getExtension(file_types::TY_PCH))) + return BridgingHeader; + + return {}; +} diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 8b7d2090f48..50ef2d8bb13 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -50,6 +50,7 @@ #include "swift/Basic/Version.h" #include "swift/ClangImporter/ClangImporterRequests.h" #include "swift/ClangImporter/ClangModule.h" +#include "swift/Frontend/CompileJobCacheKey.h" #include "swift/Parse/ParseVersion.h" #include "swift/Strings.h" #include "swift/Subsystems.h" @@ -476,11 +477,10 @@ void importer::getNormalInvocationArguments( ClangImporterOptions &importerOpts = ctx.ClangImporterOpts; auto languageVersion = ctx.LangOpts.EffectiveLanguageVersion; - if (isPCHFilenameExtension(importerOpts.BridgingHeader)) { - invocationArgStrs.insert(invocationArgStrs.end(), { - "-include-pch", importerOpts.BridgingHeader - }); - } + auto bridgingPCH = importerOpts.getPCHInputPath(); + if (!bridgingPCH.empty()) + invocationArgStrs.insert(invocationArgStrs.end(), + {"-include-pch", bridgingPCH}); // If there are no shims in the resource dir, add a search path in the SDK. SmallString<128> shimsPath(searchPathOpts.RuntimeResourcePath); @@ -1070,9 +1070,10 @@ void ClangImporter::addClangInvovcationDependencies( std::optional ClangImporter::getPCHFilename(const ClangImporterOptions &ImporterOptions, StringRef SwiftPCHHash, bool &isExplicit) { - if (isPCHFilenameExtension(ImporterOptions.BridgingHeader)) { + auto bridgingPCH = ImporterOptions.getPCHInputPath(); + if (!bridgingPCH.empty()) { isExplicit = true; - return ImporterOptions.BridgingHeader; + return bridgingPCH; } isExplicit = false; @@ -1306,8 +1307,9 @@ ClangImporter::create(ASTContext &ctx, new ClangImporter(ctx, tracker, dwarfImporterDelegate)}; auto &importerOpts = ctx.ClangImporterOpts; - if (isPCHFilenameExtension(importerOpts.BridgingHeader)) { - importer->Impl.setSinglePCHImport(importerOpts.BridgingHeader); + auto bridgingPCH = importerOpts.getPCHInputPath(); + if (!bridgingPCH.empty()) { + importer->Impl.setSinglePCHImport(bridgingPCH); importer->Impl.IsReadingBridgingPCH = true; if (tracker) { // Currently ignoring dependency on bridging .pch files because they are @@ -1315,7 +1317,7 @@ ClangImporter::create(ASTContext &ctx, // should be removed. auto &coll = static_cast( *tracker->getClangCollector()); - coll.excludePath(importerOpts.BridgingHeader); + coll.excludePath(bridgingPCH); } } @@ -1888,12 +1890,30 @@ setupIncludeTreeInput(clang::CompilerInvocation &invocation, if (!DB) return DB.takeError(); auto CAS = DB->first; + auto Cache = DB->second; auto ID = CAS->parseID(pchIncludeTree); if (!ID) return ID.takeError(); - auto includeTreeRef = CAS->getReference(*ID); - if (!includeTreeRef) + auto Ref = CAS->getReference(*ID); + if (!Ref) return llvm::cas::ObjectStore::createUnknownObjectError(*ID); + auto Key = ClangImporter::createEmbeddedBridgingHeaderCacheKey(*CAS, *Ref); + if (!Key) + return Key.takeError(); + auto Lookup = Cache->get(CAS->getID(*Key)); + if (!Lookup) + return Lookup.takeError(); + + std::optional includeTreeRef; + if (*Lookup) { + includeTreeRef = CAS->getReference(**Lookup); + if (!includeTreeRef) + return llvm::cas::ObjectStore::createUnknownObjectError(**Lookup); + } else + // Failed to look up. This is from a caching build that doesn't use bridging + // header chaining due to an older swift-driver. Just use the include tree + // for PCH directly. + includeTreeRef = *Ref; invocation.getFrontendOpts().Inputs.push_back(clang::FrontendInputFile( *includeTreeRef, headerPath, clang::Language::ObjC)); @@ -6340,7 +6360,7 @@ static bool isImplValid(ExtensionDecl *ext) { // This is diagnosed in AttributeChecker::visitObjCImplementationAttr(). if (!attr->isEarlyAdopter() && !attr->CategoryName.empty()) return false; - + return !attr->isCategoryNameInvalid(); } @@ -7614,6 +7634,15 @@ SourceLoc ClangImporter::importSourceLocation(clang::SourceLocation loc) { getClangASTContext().getSourceManager(), loc); } +llvm::Expected +ClangImporter::createEmbeddedBridgingHeaderCacheKey( + llvm::cas::ObjectStore &CAS, llvm::cas::ObjectRef ChainedPCHIncludeTree) { + // Create a cache key for looking up embedded bridging header include tree + // from chained bridging header cache key. + return CAS.store({ChainedPCHIncludeTree}, + "ChainedHeaderIncludeTree -> EmbeddedHeaderIncludeTree"); +} + static bool hasImportAsRefAttr(const clang::RecordDecl *decl) { return decl->hasAttrs() && llvm::any_of(decl->getAttrs(), [](auto *attr) { if (auto swiftAttr = dyn_cast(attr)) @@ -7940,7 +7969,7 @@ CxxRecordSemantics::evaluate(Evaluator &evaluator, if (hasIteratorAPIAttr(cxxDecl) || isIterator(cxxDecl)) { return CxxRecordSemanticsKind::Iterator; } - + if (hasCopyTypeOperations(cxxDecl)) { return CxxRecordSemanticsKind::Owned; } @@ -7997,7 +8026,7 @@ bool anySubobjectsSelfContained(const clang::CXXRecordDecl *decl) { if (hasCustomCopyOrMoveConstructor(decl) || hasOwnedValueAttr(decl)) return true; - + auto checkType = [](clang::QualType t) { if (auto recordType = dyn_cast(t.getCanonicalType())) { if (auto cxxRecord = @@ -8018,7 +8047,7 @@ bool anySubobjectsSelfContained(const clang::CXXRecordDecl *decl) { if (checkType(base.getType())) return true; } - + return false; } diff --git a/lib/ClangImporter/ClangModuleDependencyScanner.cpp b/lib/ClangImporter/ClangModuleDependencyScanner.cpp index 73b281d4c79..798d0822942 100644 --- a/lib/ClangImporter/ClangModuleDependencyScanner.cpp +++ b/lib/ClangImporter/ClangModuleDependencyScanner.cpp @@ -448,25 +448,19 @@ ClangImporter::getModuleDependencies(Identifier moduleName, } bool ClangImporter::getHeaderDependencies( - ModuleDependencyID moduleID, + ModuleDependencyID moduleID, std::optional headerPath, + std::optional sourceBuffer, clang::tooling::dependencies::DependencyScanningTool &clangScanningTool, ModuleDependenciesCache &cache, ModuleDependencyIDSetVector &headerClangModuleDependencies, std::vector &headerFileInputs, std::vector &bridgingHeaderCommandLine, std::optional &includeTreeID) { - auto targetModuleInfo = cache.findKnownDependency(moduleID); - // If we've already recorded bridging header dependencies, we're done. - if (!targetModuleInfo.getHeaderClangDependencies().empty() || - !targetModuleInfo.getHeaderInputSourceFiles().empty()) - return false; - // Scan the specified textual header file and collect its dependencies - auto scanHeaderDependencies = - [&](StringRef headerPath) -> llvm::Expected { + auto scanHeaderDependencies = [&]() -> llvm::Expected { auto &ctx = Impl.SwiftContext; std::vector commandLineArgs = - getClangDepScanningInvocationArguments(ctx, StringRef(headerPath)); + getClangDepScanningInvocationArguments(ctx, headerPath); auto optionalWorkingDir = computeClangWorkingDirectory(commandLineArgs, ctx); if (!optionalWorkingDir) { @@ -484,7 +478,7 @@ bool ClangImporter::getHeaderDependencies( }; auto dependencies = clangScanningTool.getTranslationUnitDependencies( commandLineArgs, workingDir, cache.getAlreadySeenClangModules(), - lookupModuleOutput); + lookupModuleOutput, sourceBuffer); if (!dependencies) return dependencies.takeError(); @@ -507,33 +501,27 @@ bool ClangImporter::getHeaderDependencies( return dependencies; }; + // - If a generated header is provided, scan the generated header. // - Textual module dependencies require us to process their bridging header. // - Binary module dependnecies may have arbitrary header inputs. - if (targetModuleInfo.isTextualSwiftModule() && - !targetModuleInfo.getBridgingHeader()->empty()) { - auto clangModuleDependencies = - scanHeaderDependencies(*targetModuleInfo.getBridgingHeader()); - if (!clangModuleDependencies) { - // FIXME: Route this to a normal diagnostic. - llvm::logAllUnhandledErrors(clangModuleDependencies.takeError(), - llvm::errs()); - Impl.SwiftContext.Diags.diagnose( - SourceLoc(), diag::clang_dependency_scan_error, - "failed to scan bridging header dependencies"); - return true; - } - if (auto TreeID = clangModuleDependencies->IncludeTreeID) - includeTreeID = TreeID; - - getBridgingHeaderOptions(*clangModuleDependencies, bridgingHeaderCommandLine); - } else if (targetModuleInfo.isSwiftBinaryModule()) { - auto swiftBinaryDeps = targetModuleInfo.getAsSwiftBinaryModule(); - if (!swiftBinaryDeps->headerImport.empty()) { - auto clangModuleDependencies = scanHeaderDependencies(swiftBinaryDeps->headerImport); - if (!clangModuleDependencies) - return true; - } + auto clangModuleDependencies = scanHeaderDependencies(); + if (!clangModuleDependencies) { + // FIXME: Route this to a normal diagnostic. + llvm::logAllUnhandledErrors(clangModuleDependencies.takeError(), + llvm::errs()); + Impl.SwiftContext.Diags.diagnose( + SourceLoc(), diag::clang_dependency_scan_error, + "failed to scan bridging header dependencies"); + return true; } + auto targetModuleInfo = cache.findKnownDependency(moduleID); + if (!targetModuleInfo.isTextualSwiftModule()) + return false; + + if (auto TreeID = clangModuleDependencies->IncludeTreeID) + includeTreeID = TreeID; + getBridgingHeaderOptions(*clangModuleDependencies, bridgingHeaderCommandLine); + return false; } diff --git a/lib/DependencyScan/DependencyScanJSON.cpp b/lib/DependencyScan/DependencyScanJSON.cpp index 4be95f48410..7d52006862d 100644 --- a/lib/DependencyScan/DependencyScanJSON.cpp +++ b/lib/DependencyScan/DependencyScanJSON.cpp @@ -413,15 +413,16 @@ void writeJSON(llvm::raw_ostream &out, writeJSONSingleField(out, "contextHash", swiftTextualDeps->context_hash, 5, /*trailingComma=*/true); - bool hasBridgingHeaderPath = - swiftTextualDeps->bridging_header_path.data && - get_C_string(swiftTextualDeps->bridging_header_path)[0] != '\0'; + bool hasBridgingHeader = + (swiftTextualDeps->bridging_header_path.data && + get_C_string(swiftTextualDeps->bridging_header_path)[0] != '\0') || + swiftTextualDeps->bridging_pch_command_line->count != 0; bool hasOverlayDependencies = swiftTextualDeps->swift_overlay_module_dependencies && swiftTextualDeps->swift_overlay_module_dependencies->count > 0; bool commaAfterBridgingHeaderPath = hasOverlayDependencies; bool commaAfterFramework = - hasBridgingHeaderPath || commaAfterBridgingHeaderPath; + hasBridgingHeader || commaAfterBridgingHeaderPath; if (swiftTextualDeps->cas_fs_root_id.length != 0) { writeJSONSingleField(out, "casFSRootID", @@ -433,6 +434,11 @@ void writeJSON(llvm::raw_ostream &out, swiftTextualDeps->module_cache_key, 5, /*trailingComma=*/true); } + if (swiftTextualDeps->chained_bridging_header_path.length != 0) { + writeJSONSingleField(out, "chainedBridgingHeaderPath", + swiftTextualDeps->chained_bridging_header_path, 5, + /*trailingComma=*/true); + } writeJSONSingleField(out, "userModuleVersion", swiftTextualDeps->user_module_version, 5, /*trailingComma=*/true); @@ -441,7 +447,7 @@ void writeJSON(llvm::raw_ostream &out, writeJSONSingleField(out, "isFramework", swiftTextualDeps->is_framework, 5, commaAfterFramework); /// Bridging header and its source file dependencies, if any. - if (hasBridgingHeaderPath) { + if (hasBridgingHeader) { out.indent(5 * 2); out << "\"bridgingHeader\": {\n"; writeJSONSingleField(out, "path", diff --git a/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp b/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp index 0da15e0a895..2b9578a6273 100644 --- a/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp +++ b/lib/DependencyScan/ModuleDependencyCacheSerialization.cpp @@ -171,7 +171,7 @@ bool ModuleDependenciesCacheDeserializer::readMetadata(StringRef scannerContextH if (majorVersion != MODULE_DEPENDENCY_CACHE_FORMAT_VERSION_MAJOR || minorVersion != MODULE_DEPENDENCY_CACHE_FORMAT_VERSION_MINOR) return true; - + std::string readScannerContextHash = BlobData.str(); if (readScannerContextHash != scannerContextHash) return true; @@ -286,8 +286,7 @@ bool ModuleDependenciesCacheDeserializer::readGraph( auto bridgingSourceFiles = getStringArray(bridgingSourceFilesArrayID); if (!bridgingSourceFiles) llvm::report_fatal_error("Bad bridging source files"); - for (const auto &file : *bridgingSourceFiles) - moduleDep.addHeaderSourceFile(file); + moduleDep.setHeaderSourceFiles(*bridgingSourceFiles); // Add bridging module dependencies auto bridgingModuleDeps = @@ -609,13 +608,15 @@ bool ModuleDependenciesCacheDeserializer::readGraph( unsigned bridgingHeaderFileID, sourceFilesArrayID, bridgingSourceFilesArrayID, bridgingModuleDependenciesArrayID, CASFileSystemRootID, bridgingHeaderIncludeTreeID, - buildCommandLineArrayID, bridgingHeaderBuildCommandLineArrayID; + buildCommandLineArrayID, bridgingHeaderBuildCommandLineArrayID, + chainedBridgingHeaderPathID, chainedBridgingHeaderContentID; SwiftSourceModuleDetailsLayout::readRecord( Scratch, bridgingHeaderFileID, sourceFilesArrayID, bridgingSourceFilesArrayID, bridgingModuleDependenciesArrayID, CASFileSystemRootID, bridgingHeaderIncludeTreeID, buildCommandLineArrayID, - bridgingHeaderBuildCommandLineArrayID); + bridgingHeaderBuildCommandLineArrayID, chainedBridgingHeaderPathID, + chainedBridgingHeaderContentID); auto rootFileSystemID = getIdentifier(CASFileSystemRootID); if (!rootFileSystemID) @@ -646,6 +647,15 @@ bool ModuleDependenciesCacheDeserializer::readGraph( for (const auto &file : *sourceFiles) moduleDep.addSourceFile(file); + // Add chained bridging header. + auto chainedBridgingHeaderPath = + getIdentifier(chainedBridgingHeaderPathID); + auto chainedBridgingHeaderContent = + getIdentifier(chainedBridgingHeaderContentID); + if (chainedBridgingHeaderPath && chainedBridgingHeaderContent) + moduleDep.setChainedBridgingHeaderBuffer(*chainedBridgingHeaderPath, + *chainedBridgingHeaderContent); + addCommonDependencyInfo(moduleDep); addSwiftCommonDependencyInfo(moduleDep); addSwiftTextualDependencyInfo( @@ -724,8 +734,7 @@ bool ModuleDependenciesCacheDeserializer::readGraph( if (!headerImportsSourceFiles) llvm::report_fatal_error( "Bad binary direct dependencies: no header import source files"); - for (const auto &depSource : *headerImportsSourceFiles) - moduleDep.addHeaderSourceFile(depSource); + moduleDep.setHeaderSourceFiles(*headerImportsSourceFiles); cache.recordDependency(currentModuleName, std::move(moduleDep)); hasCurrentModule = false; @@ -1537,7 +1546,9 @@ void ModuleDependenciesCacheSerializer::writeModuleInfo( ModuleIdentifierArrayKind::BuildCommandLine), getIdentifierArrayID( moduleID, - ModuleIdentifierArrayKind::BridgingHeaderBuildCommandLine)); + ModuleIdentifierArrayKind::BridgingHeaderBuildCommandLine), + getIdentifier(swiftSourceDeps->chainedBridgingHeaderPath), + getIdentifier(swiftSourceDeps->chainedBridgingHeaderContent)); break; } case swift::ModuleDependencyKind::SwiftBinary: { @@ -1859,6 +1870,8 @@ void ModuleDependenciesCacheSerializer::collectStringsAndArrays( swiftSourceDeps->bridgingHeaderBuildCommandLine); addIdentifier( swiftSourceDeps->textualModuleDetails.CASFileSystemRootID); + addIdentifier(swiftSourceDeps->chainedBridgingHeaderPath); + addIdentifier(swiftSourceDeps->chainedBridgingHeaderContent); break; } case swift::ModuleDependencyKind::Clang: { diff --git a/lib/DependencyScan/ModuleDependencyScanner.cpp b/lib/DependencyScan/ModuleDependencyScanner.cpp index 3e127b29738..07d41450fb6 100644 --- a/lib/DependencyScan/ModuleDependencyScanner.cpp +++ b/lib/DependencyScan/ModuleDependencyScanner.cpp @@ -13,6 +13,7 @@ #include "swift/AST/ASTContext.h" #include "swift/AST/DiagnosticEngine.h" #include "swift/AST/DiagnosticSuppression.h" +#include "swift/AST/DiagnosticsCommon.h" #include "swift/AST/DiagnosticsFrontend.h" #include "swift/AST/DiagnosticsSema.h" #include "swift/AST/ModuleDependencies.h" @@ -21,10 +22,12 @@ #include "swift/AST/SourceFile.h" #include "swift/AST/TypeCheckRequests.h" #include "swift/Basic/Assertions.h" +#include "swift/Basic/Defer.h" #include "swift/Basic/FileTypes.h" #include "swift/Basic/PrettyStackTrace.h" #include "swift/ClangImporter/ClangImporter.h" #include "swift/DependencyScan/ModuleDependencyScanner.h" +#include "swift/Frontend/CompileJobCacheKey.h" #include "swift/Frontend/ModuleInterfaceLoader.h" #include "swift/Serialization/SerializedModuleLoader.h" #include "swift/Subsystems.h" @@ -32,10 +35,17 @@ #include "llvm/ADT/SetOperations.h" #include "llvm/CAS/CachingOnDiskFileSystem.h" #include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" #include "llvm/Support/Threading.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Support/VirtualFileSystem.h" +#include "llvm/Support/VirtualOutputBackend.h" +#include "llvm/Support/VirtualOutputBackends.h" +#include "llvm/Support/VirtualOutputFile.h" +#include "llvm/Support/raw_ostream.h" #include +#include using namespace swift; @@ -206,6 +216,10 @@ ModuleDependencyScanningWorker::ModuleDependencyScanningWorker( FEOpts.SerializeModuleInterfaceDependencyHashes, FEOpts.shouldTrackSystemDependencies(), RequireOSSAModules_t(SILOptions)); + // Set up CAS instance. + CAS = globalScanningService.CAS; + ActionCache = globalScanningService.ActionCache; + // Set up the ClangImporter. clangScannerModuleLoader = ClangImporter::create( *workerASTContext, workerCompilerInvocation->getPCHHash(), @@ -276,6 +290,27 @@ auto ModuleDependencyScanner::withDependencyScanningWorker(Function &&F, return result; } +llvm::Error ModuleDependencyScanningWorker::createCacheKeyForEmbeddedHeader( + std::string embeddedHeaderIncludeTree, + std::string chainedHeaderIncludeTree) { + assert(CAS && ActionCache && "CAS is not available"); + auto chained = CAS->parseID(chainedHeaderIncludeTree); + if (!chained) + return chained.takeError(); + auto chainedRef = CAS->getReference(*chained); + if (!chainedRef) + return llvm::createStringError("Chained IncludeTree missing"); + auto embedded = CAS->parseID(embeddedHeaderIncludeTree); + if (!embedded) + return embedded.takeError(); + auto key = + ClangImporter::createEmbeddedBridgingHeaderCacheKey(*CAS, *chainedRef); + if (!key) + return key.takeError(); + + return ActionCache->put(CAS->getID(*key), *embedded); +} + Identifier ModuleDependencyScanner::getModuleImportIdentifier(StringRef moduleName) { return ScanASTContext.getIdentifier(moduleName); } @@ -440,7 +475,7 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) { } }); mainDependencies.updateCommandLine(buildArgs); - } + } return mainDependencies; } @@ -483,7 +518,7 @@ ModuleDependencyScanner::getNamedClangModuleDependencyInfo( }); if (moduleDependencies.empty()) return std::nullopt; - + discoveredClangModules.insert(moduleID); for (const auto &dep : moduleDependencies) discoveredClangModules.insert(dep.first); @@ -575,7 +610,7 @@ ModuleDependencyScanner::performDependencyScan( cache, discoveredClangModules); return discoveredClangModules.takeVector(); } - + // Resolve all, direct and transitive, imported module dependencies: // 1. Imported Swift modules // 2. Imported Clang modules @@ -595,6 +630,13 @@ ModuleDependencyScanner::performDependencyScan( rootModuleID.ModuleName, allModules.getArrayRef().slice(1), cache, [&](ModuleDependencyID id) { allModules.insert(id); }); + if (ScanCompilerInvocation.getSearchPathOptions().BridgingHeaderChaining) { + auto err = performBridgingHeaderChaining(rootModuleID, cache, allModules); + if (err) + Diagnostics.diagnose(SourceLoc(), diag::error_scanner_extra, + toString(std::move(err))); + } + return allModules.takeVector(); } @@ -611,19 +653,19 @@ ModuleDependencyScanner::resolveImportedModuleDependencies( resolveSwiftModuleDependencies(rootModuleID, cache, discoveredSwiftModules); allModules.insert(discoveredSwiftModules.begin(), discoveredSwiftModules.end()); - + ModuleDependencyIDSetVector discoveredClangModules; resolveAllClangModuleDependencies(discoveredSwiftModules.getArrayRef(), cache, discoveredClangModules); allModules.insert(discoveredClangModules.begin(), discoveredClangModules.end()); - + ModuleDependencyIDSetVector discoveredHeaderDependencyClangModules; resolveHeaderDependencies(discoveredSwiftModules.getArrayRef(), cache, discoveredHeaderDependencyClangModules); allModules.insert(discoveredHeaderDependencyClangModules.begin(), discoveredHeaderDependencyClangModules.end()); - + ModuleDependencyIDSetVector discoveredSwiftOverlayDependencyModules; resolveSwiftOverlayDependencies(discoveredSwiftModules.getArrayRef(), cache, discoveredSwiftOverlayDependencyModules); @@ -854,21 +896,23 @@ ModuleDependencyScanner::resolveAllClangModuleDependencies( return; } -void -ModuleDependencyScanner::resolveHeaderDependencies( +void ModuleDependencyScanner::resolveHeaderDependencies( ArrayRef allSwiftModules, ModuleDependenciesCache &cache, ModuleDependencyIDSetVector &allDiscoveredHeaderDependencyClangModules) { for (const auto &moduleID : allSwiftModules) { auto moduleDependencyInfo = cache.findKnownDependency(moduleID); if (!moduleDependencyInfo.getHeaderClangDependencies().empty()) { - allDiscoveredHeaderDependencyClangModules.insert(moduleDependencyInfo.getImportedSwiftDependencies().begin(), - moduleDependencyInfo.getImportedSwiftDependencies().end()); + allDiscoveredHeaderDependencyClangModules.insert( + moduleDependencyInfo.getHeaderClangDependencies().begin(), + moduleDependencyInfo.getHeaderClangDependencies().end()); } else { ModuleDependencyIDSetVector headerClangModuleDependencies; - resolveHeaderDependenciesForModule(moduleID, cache, headerClangModuleDependencies); - allDiscoveredHeaderDependencyClangModules.insert(headerClangModuleDependencies.begin(), - headerClangModuleDependencies.end()); + resolveHeaderDependenciesForModule(moduleID, cache, + headerClangModuleDependencies); + allDiscoveredHeaderDependencyClangModules.insert( + headerClangModuleDependencies.begin(), + headerClangModuleDependencies.end()); } } } @@ -1016,38 +1060,46 @@ void ModuleDependencyScanner::resolveHeaderDependenciesForModule( moduleDependencyInfo.isSwiftBinaryModule() && !moduleDependencyInfo.getAsSwiftBinaryModule()->headerImport.empty(); - if (isTextualModuleWithABridgingHeader || isBinaryModuleWithHeaderInput) { - withDependencyScanningWorker([&](ModuleDependencyScanningWorker - *ScanningWorker) { - auto clangImporter = static_cast( - ScanningWorker->clangScannerModuleLoader.get()); + if (!isTextualModuleWithABridgingHeader && !isBinaryModuleWithHeaderInput) + return; - std::vector headerFileInputs; - std::optional includeTreeID; - std::vector bridgingHeaderCommandLine; - auto headerScan = clangImporter->getHeaderDependencies(moduleID, ScanningWorker->clangScanningTool, cache, - headerClangModuleDependencies, headerFileInputs, - bridgingHeaderCommandLine, includeTreeID); - if (!headerScan) { - // Record direct header Clang dependencies - cache.setHeaderClangDependencies(moduleID, headerClangModuleDependencies.getArrayRef()); - // Record include Tree ID - if (includeTreeID.has_value()) - moduleDependencyInfo.addBridgingHeaderIncludeTree(*includeTreeID); - // Record the bridging header command line - if (isTextualModuleWithABridgingHeader) - moduleDependencyInfo.updateBridgingHeaderCommandLine(bridgingHeaderCommandLine); - for (const auto &headerInput : headerFileInputs) - moduleDependencyInfo.addHeaderSourceFile(headerInput); - // Update the dependency in the cache - cache.updateDependency(moduleID, moduleDependencyInfo); - } else { - // Failure to scan header - } - return true; - }); - cache.setHeaderClangDependencies(moduleID, headerClangModuleDependencies.getArrayRef()); - } + withDependencyScanningWorker( + [&](ModuleDependencyScanningWorker *ScanningWorker) { + auto clangImporter = static_cast( + ScanningWorker->clangScannerModuleLoader.get()); + + std::vector headerFileInputs; + std::optional includeTreeID; + std::vector bridgingHeaderCommandLine; + auto headerScan = clangImporter->getHeaderDependencies( + moduleID, + isTextualModuleWithABridgingHeader + ? *moduleDependencyInfo.getBridgingHeader() + : moduleDependencyInfo.getAsSwiftBinaryModule()->headerImport, + /*sourceBuffer=*/std::nullopt, ScanningWorker->clangScanningTool, + cache, headerClangModuleDependencies, headerFileInputs, + bridgingHeaderCommandLine, includeTreeID); + if (!headerScan) { + // Record direct header Clang dependencies + cache.setHeaderClangDependencies( + moduleID, headerClangModuleDependencies.getArrayRef()); + // Record include Tree ID + if (includeTreeID) + moduleDependencyInfo.addBridgingHeaderIncludeTree(*includeTreeID); + // Record the bridging header command line + if (isTextualModuleWithABridgingHeader) + moduleDependencyInfo.updateBridgingHeaderCommandLine( + bridgingHeaderCommandLine); + moduleDependencyInfo.setHeaderSourceFiles(headerFileInputs); + // Update the dependency in the cache + cache.updateDependency(moduleID, moduleDependencyInfo); + } else { + // Failure to scan header + } + return true; + }); + cache.setHeaderClangDependencies(moduleID, + headerClangModuleDependencies.getArrayRef()); } void ModuleDependencyScanner::resolveSwiftOverlayDependenciesForModule( @@ -1207,3 +1259,137 @@ void ModuleDependencyScanner::discoverCrossImportOverlayDependencies( std::for_each(/* +1 to exclude dummy main*/ allModules.begin() + 1, allModules.end(), action); } + +llvm::Error ModuleDependencyScanner::performBridgingHeaderChaining( + const ModuleDependencyID &rootModuleID, ModuleDependenciesCache &cache, + ModuleDependencyIDSetVector &allModules) { + if (rootModuleID.Kind != ModuleDependencyKind::SwiftSource) + return llvm::Error::success(); + + bool hasBridgingHeader = false; + llvm::vfs::OnDiskOutputBackend outputBackend; + + SmallString<256> outputPath( + ScanCompilerInvocation.getFrontendOptions().ScannerOutputDir); + + if (outputPath.empty()) + outputPath = "/"; + + llvm::sys::path::append( + outputPath, ScanCompilerInvocation.getFrontendOptions().ModuleName + "-" + + ScanCompilerInvocation.getModuleScanningHash() + + "-ChainedBridgingHeader.h"); + + llvm::SmallString<256> sourceBuf; + llvm::raw_svector_ostream outOS(sourceBuf); + + // Iterate through all the modules and collect all the bridging header + // and chain them into a single file. The allModules list is in the order of + // discover, thus providing stable ordering for a deterministic generated + // buffer. + auto FS = ScanASTContext.SourceMgr.getFileSystem(); + for (const auto &moduleID: allModules) { + if (moduleID.Kind != ModuleDependencyKind::SwiftSource && + moduleID.Kind != ModuleDependencyKind::SwiftBinary) + continue; + + auto moduleDependencyInfo = cache.findKnownDependency(moduleID); + if (auto *binaryMod = moduleDependencyInfo.getAsSwiftBinaryModule()) { + if (!binaryMod->headerImport.empty()) { + hasBridgingHeader = true; + if (FS->exists(binaryMod->headerImport)) { + outOS << "#include \"" << binaryMod->headerImport << "\"\n"; + } else { + // Extract the embedded bridging header + auto moduleBuf = FS->getBufferForFile(binaryMod->compiledModulePath); + if (!moduleBuf) + return llvm::errorCodeToError(moduleBuf.getError()); + + auto content = extractEmbeddedBridgingHeaderContent( + std::move(*moduleBuf), ScanASTContext); + if (content.empty()) + return llvm::createStringError("can't load embedded header from " + + binaryMod->compiledModulePath); + + outOS << content << "\n"; + } + } + } else if (auto *srcMod = moduleDependencyInfo.getAsSwiftSourceModule()) { + if (srcMod->textualModuleDetails.bridgingHeaderFile) { + hasBridgingHeader = true; + outOS << "#include \"" + << *srcMod->textualModuleDetails.bridgingHeaderFile << "\"\n"; + } + } + } + + if (!hasBridgingHeader) + return llvm::Error::success(); + + if (ScanCompilerInvocation.getFrontendOptions().WriteScannerOutput) { + auto outFile = outputBackend.createFile(outputPath); + if (!outFile) + return outFile.takeError(); + *outFile << sourceBuf; + if (auto err = outFile->keep()) + return err; + } + + auto sourceBuffer = + llvm::MemoryBuffer::getMemBufferCopy(sourceBuf, outputPath); + // Scan and update the main module dependency. + auto mainModuleDeps = cache.findKnownDependency(rootModuleID); + ModuleDependencyIDSetVector headerClangModuleDependencies; + std::optional includeTreeID; + auto err = withDependencyScanningWorker( + [&](ModuleDependencyScanningWorker *ScanningWorker) -> llvm::Error { + auto clangImporter = static_cast( + ScanningWorker->clangScannerModuleLoader.get()); + std::vector headerFileInputs; + std::vector bridgingHeaderCommandLine; + if (clangImporter->getHeaderDependencies( + rootModuleID, /*headerPath=*/std::nullopt, + sourceBuffer->getMemBufferRef(), + ScanningWorker->clangScanningTool, cache, + headerClangModuleDependencies, headerFileInputs, + bridgingHeaderCommandLine, includeTreeID)) + return llvm::createStringError( + "failed to scan generated bridging header " + outputPath); + + cache.setHeaderClangDependencies( + rootModuleID, headerClangModuleDependencies.getArrayRef()); + // Record include Tree ID + if (includeTreeID) { + // Save the old include tree ID inside the CAS for lookup. Old include + // tree can be used to create embedded header for the original + // bridging header. + if (auto embeddedHeaderIncludeTree = + mainModuleDeps.getBridgingHeaderIncludeTree()) { + if (auto err = ScanningWorker->createCacheKeyForEmbeddedHeader( + *embeddedHeaderIncludeTree, *includeTreeID)) + return err; + } + mainModuleDeps.addBridgingHeaderIncludeTree(*includeTreeID); + } + mainModuleDeps.updateBridgingHeaderCommandLine( + bridgingHeaderCommandLine); + mainModuleDeps.setHeaderSourceFiles(headerFileInputs); + mainModuleDeps.setChainedBridgingHeaderBuffer( + outputPath, sourceBuffer->getBuffer()); + // Update the dependency in the cache + cache.updateDependency(rootModuleID, mainModuleDeps); + return llvm::Error::success(); + }); + + if (err) + return err; + + cache.setHeaderClangDependencies(rootModuleID, + headerClangModuleDependencies.getArrayRef()); + + llvm::for_each( + headerClangModuleDependencies, + [&allModules](const ModuleDependencyID &dep) { allModules.insert(dep); }); + + return llvm::Error::success(); +} diff --git a/lib/DependencyScan/ScanDependencies.cpp b/lib/DependencyScan/ScanDependencies.cpp index 40efb94e4ab..25f8a26590e 100644 --- a/lib/DependencyScan/ScanDependencies.cpp +++ b/lib/DependencyScan/ScanDependencies.cpp @@ -707,9 +707,10 @@ generateFullDependencyGraph(const CompilerInstance &instance, create_clone(swiftTextualDeps->textualModuleDetails .CASBridgingHeaderIncludeTreeRootID.c_str()), create_clone(swiftTextualDeps->moduleCacheKey.c_str()), - createMacroDependencySet( - swiftTextualDeps->macroDependencies), - create_clone(swiftTextualDeps->userModuleVersion.c_str())}; + createMacroDependencySet(swiftTextualDeps->macroDependencies), + create_clone(swiftTextualDeps->userModuleVersion.c_str()), + /*chained_bridging_header_path=*/create_clone(""), + /*chained_bridging_header_content=*/create_clone("")}; } else if (swiftSourceDeps) { swiftscan_string_ref_t moduleInterfacePath = create_null(); swiftscan_string_ref_t bridgingHeaderPath = @@ -743,9 +744,11 @@ generateFullDependencyGraph(const CompilerInstance &instance, create_clone(swiftSourceDeps->textualModuleDetails .CASBridgingHeaderIncludeTreeRootID.c_str()), /*CacheKey*/ create_clone(""), - createMacroDependencySet( - swiftSourceDeps->macroDependencies), - /*userModuleVersion*/ create_clone("")}; + createMacroDependencySet(swiftSourceDeps->macroDependencies), + /*userModuleVersion*/ create_clone(""), + create_clone(swiftSourceDeps->chainedBridgingHeaderPath.c_str()), + create_clone( + swiftSourceDeps->chainedBridgingHeaderContent.c_str())}; } else if (swiftPlaceholderDeps) { details->kind = SWIFTSCAN_DEPENDENCY_INFO_SWIFT_PLACEHOLDER; details->swift_placeholder_details = { @@ -1320,6 +1323,7 @@ swift::dependencies::performModuleScan( auto topologicallySortedModuleList = computeTopologicalSortOfExplicitDependencies(allModules, cache); + resolveDependencyCommandLineArguments(instance, cache, topologicallySortedModuleList); resolveImplicitLinkLibraries(instance, cache); diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index 82d39d2a7d1..08b47d1eaf2 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -162,6 +162,9 @@ bool ArgsToFrontendOptionsConverter::convert( Opts.SerializedDependencyScannerCachePath = A->getValue(); } + Opts.ScannerOutputDir = Args.getLastArgValue(OPT_scanner_output_dir); + Opts.WriteScannerOutput |= Args.hasArg(OPT_scanner_debug_write_output); + Opts.DisableCrossModuleIncrementalBuild |= Args.hasArg(OPT_disable_incremental_imports); @@ -398,11 +401,11 @@ bool ArgsToFrontendOptionsConverter::convert( computeLLVMArgs(); Opts.EmitSymbolGraph |= Args.hasArg(OPT_emit_symbol_graph); - + if (const Arg *A = Args.getLastArg(OPT_emit_symbol_graph_dir)) { Opts.SymbolGraphOutputDir = A->getValue(); } - + Opts.SkipInheritedDocs = Args.hasArg(OPT_skip_inherited_docs); Opts.IncludeSPISymbolsInSymbolGraph = Args.hasArg(OPT_include_spi_symbols); @@ -883,12 +886,25 @@ bool ArgsToFrontendOptionsConverter::checkUnusedSupplementaryOutputPaths() return false; } +static inline bool isPCHFilenameExtension(StringRef path) { + return llvm::sys::path::extension(path) + .ends_with(file_types::getExtension(file_types::TY_PCH)); +} + void ArgsToFrontendOptionsConverter::computeImportObjCHeaderOptions() { using namespace options; if (const Arg *A = Args.getLastArgNoClaim(OPT_import_objc_header)) { - Opts.ImplicitObjCHeaderPath = A->getValue(); - Opts.SerializeBridgingHeader |= !Opts.InputsAndOutputs.hasPrimaryInputs(); + // Legacy support for passing PCH file through `-import-objc-header`. + if (isPCHFilenameExtension(A->getValue())) + Opts.ImplicitObjCPCHPath = A->getValue(); + else + Opts.ImplicitObjCHeaderPath = A->getValue(); + // If `-import-object-header` is used, it means the module has a direct + // bridging header dependency and it can be serialized into binary module. + Opts.SerializeBridgingHeader |= true; } + if (const Arg *A = Args.getLastArgNoClaim(OPT_import_pch)) + Opts.ImplicitObjCPCHPath = A->getValue(); } void ArgsToFrontendOptionsConverter:: computeImplicitImportModuleNames(OptSpecifier id, bool isTestable) { @@ -917,7 +933,7 @@ bool ModuleAliasesConverter::computeModuleAliases(std::vector args, // ModuleAliasMap should initially be empty as setting // it should be called only once options.ModuleAliasMap.clear(); - + auto validate = [&options, &diags](StringRef value, bool allowModuleName) -> bool { if (!allowModuleName) { @@ -935,14 +951,14 @@ bool ModuleAliasesConverter::computeModuleAliases(std::vector args, } return true; }; - + for (auto item: args) { auto str = StringRef(item); // splits to an alias and its real name auto pair = str.split('='); auto lhs = pair.first; auto rhs = pair.second; - + if (rhs.empty()) { // '=' is missing diags.diagnose(SourceLoc(), diag::error_module_alias_invalid_format, str); return false; @@ -950,7 +966,7 @@ bool ModuleAliasesConverter::computeModuleAliases(std::vector args, if (!validate(lhs, false) || !validate(rhs, true)) { return false; } - + // First, add the real name as a key to prevent it from being // used as an alias if (!options.ModuleAliasMap.insert({rhs, StringRef()}).second) { diff --git a/lib/Frontend/CompileJobCacheKey.cpp b/lib/Frontend/CompileJobCacheKey.cpp index f9ad2291644..bc9005e3d2f 100644 --- a/lib/Frontend/CompileJobCacheKey.cpp +++ b/lib/Frontend/CompileJobCacheKey.cpp @@ -16,6 +16,7 @@ #include "swift/Option/Options.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/CAS/CASReference.h" #include "llvm/CAS/HierarchicalTreeBuilder.h" #include "llvm/CAS/ObjectStore.h" #include "llvm/CAS/TreeEntry.h" diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 01fdeb8f42a..7e3b85b6134 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1029,7 +1029,7 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.EnableTargetOSChecking = A->getOption().matches(OPT_enable_target_os_checking); } - + Opts.EnableNewOperatorLookup = Args.hasFlag(OPT_enable_new_operator_lookup, OPT_disable_new_operator_lookup, /*default*/ false); @@ -1436,7 +1436,7 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, if (const Arg *A = Args.getLastArg(OPT_clang_target)) { Opts.ClangTarget = llvm::Triple(A->getValue()); } - + Opts.setCxxInteropFromArgs(Args, Diags); Opts.EnableObjCInterop = @@ -1486,7 +1486,7 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, auto getDefaultMinimumInliningTargetVersion = [&](const llvm::Triple &triple) -> llvm::VersionTuple { const auto targetVersion = getVersionTuple(triple); - + // In API modules, default to the version when Swift first became available. if (Opts.LibraryLevel == LibraryLevel::API) { if (auto minVersion = minimumAvailableOSVersionForTriple(triple)) @@ -1973,6 +1973,8 @@ static bool ParseClangImporterArgs(ClangImporterOptions &Opts, ArgList &Args, if (auto *A = Args.getLastArg(OPT_import_objc_header)) Opts.BridgingHeader = A->getValue(); + if (auto *A = Args.getLastArg(OPT_import_pch)) + Opts.BridgingHeaderPCH = A->getValue(); Opts.DisableSwiftBridgeAttr |= Args.hasArg(OPT_disable_swift_bridge_attr); Opts.DisableOverlayModules |= Args.hasArg(OPT_emit_imported_modules); @@ -2294,7 +2296,9 @@ static bool ParseSearchPathArgs(SearchPathOptions &Opts, ArgList &Args, Opts.ScannerModuleValidation |= Args.hasFlag(OPT_scanner_module_validation, OPT_no_scanner_module_validation, CASOpts.EnableCaching); - + Opts.BridgingHeaderChaining |= + Args.hasFlag(OPT_auto_bridging_header_chaining, + OPT_no_auto_bridging_header_chaining, false); bool buildingFromInterface = FrontendOpts.InputMode == FrontendOptions::ParseInputMode::SwiftModuleInterface; @@ -2993,7 +2997,7 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args, Opts.NoAllocations = Args.hasArg(OPT_no_allocations); - Opts.EnableExperimentalSwiftBasedClosureSpecialization = + Opts.EnableExperimentalSwiftBasedClosureSpecialization = Args.hasArg(OPT_enable_experimental_swift_based_closure_specialization); // If these optimizations are enabled never preserve functions for the diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index 967fa7a0388..0de8ffe3437 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -197,7 +197,13 @@ SerializationOptions CompilerInvocation::computeSerializationOptions( serializationOpts.SourceInfoOutputPath = outs.ModuleSourceInfoOutputPath; serializationOpts.GroupInfoPath = opts.GroupInfoPath.c_str(); if (opts.SerializeBridgingHeader && !outs.ModuleOutputPath.empty()) - serializationOpts.ImportedHeader = opts.ImplicitObjCHeaderPath; + serializationOpts.SerializeBridgingHeader = true; + // For batch mode, emit empty header path as placeholder. + if (serializationOpts.SerializeBridgingHeader && + opts.InputsAndOutputs.hasPrimaryInputs()) + serializationOpts.SerializeEmptyBridgingHeader = true; + serializationOpts.ImportedHeader = opts.ImplicitObjCHeaderPath; + serializationOpts.ImportedPCHPath = opts.ImplicitObjCPCHPath; serializationOpts.ModuleLinkName = opts.ModuleLinkName; serializationOpts.UserModuleVersion = opts.UserModuleVersion; serializationOpts.AllowableClients = opts.AllowableClients; @@ -317,7 +323,7 @@ bool CompilerInstance::setUpASTContextIfNeeded() { registerSILOptimizerRequestFunctions(Context->evaluator); registerTBDGenRequestFunctions(Context->evaluator); registerIRGenRequestFunctions(Context->evaluator); - + // Migrator, indexing and typo correction need some IDE requests. // The integrated REPL needs IDE requests for completion. if (Invocation.getMigratorOptions().shouldRunMigrator() || @@ -653,13 +659,13 @@ bool CompilerInstance::setUpVirtualFileSystemOverlays() { if (auto loadedBuffer = loadCachedCompileResultFromCacheKey( getObjectStore(), getActionCache(), Diagnostics, CASOpts.BridgingHeaderPCHCacheKey, file_types::ID::TY_PCH, - ClangOpts.BridgingHeader)) - MemFS->addFile(Invocation.getClangImporterOptions().BridgingHeader, 0, - std::move(loadedBuffer)); + ClangOpts.getPCHInputPath())) + MemFS->addFile(Invocation.getClangImporterOptions().getPCHInputPath(), + 0, std::move(loadedBuffer)); else Diagnostics.diagnose( SourceLoc(), diag::error_load_input_from_cas, - Invocation.getClangImporterOptions().BridgingHeader); + Invocation.getClangImporterOptions().getPCHInputPath()); } if (!CASOpts.InputFileKey.empty()) { if (Invocation.getFrontendOptions() @@ -903,14 +909,9 @@ SourceFile *CompilerInstance::getIDEInspectionFile() const { return evaluateOrDefault(eval, IDEInspectionFileRequest{mod}, nullptr); } -static inline bool isPCHFilenameExtension(StringRef path) { - return llvm::sys::path::extension(path) - .ends_with(file_types::getExtension(file_types::TY_PCH)); -} - std::string CompilerInstance::getBridgingHeaderPath() const { const FrontendOptions &opts = Invocation.getFrontendOptions(); - if (!isPCHFilenameExtension(opts.ImplicitObjCHeaderPath)) + if (opts.ImplicitObjCPCHPath.empty()) return opts.ImplicitObjCHeaderPath; auto clangImporter = @@ -920,7 +921,7 @@ std::string CompilerInstance::getBridgingHeaderPath() const { if (!clangImporter) return std::string(); - return clangImporter->getOriginalSourceFile(opts.ImplicitObjCHeaderPath); + return clangImporter->getOriginalSourceFile(opts.ImplicitObjCPCHPath); } bool CompilerInstance::setUpInputs() { @@ -1301,7 +1302,10 @@ ImplicitImportInfo CompilerInstance::getImplicitImportInfo() const { } imports.ShouldImportUnderlyingModule = frontendOpts.ImportUnderlyingModule; - imports.BridgingHeaderPath = frontendOpts.ImplicitObjCHeaderPath; + if (frontendOpts.ImplicitObjCPCHPath.empty()) + imports.BridgingHeaderPath = frontendOpts.ImplicitObjCHeaderPath; + else + imports.BridgingHeaderPath = frontendOpts.ImplicitObjCPCHPath; return imports; } diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index 1665e3262b5..314a610ad5d 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -156,7 +156,8 @@ ModuleFile::loadDependenciesForFileContext(const FileUnit *file, if (dependency.isHeader()) { // The path may be empty if the file being loaded is a partial AST, // and the current compiler invocation is a merge-modules step. - if (!dependency.Core.RawPath.empty()) { + if (!dependency.Core.RawPath.empty() && + !M->getASTContext().SearchPathOpts.BridgingHeaderChaining) { bool hadError = clangImporter->importHeader(dependency.Core.RawPath, file->getParentModule(), diff --git a/lib/Serialization/ModuleFileSharedCore.h b/lib/Serialization/ModuleFileSharedCore.h index 59e9ccbe4d6..001882a62ab 100644 --- a/lib/Serialization/ModuleFileSharedCore.h +++ b/lib/Serialization/ModuleFileSharedCore.h @@ -601,7 +601,7 @@ public: /// Outputs information useful for diagnostics to \p out void outputDiagnosticInfo(llvm::raw_ostream &os) const; - + // Out of line to avoid instantiation OnDiskChainedHashTable here. ~ModuleFileSharedCore(); @@ -653,6 +653,12 @@ public: return MacroModuleNames; } + /// Get embedded bridging header. + std::string getEmbeddedHeader() const { + // Don't include the '\0' in the end. + return importedHeaderInfo.contents.drop_back().str(); + } + /// If the module-defining `.swiftinterface` file is an SDK-relative path, /// resolve it to be absolute to the specified SDK. std::string resolveModuleDefiningFilePath(const StringRef SDKPath) const; diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 6b5e945e70a..78eb6ada8d4 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -1425,30 +1425,33 @@ void Serializer::writeInputBlock() { // Make sure the bridging header module is always at the top of the import // list, mimicking how it is processed before any module imports when // compiling source files. - if (llvm::is_contained(allLocalImports, bridgingHeaderImport)) { + if (llvm::is_contained(allLocalImports, bridgingHeaderImport) && + Options.SerializeBridgingHeader) { off_t importedHeaderSize = 0; time_t importedHeaderModTime = 0; std::string contents; - auto importedHeaderPath = Options.ImportedHeader; - std::string pchIncludeTree; - // We do not want to serialize the explicitly-specified .pch path if one was - // provided. Instead we write out the path to the original header source so - // that clients can consume it. - if (Options.ExplicitModuleBuild && - llvm::sys::path::extension(importedHeaderPath) - .ends_with(file_types::getExtension(file_types::TY_PCH))) { - auto *pch = clangImporter->getClangInstance() - .getASTReader() - ->getModuleManager() - .lookupByFileName(importedHeaderPath); - pchIncludeTree = pch->IncludeTreeID; - importedHeaderPath = pch->OriginalSourceFileName; - } + std::string importedHeaderPath; + if (!Options.SerializeEmptyBridgingHeader) { + importedHeaderPath = Options.ImportedHeader; + std::string pchIncludeTree; + // We do not want to serialize the explicitly-specified .pch path if one + // was provided. Instead we write out the path to the original header + // source so that clients can consume it. + if (!Options.ImportedPCHPath.empty()) { + auto *pch = clangImporter->getClangInstance() + .getASTReader() + ->getModuleManager() + .lookupByFileName(Options.ImportedPCHPath); + if (importedHeaderPath.empty()) + importedHeaderPath = pch->OriginalSourceFileName; + pchIncludeTree = pch->IncludeTreeID; + } - if (!importedHeaderPath.empty()) { - contents = clangImporter->getBridgingHeaderContents( - importedHeaderPath, importedHeaderSize, importedHeaderModTime, - pchIncludeTree); + if (!importedHeaderPath.empty()) { + contents = clangImporter->getBridgingHeaderContents( + importedHeaderPath, importedHeaderSize, importedHeaderModTime, + pchIncludeTree); + } } assert(publicImportSet.count(bridgingHeaderImport)); ImportedHeader.emit(ScratchRecord, @@ -1542,7 +1545,7 @@ static uint8_t getRawStableDefaultArgumentKind(swift::DefaultArgumentKind kind) llvm_unreachable("Unhandled DefaultArgumentKind in switch."); } -static uint8_t +static uint8_t getRawStableActorIsolationKind(swift::ActorIsolation::Kind kind) { switch (kind) { #define CASE(X) \ @@ -3452,14 +3455,14 @@ class Serializer::DeclSerializer : public DeclVisitor { case DeclAttrKind::RawLayout: { auto *attr = cast(DA); auto abbrCode = S.DeclTypeAbbrCodes[RawLayoutDeclAttrLayout::Code]; - + uint32_t rawSize; uint8_t rawAlign; TypeID typeID; TypeID countID; - + auto SD = const_cast(cast(D)); - + if (auto sizeAndAlign = attr->getSizeAndAlignment()) { typeID = 0; countID = 0; @@ -3480,7 +3483,7 @@ class Serializer::DeclSerializer : public DeclVisitor { } else { llvm_unreachable("unhandled raw layout attribute, or trying to serialize unresolved attr!"); } - + RawLayoutDeclAttrLayout::emitRecord( S.Out, S.ScratchRecord, abbrCode, attr->isImplicit(), typeID, countID, rawSize, rawAlign, attr->shouldMoveAsLikeType()); @@ -4102,7 +4105,7 @@ public: assert(typeRef >> (NumProtocolConformanceOptions+1) == originalTypeRef); (void)originalTypeRef; - + result.push_back(typeRef); } @@ -5523,7 +5526,7 @@ public: void visitBuiltinType(BuiltinType *ty) { visitBuiltinTypeImpl(ty); } - + void visitBuiltinFixedArrayType(BuiltinFixedArrayType *ty) { using namespace decls_block; unsigned abbrCode = S.DeclTypeAbbrCodes[BuiltinFixedArrayTypeLayout::Code]; diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index f6ebfd4c6fc..882ab39fcf0 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -41,6 +41,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/CommandLine.h" +#include #include #include @@ -1557,6 +1558,21 @@ swift::extractUserModuleVersionFromInterface(StringRef moduleInterfacePath) { return result; } +std::string swift::extractEmbeddedBridgingHeaderContent( + std::unique_ptr file, ASTContext &Context) { + std::shared_ptr loadedModuleFile; + serialization::ValidationInfo loadInfo = ModuleFileSharedCore::load( + "", "", std::move(file), nullptr, nullptr, false, + Context.SILOpts.EnableOSSAModules, Context.LangOpts.SDKName, + Context.SearchPathOpts.DeserializedPathRecoverer, + loadedModuleFile); + + if (loadInfo.status != serialization::Status::Valid) + return {}; + + return loadedModuleFile->getEmbeddedHeader(); +} + bool SerializedModuleLoaderBase::canImportModule( ImportPath::Module path, SourceLoc loc, ModuleVersionInfo *versionInfo, bool isTestableDependencyLookup) { diff --git a/lib/Tooling/libSwiftScan/libSwiftScan.cpp b/lib/Tooling/libSwiftScan/libSwiftScan.cpp index 3f407e1aaf0..c6b819c51c2 100644 --- a/lib/Tooling/libSwiftScan/libSwiftScan.cpp +++ b/lib/Tooling/libSwiftScan/libSwiftScan.cpp @@ -334,6 +334,18 @@ swiftscan_string_ref_t swiftscan_swift_textual_detail_get_user_module_version( return details->swift_textual_details.user_module_version; } +swiftscan_string_ref_t +swiftscan_swift_textual_detail_get_chained_bridging_header_path( + swiftscan_module_details_t details) { + return details->swift_textual_details.chained_bridging_header_path; +} + +swiftscan_string_ref_t +swiftscan_swift_textual_detail_get_chained_bridging_header_content( + swiftscan_module_details_t details) { + return details->swift_textual_details.chained_bridging_header_content; +} + //=== Swift Binary Module Details query APIs ------------------------------===// swiftscan_string_ref_t swiftscan_swift_binary_detail_get_compiled_module_path( @@ -570,7 +582,7 @@ swiftscan_scanner_diagnostics_query(swiftscan_scanner_t scanner) { swiftscan_diagnostic_set_t *Result = new swiftscan_diagnostic_set_t; Result->count = NumDiagnostics; Result->diagnostics = new swiftscan_diagnostic_info_t[NumDiagnostics]; - + for (size_t i = 0; i < NumDiagnostics; ++i) { const auto &Diagnostic = Diagnostics[i]; swiftscan_diagnostic_info_s *DiagnosticInfo = new swiftscan_diagnostic_info_s; diff --git a/lib/Tooling/libSwiftScan/libSwiftScan.exports b/lib/Tooling/libSwiftScan/libSwiftScan.exports index 96d63d6ee12..ce39f527f44 100644 --- a/lib/Tooling/libSwiftScan/libSwiftScan.exports +++ b/lib/Tooling/libSwiftScan/libSwiftScan.exports @@ -24,6 +24,8 @@ swiftscan_swift_textual_detail_get_swift_overlay_dependencies swiftscan_swift_textual_detail_get_cas_fs_root_id swiftscan_swift_textual_detail_get_module_cache_key swiftscan_swift_textual_detail_get_user_module_version +swiftscan_swift_textual_detail_get_chained_bridging_header_path +swiftscan_swift_textual_detail_get_chained_bridging_header_content swiftscan_swift_binary_detail_get_compiled_module_path swiftscan_swift_binary_detail_get_module_doc_path swiftscan_swift_binary_detail_get_module_source_info_path diff --git a/test/CAS/Inputs/BuildCommandExtractor.py b/test/CAS/Inputs/BuildCommandExtractor.py index c53a1820f93..7140e0193e7 100755 --- a/test/CAS/Inputs/BuildCommandExtractor.py +++ b/test/CAS/Inputs/BuildCommandExtractor.py @@ -8,13 +8,13 @@ import sys input_json = sys.argv[1] module_name = sys.argv[2] -mode = 'swift' +mode = "swift" -if module_name.startswith('clang:'): - mode = 'clang' +if module_name.startswith("clang:"): + mode = "clang" module_name = module_name[6:] -elif module_name.startswith('swiftPrebuiltExternal:'): - mode = 'swiftPrebuiltExternal' +elif module_name.startswith("swiftPrebuiltExternal:"): + mode = "swiftPrebuiltExternal" module_name = module_name[22:] @@ -23,16 +23,20 @@ def printCmd(cmd): print('"{}"'.format(c)) -with open(input_json, 'r') as file: +with open(input_json, "r") as file: deps = json.load(file) - if module_name == 'bridgingHeader': - cmd = deps['modules'][1]['details']['swift']['bridgingHeader']['commandLine'] + if module_name == "bridgingHeader": + info = deps["modules"][1]["details"]["swift"] + # the first argument is `-frontend` + cmd = info["bridgingHeader"]["commandLine"][1:] printCmd(cmd) + # print input file name. + print(info["chainedBridgingHeaderPath"]) else: - module_names = deps['modules'][::2] - module_details = deps['modules'][1::2] + module_names = deps["modules"][::2] + module_details = deps["modules"][1::2] for name, detail in zip(module_names, module_details): - if name.get(mode, '') != module_name: + if name.get(mode, "") != module_name: continue - printCmd(detail['details'][mode]['commandLine']) + printCmd(detail["details"][mode]["commandLine"]) diff --git a/test/CAS/Inputs/ExtractOutputKey.py b/test/CAS/Inputs/ExtractOutputKey.py index 0ebac5bc319..7a7e35c335d 100755 --- a/test/CAS/Inputs/ExtractOutputKey.py +++ b/test/CAS/Inputs/ExtractOutputKey.py @@ -6,12 +6,15 @@ import json import sys input_json = sys.argv[1] -input_path = sys.argv[2] with open(input_json, 'r') as file: entries = json.load(file) + if len(sys.argv) == 2: + print(entries[0]['CacheKey']) + exit(0) + for entry in entries: - if entry['Input'] != input_path: + if entry['Input'] != sys.argv[2]: continue print(entry['CacheKey']) diff --git a/test/CAS/bridging-header.swift b/test/CAS/bridging-header.swift index bc0691e9af0..b0bdb8db75a 100644 --- a/test/CAS/bridging-header.swift +++ b/test/CAS/bridging-header.swift @@ -2,14 +2,9 @@ // RUN: %empty-directory(%t) // RUN: split-file %s %t -// RUN: %target-swift-frontend -emit-module -o %t/temp.swiftmodule -module-name Test -swift-version 5 \ -// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \ -// RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap -import-objc-header %t/Bridging.h \ -// RUN: %t/test.swift - // RUN: %target-swift-frontend -scan-dependencies -module-name Test -module-cache-path %t/clang-module-cache -O \ // 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 \ +// RUN: %t/test.swift -o %t/deps.json -auto-bridging-header-chaining -cache-compile-job -cas-path %t/cas \ // RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap -import-objc-header %t/Bridging.h // RUN: %{python} %S/Inputs/SwiftDepsExtractor.py %t/deps.json Test bridgingHeader | %FileCheck %s @@ -23,13 +18,13 @@ // CHECK: "-dwarf-ext-refs" // CHECK: "-fmodule-file-cache-key", // CHECK-NEXT: "-Xcc", -// CHECK-NEXT: "{{.*}}{{/|\\}}A-{{.*}}.pcm", +// CHECK-NEXT: "{{.*}}{{/|\\}}A-{{.*}}.pcm", // CHECK-NEXT: "-Xcc", -// CHECK-NEXT: "llvmcas://{{.*}}", +// CHECK-NEXT: "llvmcas://{{.*}}", // CHECK-NEXT: "-Xcc", // CHECK-NEXT: "-fmodule-file-cache-key", // CHECK-NEXT: "-Xcc", -// CHECK-NEXT: "{{.*}}{{/|\\}}B-{{.*}}.pcm", +// CHECK-NEXT: "{{.*}}{{/|\\}}B-{{.*}}.pcm", // CHECK-NEXT: "-Xcc", // CHECK-NEXT: "llvmcas://{{.*}}" @@ -45,17 +40,19 @@ // RUN: %{python} %S/Inputs/GenerateExplicitModuleMap.py %t/deps.json > %t/map.json // RUN: llvm-cas --cas %t/cas --make-blob --data %t/map.json > %t/map.casid -// 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 %t/Bridging.h -O -o %t/bridging.pch +// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json bridgingHeader > %t/header.cmd +// RUN: %target-swift-frontend @%t/header.cmd -disable-implicit-swift-modules -O -o %t/bridging.pch // RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-output-keys -- \ -// RUN: %target-swift-frontend @%t/header.cmd -disable-implicit-swift-modules %t/Bridging.h -O -o %t/bridging.pch > %t/keys.json -// RUN: %{python} %S/Inputs/ExtractOutputKey.py %t/keys.json %t/Bridging.h > %t/key +// RUN: %target-swift-frontend @%t/header.cmd -disable-implicit-swift-modules -O -o %t/bridging.pch > %t/keys.json +// RUN: %{python} %S/Inputs/ExtractOutputKey.py %t/keys.json > %t/key // RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json Test > %t/MyApp.cmd // RUN: echo "\"-disable-implicit-string-processing-module-import\"" >> %t/MyApp.cmd // RUN: echo "\"-disable-implicit-concurrency-module-import\"" >> %t/MyApp.cmd // RUN: echo "\"-disable-implicit-swift-modules\"" >> %t/MyApp.cmd // RUN: echo "\"-import-objc-header\"" >> %t/MyApp.cmd +// RUN: echo "\"%t/Bridging.h\"" >> %t/MyApp.cmd +// RUN: echo "\"-import-pch\"" >> %t/MyApp.cmd // RUN: echo "\"%t/bridging.pch\"" >> %t/MyApp.cmd // RUN: echo "\"-bridging-header-pch-key\"" >> %t/MyApp.cmd // RUN: echo "\"@%t/key\"" >> %t/MyApp.cmd @@ -67,25 +64,134 @@ /// Importing binary module with bridging header built from CAS from a regluar build. /// This should succeed even it is also importing a bridging header that shares same header dependencies (with proper header guard). -// RUN: %target-swift-frontend -typecheck -module-name User -swift-version 5 \ +// RUN: %target-swift-frontend -typecheck -module-name User -O \ // RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \ // RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap \ -// RUN: -I %t %t/user.swift -import-objc-header %t/Bridging2.h +// RUN: -I %t %t/user2.swift -import-objc-header %t/Bridging2.h /// Importing binary module with bridging header built from CAS from a cached build. This should work without additional bridging header deps. // RUN: %target-swift-frontend -scan-dependencies -module-name User -module-cache-path %t/clang-module-cache -O \ // RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \ -// RUN: %t/user.swift -o %t/deps2.json -swift-version 5 -cache-compile-job -cas-path %t/cas \ +// RUN: %t/user.swift -o %t/deps2.json -auto-bridging-header-chaining -cache-compile-job -cas-path %t/cas \ // RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap -I %t +// RUN: %{python} %S/Inputs/SwiftDepsExtractor.py %t/deps2.json User chainedBridgingHeaderPath | %FileCheck %s --check-prefix HEADER-PATH +// HEADER-PATH: {{/|\\}}User-{{.*}}-ChainedBridgingHeader.h + +// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps2.json bridgingHeader > %t/header1.cmd +// RUN: %target-swift-frontend @%t/header1.cmd -disable-implicit-swift-modules -O -o %t/bridging1.pch + +// RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-output-keys -- \ +// RUN: %target-swift-frontend @%t/header1.cmd -disable-implicit-swift-modules -O -o %t/bridging1.pch > %t/keys1.json +// RUN: %{python} %S/Inputs/ExtractOutputKey.py %t/keys1.json > %t/key1 + // RUN: %{python} %S/Inputs/GenerateExplicitModuleMap.py %t/deps2.json > %t/map2.json // RUN: llvm-cas --cas %t/cas --make-blob --data %t/map2.json > %t/map2.casid // RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps2.json User > %t/User.cmd // RUN: %target-swift-frontend -cache-compile-job -module-name User -O -cas-path %t/cas \ // RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -disable-implicit-swift-modules \ +// RUN: -import-pch %t/bridging1.pch -bridging-header-pch-key @%t/key1 \ // RUN: -explicit-swift-module-map-file @%t/map2.casid @%t/User.cmd %t/user.swift \ // RUN: -emit-module -o %t/User.swiftmodule +// RUN: llvm-bcanalyzer -dump %t/User.swiftmodule | %FileCheck %s --check-prefix CHECK-NO-HEADER +// CHECK-NO-HEADER-NOT: %t/shim2.cmd +// RUN: %swift_frontend_plain @%t/shim2.cmd +// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps3.json clang:B > %t/B2.cmd +// RUN: %swift_frontend_plain @%t/B2.cmd +// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps3.json clang:A > %t/A2.cmd +// RUN: %swift_frontend_plain @%t/A2.cmd +// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps3.json bridgingHeader > %t/header2.cmd +// RUN: %target-swift-frontend @%t/header2.cmd -disable-implicit-swift-modules -O -o %t/bridging2.pch + +// RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-output-keys -- \ +// RUN: %target-swift-frontend @%t/header2.cmd -disable-implicit-swift-modules -O -o %t/bridging2.pch > %t/keys2.json +// RUN: %{python} %S/Inputs/ExtractOutputKey.py %t/keys2.json > %t/key2 + +// RUN: %{python} %S/Inputs/GenerateExplicitModuleMap.py %t/deps3.json > %t/map3.json +// RUN: llvm-cas --cas %t/cas --make-blob --data %t/map3.json > %t/map3.casid +// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps3.json User > %t/User2.cmd +// RUN: echo "\"-import-objc-header\"" >> %t/User2.cmd +// RUN: echo "\"%t/Bridging2.h\"" >> %t/User2.cmd +// RUN: echo "\"-import-pch\"" >> %t/User2.cmd +// RUN: echo "\"%t/bridging2.pch\"" >> %t/User2.cmd +// RUN: echo "\"-bridging-header-pch-key\"" >> %t/User2.cmd +// RUN: echo "\"@%t/key2\"" >> %t/User2.cmd + +// RUN: %target-swift-frontend -cache-compile-job -module-name User -O -cas-path %t/cas \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -disable-implicit-swift-modules \ +// RUN: -explicit-swift-module-map-file @%t/map3.casid @%t/User2.cmd %t/user2.swift \ +// RUN: -emit-module -o %t/User2.swiftmodule + +// RUN: %target-swift-frontend -scan-dependencies -module-name User -O \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \ +// RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap \ +// RUN: -I %t %t/user2.swift -import-objc-header %t/Bridging3.h -cache-compile-job -cas-path %t/cas \ +// RUN: -o %t/deps4.json -auto-bridging-header-chaining +// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps4.json bridgingHeader > %t/header3.cmd +// RUN: %target-swift-frontend @%t/header3.cmd -disable-implicit-swift-modules -O -o %t/bridging3.pch + +// RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-output-keys -- \ +// RUN: %target-swift-frontend @%t/header3.cmd -disable-implicit-swift-modules -O -o %t/bridging3.pch > %t/keys3.json +// RUN: %{python} %S/Inputs/ExtractOutputKey.py %t/keys3.json > %t/key3 + +// RUN: %{python} %S/Inputs/GenerateExplicitModuleMap.py %t/deps4.json > %t/map4.json +// RUN: llvm-cas --cas %t/cas --make-blob --data %t/map4.json > %t/map4.casid +// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps4.json User > %t/User3.cmd +// RUN: echo "\"-import-pch\"" >> %t/User3.cmd +// RUN: echo "\"%t/bridging3.pch\"" >> %t/User3.cmd +// RUN: echo "\"-import-objc-header\"" >> %t/User3.cmd +// RUN: echo "\"%t/Bridging3.h\"" >> %t/User3.cmd +// RUN: echo "\"-bridging-header-pch-key\"" >> %t/User3.cmd +// RUN: echo "\"@%t/key3\"" >> %t/User3.cmd + +// RUN: %target-swift-frontend -cache-compile-job -module-name User -O -cas-path %t/cas \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -disable-implicit-swift-modules \ +// RUN: -explicit-swift-module-map-file @%t/map4.casid @%t/User3.cmd %t/user2.swift \ +// RUN: -emit-module -o %t/User3.swiftmodule + +/// Verify the encoded here is just the `-import-objc-header` option. +// RUN: llvm-bcanalyzer -dump %t/User3.swiftmodule | %FileCheck %s --check-prefix CHECK-HEADER +// CHECK-HEADER: %t/header4.cmd +// RUN: %target-swift-frontend @%t/header4.cmd -disable-implicit-swift-modules -O -o %t/bridging4.pch + +// RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-output-keys -- \ +// RUN: %target-swift-frontend @%t/header4.cmd -disable-implicit-swift-modules -O -o %t/bridging4.pch > %t/keys4.json +// RUN: %{python} %S/Inputs/ExtractOutputKey.py %t/keys4.json > %t/key4 + +// RUN: %{python} %S/Inputs/GenerateExplicitModuleMap.py %t/deps5.json > %t/map5.json +// RUN: llvm-cas --cas %t/cas --make-blob --data %t/map5.json > %t/map5.casid +// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps5.json User > %t/User4.cmd +// RUN: echo "\"-import-pch\"" >> %t/User4.cmd +// RUN: echo "\"%t/bridging4.pch\"" >> %t/User4.cmd +// RUN: echo "\"-import-objc-header\"" >> %t/User4.cmd +// RUN: echo "\"%t/Bridging4.h\"" >> %t/User4.cmd +// RUN: echo "\"-bridging-header-pch-key\"" >> %t/User4.cmd +// RUN: echo "\"@%t/key4\"" >> %t/User4.cmd + +// RUN: %target-swift-frontend -cache-compile-job -module-name User -O -cas-path %t/cas \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -disable-implicit-swift-modules \ +// RUN: -explicit-swift-module-map-file @%t/map5.casid @%t/User4.cmd %t/user2.swift \ +// RUN: -emit-module -o %t/User5.swiftmodule + //--- test.swift public func test() { b() @@ -104,6 +210,19 @@ extension A { public func testA() {} } +//--- user2.swift +import Test + +func user() { + var b: TestB + var bridging: Bridging2 + test() +} + +extension Bridging2 { + public func testA() {} +} + //--- Bridging.h #include "Foo.h" @@ -112,13 +231,25 @@ extension A { //--- Bridging2.h #include "Foo.h" #include "Foo2.h" +@interface Bridging2 +@end + +//--- Bridging3.h +@interface Bridging2 +@end //--- Foo.h #import "a.h" +#ifndef IMPORT_FOO +#define IMPORT_FOO +int Foo = 0; +#endif //--- Foo2.h -#pragma once -int Foo = 0; +#ifndef IMPORT_FOO2 +#define IMPORT_FOO2 +int Foo2 = 0; +#endif //--- a.h #include "b.h" diff --git a/test/CAS/cached_diagnostics.swift b/test/CAS/cached_diagnostics.swift index 65d0820ae58..8f5422f34c8 100644 --- a/test/CAS/cached_diagnostics.swift +++ b/test/CAS/cached_diagnostics.swift @@ -1,17 +1,17 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -scan-dependencies -module-name Test -O -import-objc-header %S/Inputs/objc.h \ +// RUN: %target-swift-frontend -scan-dependencies -module-name Test -O -import-objc-header %S/Inputs/objc.h -auto-bridging-header-chaining \ // 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 -module-load-mode prefer-serialized +// RUN: %s -o %t/deps.json -cache-compile-job -cas-path %t/cas -module-load-mode prefer-serialized -scanner-output-dir %t // 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 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 +// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json bridgingHeader > %t/header.cmd +// RUN: %target-swift-frontend @%t/header.cmd -disable-implicit-swift-modules -O -o %t/objc.pch 2>&1 | %FileCheck %s -check-prefix CHECK-BRIDGE // RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-output-keys -- \ -// RUN: %target-swift-frontend @%t/header.cmd -disable-implicit-swift-modules %S/Inputs/objc.h -O -o %t/objc.pch > %t/keys.json -// RUN: %{python} %S/Inputs/ExtractOutputKey.py %t/keys.json %S/Inputs/objc.h > %t/key +// RUN: %target-swift-frontend @%t/header.cmd -disable-implicit-swift-modules -O -o %t/objc.pch > %t/keys.json +// RUN: %{python} %S/Inputs/ExtractOutputKey.py %t/keys.json > %t/key // RUN: %{python} %S/Inputs/GenerateExplicitModuleMap.py %t/deps.json > %t/map.json // RUN: llvm-cas --cas %t/cas --make-blob --data %t/map.json > %t/map.casid diff --git a/test/CAS/cached_diagnostics_remap.swift b/test/CAS/cached_diagnostics_remap.swift index b052f6283cb..8d80802a0d2 100644 --- a/test/CAS/cached_diagnostics_remap.swift +++ b/test/CAS/cached_diagnostics_remap.swift @@ -2,19 +2,19 @@ // RUN: split-file %s %t /// Check path remapping. -// RUN: %target-swift-frontend -scan-dependencies -module-name Test -O -import-objc-header %t/objc.h \ +// RUN: %target-swift-frontend -scan-dependencies -module-name Test -O -import-objc-header %t/objc.h -auto-bridging-header-chaining \ // RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \ -// RUN: %t/test.swift -o %t/deps.json -cache-compile-job -cas-path %t/cas -scanner-prefix-map %t=/^test +// RUN: %t/test.swift -o %t/deps.json -cache-compile-job -cas-path %t/cas -scanner-prefix-map %t=/^test -scanner-output-dir %t.noremap -// 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 /^test/objc.h -O -o %t/objc.pch 2>&1 | %FileCheck %s -check-prefix BRIDGE +// RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json bridgingHeader > %t/header.cmd +// RUN: %target-swift-frontend @%t/header.cmd -disable-implicit-swift-modules -O -o %t/objc.pch 2>&1 | %FileCheck %s -check-prefix BRIDGE // RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-output-keys -- \ -// RUN: %target-swift-frontend @%t/header.cmd -disable-implicit-swift-modules /^test/objc.h -O -o %t/objc.pch > %t/keys.json +// RUN: %target-swift-frontend @%t/header.cmd -disable-implicit-swift-modules -O -o %t/objc.pch > %t/keys.json // RUN: %cache-tool -cas-path %t/cas -cache-tool-action render-diags %t/keys.json -- \ -// RUN: %target-swift-frontend @%t/header.cmd -disable-implicit-swift-modules /^test/objc.h -O -o %t/objc.pch -cache-replay-prefix-map /^test=%t 2>&1 \ +// RUN: %target-swift-frontend @%t/header.cmd -disable-implicit-swift-modules -O -o %t/objc.pch -cache-replay-prefix-map /^test=%t 2>&1 \ // RUN: | %FileCheck %s -check-prefix BRIDGE -check-prefix BRIDGE-REMAP -// RUN: %{python} %S/Inputs/ExtractOutputKey.py %t/keys.json /^test/objc.h > %t/key +// RUN: %{python} %S/Inputs/ExtractOutputKey.py %t/keys.json > %t/key // RUN: %{python} %S/Inputs/BuildCommandExtractor.py %t/deps.json Test > %t/MyApp.cmd // RUN: echo "\"-disable-implicit-string-processing-module-import\"" >> %t/MyApp.cmd @@ -33,7 +33,7 @@ // RUN: -emit-module -o %t/test.swiftmodule /^test/test.swift > %t/cache_key.json // RUN: %cache-tool -cas-path %t/cas -cache-tool-action render-diags %t/cache_key.json -- %target-swift-frontend -cache-compile-job -module-name Test \ // RUN: -O -cas-path %t/cas @%t/MyApp.cmd \ -// RUN: -emit-module -o %t/test.swiftmodule /^test/test.swift -cache-replay-prefix-map /^test=%t 2>&1 | %FileCheck %s --check-prefix REMAP +// RUN: -emit-module -o %t/test.swiftmodule /^test/test.swift -cache-replay-prefix-map /^test=%t 2>&1 | %FileCheck %s --check-prefix REMAP // BRIDGE: /^test/objc.h:3:2: warning: warning in bridging header // BRIDGE-REMAP: BUILD_DIR{{.*}}{{/|\\}}objc.h:3:2: warning: warning in bridging header diff --git a/test/CAS/deps_cas_fs.swift b/test/CAS/deps_cas_fs.swift index 7e96b2a979a..c3188495036 100644 --- a/test/CAS/deps_cas_fs.swift +++ b/test/CAS/deps_cas_fs.swift @@ -7,7 +7,7 @@ // RUN: mkdir -p %t/resource/macosx // RUN: cp %S/../IRGen/Inputs/legacy_type_info/a.yaml %t/resource/macosx/layouts-x86_64.yaml -// 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 -module-name Test -resource-dir %t/resource +// 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 -module-name Test -resource-dir %t/resource -scanner-output-dir %t // Check the contents of the JSON output // RUN: %validate-json %t/deps.json &>/dev/null diff --git a/test/CAS/module_deps.swift b/test/CAS/module_deps.swift index 378b76df863..509f3d2984b 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-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 -enable-cross-import-overlays -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 -enable-cross-import-overlays -cache-compile-job -cas-path %t/cas -no-clang-include-tree -scanner-output-dir %t -auto-bridging-header-chaining // 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,7 +15,7 @@ // Check the make-style dependencies file // RUN: %FileCheck %s -check-prefix CHECK-MAKE-DEPS < %t/deps.d -// 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 -enable-cross-import-overlays -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 -enable-cross-import-overlays -cache-compile-job -cas-path %t/cas -no-clang-include-tree -scanner-output-dir %t -auto-bridging-header-chaining // RUN: %validate-json %t/deps.json &>/dev/null // RUN: %FileCheck -check-prefix CHECK -check-prefix CHECK_NO_CLANG_TARGET %s < %t/deps.json @@ -79,6 +79,7 @@ import SubE // CHECK-SAME: Bridging.h // CHECK-NEXT: "sourceFiles": +// CHECK-NEXT: ChainedBridgingHeader.h // CHECK-NEXT: Bridging.h // CHECK-NEXT: BridgingOther.h @@ -118,7 +119,6 @@ import SubE // CHECK-MAKE-DEPS-SAME: A.swiftinterface // CHECK-MAKE-DEPS-SAME: G.swiftinterface // CHECK-MAKE-DEPS-SAME: B.h -// CHECK-MAKE-DEPS-SAME: F.h // CHECK-MAKE-DEPS-SAME: Bridging.h // CHECK-MAKE-DEPS-SAME: BridgingOther.h // CHECK-MAKE-DEPS-SAME: module.modulemap diff --git a/test/CAS/module_deps_include_tree.swift b/test/CAS/module_deps_include_tree.swift index 7e72cda071b..711d84a6808 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-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 -enable-cross-import-overlays -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 -enable-cross-import-overlays -cache-compile-job -cas-path %t/cas -auto-bridging-header-chaining // Check the contents of the JSON output // RUN: %FileCheck %s -check-prefix CHECK -check-prefix CHECK-NO-SEARCH-PATHS < %t/deps.json @@ -12,10 +12,10 @@ // Check the make-style dependencies file // RUN: %FileCheck %s -check-prefix CHECK-MAKE-DEPS < %t/deps.d -// 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 -enable-cross-import-overlays -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 -enable-cross-import-overlays -cache-compile-job -cas-path %t/cas -auto-bridging-header-chaining // 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-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 -enable-cross-import-overlays -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 -enable-cross-import-overlays -clang-target %target-cpu-apple-macosx10.14 -cache-compile-job -cas-path %t/cas -auto-bridging-header-chaining /// check cas-fs content // RUN: %{python} %S/Inputs/SwiftDepsExtractor.py %t/deps.json E casFSRootID > %t/E_fs.casid @@ -73,6 +73,7 @@ import SubE // CHECK-SAME: Bridging.h // CHECK-NEXT: "sourceFiles": +// CHECK-NEXT: ChainedBridgingHeader.h // CHECK-NEXT: Bridging.h // CHECK-NEXT: BridgingOther.h @@ -119,7 +120,6 @@ import SubE // CHECK-MAKE-DEPS-SAME: A.swiftinterface // CHECK-MAKE-DEPS-SAME: G.swiftinterface // CHECK-MAKE-DEPS-SAME: B.h -// CHECK-MAKE-DEPS-SAME: F.h // CHECK-MAKE-DEPS-SAME: Bridging.h // CHECK-MAKE-DEPS-SAME: BridgingOther.h // CHECK-MAKE-DEPS-SAME: module.modulemap diff --git a/test/CAS/module_path_remap.swift b/test/CAS/module_path_remap.swift index fe9b936f5a1..a8691ec8a09 100644 --- a/test/CAS/module_path_remap.swift +++ b/test/CAS/module_path_remap.swift @@ -7,7 +7,7 @@ // RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json \ // RUN: -I %S/../ScanDependencies/Inputs/CHeaders -I %S/../ScanDependencies/Inputs/Swift -emit-dependencies \ // RUN: -import-objc-header %S/../ScanDependencies/Inputs/CHeaders/Bridging.h -swift-version 4 -cache-compile-job \ -// RUN: -cas-path %t/cas -scanner-prefix-map %swift_src_root=/^src -scanner-prefix-map %t=/^tmp +// RUN: -cas-path %t/cas -scanner-prefix-map %swift_src_root=/^src -scanner-prefix-map %t=/^tmp -scanner-output-dir %t -auto-bridging-header-chaining // RUN: %{python} %S/Inputs/SwiftDepsExtractor.py %t/deps.json deps casFSRootID > %t/deps.fs.casid // RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-include-tree-list @%t/deps.fs.casid | %FileCheck %s -check-prefix DEPS-FS diff --git a/test/CAS/plugin_cas.swift b/test/CAS/plugin_cas.swift index 04bbb3dbf8d..735fc133d5b 100644 --- a/test/CAS/plugin_cas.swift +++ b/test/CAS/plugin_cas.swift @@ -8,7 +8,7 @@ // 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 -enable-cross-import-overlays -cache-compile-job \ -// RUN: -cas-path %t/cas \ +// RUN: -cas-path %t/cas -scanner-output-dir %t -auto-bridging-header-chaining \ // RUN: -cas-plugin-path %llvm_libs_dir/libCASPluginTest%llvm_plugin_ext \ // RUN: -cas-plugin-option first-prefix=myfirst- -cas-plugin-option second-prefix=mysecond- \ // RUN: -cas-plugin-option upstream-path=%t/cas-upstream @@ -27,7 +27,7 @@ // 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 -enable-cross-import-overlays -clang-target %target-cpu-apple-macosx10.14 -cache-compile-job \ -// RUN: -cas-path %t/cas \ +// RUN: -cas-path %t/cas -scanner-output-dir %t -auto-bridging-header-chaining \ // RUN: -cas-plugin-path %llvm_libs_dir/libCASPluginTest%llvm_plugin_ext \ // RUN: -cas-plugin-option first-prefix=myfirst- -cas-plugin-option second-prefix=mysecond- \ // RUN: -cas-plugin-option upstream-path=%t/cas-upstream @@ -62,6 +62,7 @@ import SubE // CHECK-SAME: Bridging.h // CHECK-NEXT: "sourceFiles": +// CHECK-NEXT: ChainedBridgingHeader.h // CHECK-NEXT: Bridging.h // CHECK-NEXT: BridgingOther.h @@ -102,7 +103,6 @@ import SubE // CHECK-MAKE-DEPS-SAME: A.swiftinterface // CHECK-MAKE-DEPS-SAME: G.swiftinterface // CHECK-MAKE-DEPS-SAME: B.h -// CHECK-MAKE-DEPS-SAME: F.h // CHECK-MAKE-DEPS-SAME: Bridging.h // CHECK-MAKE-DEPS-SAME: BridgingOther.h // CHECK-MAKE-DEPS-SAME: module.modulemap diff --git a/test/ScanDependencies/bridging-header-autochaining.swift b/test/ScanDependencies/bridging-header-autochaining.swift new file mode 100644 index 00000000000..f986366b30b --- /dev/null +++ b/test/ScanDependencies/bridging-header-autochaining.swift @@ -0,0 +1,242 @@ +// REQUIRES: objc_interop +// RUN: %empty-directory(%t) +// RUN: split-file %s %t + +// RUN: %target-swift-frontend -scan-dependencies -module-name Test -module-cache-path %t/clang-module-cache -O \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \ +// RUN: %t/test.swift -o %t/deps.json -auto-bridging-header-chaining -scanner-output-dir %t -scanner-debug-write-output \ +// RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap -import-objc-header %t/Bridging.h + +// RUN: %{python} %S/../CAS/Inputs/SwiftDepsExtractor.py %t/deps.json Test bridgingHeader | %FileCheck %s + +// CHECK: "moduleDependencies": [ +// CHECK-NEXT: "A" +// CHECK-NEXT: ], + +/// Try build then import from a non-caching compilation. + +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps.json clang:SwiftShims > %t/shim.cmd +// RUN: %swift_frontend_plain @%t/shim.cmd +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps.json Swift > %t/swift.cmd +// RUN: %swift_frontend_plain @%t/swift.cmd +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps.json clang:B > %t/B.cmd +// RUN: %swift_frontend_plain @%t/B.cmd +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps.json clang:A > %t/A.cmd +// RUN: %swift_frontend_plain @%t/A.cmd + +// RUN: %{python} %S/../CAS/Inputs/GenerateExplicitModuleMap.py %t/deps.json > %t/map.json + +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps.json bridgingHeader > %t/header.cmd +// RUN: %target-swift-frontend @%t/header.cmd -disable-implicit-swift-modules -O -o %t/bridging.pch + +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps.json Test > %t/MyApp.cmd +// RUN: echo "\"-disable-implicit-string-processing-module-import\"" >> %t/MyApp.cmd +// RUN: echo "\"-disable-implicit-concurrency-module-import\"" >> %t/MyApp.cmd +// RUN: echo "\"-disable-implicit-swift-modules\"" >> %t/MyApp.cmd +// RUN: echo "\"-import-objc-header\"" >> %t/MyApp.cmd +// RUN: echo "\"%t/Bridging.h\"" >> %t/MyApp.cmd +// RUN: echo "\"-import-pch\"" >> %t/MyApp.cmd +// RUN: echo "\"%t/bridging.pch\"" >> %t/MyApp.cmd +// RUN: echo "\"-explicit-swift-module-map-file\"" >> %t/MyApp.cmd +// RUN: echo "\"%t/map.json\"" >> %t/MyApp.cmd + +// RUN: %target-swift-frontend -module-name Test -O @%t/MyApp.cmd %t/test.swift \ +// RUN: -emit-module -o %t/Test.swiftmodule + +/// Importing binary module with bridging header built from CAS from a regluar build. +/// This should succeed even it is also importing a bridging header that shares same header dependencies (with proper header guard). +// RUN: %target-swift-frontend -typecheck -module-name User \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \ +// RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap \ +// RUN: -I %t %t/user2.swift -import-objc-header %t/Bridging2.h + +/// Importing binary module with bridging header built from CAS from a cached build. This should work without additional bridging header deps. +// RUN: %target-swift-frontend -scan-dependencies -module-name User -module-cache-path %t/clang-module-cache -O \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \ +// RUN: %t/user.swift -o %t/deps2.json -auto-bridging-header-chaining -scanner-output-dir %t -scanner-debug-write-output \ +// RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap -I %t + +// RUN: %swift-scan-test -action get_chained_bridging_header -- %target-swift-frontend -emit-module \ +// RUN: -module-name User -module-cache-path %t/clang-module-cache -O \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \ +// RUN: %t/user.swift -auto-bridging-header-chaining -o %t/User.swiftmodule \ +// RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap -I %t > %t/header1.h +// RUN: %FileCheck %s --check-prefix=HEADER1 --input-file=%t/header1.h +// HEADER1: #include +// HEADER1-SAME: Bridging.h + +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps2.json bridgingHeader > %t/header1.cmd +// RUN: %target-swift-frontend @%t/header1.cmd -disable-implicit-swift-modules -O -o %t/bridging1.pch + +// RUN: %{python} %S/../CAS/Inputs/GenerateExplicitModuleMap.py %t/deps2.json > %t/map2.json +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps2.json User > %t/User.cmd +// RUN: %target-swift-frontend -module-name User -O \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -disable-implicit-swift-modules \ +// RUN: -import-pch %t/bridging1.pch \ +// RUN: -explicit-swift-module-map-file %t/map2.json @%t/User.cmd %t/user.swift \ +// RUN: -emit-module -o %t/User.swiftmodule + +// RUN: llvm-bcanalyzer -dump %t/User.swiftmodule | %FileCheck %s --check-prefix CHECK-NO-HEADER +// CHECK-NO-HEADER-NOT: %t/header2.h +// RUN: %FileCheck %s --check-prefix=HEADER2 --input-file=%t/header2.h +// HEADER2: #include +// HEADER2-SAME: Bridging2.h +// HEADER2: #include +// HEADER2-SAME: Bridging.h + +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps3.json clang:SwiftShims > %t/shim2.cmd +// RUN: %swift_frontend_plain @%t/shim2.cmd +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps3.json Swift > %t/swift2.cmd +// RUN: %swift_frontend_plain @%t/swift2.cmd +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps3.json clang:B > %t/B2.cmd +// RUN: %swift_frontend_plain @%t/B2.cmd +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps3.json clang:A > %t/A2.cmd +// RUN: %swift_frontend_plain @%t/A2.cmd +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps3.json bridgingHeader > %t/header2.cmd +// RUN: %target-swift-frontend @%t/header2.cmd -disable-implicit-swift-modules -O -o %t/bridging2.pch + +// RUN: %{python} %S/../CAS/Inputs/GenerateExplicitModuleMap.py %t/deps3.json > %t/map3.json +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps3.json User > %t/User2.cmd +// RUN: echo "\"-import-objc-header\"" >> %t/User2.cmd +// RUN: echo "\"%t/Bridging2.h\"" >> %t/User2.cmd +// RUN: echo "\"-import-pch\"" >> %t/User2.cmd +// RUN: echo "\"%t/bridging2.pch\"" >> %t/User2.cmd + +// RUN: %target-swift-frontend -module-name User -O \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -disable-implicit-swift-modules \ +// RUN: -explicit-swift-module-map-file %t/map3.json @%t/User2.cmd %t/user2.swift \ +// RUN: -emit-module -o %t/User2.swiftmodule + +// RUN: %target-swift-frontend -scan-dependencies -module-name User -O \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \ +// RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap \ +// RUN: -I %t %t/user2.swift -import-objc-header %t/Bridging3.h -auto-bridging-header-chaining -scanner-output-dir %t -scanner-debug-write-output \ +// RUN: -o %t/deps4.json -Rdependency-scan-cache -serialize-dependency-scan-cache -dependency-scan-cache-path %t/cache.moddepcache + +/// Make sure the cache is correct. +// RUN: %target-swift-frontend -scan-dependencies -module-name User -O \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \ +// RUN: -Xcc -fmodule-map-file=%t/a.modulemap -Xcc -fmodule-map-file=%t/b.modulemap \ +// RUN: -I %t %t/user2.swift -import-objc-header %t/Bridging3.h -auto-bridging-header-chaining -scanner-output-dir %t -scanner-debug-write-output \ +// RUN: -o %t/deps4.json -Rdependency-scan-cache -load-dependency-scan-cache -serialize-dependency-scan-cache \ +// RUN: -dependency-scan-cache-path %t/cache.moddepcache 2>&1 | %FileCheck %s -check-prefix=CACHE-LOAD +// CACHE-LOAD: remark: Incremental module scan: Re-using serialized module scanning dependency cache from: + +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps4.json bridgingHeader > %t/header3.cmd +// RUN: %target-swift-frontend @%t/header3.cmd -disable-implicit-swift-modules -O -o %t/bridging3.pch + +// RUN: %{python} %S/../CAS/Inputs/GenerateExplicitModuleMap.py %t/deps4.json > %t/map4.json +// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps4.json User > %t/User3.cmd +// RUN: echo "\"-import-pch\"" >> %t/User3.cmd +// RUN: echo "\"%t/bridging3.pch\"" >> %t/User3.cmd +// RUN: echo "\"-import-objc-header\"" >> %t/User3.cmd +// RUN: echo "\"%t/Bridging3.h\"" >> %t/User3.cmd + +// RUN: %target-swift-frontend -module-name User -O \ +// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -disable-implicit-swift-modules \ +// RUN: -explicit-swift-module-map-file %t/map4.json @%t/User3.cmd %t/user2.swift \ +// RUN: -emit-module -o %t/User3.swiftmodule + +/// Verify the encoded here is just the `-import-objc-header` option. +// RUN: llvm-bcanalyzer -dump %t/User3.swiftmodule | %FileCheck %s --check-prefix CHECK-HEADER +// CHECK-HEADER: "compute cache key from index"), clEnumVal(cache_query, "cache query"), clEnumVal(replay_result, "replay result"), - clEnumVal(scan_dependency, "scan dependency")), + clEnumVal(scan_dependency, "scan dependency"), + clEnumVal(get_chained_bridging_header, + "get cached bridging header")), llvm::cl::cat(Category)); llvm::cl::list SwiftCommands(llvm::cl::Positional, llvm::cl::desc(""), @@ -197,7 +200,8 @@ static int action_replay_result(swiftscan_cas_t cas, const char *key, } static int action_scan_dependency(std::vector &Args, - StringRef WorkingDirectory) { + StringRef WorkingDirectory, + bool PrintChainedBridgingHeader) { auto scanner = swiftscan_scanner_create(); auto invocation = swiftscan_scan_invocation_create(); auto error = [&](StringRef msg) { @@ -235,7 +239,22 @@ static int action_scan_dependency(std::vector &Args, llvm::errs() << swift::c_string_utils::get_C_string(msg) << "\n"; } - swift::dependencies::writeJSON(llvm::outs(), graph); + if (PrintChainedBridgingHeader) { + auto deps = swiftscan_dependency_graph_get_dependencies(graph); + if (!deps || deps->count < 1) + error("failed to get dependencies"); + // Assume the main module is the first only. + auto details = swiftscan_module_info_get_details(deps->modules[0]); + auto kind = swiftscan_module_detail_get_kind(details); + if (kind != SWIFTSCAN_DEPENDENCY_INFO_SWIFT_TEXTUAL) + error("not the correct dependency kind"); + + auto content = + swiftscan_swift_textual_detail_get_chained_bridging_header_content( + details); + llvm::outs() << toString(content); + } else + swift::dependencies::writeJSON(llvm::outs(), graph); swiftscan_scan_invocation_dispose(invocation); swiftscan_scanner_dispose(scanner); @@ -249,7 +268,8 @@ createArgs(ArrayRef Cmd, StringSaver &Saver, Actions Action) { // Quote all the arguments before passing to scanner. The scanner is currently // tokenize the command-line again before parsing. - bool Quoted = Action == Actions::scan_dependency; + bool Quoted = (Action == Actions::scan_dependency || + Action == Actions::get_chained_bridging_header); std::vector Args; for (auto A : Cmd) { @@ -301,7 +321,9 @@ int main(int argc, char *argv[]) { Ret += action_replay_result(cas, CASID.c_str(), Args); break; case scan_dependency: - Ret += action_scan_dependency(Args, WorkingDirectory); + case get_chained_bridging_header: + Ret += action_scan_dependency(Args, WorkingDirectory, + Action == get_chained_bridging_header); } }); }