[Dependency Scanning] Specify Explicit Module output path to the scanner explicitly

Instead of the code querying the compiler's built-in Clang instance, refactor the
dependency scanner to explicitly keep track of module output path. It is still
set according to '-module-cache-path' as it has been prior to this change, but
now the scanner can use a different module cache for scanning PCMs, as specified
with '-clang-scanner-module-cache-path', without affecting module output path.

Resolves rdar://113222853
This commit is contained in:
Artem Chikin
2023-08-04 13:14:44 -07:00
parent 8501f99cb2
commit 6ef79c4ba0
12 changed files with 79 additions and 55 deletions

View File

@@ -945,6 +945,8 @@ private:
std::string mainScanModuleName;
/// The context hash of the current scanning invocation
std::string scannerContextHash;
/// The location of where the built modules will be output to
std::string moduleOutputPath;
/// The Clang dependency scanner tool
clang::tooling::dependencies::DependencyScanningTool clangScanningTool;
@@ -958,6 +960,7 @@ private:
public:
ModuleDependenciesCache(SwiftDependencyScanningService &globalScanningService,
std::string mainScanModuleName,
std::string moduleOutputPath,
std::string scanningContextHash);
ModuleDependenciesCache(const ModuleDependenciesCache &) = delete;
ModuleDependenciesCache &operator=(const ModuleDependenciesCache &) = delete;
@@ -980,6 +983,9 @@ public:
void addSeenClangModule(clang::tooling::dependencies::ModuleID newModule) {
alreadySeenClangModules.insert(newModule);
}
std::string getModuleOutputPath() {
return moduleOutputPath;
}
/// Look for module dependencies for a module with the given name
///

View File

@@ -91,6 +91,10 @@ public:
/// binary module has already been built for use by the compiler.
std::string PrebuiltModuleCachePath;
/// The path to output explicit module dependencies. Only relevant during
/// dependency scanning.
std::string ExplicitModulesOutputPath;
/// The path to look in to find backup .swiftinterface files if those found
/// from SDKs are failing.
std::string BackupModuleInterfaceDir;

View File

