@@ -415,6 +415,97 @@ static llvm::Error resolveExplicitModuleInputs(
415
415
return llvm::Error::success ();
416
416
}
417
417
418
+ static llvm::Error pruneUnusedVFSOverlays (
419
+ ModuleDependencyID moduleID, const ModuleDependencyInfo &resolvingDepInfo,
420
+ const std::set<ModuleDependencyID> &dependencies,
421
+ ModuleDependenciesCache &cache, CompilerInstance &instance) {
422
+ auto isVFSOverlayFlag = [](StringRef arg) {
423
+ return arg == " -ivfsoverlay" || arg == " -vfsoverlay" ;
424
+ };
425
+ auto isXCCArg = [](StringRef arg) {
426
+ return arg == " -Xcc" ;
427
+ };
428
+
429
+ // Pruning of unused VFS overlay options for Clang dependencies
430
+ // is performed by the Clang dependency scanner.
431
+ if (!resolvingDepInfo.isSwiftModule ())
432
+ return llvm::Error::success ();
433
+
434
+ // If this Swift dependency contains any VFS overlay paths,
435
+ // then attempt to prune the ones not used by any of the Clang dependencies.
436
+ if (!llvm::any_of (resolvingDepInfo.getCommandline (),
437
+ [&isVFSOverlayFlag](const std::string &arg) {
438
+ return isVFSOverlayFlag (arg);
439
+ }))
440
+ return llvm::Error::success ();
441
+
442
+ // 1. For each Clang dependency, gather its ivfsoverlay path arguments
443
+ // to keep track of which overlays are actually used and were not
444
+ // pruned by the Clang dependency scanner.
445
+ llvm::StringSet<> usedVFSOverlayPaths;
446
+ for (const auto &depModuleID : dependencies) {
447
+ const auto optionalDepInfo = cache.findDependency (depModuleID);
448
+ assert (optionalDepInfo.has_value ());
449
+ const auto depInfo = optionalDepInfo.value ();
450
+ if (auto clangDepDetails = depInfo->getAsClangModule ()) {
451
+ const auto &depCommandLine = clangDepDetails->buildCommandLine ;
452
+ // true if the previous argument was the dash-option of an option pair
453
+ bool getNext = false ;
454
+ for (const auto &A : depCommandLine) {
455
+ StringRef arg (A);
456
+ if (isXCCArg (arg))
457
+ continue ;
458
+ if (getNext) {
459
+ getNext = false ;
460
+ usedVFSOverlayPaths.insert (arg);
461
+ } else if (isVFSOverlayFlag (arg))
462
+ getNext = true ;
463
+ }
464
+ }
465
+ }
466
+
467
+ // 2. Each -Xcc VFS overlay path on the resolving command-line which is not used by
468
+ // any of the Clang dependencies can be removed from the command-line.
469
+ const std::vector<std::string> ¤tCommandLine =
470
+ resolvingDepInfo.getCommandline ();
471
+ std::vector<std::string> resolvedCommandLine;
472
+ size_t skip = 0 ;
473
+ for (auto it = currentCommandLine.begin (), end = currentCommandLine.end ();
474
+ it != end; it++) {
475
+ if (skip) {
476
+ skip--;
477
+ continue ;
478
+ }
479
+ // If this VFS overlay was not used across any of the dependencies, skip it.
480
+ if ((it+1 ) != end && isXCCArg (*it) && isVFSOverlayFlag (*(it + 1 ))) {
481
+ assert (it + 2 != end); // Extra -Xcc
482
+ assert (it + 3 != end); // Actual VFS overlay path argument
483
+ if (!usedVFSOverlayPaths.contains (*(it + 3 ))) {
484
+ skip = 3 ;
485
+ continue ;
486
+ }
487
+ }
488
+ resolvedCommandLine.push_back (*it);
489
+ }
490
+
491
+ // 3. Update the dependency in the cache if the command-line has been modified.
492
+ if (currentCommandLine.size () != resolvedCommandLine.size ()) {
493
+ auto dependencyInfoCopy = resolvingDepInfo;
494
+ dependencyInfoCopy.updateCommandLine (resolvedCommandLine);
495
+
496
+ // Update the CAS cache key for the new command-line
497
+ if (instance.getInvocation ().getCASOptions ().EnableCaching ) {
498
+ auto &CAS = cache.getScanService ().getSharedCachingFS ().getCAS ();
499
+ auto Key = updateModuleCacheKey (dependencyInfoCopy, cache, CAS);
500
+ if (!Key)
501
+ return Key.takeError ();
502
+ }
503
+ cache.updateDependency (moduleID, dependencyInfoCopy);
504
+ }
505
+
506
+ return llvm::Error::success ();
507
+ }
508
+
418
509
namespace {
419
510
std::string quote (StringRef unquoted) {
420
511
llvm::SmallString<128 > buffer;
@@ -1658,7 +1749,7 @@ swift::dependencies::createEncodedModuleKindAndName(ModuleDependencyID id) {
1658
1749
}
1659
1750
}
1660
1751
1661
- static void resolveDependencyInputCommandLineArguments (
1752
+ static void resolveDependencyCommandLineArguments (
1662
1753
CompilerInstance &instance, ModuleDependenciesCache &cache,
1663
1754
const std::vector<ModuleDependencyID> &topoSortedModuleList) {
1664
1755
auto moduleTransitiveClosures =
@@ -1676,6 +1767,11 @@ static void resolveDependencyInputCommandLineArguments(
1676
1767
cache, instance))
1677
1768
instance.getDiags ().diagnose (SourceLoc (), diag::error_cas,
1678
1769
toString (std::move (E)));
1770
+
1771
+ if (auto E = pruneUnusedVFSOverlays (modID, *deps, dependencyClosure,
1772
+ cache, instance))
1773
+ instance.getDiags ().diagnose (SourceLoc (), diag::error_cas,
1774
+ toString (std::move (E)));
1679
1775
}
1680
1776
}
1681
1777
@@ -1756,8 +1852,8 @@ swift::dependencies::performModuleScan(CompilerInstance &instance,
1756
1852
1757
1853
auto topologicallySortedModuleList =
1758
1854
computeTopologicalSortOfExplicitDependencies (allModules, cache);
1759
- resolveDependencyInputCommandLineArguments (instance, cache,
1760
- topologicallySortedModuleList);
1855
+ resolveDependencyCommandLineArguments (instance, cache,
1856
+ topologicallySortedModuleList);
1761
1857
1762
1858
updateDependencyTracker (instance, cache, allModules);
1763
1859
return generateFullDependencyGraph (instance, cache,
0 commit comments