23
23
#include " swift/AST/SourceFile.h"
24
24
#include " swift/Frontend/Frontend.h"
25
25
#include " swift/Strings.h"
26
+ #include " clang/Lex/HeaderSearchOptions.h"
26
27
#include " llvm/Config/config.h"
27
28
#include " llvm/Support/Path.h"
28
29
using namespace swift ;
@@ -598,6 +599,120 @@ void swift::dependencies::registerCxxInteropLibraries(
598
599
}
599
600
}
600
601
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
+
601
716
void
602
717
swift::dependencies::registerBackDeployLibraries (
603
718
const IRGenOptions &IRGenOpts,
@@ -779,16 +894,19 @@ void ModuleDependenciesCache::recordDependency(
779
894
}
780
895
781
896
void 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) {
783
901
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 )) {
787
905
auto priorClangModuleDetails =
788
- findKnownDependency (dep. first ).getAsClangModule ();
789
- DEBUG_ASSERT (priorClangModuleDetails && newClangModuleDetails );
906
+ findKnownDependency (depID ).getAsClangModule ();
907
+ DEBUG_ASSERT (priorClangModuleDetails);
790
908
auto priorContextHash = priorClangModuleDetails->contextHash ;
791
- auto newContextHash = newClangModuleDetails-> contextHash ;
909
+ auto newContextHash = dep. ID . ContextHash ;
792
910
if (priorContextHash != newContextHash) {
793
911
// This situation means that within the same scanning action, Clang
794
912
// Dependency Scanner has produced two different variants of the same
@@ -799,28 +917,33 @@ void ModuleDependenciesCache::recordClangDependencies(
799
917
//
800
918
// Emit a failure diagnostic here that is hopefully more actionable
801
919
// 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 (
805
924
SourceLoc (),
806
925
diag::dependency_scan_unexpected_variant_context_hash_note,
807
926
priorContextHash, newContextHash);
808
- diags .diagnose (
927
+ ctx. Diags .diagnose (
809
928
SourceLoc (),
810
929
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 ();
813
936
814
937
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 {
818
941
std::unordered_set<std::string> baseCommandLineSet (
819
942
baseModuleDetails->buildCommandLine .begin (),
820
943
baseModuleDetails->buildCommandLine .end ());
821
944
for (const auto &checkArg : checkModuleDetails->buildCommandLine )
822
945
if (baseCommandLineSet.find (checkArg) == baseCommandLineSet.end ())
823
- diags .diagnose (
946
+ ctx. Diags .diagnose (
824
947
SourceLoc (),
825
948
diag::dependency_scan_unexpected_variant_extra_arg_note,
826
949
isNewlyDiscovered, checkArg);
@@ -831,9 +954,10 @@ void ModuleDependenciesCache::recordClangDependencies(
831
954
priorClangModuleDetails, false );
832
955
}
833
956
} 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 );
837
961
}
838
962
}
839
963
}
0 commit comments