@@ -456,7 +456,7 @@ def localization_path : Separate<["-"], "localization-path">,
def module_cache_path : Separate<["-"], "module-cache-path">,
Flags<[FrontendOption, DoesNotAffectIncrementalBuild, ArgumentIsPath, SwiftAPIExtractOption,
SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
HelpText<"Specifies the Clang module cache path">;
HelpText<"Specifies the module cache path">;
def enable_library_evolution : Flag<["-"], "enable-library-evolution">,
Flags<[FrontendOption, ModuleInterfaceOption]>,

View File

@@ -41,7 +41,7 @@ namespace swift {
InterfaceSubContextDelegate &astDelegate;
/// Location where pre-built moduels are to be built into.
std::string moduleCachePath;
std::string moduleOutputPath;
llvm::Optional<SwiftDependencyTracker> dependencyTracker;
@@ -51,13 +51,13 @@ namespace swift {
ModuleDependencyScanner(
ASTContext &ctx, ModuleLoadingMode LoadMode, Identifier moduleName,
InterfaceSubContextDelegate &astDelegate,
StringRef moduleOutputPath,
ScannerKind kind = MDS_plain,
llvm::Optional<SwiftDependencyTracker> tracker = llvm::None)
: SerializedModuleLoaderBase(ctx, nullptr, LoadMode,
/*IgnoreSwiftSourceInfoFile=*/true),
kind(kind), moduleName(moduleName), astDelegate(astDelegate),
moduleCachePath(getModuleCachePathFromClang(
ctx.getClangModuleLoader()->getClangInstance())),
moduleOutputPath(moduleOutputPath),
dependencyTracker(tracker) {}
std::error_code findModuleFilesInDirectory(
@@ -123,9 +123,10 @@ namespace swift {
ASTContext &ctx, ModuleLoadingMode LoadMode, Identifier moduleName,
StringRef PlaceholderDependencyModuleMap,
InterfaceSubContextDelegate &astDelegate,
StringRef moduleOutputPath,
llvm::Optional<SwiftDependencyTracker> tracker = llvm::None)
: ModuleDependencyScanner(ctx, LoadMode, moduleName, astDelegate,
MDS_placeholder, tracker) {
moduleOutputPath, MDS_placeholder, tracker) {
// FIXME: Find a better place for this map to live, to avoid
// doing the parsing on every module.

View File

@@ -618,9 +618,11 @@ ModuleDependenciesCache::getDependencyReferencesMap(
ModuleDependenciesCache::ModuleDependenciesCache(
SwiftDependencyScanningService &globalScanningService,
std::string mainScanModuleName, std::string scannerContextHash)
std::string mainScanModuleName, std::string moduleOutputPath,
std::string scannerContextHash)
: globalScanningService(globalScanningService),
mainScanModuleName(mainScanModuleName),
moduleOutputPath(moduleOutputPath),
scannerContextHash(scannerContextHash),
clangScanningTool(*globalScanningService.ClangScanningService,
globalScanningService.getClangScanningFS()) {

View File

@@ -174,7 +174,7 @@ void ClangImporter::recordModuleDependencies(
auto pcmPath = moduleCacheRelativeLookupModuleOutput(
clangModuleDep.ID, ModuleOutputKind::ModuleFile,
getModuleCachePathFromClang(getClangInstance()));
cache.getModuleOutputPath());
swiftArgs.push_back("-o");
swiftArgs.push_back(pcmPath);
@@ -421,7 +421,7 @@ ClangImporter::getModuleDependencies(StringRef moduleName,
}
std::string workingDir = *optionalWorkingDir;
auto moduleCachePath = getModuleCachePathFromClang(getClangInstance());
auto moduleCachePath = cache.getModuleOutputPath();
auto lookupModuleOutput =
[moduleCachePath](const ModuleID &MID,
ModuleOutputKind MOK) -> std::string {

View File

@@ -131,9 +131,10 @@ DependencyScanningTool::getDependencies(
auto Instance = std::move(*InstanceOrErr);
// Local scan cache instance, wrapping the shared global cache.
ModuleDependenciesCache cache(*ScanningService,
Instance->getMainModule()->getNameStr().str(),
Instance->getInvocation().getModuleScanningHash());
ModuleDependenciesCache cache(
*ScanningService, Instance->getMainModule()->getNameStr().str(),
Instance->getInvocation().getFrontendOptions().ExplicitModulesOutputPath,
Instance->getInvocation().getModuleScanningHash());
// Execute the scanning action, retrieving the in-memory result
auto DependenciesOrErr = performModuleScan(*Instance.get(), cache);
if (DependenciesOrErr.getError())
@@ -173,9 +174,10 @@ DependencyScanningTool::getDependencies(
auto Instance = std::move(*InstanceOrErr);
// Local scan cache instance, wrapping the shared global cache.
ModuleDependenciesCache cache(*ScanningService,
Instance->getMainModule()->getNameStr().str(),
Instance->getInvocation().getModuleScanningHash());
ModuleDependenciesCache cache(
*ScanningService, Instance->getMainModule()->getNameStr().str(),
Instance->getInvocation().getFrontendOptions().ExplicitModulesOutputPath,
Instance->getInvocation().getModuleScanningHash());
auto BatchScanResults = performBatchModuleScan(
*Instance.get(), cache, VersionedPCMInstanceCacheCache.get(),
Saver, BatchInput);

View File

@@ -1626,9 +1626,13 @@ forEachBatchEntry(CompilerInstance &invocationInstance,
return true;
}
auto mainModuleName = newInstance->getMainModule()->getNameStr();
auto scanContextHash = newInstance->getInvocation().getModuleScanningHash();
auto scanContextHash =
newInstance->getInvocation().getModuleScanningHash();
auto moduleOutputPath = newInstance->getInvocation()
.getFrontendOptions()
.ExplicitModulesOutputPath;
auto newLocalCache = std::make_unique<ModuleDependenciesCache>(
*newService, mainModuleName.str(), scanContextHash);
*newService, mainModuleName.str(), moduleOutputPath, scanContextHash);
pInstance = newInstance.get();
pCache = newLocalCache.get();
subInstanceMap->insert(
@@ -1800,11 +1804,10 @@ bool swift::dependencies::scanDependencies(CompilerInstance &instance) {
if (service.setupCachingDependencyScanningService(instance))
return true;
ModuleDependenciesCache cache(service,
instance.getMainModule()->getNameStr().str(),
instance.getInvocation().getModuleScanningHash());
auto ModuleCachePath = getModuleCachePathFromClang(
Context.getClangModuleLoader()->getClangInstance());
ModuleDependenciesCache cache(
service, instance.getMainModule()->getNameStr().str(),
instance.getInvocation().getFrontendOptions().ExplicitModulesOutputPath,
instance.getInvocation().getModuleScanningHash());
// Execute scan
auto dependenciesOrErr = performModuleScan(instance, cache);
@@ -1837,9 +1840,10 @@ bool swift::dependencies::prescanDependencies(CompilerInstance &instance) {
// `-scan-dependencies` invocations use a single new instance
// of a module cache
SwiftDependencyScanningService singleUseService;
ModuleDependenciesCache cache(singleUseService,
instance.getMainModule()->getNameStr().str(),
instance.getInvocation().getModuleScanningHash());
ModuleDependenciesCache cache(
singleUseService, instance.getMainModule()->getNameStr().str(),
instance.getInvocation().getFrontendOptions().ExplicitModulesOutputPath,
instance.getInvocation().getModuleScanningHash());
// Execute import prescan, and write JSON output to the output stream
auto importSetOrErr = performModulePrescan(instance);
@@ -1870,9 +1874,10 @@ bool swift::dependencies::batchScanDependencies(
if (singleUseService.setupCachingDependencyScanningService(instance))
return true;
ModuleDependenciesCache cache(singleUseService,
instance.getMainModule()->getNameStr().str(),
instance.getInvocation().getModuleScanningHash());
ModuleDependenciesCache cache(
singleUseService, instance.getMainModule()->getNameStr().str(),
instance.getInvocation().getFrontendOptions().ExplicitModulesOutputPath,
instance.getInvocation().getModuleScanningHash());
(void)instance.getMainModule();
llvm::BumpPtrAllocator alloc;
llvm::StringSaver saver(alloc);
@@ -1906,9 +1911,10 @@ bool swift::dependencies::batchPrescanDependencies(
// The primary cache used for scans carried out with the compiler instance
// we have created
SwiftDependencyScanningService singleUseService;
ModuleDependenciesCache cache(singleUseService,
instance.getMainModule()->getNameStr().str(),
instance.getInvocation().getModuleScanningHash());
ModuleDependenciesCache cache(
singleUseService, instance.getMainModule()->getNameStr().str(),
instance.getInvocation().getFrontendOptions().ExplicitModulesOutputPath,
instance.getInvocation().getModuleScanningHash());
(void)instance.getMainModule();
llvm::BumpPtrAllocator alloc;
llvm::StringSaver saver(alloc);
@@ -1984,14 +1990,14 @@ swift::dependencies::performModuleScan(CompilerInstance &instance,
cache.recordDependency(mainModuleName, std::move(*mainDependencies));
}
auto ModuleCachePath = getModuleCachePathFromClang(
auto ClangModuleCachePath = getModuleCachePathFromClang(
ctx.getClangModuleLoader()->getClangInstance());
auto &FEOpts = instance.getInvocation().getFrontendOptions();
ModuleInterfaceLoaderOptions LoaderOpts(FEOpts);
InterfaceSubContextDelegateImpl ASTDelegate(
ctx.SourceMgr, &ctx.Diags, ctx.SearchPathOpts, ctx.LangOpts,
ctx.ClangImporterOpts, LoaderOpts,
/*buildModuleCacheDirIfAbsent*/ false, ModuleCachePath,
/*buildModuleCacheDirIfAbsent*/ false, ClangModuleCachePath,
FEOpts.PrebuiltModuleCachePath,
FEOpts.BackupModuleInterfaceDir,
FEOpts.SerializeModuleInterfaceDependencyHashes,
@@ -2114,14 +2120,14 @@ swift::dependencies::performBatchModuleScan(
ASTContext &ctx = instance.getASTContext();
auto &FEOpts = instance.getInvocation().getFrontendOptions();
ModuleInterfaceLoaderOptions LoaderOpts(FEOpts);
auto ModuleCachePath = getModuleCachePathFromClang(
auto ClangModuleCachePath = getModuleCachePathFromClang(
ctx.getClangModuleLoader()->getClangInstance());
ModuleDependencyIDSetVector allModules;
InterfaceSubContextDelegateImpl ASTDelegate(
ctx.SourceMgr, &ctx.Diags, ctx.SearchPathOpts, ctx.LangOpts,
ctx.ClangImporterOpts, LoaderOpts,
/*buildModuleCacheDirIfAbsent*/ false, ModuleCachePath,
/*buildModuleCacheDirIfAbsent*/ false, ClangModuleCachePath,
FEOpts.PrebuiltModuleCachePath,
FEOpts.BackupModuleInterfaceDir,
FEOpts.SerializeModuleInterfaceDependencyHashes,
@@ -2183,13 +2189,13 @@ swift::dependencies::performBatchModulePrescan(
ASTContext &ctx = instance.getASTContext();
auto &FEOpts = instance.getInvocation().getFrontendOptions();
ModuleInterfaceLoaderOptions LoaderOpts(FEOpts);
auto ModuleCachePath = getModuleCachePathFromClang(
auto ClangModuleCachePath = getModuleCachePathFromClang(
ctx.getClangModuleLoader()->getClangInstance());
ModuleDependencyIDSetVector allModules;
InterfaceSubContextDelegateImpl ASTDelegate(
ctx.SourceMgr, &ctx.Diags, ctx.SearchPathOpts, ctx.LangOpts,
ctx.ClangImporterOpts, LoaderOpts,
/*buildModuleCacheDirIfAbsent*/ false, ModuleCachePath,
/*buildModuleCacheDirIfAbsent*/ false, ClangModuleCachePath,
FEOpts.PrebuiltModuleCachePath,
FEOpts.BackupModuleInterfaceDir,
FEOpts.SerializeModuleInterfaceDependencyHashes,

View File

@@ -64,6 +64,9 @@ bool ArgsToFrontendOptionsConverter::convert(
if (const Arg *A = Args.getLastArg(OPT_prebuilt_module_cache_path)) {
Opts.PrebuiltModuleCachePath = A->getValue();
}
if (const Arg *A = Args.getLastArg(OPT_module_cache_path)) {
Opts.ExplicitModulesOutputPath = A->getValue();
}
if (const Arg *A = Args.getLastArg(OPT_backup_module_interface_path)) {
Opts.BackupModuleInterfaceDir = A->getValue();
}

View File

@@ -751,30 +751,28 @@ bool CompilerInstance::setUpModuleLoaders() {
Context->addModuleLoader(std::move(clangImporter), /*isClang*/ true);
// When scanning for dependencies, we must add the scanner loaders in order to handle
// ASTContext operations such as canImportModule
// When scanning for dependencies, we must add the scanner loaders in order to
// handle ASTContext operations such as canImportModule
if (Invocation.getFrontendOptions().RequestedAction ==
FrontendOptions::ActionType::ScanDependencies) {
auto ModuleCachePath = getModuleCachePathFromClang(Context
->getClangModuleLoader()->getClangInstance());
auto ClangModuleCachePath = getModuleCachePathFromClang(
Context->getClangModuleLoader()->getClangInstance());
auto &FEOpts = Invocation.getFrontendOptions();
ModuleInterfaceLoaderOptions LoaderOpts(FEOpts);
InterfaceSubContextDelegateImpl ASTDelegate(
Context->SourceMgr, &Context->Diags, Context->SearchPathOpts,
Context->LangOpts, Context->ClangImporterOpts, LoaderOpts,
/*buildModuleCacheDirIfAbsent*/ false, ModuleCachePath,
FEOpts.PrebuiltModuleCachePath,
FEOpts.BackupModuleInterfaceDir,
/*buildModuleCacheDirIfAbsent*/ false, ClangModuleCachePath,
FEOpts.PrebuiltModuleCachePath, FEOpts.BackupModuleInterfaceDir,
FEOpts.SerializeModuleInterfaceDependencyHashes,
FEOpts.shouldTrackSystemDependencies(),
RequireOSSAModules_t(Invocation.getSILOptions()));
auto mainModuleName = Context->getIdentifier(FEOpts.ModuleName);
std::unique_ptr<PlaceholderSwiftModuleScanner> PSMS =
std::make_unique<PlaceholderSwiftModuleScanner>(*Context,
MLM,
mainModuleName,
Context->SearchPathOpts.PlaceholderDependencyModuleMap,
ASTDelegate);
std::make_unique<PlaceholderSwiftModuleScanner>(
*Context, MLM, mainModuleName,
Context->SearchPathOpts.PlaceholderDependencyModuleMap, ASTDelegate,
getInvocation().getFrontendOptions().ExplicitModulesOutputPath);
Context->addModuleLoader(std::move(PSMS));
}

View File

@@ -147,7 +147,7 @@ ErrorOr<ModuleDependencyInfo> ModuleDependencyScanner::scanInterfaceFile(
}
// Compute the output path and add it to the command line
SmallString<128> outputPathBase(moduleCachePath);
SmallString<128> outputPathBase(moduleOutputPath);
llvm::sys::path::append(
outputPathBase,
moduleName.str() + "-" + Hash + "." +
@@ -281,9 +281,11 @@ SerializedModuleLoaderBase::getModuleDependencies(
// FIXME: submodules?
scanners.push_back(std::make_unique<PlaceholderSwiftModuleScanner>(
Ctx, LoadMode, moduleId, Ctx.SearchPathOpts.PlaceholderDependencyModuleMap,
delegate, cache.getScanService().createSwiftDependencyTracker()));
delegate, cache.getModuleOutputPath(),
cache.getScanService().createSwiftDependencyTracker()));
scanners.push_back(std::make_unique<ModuleDependencyScanner>(
Ctx, LoadMode, moduleId, delegate, ModuleDependencyScanner::MDS_plain,
Ctx, LoadMode, moduleId, delegate, cache.getModuleOutputPath(),
ModuleDependencyScanner::MDS_plain,
cache.getScanService().createSwiftDependencyTracker()));
// Check whether there is a module with this name that we can import.

View File

@@ -4,12 +4,12 @@
// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t.module-cache -clang-scanner-module-cache-path %t.scanner-cache %s -o %t.deps.json -I %S/Inputs/SwiftDifferent -dump-clang-diagnostics 2>&1 | %FileCheck %s --check-prefix=CHECK-CLANG-COMMAND
// RUN: %validate-json %t.deps.json | %FileCheck %s --check-prefix=CHECK-DEPS
// Ensure we prefer clang scanner module cache path
// CHECK-CLANG-COMMAND: '-fmodules-cache-path={{.*}}.scanner-cache'
// Ensure we the modules' output path is set to the module cache
// CHECK-DEPS: "swift": "A"
// CHECK-DEPS: "swift": "A"
// CHECK-DEPS-NEXT: },
// CHECK-DEPS-NEXT: {
// CHECK-DEPS-NEXT: "modulePath": "{{.*}}.module-cache/A-{{.*}}.swiftmodule",
// CHECK-DEPS-NEXT: "sourceFiles": [
// CHECK-DEPS: "modulePath": "{{.*}}separate_clang_scan_cache.swift.tmp.module-cache{{/|\\\\}}A-{{.*}}.swiftmodule"
import A