2323#include " swift/AST/SourceFile.h"
2424#include " swift/Frontend/Frontend.h"
2525#include " swift/Strings.h"
26+ #include " clang/Lex/HeaderSearchOptions.h"
2627#include " llvm/Config/config.h"
2728#include " llvm/Support/Path.h"
2829using namespace swift ;
@@ -598,6 +599,120 @@ void swift::dependencies::registerCxxInteropLibraries(
598599 }
599600}
600601
602+ ModuleDependencyInfo swift::dependencies::bridgeClangModuleDependency (
603+ const ASTContext &ctx,
604+ const clang::tooling::dependencies::ModuleDeps &clangModuleDep,
605+ LookupModuleOutputCallback lookupModuleOutput, RemapPathCallback callback) {
606+ auto remapPath = [&](StringRef path) {
607+ if (callback)
608+ return callback (path);
609+ return path.str ();
610+ };
611+
612+ // File dependencies for this module.
613+ std::vector<std::string> fileDeps;
614+ clangModuleDep.forEachFileDep (
615+ [&fileDeps](StringRef fileDep) { fileDeps.emplace_back (fileDep); });
616+
617+ std::vector<std::string> swiftArgs;
618+ auto addClangArg = [&](Twine arg) {
619+ swiftArgs.push_back (" -Xcc" );
620+ swiftArgs.push_back (arg.str ());
621+ };
622+
623+ // We are using Swift frontend mode.
624+ swiftArgs.push_back (" -frontend" );
625+
626+ // Swift frontend action: -emit-pcm
627+ swiftArgs.push_back (" -emit-pcm" );
628+ swiftArgs.push_back (" -module-name" );
629+ swiftArgs.push_back (clangModuleDep.ID .ModuleName );
630+
631+ auto pcmPath = lookupModuleOutput (
632+ clangModuleDep,
633+ clang::tooling::dependencies::ModuleOutputKind::ModuleFile);
634+ swiftArgs.push_back (" -o" );
635+ swiftArgs.push_back (pcmPath);
636+
637+ // Ensure that the resulting PCM build invocation uses Clang frontend
638+ // directly
639+ swiftArgs.push_back (" -direct-clang-cc1-module-build" );
640+
641+ // Swift frontend option for input file path (Foo.modulemap).
642+ swiftArgs.push_back (remapPath (clangModuleDep.ClangModuleMapFile ));
643+
644+ auto invocation = clangModuleDep.getUnderlyingCompilerInvocation ();
645+ // Clear some options from clang scanner.
646+ invocation.getMutFrontendOpts ().ModuleCacheKeys .clear ();
647+ invocation.getMutFrontendOpts ().PathPrefixMappings .clear ();
648+ invocation.getMutFrontendOpts ().OutputFile .clear ();
649+
650+ // Reset CASOptions since that should be coming from swift.
651+ invocation.getMutCASOpts () = clang::CASOptions ();
652+ invocation.getMutFrontendOpts ().CASIncludeTreeID .clear ();
653+
654+ // FIXME: workaround for rdar://105684525: find the -ivfsoverlay option
655+ // from clang scanner and pass to swift.
656+ if (!ctx.CASOpts .EnableCaching ) {
657+ auto &overlayFiles = invocation.getMutHeaderSearchOpts ().VFSOverlayFiles ;
658+ for (auto overlay : overlayFiles) {
659+ swiftArgs.push_back (" -vfsoverlay" );
660+ swiftArgs.push_back (overlay);
661+ }
662+ }
663+
664+ // Add args reported by the scanner.
665+ auto clangArgs = invocation.getCC1CommandLine ();
666+ llvm::for_each (clangArgs, addClangArg);
667+
668+ // CASFileSystemRootID.
669+ std::string RootID = clangModuleDep.CASFileSystemRootID
670+ ? clangModuleDep.CASFileSystemRootID ->toString ()
671+ : " " ;
672+
673+ std::string IncludeTree =
674+ clangModuleDep.IncludeTreeID ? *clangModuleDep.IncludeTreeID : " " ;
675+
676+ ctx.CASOpts .enumerateCASConfigurationFlags (
677+ [&](StringRef Arg) { swiftArgs.push_back (Arg.str ()); });
678+
679+ if (!IncludeTree.empty ()) {
680+ swiftArgs.push_back (" -clang-include-tree-root" );
681+ swiftArgs.push_back (IncludeTree);
682+ }
683+ std::string mappedPCMPath = remapPath (pcmPath);
684+
685+ std::vector<LinkLibrary> LinkLibraries;
686+ for (const auto &ll : clangModuleDep.LinkLibraries )
687+ LinkLibraries.emplace_back (ll.Library ,
688+ ll.IsFramework ? LibraryKind::Framework
689+ : LibraryKind::Library,
690+ /* static=*/ false );
691+
692+ // Module-level dependencies.
693+ llvm::StringSet<> alreadyAddedModules;
694+ auto bridgedDependencyInfo = ModuleDependencyInfo::forClangModule (
695+ pcmPath, mappedPCMPath, clangModuleDep.ClangModuleMapFile ,
696+ clangModuleDep.ID .ContextHash , swiftArgs, fileDeps, LinkLibraries, RootID,
697+ IncludeTree, /* module-cache-key*/ " " , clangModuleDep.IsSystem );
698+
699+ std::vector<ModuleDependencyID> directDependencyIDs;
700+ for (const auto &moduleName : clangModuleDep.ClangModuleDeps ) {
701+ // FIXME: This assumes, conservatively, that all Clang module imports
702+ // are exported. We need to fix this once the clang scanner gains the
703+ // appropriate API to query this.
704+ bridgedDependencyInfo.addModuleImport (
705+ moduleName.ModuleName , /* isExported */ true , AccessLevel::Public,
706+ &alreadyAddedModules);
707+ // It is safe to assume that all dependencies of a Clang module are Clang
708+ // modules.
709+ directDependencyIDs.push_back (
710+ {moduleName.ModuleName , ModuleDependencyKind::Clang});
711+ }
712+ bridgedDependencyInfo.setImportedClangDependencies (directDependencyIDs);
713+ return bridgedDependencyInfo;
714+ }
715+
601716void
602717swift::dependencies::registerBackDeployLibraries (
603718 const IRGenOptions &IRGenOpts,
@@ -779,16 +894,19 @@ void ModuleDependenciesCache::recordDependency(
779894}
780895
781896void ModuleDependenciesCache::recordClangDependencies (
782- ModuleDependencyVector dependencies, DiagnosticEngine &diags) {
897+ const clang::tooling::dependencies::ModuleDepsGraph &dependencies,
898+ const ASTContext &ctx,
899+ dependencies::LookupModuleOutputCallback lookupModuleOutput,
900+ dependencies::RemapPathCallback remapPath) {
783901 for (const auto &dep : dependencies) {
784- ASSERT (dep. first . Kind == ModuleDependencyKind::Clang);
785- auto newClangModuleDetails = dep.second . getAsClangModule () ;
786- if (hasDependency (dep. first )) {
902+ auto depID =
903+ ModuleDependencyID{ dep.ID . ModuleName , ModuleDependencyKind::Clang} ;
904+ if (hasDependency (depID )) {
787905 auto priorClangModuleDetails =
788- findKnownDependency (dep. first ).getAsClangModule ();
789- DEBUG_ASSERT (priorClangModuleDetails && newClangModuleDetails );
906+ findKnownDependency (depID ).getAsClangModule ();
907+ DEBUG_ASSERT (priorClangModuleDetails);
790908 auto priorContextHash = priorClangModuleDetails->contextHash ;
791- auto newContextHash = newClangModuleDetails-> contextHash ;
909+ auto newContextHash = dep. ID . ContextHash ;
792910 if (priorContextHash != newContextHash) {
793911 // This situation means that within the same scanning action, Clang
794912 // Dependency Scanner has produced two different variants of the same
@@ -799,28 +917,33 @@ void ModuleDependenciesCache::recordClangDependencies(
799917 //
800918 // Emit a failure diagnostic here that is hopefully more actionable
801919 // for the time being.
802- diags.diagnose (SourceLoc (), diag::dependency_scan_unexpected_variant,
803- dep.first .ModuleName );
804- diags.diagnose (
920+ ctx.Diags .diagnose (SourceLoc (),
921+ diag::dependency_scan_unexpected_variant,
922+ dep.ID .ModuleName );
923+ ctx.Diags .diagnose (
805924 SourceLoc (),
806925 diag::dependency_scan_unexpected_variant_context_hash_note,
807926 priorContextHash, newContextHash);
808- diags .diagnose (
927+ ctx. Diags .diagnose (
809928 SourceLoc (),
810929 diag::dependency_scan_unexpected_variant_module_map_note,
811- priorClangModuleDetails->moduleMapFile ,
812- newClangModuleDetails->moduleMapFile );
930+ priorClangModuleDetails->moduleMapFile , dep.ClangModuleMapFile );
931+
932+ auto newClangModuleDetails =
933+ dependencies::bridgeClangModuleDependency (
934+ ctx, dep, lookupModuleOutput, remapPath)
935+ .getAsClangModule ();
813936
814937 auto diagnoseExtraCommandLineFlags =
815- [&diags ](const ClangModuleDependencyStorage *checkModuleDetails,
816- const ClangModuleDependencyStorage *baseModuleDetails,
817- bool isNewlyDiscovered) -> void {
938+ [&ctx ](const ClangModuleDependencyStorage *checkModuleDetails,
939+ const ClangModuleDependencyStorage *baseModuleDetails,
940+ bool isNewlyDiscovered) -> void {
818941 std::unordered_set<std::string> baseCommandLineSet (
819942 baseModuleDetails->buildCommandLine .begin (),
820943 baseModuleDetails->buildCommandLine .end ());
821944 for (const auto &checkArg : checkModuleDetails->buildCommandLine )
822945 if (baseCommandLineSet.find (checkArg) == baseCommandLineSet.end ())
823- diags .diagnose (
946+ ctx. Diags .diagnose (
824947 SourceLoc (),
825948 diag::dependency_scan_unexpected_variant_extra_arg_note,
826949 isNewlyDiscovered, checkArg);
@@ -831,9 +954,10 @@ void ModuleDependenciesCache::recordClangDependencies(
831954 priorClangModuleDetails, false );
832955 }
833956 } else {
834- recordDependency (dep.first .ModuleName , dep.second );
835- addSeenClangModule (clang::tooling::dependencies::ModuleID{
836- dep.first .ModuleName , newClangModuleDetails->contextHash });
957+ recordDependency (dep.ID .ModuleName ,
958+ dependencies::bridgeClangModuleDependency (
959+ ctx, dep, lookupModuleOutput, remapPath));
960+ addSeenClangModule (dep.ID );
837961 }
838962 }
839963}
0 commit comments