Merge pull request #81720 from cachemeifyoucan/eng/PR-release-148752988-151339073-151395300

[6.2][Caching] Swift Caching Dependency Scanning Improvements
This commit is contained in:
Steven Wu
2025-05-28 11:44:00 -07:00
committed by GitHub
27 changed files with 293 additions and 599 deletions

View File

@@ -520,7 +520,7 @@ REMARK(matching_output_produced,none,
// Caching related diagnostics
ERROR(error_caching_no_cas_fs, none,
"caching is enabled without -cas-fs option, input is not immutable", ())
"caching is enabled without CAS file-system options, input is not immutable", ())
ERROR(error_prefix_mapping, none, "cannot create scanner prefix mapping: '%0'", (StringRef))
REMARK(replay_output, none, "replay output file '%0': key '%1'", (StringRef, StringRef))
@@ -534,6 +534,7 @@ ERROR(error_cache_key_creation, none, "cannot create cache key for compilation %
ERROR(error_cas_file_ref, none, "cannot load file %0 from CAS filesystem", (StringRef))
ERROR(error_cas_conflict_options, none, "cannot setup CAS due to conflicting '-cas-*' options", ())
ERROR(error_cas_initialization, none, "CAS cannot be initialized from the specified '-cas-*' options: %0", (StringRef))
ERROR(error_cas_malformed_input, none, "CAS input '%0' is malformed: %1", (StringRef, StringRef))
WARNING(cache_replay_failed, none, "cache replay failed: %0", (StringRef))
ERROR(error_failed_cached_diag, none, "failed to serialize cached diagnostics: %0", (StringRef))

View File

@@ -1005,7 +1005,7 @@ using ModuleDependenciesKindMap =
/// Track swift dependency
class SwiftDependencyTracker {
public:
SwiftDependencyTracker(llvm::cas::CachingOnDiskFileSystem &FS,
SwiftDependencyTracker(std::shared_ptr<llvm::cas::ObjectStore> CAS,
llvm::PrefixMapper *Mapper,
const CompilerInvocation &CI);
@@ -1014,7 +1014,8 @@ public:
llvm::Expected<llvm::cas::ObjectProxy> createTreeFromDependencies();
private:
llvm::IntrusiveRefCntPtr<llvm::cas::CachingOnDiskFileSystem> FS;
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
std::shared_ptr<llvm::cas::ObjectStore> CAS;
llvm::PrefixMapper *Mapper;
struct FileEntry {
@@ -1040,10 +1041,7 @@ class SwiftDependencyScanningService {
ClangScanningService;
/// CachingOnDiskFileSystem for dependency tracking.
llvm::IntrusiveRefCntPtr<llvm::cas::CachingOnDiskFileSystem> CacheFS;
/// If use clang include tree.
bool UseClangIncludeTree = false;
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> CacheFS;
/// CAS Instance.
std::shared_ptr<llvm::cas::ObjectStore> CAS;
@@ -1081,8 +1079,8 @@ public:
return *SharedFilesystemCache;
}
llvm::cas::CachingOnDiskFileSystem &getSharedCachingFS() const {
assert(CacheFS && "Expect CachingOnDiskFileSystem");
llvm::vfs::FileSystem &getSharedCachingFS() const {
assert(CacheFS && "Expect a CASFileSystem");
return *CacheFS;
}
@@ -1093,20 +1091,17 @@ public:
std::optional<SwiftDependencyTracker>
createSwiftDependencyTracker(const CompilerInvocation &CI) {
if (!CacheFS)
if (!CAS)
return std::nullopt;
return SwiftDependencyTracker(*CacheFS, Mapper.get(), CI);
return SwiftDependencyTracker(CAS, Mapper.get(), CI);
}
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> getClangScanningFS() const {
if (UseClangIncludeTree)
if (CAS)
return llvm::cas::createCASProvidingFileSystem(
CAS, llvm::vfs::createPhysicalFileSystem());
if (CacheFS)
return CacheFS->createProxyFS();
return llvm::vfs::createPhysicalFileSystem();
}

View File

@@ -37,14 +37,11 @@ public:
/// CASOptions
clang::CASOptions CASOpts;
/// CASFS Root.
std::vector<std::string> CASFSRootIDs;
/// Clang Include Trees.
std::vector<std::string> ClangIncludeTrees;
std::string ClangIncludeTree;
/// Clang Include Tree FileList.
std::vector<std::string> ClangIncludeTreeFileList;
std::string ClangIncludeTreeFileList;
/// CacheKey for input file.
std::string InputFileKey;
@@ -62,9 +59,8 @@ public:
/// Check to see if a CASFileSystem is required.
bool requireCASFS() const {
return EnableCaching &&
(!CASFSRootIDs.empty() || !ClangIncludeTrees.empty() ||
!ClangIncludeTreeFileList.empty() || !InputFileKey.empty() ||
!BridgingHeaderPCHCacheKey.empty());
(!ClangIncludeTree.empty() || !ClangIncludeTreeFileList.empty() ||
!InputFileKey.empty() || !BridgingHeaderPCHCacheKey.empty());
}
/// Return a hash code of any components from these options that should

View File

@@ -1094,12 +1094,6 @@ namespace swift {
/// built and provided to the compiler invocation.
bool DisableImplicitClangModules = false;
/// Enable ClangIncludeTree for explicit module builds scanning.
bool UseClangIncludeTree = false;
/// Using ClangIncludeTreeRoot for compilation.
bool HasClangIncludeTreeRoot = false;
/// Whether the dependency scanner should construct all swift-frontend
/// invocations directly from clang cc1 args.
bool ClangImporterDirectCC1Scan = false;

View File

@@ -472,11 +472,6 @@ public:
/// Reads the original source file name from PCH.
std::string getOriginalSourceFile(StringRef PCHFilename);
/// Add clang dependency file names.
///
/// \param files The list of file to append dependencies to.
void addClangInvovcationDependencies(std::vector<std::string> &files);
/// Makes a temporary replica of the ClangImporter's CompilerInstance, reads a
/// module map into the replica and emits a PCM file for one of the modules it
/// declares. Delegates to clang for everything except construction of the

View File

@@ -70,9 +70,9 @@ std::unique_ptr<llvm::MemoryBuffer> loadCachedCompileResultFromCacheKey(
llvm::StringRef Filename = "");
llvm::Expected<llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>>
createCASFileSystem(llvm::cas::ObjectStore &CAS, ArrayRef<std::string> FSRoots,
ArrayRef<std::string> IncludeTreeRoots,
ArrayRef<std::string> IncludeTreeFileList);
createCASFileSystem(llvm::cas::ObjectStore &CAS,
const std::string &IncludeTreeRoot,
const std::string &IncludeTreeFileList);
std::vector<std::string> remapPathsFromCommandLine(
ArrayRef<std::string> Args,

View File

@@ -1454,9 +1454,6 @@ def bridging_header_pch_key : Separate<["-"], "bridging-header-pch-key">,
def no_clang_include_tree: Flag<["-"], "no-clang-include-tree">,
HelpText<"Do not use clang include tree, fallback to use CAS filesystem to build clang modules">;
def cas_fs: Separate<["-"], "cas-fs">,
HelpText<"Root CASID for CAS FileSystem">, MetaVarName<"<cas-id>">;
def clang_include_tree_root: Separate<["-"], "clang-include-tree-root">,
HelpText<"Clang Include Tree CASID">, MetaVarName<"<cas-id>">;
def clang_include_tree_filelist: Separate<["-"], "clang-include-tree-filelist">,

View File

@@ -25,7 +25,6 @@
#include "swift/Strings.h"
#include "clang/CAS/IncludeTree.h"
#include "llvm/CAS/CASProvidingFileSystem.h"
#include "llvm/CAS/CachingOnDiskFileSystem.h"
#include "llvm/Config/config.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -602,13 +601,16 @@ swift::dependencies::registerBackDeployLibraries(
}
SwiftDependencyTracker::SwiftDependencyTracker(
llvm::cas::CachingOnDiskFileSystem &FS, llvm::PrefixMapper *Mapper,
std::shared_ptr<llvm::cas::ObjectStore> CAS, llvm::PrefixMapper *Mapper,
const CompilerInvocation &CI)
: FS(FS.createProxyFS()), Mapper(Mapper) {
: CAS(CAS), Mapper(Mapper) {
auto &SearchPathOpts = CI.getSearchPathOptions();
FS = llvm::cas::createCASProvidingFileSystem(
CAS, llvm::vfs::createPhysicalFileSystem());
auto addCommonFile = [&](StringRef path) {
auto file = FS.openFileForRead(path);
auto file = FS->openFileForRead(path);
if (!file)
return;
auto status = (*file)->status();
@@ -679,7 +681,7 @@ SwiftDependencyTracker::createTreeFromDependencies() {
llvm::SmallVector<clang::cas::IncludeTree::FileList::FileEntry> Files;
for (auto &file : TrackedFiles) {
auto includeTreeFile = clang::cas::IncludeTree::File::create(
FS->getCAS(), file.first, file.second.FileRef);
*CAS, file.first, file.second.FileRef);
if (!includeTreeFile) {
return llvm::createStringError("CASFS createTree failed for " +
file.first + ": " +
@@ -691,7 +693,7 @@ SwiftDependencyTracker::createTreeFromDependencies() {
}
auto includeTreeList =
clang::cas::IncludeTree::FileList::create(FS->getCAS(), Files, {});
clang::cas::IncludeTree::FileList::create(*CAS, Files, {});
if (!includeTreeList)
return llvm::createStringError("casfs include-tree filelist error: " +
toString(includeTreeList.takeError()));
@@ -719,14 +721,8 @@ bool SwiftDependencyScanningService::setupCachingDependencyScanningService(
CAS = Instance.getSharedCASInstance();
ActionCache = Instance.getSharedCacheInstance();
auto CachingFS =
llvm::cas::createCachingOnDiskFileSystem(Instance.getObjectStore());
if (!CachingFS) {
Instance.getDiags().diagnose(SourceLoc(), diag::error_cas_fs_creation,
toString(CachingFS.takeError()));
return true;
}
CacheFS = std::move(*CachingFS);
CacheFS = llvm::cas::createCASProvidingFileSystem(
CAS, llvm::vfs::createPhysicalFileSystem());
// Setup prefix mapping.
auto &ScannerPrefixMapper =
@@ -744,19 +740,14 @@ bool SwiftDependencyScanningService::setupCachingDependencyScanningService(
Mapper->sort();
}
UseClangIncludeTree =
Instance.getInvocation().getClangImporterOptions().UseClangIncludeTree;
const clang::tooling::dependencies::ScanningOutputFormat ClangScanningFormat =
UseClangIncludeTree
? clang::tooling::dependencies::ScanningOutputFormat::FullIncludeTree
: clang::tooling::dependencies::ScanningOutputFormat::FullTree;
clang::tooling::dependencies::ScanningOutputFormat::FullIncludeTree;
ClangScanningService.emplace(
clang::tooling::dependencies::ScanningMode::DependencyDirectivesScan,
ClangScanningFormat,
Instance.getInvocation().getCASOptions().CASOpts,
ClangScanningFormat, Instance.getInvocation().getCASOptions().CASOpts,
Instance.getSharedCASInstance(), Instance.getSharedCacheInstance(),
UseClangIncludeTree ? nullptr : CacheFS,
/*CachingOnDiskFileSystem=*/nullptr,
// The current working directory optimization (off by default)
// should not impact CAS. We set the optization to all to be
// consistent with the non-CAS case.

View File

@@ -64,9 +64,9 @@ static StringRef pluginModuleNameStringFromPath(StringRef path) {
static llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
getPluginLoadingFS(ASTContext &Ctx) {
// If there is a clang include tree FS, using real file system to load plugin
// If there is an immutable file system, using real file system to load plugin
// as the FS in SourceMgr doesn't support directory iterator.
if (Ctx.ClangImporterOpts.HasClangIncludeTreeRoot)
if (Ctx.CASOpts.HasImmutableFileSystem)
return llvm::vfs::getRealFileSystem();
return Ctx.SourceMgr.getFileSystem();
}

View File

@@ -90,6 +90,7 @@
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTWriter.h"
#include "clang/Serialization/ObjectFilePCHContainerReader.h"
#include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"
#include "clang/Tooling/DependencyScanning/ScanAndUpdateArgs.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/STLExtras.h"
@@ -1062,27 +1063,6 @@ std::string ClangImporter::getOriginalSourceFile(StringRef PCHFilename) {
Impl.Instance->getPCHContainerReader(), Impl.Instance->getDiagnostics());
}
void ClangImporter::addClangInvovcationDependencies(
std::vector<std::string> &files) {
auto addFiles = [&files](const auto &F) {
files.insert(files.end(), F.begin(), F.end());
};
auto &invocation = *Impl.Invocation;
// FIXME: Add file dependencies that are not accounted. The long term solution
// is to do a dependency scanning for clang importer and use that directly.
SmallVector<std::string, 4> HeaderMapFileNames;
Impl.Instance->getPreprocessor().getHeaderSearchInfo().getHeaderMapFileNames(
HeaderMapFileNames);
addFiles(HeaderMapFileNames);
addFiles(invocation.getHeaderSearchOpts().VFSOverlayFiles);
// FIXME: Should not depend on working directory. Build system/swift driver
// should not pass working directory here but if that option is passed,
// repect that and add that into CASFS.
auto CWD = invocation.getFileSystemOpts().WorkingDir;
if (!CWD.empty())
files.push_back(CWD);
}
std::optional<std::string>
ClangImporter::getPCHFilename(const ClangImporterOptions &ImporterOptions,
StringRef SwiftPCHHash, bool &isExplicit) {
@@ -1210,9 +1190,8 @@ std::optional<std::vector<std::string>> ClangImporter::getClangCC1Arguments(
clang::frontend::ActionKind::GenerateModule ||
CI->getFrontendOpts().ProgramAction ==
clang::frontend::ActionKind::GeneratePCH) &&
ctx.ClangImporterOpts.HasClangIncludeTreeRoot) {
CI->getFrontendOpts().CASIncludeTreeID =
ctx.CASOpts.ClangIncludeTrees.back();
!ctx.CASOpts.ClangIncludeTree.empty()) {
CI->getFrontendOpts().CASIncludeTreeID = ctx.CASOpts.ClangIncludeTree;
CI->getFrontendOpts().Inputs.clear();
}
}
@@ -1271,7 +1250,7 @@ std::optional<std::vector<std::string>> ClangImporter::getClangCC1Arguments(
std::vector<std::string> FilteredModuleMapFiles;
for (auto ModuleMapFile : CI->getFrontendOpts().ModuleMapFiles) {
if (ctx.ClangImporterOpts.HasClangIncludeTreeRoot) {
if (ctx.CASOpts.HasImmutableFileSystem) {
// There is no need to add any module map file here. Issue a warning and
// drop the option.
Impl.diagnose(SourceLoc(), diag::module_map_ignored, ModuleMapFile);
@@ -1351,7 +1330,7 @@ ClangImporter::create(ASTContext &ctx,
fileMapping.requiresBuiltinHeadersInSystemModules;
// Avoid creating indirect file system when using include tree.
if (!ctx.ClangImporterOpts.HasClangIncludeTreeRoot) {
if (!ctx.CASOpts.HasImmutableFileSystem) {
// Wrap Swift's FS to allow Clang to override the working directory
VFS = llvm::vfs::RedirectingFileSystem::create(
fileMapping.redirectedFiles, true, *ctx.SourceMgr.getFileSystem());
@@ -2756,7 +2735,6 @@ ClangImporter::Implementation::Implementation(
!ctx.ClangImporterOpts.BridgingHeader.empty()),
DisableOverlayModules(ctx.ClangImporterOpts.DisableOverlayModules),
EnableClangSPI(ctx.ClangImporterOpts.EnableClangSPI),
UseClangIncludeTree(ctx.ClangImporterOpts.UseClangIncludeTree),
importSymbolicCXXDecls(
ctx.LangOpts.hasFeature(Feature::ImportSymbolicCXXDecls)),
IsReadingBridgingPCH(false),
@@ -4281,15 +4259,14 @@ ClangImporter::getSwiftExplicitModuleDirectCC1Args() const {
PPOpts.MacroIncludes.clear();
PPOpts.Includes.clear();
// CodeGenOptions.
auto &CGOpts = instance.getCodeGenOpts();
CGOpts.DebugCompilationDir.clear();
// Clear benign CodeGenOptions.
clang::tooling::dependencies::resetBenignCodeGenOptions(
clang::frontend::ActionKind::GenerateModule, instance.getLangOpts(),
instance.getCodeGenOpts());
if (Impl.SwiftContext.ClangImporterOpts.UseClangIncludeTree) {
// FileSystemOptions.
auto &FSOpts = instance.getFileSystemOpts();
FSOpts.WorkingDir.clear();
}
// FileSystemOptions.
auto &FSOpts = instance.getFileSystemOpts();
FSOpts.WorkingDir.clear();
if (!Impl.SwiftContext.SearchPathOpts.ScannerPrefixMapper.empty()) {
// Remap all the paths if requested.

View File

@@ -81,25 +81,6 @@ std::vector<std::string> ClangImporter::getClangDepScanningInvocationArguments(
return commandLineArgs;
}
static std::unique_ptr<llvm::PrefixMapper>
getClangPrefixMapper(DependencyScanningTool &clangScanningTool,
ModuleDeps &clangModuleDep,
clang::CompilerInvocation &depsInvocation) {
std::unique_ptr<llvm::PrefixMapper> Mapper;
if (clangModuleDep.IncludeTreeID) {
Mapper = std::make_unique<llvm::PrefixMapper>();
} else if (clangModuleDep.CASFileSystemRootID) {
assert(clangScanningTool.getCachingFileSystem());
Mapper = std::make_unique<llvm::TreePathPrefixMapper>(
clangScanningTool.getCachingFileSystem());
}
if (Mapper)
DepscanPrefixMapping::configurePrefixMapper(depsInvocation, *Mapper);
return Mapper;
}
ModuleDependencyVector ClangImporter::bridgeClangModuleDependencies(
const ASTContext &ctx,
clang::tooling::dependencies::DependencyScanningTool &clangScanningTool,
@@ -147,63 +128,30 @@ ModuleDependencyVector ClangImporter::bridgeClangModuleDependencies(
// Swift frontend option for input file path (Foo.modulemap).
swiftArgs.push_back(remapPath(clangModuleDep.ClangModuleMapFile));
// Handle VFSOverlay. If include tree is used, there is no need for overlay.
if (!ctx.ClangImporterOpts.UseClangIncludeTree) {
for (auto &overlay : ctx.SearchPathOpts.VFSOverlayFiles) {
swiftArgs.push_back("-vfsoverlay");
swiftArgs.push_back(remapPath(overlay));
}
}
// Add args reported by the scanner.
// Round-trip clang args to canonicalize and clear the options that swift
// compiler doesn't need.
clang::CompilerInvocation depsInvocation;
clang::DiagnosticsEngine clangDiags(new clang::DiagnosticIDs(),
new clang::DiagnosticOptions(),
new clang::IgnoringDiagConsumer());
llvm::SmallVector<const char*> clangArgs;
llvm::for_each(
clangModuleDep.getBuildArguments(),
[&](const std::string &Arg) { clangArgs.push_back(Arg.c_str()); });
bool success = clang::CompilerInvocation::CreateFromArgs(
depsInvocation, clangArgs, clangDiags);
(void)success;
assert(success && "clang option from dep scanner round trip failed");
// Create a prefix mapper that matches clang's configuration.
auto Mapper =
getClangPrefixMapper(clangScanningTool, clangModuleDep, depsInvocation);
// Clear the cache key for module. The module key is computed from clang
// invocation, not swift invocation.
depsInvocation.getFrontendOpts().ModuleCacheKeys.clear();
depsInvocation.getFrontendOpts().PathPrefixMappings.clear();
depsInvocation.getFrontendOpts().OutputFile.clear();
auto invocation = clangModuleDep.getUnderlyingCompilerInvocation();
// Clear some options from clang scanner.
invocation.getMutFrontendOpts().ModuleCacheKeys.clear();
invocation.getMutFrontendOpts().PathPrefixMappings.clear();
invocation.getMutFrontendOpts().OutputFile.clear();
// Reset CASOptions since that should be coming from swift.
depsInvocation.getCASOpts() = clang::CASOptions();
depsInvocation.getFrontendOpts().CASIncludeTreeID.clear();
invocation.getMutCASOpts() = clang::CASOptions();
invocation.getMutFrontendOpts().CASIncludeTreeID.clear();
// FIXME: workaround for rdar://105684525: find the -ivfsoverlay option
// from clang scanner and pass to swift.
for (auto overlay : depsInvocation.getHeaderSearchOpts().VFSOverlayFiles) {
if (llvm::is_contained(ctx.SearchPathOpts.VFSOverlayFiles, overlay))
continue;
swiftArgs.push_back("-vfsoverlay");
swiftArgs.push_back(overlay);
if (!ctx.CASOpts.EnableCaching) {
auto &overlayFiles = invocation.getMutHeaderSearchOpts().VFSOverlayFiles;
for (auto overlay : overlayFiles) {
swiftArgs.push_back("-vfsoverlay");
swiftArgs.push_back(overlay);
}
// Clear overlay files since they are forwarded from swift to clang.
overlayFiles.clear();
}
llvm::BumpPtrAllocator allocator;
llvm::StringSaver saver(allocator);
clangArgs.clear();
depsInvocation.generateCC1CommandLine(
clangArgs,
[&saver](const llvm::Twine &T) { return saver.save(T).data(); });
// Add args reported by the scanner.
auto clangArgs = invocation.getCC1CommandLine();
llvm::for_each(clangArgs, addClangArg);
// CASFileSystemRootID.
@@ -217,20 +165,11 @@ ModuleDependencyVector ClangImporter::bridgeClangModuleDependencies(
ctx.CASOpts.enumerateCASConfigurationFlags(
[&](StringRef Arg) { swiftArgs.push_back(Arg.str()); });
if (!RootID.empty()) {
swiftArgs.push_back("-no-clang-include-tree");
swiftArgs.push_back("-cas-fs");
swiftArgs.push_back(RootID);
}
if (!IncludeTree.empty()) {
swiftArgs.push_back("-clang-include-tree-root");
swiftArgs.push_back(IncludeTree);
}
std::string mappedPCMPath = pcmPath;
if (Mapper)
Mapper->mapInPlace(mappedPCMPath);
std::string mappedPCMPath = remapPath(pcmPath);
std::vector<LinkLibrary> LinkLibraries;
for (const auto &ll : clangModuleDep.LinkLibraries)
@@ -326,11 +265,6 @@ void ClangImporter::getBridgingHeaderOptions(
swiftArgs.push_back("-clang-include-tree-root");
swiftArgs.push_back(*Tree);
}
if (auto CASFS = deps.CASFileSystemRootID) {
swiftArgs.push_back("-no-clang-include-tree");
swiftArgs.push_back("-cas-fs");
swiftArgs.push_back(*CASFS);
}
}
ModuleDependencyVector

View File

@@ -474,7 +474,6 @@ public:
const bool BridgingHeaderExplicitlyRequested;
const bool DisableOverlayModules;
const bool EnableClangSPI;
const bool UseClangIncludeTree;
bool importSymbolicCXXDecls;
bool IsReadingBridgingPCH;

View File

@@ -595,14 +595,6 @@ ModuleDependencyScanner::getMainModuleDependencyInfo(ModuleDecl *mainModule) {
auto mainDependencies = ModuleDependencyInfo::forSwiftSourceModule(
{}, buildCommands, {}, {}, {});
if (ScanASTContext.CASOpts.EnableCaching) {
std::vector<std::string> clangDependencyFiles;
clangImporter->addClangInvovcationDependencies(clangDependencyFiles);
llvm::for_each(clangDependencyFiles, [&](std::string &file) {
mainDependencies.addAuxiliaryFile(file);
});
}
llvm::StringSet<> alreadyAddedModules;
// Compute Implicit dependencies of the main module
{

View File

@@ -45,7 +45,7 @@
#include "swift/Frontend/FrontendOptions.h"
#include "swift/Frontend/ModuleInterfaceLoader.h"
#include "swift/Strings.h"
#include "clang/Basic/Module.h"
#include "clang/CAS/IncludeTree.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/SetVector.h"
@@ -69,7 +69,6 @@
#include <sstream>
#include <stack>
#include <string>
#include <algorithm>
using namespace swift;
using namespace swift::dependencies;
@@ -101,9 +100,6 @@ public:
if (resolvingDepInfo.isFinalized())
return false;
if (auto ID = resolvingDepInfo.getClangIncludeTree())
includeTrees.push_back(*ID);
for (const auto &depModuleID : dependencies) {
const auto &depInfo = cache.findKnownDependency(depModuleID);
switch (depModuleID.Kind) {
@@ -320,10 +316,10 @@ private:
}
// Collect CAS deppendencies from clang modules.
if (!clangDepDetails.CASFileSystemRootID.empty())
rootIDs.push_back(clangDepDetails.CASFileSystemRootID);
if (!clangDepDetails.CASClangIncludeTreeRootID.empty())
includeTrees.push_back(clangDepDetails.CASClangIncludeTreeRootID);
if (!clangDepDetails.CASClangIncludeTreeRootID.empty()) {
if (addIncludeTree(clangDepDetails.CASClangIncludeTreeRootID))
return true;
}
collectUsedVFSOverlay(clangDepDetails);
@@ -358,12 +354,14 @@ private:
auto bridgeRoot = tracker->createTreeFromDependencies();
if (!bridgeRoot)
return diagnoseCASFSCreationError(bridgeRoot.takeError());
fileListIDs.push_back(bridgeRoot->getID().toString());
fileListRefs.push_back(bridgeRoot->getRef());
}
}
} else
includeTrees.push_back(sourceDepDetails.textualModuleDetails
.CASBridgingHeaderIncludeTreeRootID);
} else if (addIncludeTree(sourceDepDetails.textualModuleDetails
.CASBridgingHeaderIncludeTreeRootID))
return true;
return false;
};
@@ -499,9 +497,7 @@ private:
auto root = tracker->createTreeFromDependencies();
if (!root)
return diagnoseCASFSCreationError(root.takeError());
auto rootID = root->getID().toString();
dependencyInfoCopy.updateCASFileSystemRootID(rootID);
fileListIDs.push_back(rootID);
fileListRefs.push_back(root->getRef());
} else if (auto *textualDep =
resolvingDepInfo.getAsSwiftInterfaceModule()) {
tracker->startTracking();
@@ -516,29 +512,15 @@ private:
auto root = tracker->createTreeFromDependencies();
if (!root)
return diagnoseCASFSCreationError(root.takeError());
auto rootID = root->getID().toString();
dependencyInfoCopy.updateCASFileSystemRootID(rootID);
fileListIDs.push_back(rootID);
fileListRefs.push_back(root->getRef());
}
// Update build command line.
if (resolvingDepInfo.isSwiftInterfaceModule() ||
resolvingDepInfo.isSwiftSourceModule()) {
// Update with casfs option.
for (auto rootID : rootIDs) {
commandline.push_back("-cas-fs");
commandline.push_back(rootID);
}
for (auto tree : includeTrees) {
commandline.push_back("-clang-include-tree-root");
commandline.push_back(tree);
}
for (auto list : fileListIDs) {
commandline.push_back("-clang-include-tree-filelist");
commandline.push_back(list);
}
if (computeCASFileSystem(dependencyInfoCopy))
return true;
}
// Compute and update module cache key.
@@ -636,6 +618,53 @@ private:
cmd.push_back("-cache-disable-replay");
}
bool addIncludeTree(StringRef includeTree) {
auto &db = cache.getScanService().getCAS();
auto casID = db.parseID(includeTree);
if (!casID) {
instance.getDiags().diagnose(SourceLoc(), diag::error_invalid_cas_id,
includeTree, toString(casID.takeError()));
return true;
}
auto ref = db.getReference(*casID);
if (!ref) {
instance.getDiags().diagnose(SourceLoc(), diag::error_load_input_from_cas,
includeTree);
return true;
}
auto root = clang::cas::IncludeTreeRoot::get(db, *ref);
if (!root) {
instance.getDiags().diagnose(SourceLoc(), diag::error_cas_malformed_input,
includeTree, toString(root.takeError()));
return true;
}
fileListRefs.push_back(root->getFileListRef());
return false;
}
bool computeCASFileSystem(ModuleDependencyInfo &dependencyInfoCopy) {
if (fileListRefs.empty())
return false;
auto &db = cache.getScanService().getCAS();
auto casFS =
clang::cas::IncludeTree::FileList::create(db, {}, fileListRefs);
if (!casFS) {
instance.getDiags().diagnose(SourceLoc(), diag::error_cas,
"CAS IncludeTree FileList creation",
toString(casFS.takeError()));
return true;
}
auto casID = casFS->getID().toString();
dependencyInfoCopy.updateCASFileSystemRootID(casID);
commandline.push_back("-clang-include-tree-filelist");
commandline.push_back(casID);
return false;
}
private:
const ModuleDependencyID &moduleID;
ModuleDependenciesCache &cache;
@@ -643,9 +672,7 @@ private:
const ModuleDependencyInfo &resolvingDepInfo;
std::optional<SwiftDependencyTracker> tracker;
std::vector<std::string> rootIDs;
std::vector<std::string> includeTrees;
std::vector<std::string> fileListIDs;
std::vector<llvm::cas::ObjectRef> fileListRefs;
std::vector<std::string> commandline;
std::vector<std::string> bridgingHeaderBuildCmd;
llvm::StringMap<MacroPluginDependency> macros;

View File

@@ -449,53 +449,14 @@ static llvm::Error createCASObjectNotFoundError(const llvm::cas::CASID &ID) {
"CASID missing from Object Store " + ID.toString());
}
static Expected<ObjectRef> mergeCASFileSystem(ObjectStore &CAS,
ArrayRef<std::string> FSRoots) {
llvm::cas::HierarchicalTreeBuilder Builder;
for (auto &Root : FSRoots) {
auto ID = CAS.parseID(Root);
if (!ID)
return ID.takeError();
auto Ref = CAS.getReference(*ID);
if (!Ref)
return createCASObjectNotFoundError(*ID);
Builder.pushTreeContent(*Ref, "");
}
auto NewRoot = Builder.create(CAS);
if (!NewRoot)
return NewRoot.takeError();
return NewRoot->getRef();
}
Expected<IntrusiveRefCntPtr<vfs::FileSystem>>
createCASFileSystem(ObjectStore &CAS, ArrayRef<std::string> FSRoots,
ArrayRef<std::string> IncludeTrees,
ArrayRef<std::string> IncludeTreeFileList) {
assert(!FSRoots.empty() || !IncludeTrees.empty() ||
createCASFileSystem(ObjectStore &CAS, const std::string &IncludeTree,
const std::string &IncludeTreeFileList) {
assert(!IncludeTree.empty() ||
!IncludeTreeFileList.empty() && "no root ID provided");
if (FSRoots.size() == 1 && IncludeTrees.empty()) {
auto ID = CAS.parseID(FSRoots.front());
if (!ID)
return ID.takeError();
return createCASFileSystem(CAS, *ID);
}
auto NewRoot = mergeCASFileSystem(CAS, FSRoots);
if (!NewRoot)
return NewRoot.takeError();
auto FS = createCASFileSystem(CAS, CAS.getID(*NewRoot));
if (!FS)
return FS.takeError();
auto CASFS = makeIntrusiveRefCnt<vfs::OverlayFileSystem>(std::move(*FS));
std::vector<clang::cas::IncludeTree::FileList::FileEntry> Files;
// Push all Include File System onto overlay.
for (auto &Tree : IncludeTrees) {
auto ID = CAS.parseID(Tree);
if (!IncludeTree.empty()) {
auto ID = CAS.parseID(IncludeTree);
if (!ID)
return ID.takeError();
@@ -510,47 +471,33 @@ createCASFileSystem(ObjectStore &CAS, ArrayRef<std::string> FSRoots,
if (!ITF)
return ITF.takeError();
auto Err = ITF->forEachFile(
[&](clang::cas::IncludeTree::File File,
clang::cas::IncludeTree::FileList::FileSizeTy Size) -> llvm::Error {
Files.push_back({File.getRef(), Size});
return llvm::Error::success();
});
auto ITFS = clang::cas::createIncludeTreeFileSystem(*ITF);
if (!ITFS)
return ITFS.takeError();
if (Err)
return std::move(Err);
return *ITFS;
}
for (auto &List: IncludeTreeFileList) {
auto ID = CAS.parseID(List);
if (!IncludeTreeFileList.empty()) {
auto ID = CAS.parseID(IncludeTreeFileList);
if (!ID)
return ID.takeError();
auto Ref = CAS.getReference(*ID);
if (!Ref)
return createCASObjectNotFoundError(*ID);
auto IT = clang::cas::IncludeTree::FileList::get(CAS, *Ref);
if (!IT)
return IT.takeError();
auto ITF = clang::cas::IncludeTree::FileList::get(CAS, *Ref);
if (!ITF)
return ITF.takeError();
auto Err = IT->forEachFile(
[&](clang::cas::IncludeTree::File File,
clang::cas::IncludeTree::FileList::FileSizeTy Size) -> llvm::Error {
Files.push_back({File.getRef(), Size});
return llvm::Error::success();
});
auto ITFS = clang::cas::createIncludeTreeFileSystem(*ITF);
if (!ITFS)
return ITFS.takeError();
if (Err)
return std::move(Err);
return *ITFS;
}
auto ITFS = clang::cas::createIncludeTreeFileSystem(CAS, Files);
if (!ITFS)
return ITFS.takeError();
CASFS->pushOverlay(std::move(*ITFS));
return CASFS;
return nullptr;
}
std::vector<std::string> remapPathsFromCommandLine(

View File

@@ -761,12 +761,10 @@ static bool ParseCASArgs(CASOptions &Opts, ArgList &Args,
std::string(Value));
}
for (const auto &A : Args.getAllArgValues(OPT_cas_fs))
Opts.CASFSRootIDs.emplace_back(A);
for (const auto &A : Args.getAllArgValues(OPT_clang_include_tree_root))
Opts.ClangIncludeTrees.emplace_back(A);
for (const auto &A : Args.getAllArgValues(OPT_clang_include_tree_filelist))
Opts.ClangIncludeTreeFileList.emplace_back(A);
if (auto *A = Args.getLastArg(OPT_clang_include_tree_root))
Opts.ClangIncludeTree = A->getValue();
if (auto *A = Args.getLastArg(OPT_clang_include_tree_filelist))
Opts.ClangIncludeTreeFileList = A->getValue();
if (const Arg *A = Args.getLastArg(OPT_input_file_key))
Opts.InputFileKey = A->getValue();
@@ -774,8 +772,7 @@ static bool ParseCASArgs(CASOptions &Opts, ArgList &Args,
if (const Arg*A = Args.getLastArg(OPT_bridging_header_pch_key))
Opts.BridgingHeaderPCHCacheKey = A->getValue();
if (!Opts.CASFSRootIDs.empty() || !Opts.ClangIncludeTrees.empty() ||
!Opts.ClangIncludeTreeFileList.empty())
if (!Opts.ClangIncludeTree.empty() || !Opts.ClangIncludeTreeFileList.empty())
Opts.HasImmutableFileSystem = true;
return false;
@@ -2131,10 +2128,6 @@ static bool ParseClangImporterArgs(ClangImporterOptions &Opts, ArgList &Args,
// Forward the FrontendOptions to clang importer option so it can be
// accessed when creating clang module compilation invocation.
if (CASOpts.EnableCaching) {
// Only set UseClangIncludeTree when caching is enabled since it is not
// useful in non-caching context.
Opts.UseClangIncludeTree |= !Args.hasArg(OPT_no_clang_include_tree);
Opts.HasClangIncludeTreeRoot |= Args.hasArg(OPT_clang_include_tree_root);
// Caching requires direct clang import cc1 scanning.
Opts.ClangImporterDirectCC1Scan = true;
}

View File

@@ -630,11 +630,9 @@ bool CompilerInstance::setUpVirtualFileSystemOverlays() {
}
if (Invocation.getCASOptions().requireCASFS()) {
if (!CASOpts.CASFSRootIDs.empty() || !CASOpts.ClangIncludeTrees.empty() ||
!CASOpts.ClangIncludeTreeFileList.empty()) {
if (Invocation.getCASOptions().HasImmutableFileSystem) {
// Set up CASFS as BaseFS.
auto FS = createCASFileSystem(*CAS, CASOpts.CASFSRootIDs,
CASOpts.ClangIncludeTrees,
auto FS = createCASFileSystem(*CAS, CASOpts.ClangIncludeTree,
CASOpts.ClangIncludeTreeFileList);
if (!FS) {
Diagnostics.diagnose(SourceLoc(), diag::error_cas_fs_creation,
@@ -682,8 +680,8 @@ bool CompilerInstance::setUpVirtualFileSystemOverlays() {
}
}
llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayVFS =
new llvm::vfs::OverlayFileSystem(SourceMgr.getFileSystem());
OverlayVFS->pushOverlay(MemFS);
new llvm::vfs::OverlayFileSystem(MemFS);
OverlayVFS->pushOverlay(SourceMgr.getFileSystem());
SourceMgr.setFileSystem(std::move(OverlayVFS));
}
@@ -785,15 +783,6 @@ bool CompilerInstance::setUpModuleLoaders() {
this->DefaultSerializedLoader = ISML.get();
Context->addModuleLoader(std::move(ISML));
// When caching is enabled, we rely on ClangImporter for
// 'addClangInvovcationDependencies'
if (Invocation.getCASOptions().EnableCaching) {
std::unique_ptr<ClangImporter> clangImporter =
ClangImporter::create(*Context, Invocation.getPCHHash(),
getDependencyTracker());
Context->addModuleLoader(std::move(clangImporter), /*isClang*/ true);
}
return false;
}
@@ -967,10 +956,10 @@ std::string CompilerInstance::getBridgingHeaderPath() const {
}
bool CompilerInstance::setUpInputs() {
// There is no input file when building PCM using ClangIncludeTree.
// There is no input file when building PCM using Caching.
if (Invocation.getFrontendOptions().RequestedAction ==
FrontendOptions::ActionType::EmitPCM &&
Invocation.getClangImporterOptions().HasClangIncludeTreeRoot)
Invocation.getCASOptions().EnableCaching)
return false;
// Adds to InputSourceCodeBufferIDs, so may need to happen before the

View File

@@ -1815,13 +1815,6 @@ void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface(
casOpts.HasImmutableFileSystem;
casOpts.enumerateCASConfigurationFlags(
[&](StringRef Arg) { GenericArgs.push_back(ArgSaver.save(Arg)); });
// ClangIncludeTree is default on when caching is enabled.
genericSubInvocation.getClangImporterOptions().UseClangIncludeTree = true;
}
if (!clangImporterOpts.UseClangIncludeTree) {
genericSubInvocation.getClangImporterOptions().UseClangIncludeTree = false;
GenericArgs.push_back("-no-clang-include-tree");
}
}
@@ -2521,8 +2514,7 @@ struct ExplicitCASModuleLoader::Implementation {
};
for (auto &entry : ExplicitClangModuleMap) {
const auto &moduleMapPath = entry.getValue().moduleMapPath;
if (!moduleMapPath.empty() &&
!Ctx.ClangImporterOpts.UseClangIncludeTree &&
if (!moduleMapPath.empty() && !Ctx.CASOpts.EnableCaching &&
moduleMapsSeen.find(moduleMapPath) == moduleMapsSeen.end()) {
moduleMapsSeen.insert(moduleMapPath);
extraClangArgs.push_back(

View File

@@ -282,7 +282,7 @@ initializePlugin(ASTContext &ctx, CompilerPlugin *plugin, StringRef libraryPath,
if (!libraryPath.empty()) {
#if SWIFT_BUILD_SWIFT_SYNTAX
llvm::SmallString<128> resolvedLibraryPath;
auto fs = ctx.ClangImporterOpts.HasClangIncludeTreeRoot
auto fs = ctx.CASOpts.HasImmutableFileSystem
? llvm::vfs::getRealFileSystem()
: ctx.SourceMgr.getFileSystem();
if (auto err = fs->getRealPath(libraryPath, resolvedLibraryPath)) {

View File

@@ -231,16 +231,6 @@ SwiftModuleScanner::scanInterfaceFile(Twine moduleInterfacePath,
InPath, compiledCandidatesRefs, ArgsRefs, {}, {}, linkLibraries,
isFramework, isStatic, {}, /*module-cache-key*/ "", UserModVer);
if (Ctx.CASOpts.EnableCaching) {
std::vector<std::string> clangDependencyFiles;
auto clangImporter =
static_cast<ClangImporter *>(Ctx.getClangModuleLoader());
clangImporter->addClangInvovcationDependencies(clangDependencyFiles);
llvm::for_each(clangDependencyFiles, [&](std::string &file) {
Result->addAuxiliaryFile(file);
});
}
// Walk the source file to find the import declarations.
llvm::StringSet<> alreadyAddedModules;
Result->addModuleImports(*sourceFile, alreadyAddedModules,

View File

@@ -1,28 +0,0 @@
// RUN: %empty-directory(%t)
// RUN: mkdir -p %t/empty
// RUN: mkdir -p %t/cas
// RUN: llvm-cas --cas %t/cas --ingest %t/empty > %t/empty.casid
// RUN: not %target-swift-frontend -typecheck -cache-compile-job -cas-fs @%t/empty.casid -cas-path %t/cas %s 2>&1 | %FileCheck %s --check-prefix NO-INPUTS
// NO-INPUTS: error: error opening input file
// RUN: llvm-cas --cas %t/cas --ingest %s > %t/source.casid
// RUN: not %target-swift-frontend -typecheck -cache-compile-job -cas-fs @%t/source.casid -cas-path %t/cas %s 2>&1 | %FileCheck %s --check-prefix NO-RESOURCES
// NO-RESOURCES: error: unable to load standard library
/// Ingest the resource directory to satisfy the file system requirement. Also switch CWD to resource dir.
// RUN: llvm-cas --cas %t/cas --merge @%t/source.casid %test-resource-dir > %t/full.casid
// RUN: cd %test-resource-dir
// RUN: %target-swift-frontend -typecheck -cache-compile-job -cas-fs @%t/full.casid -cas-path %t/cas %s
/// Try clang importer.
// RUN: not %target-swift-frontend -typecheck -cache-compile-job -cas-fs @%t/full.casid -cas-path %t/cas %s -import-objc-header %S/Inputs/objc.h 2>&1 | %FileCheck %s --check-prefix NO-BRIDGING-HEADER
// NO-BRIDGING-HEADER: error: bridging header
// RUN: llvm-cas --cas %t/cas --merge @%t/full.casid %S/Inputs/objc.h > %t/bridging_header.casid
// RUN: %target-swift-frontend -typecheck -cache-compile-job -cas-fs @%t/bridging_header.casid -cas-path %t/cas %s -import-objc-header %S/Inputs/objc.h
/// Clean the CAS to save space.
// RUN: %empty-directory(%t)
func testFunc() {}

View File

@@ -2,7 +2,7 @@
// RUN: mkdir -p %t/cas
// RUN: not %target-swift-frontend -c -cache-compile-job -cas-path %t/cas %s -o %t/test.o 2>&1 | %FileCheck %s --check-prefix=NO-CASFS
// NO-CASFS: caching is enabled without -cas-fs option
// NO-CASFS: caching is enabled without CAS file-system options
// RUN: %target-swift-frontend -scan-dependencies -module-name Test -O \
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib \

View File

@@ -0,0 +1,28 @@
// RUN: %empty-directory(%t)
// RUN: split-file %s %t
// RUN: %target-swift-frontend -scan-dependencies -module-name Test -O -I %t/include \
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \
// RUN: %t/main.swift -o %t/deps.json -cache-compile-job -cas-path %t/cas -profile-coverage-mapping -profile-generate
// 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 A > %t/A.cmd
// RUN: %swift_frontend_plain @%t/A.cmd
// RUN: %FileCheck %s --input-file=%t/shim.cmd
// RUN: %FileCheck %s --input-file=%t/A.cmd
// CHECK: -direct-clang-cc1-module-build
// CHECK-NOT: -fcoverage-compilation-dir
//--- main.swift
import A
func test() {
a();
}
//--- include/A.swiftinterface
// swift-interface-format-version: 1.0
// swift-module-flags: -module-name A -O -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import -parse-stdlib -user-module-version 1.0
public func a() { }

View File

@@ -1,197 +0,0 @@
// REQUIRES: objc_interop
// RUN: %empty-directory(%t)
// 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 -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
// Check the contents of the JSON output
// RUN: %FileCheck %s -check-prefix CHECK -check-prefix CHECK-NO-SEARCH-PATHS < %t/deps.json
// 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 -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
// 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 -no-clang-include-tree
/// check cas-fs content
// RUN: %{python} %S/Inputs/SwiftDepsExtractor.py %t/deps.json E casFSRootID > %t/E_fs.casid
// RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-include-tree-list @%t/E_fs.casid | %FileCheck %s -check-prefix FS_ROOT_E
// RUN: %{python} %S/Inputs/SwiftDepsExtractor.py %t/deps.json clang:F casFSRootID > %t/F_fs.casid
// RUN: llvm-cas --cas %t/cas --ls-tree-recursive @%t/F_fs.casid | %FileCheck %s -check-prefix FS_ROOT_F
// RUN: %{python} %S/Inputs/SwiftDepsExtractor.py %t/deps.json deps commandLine > %t/deps.cmd
// RUN: %FileCheck %s -check-prefix MAIN_CMD -input-file=%t/deps.cmd
// FS_ROOT_E-DAG: E.swiftinterface
// FS_ROOT_E-DAG: SDKSettings.json
// FS_ROOT_F: CHeaders/A.h
// FS_ROOT_F: CHeaders/B.h
// FS_ROOT_F: CHeaders/C.h
// FS_ROOT_F: CHeaders/D.h
// FS_ROOT_F: CHeaders/F.h
// FS_ROOT_F: CHeaders/G.h
// FS_ROOT_F: CHeaders/H.h
// FS_ROOT_F: CHeaders/I.h
// FS_ROOT_F: CHeaders/X.h
// FS_ROOT_F: CHeaders/module.modulemap
// MAIN_CMD: -direct-clang-cc1-module-build
// MAIN_CMD: -cas-fs
// MAIN_CMD-NOT: -clang-include-tree-root
import C
import E
import G
import SubE
// CHECK: "mainModuleName": "deps"
/// --------Main module
// CHECK-LABEL: "modulePath": "deps.swiftmodule",
// CHECK-NEXT: sourceFiles
// CHECK-NEXT: module_deps.swift
// CHECK-NEXT: ],
// CHECK-NEXT: "directDependencies": [
// CHECK-DAG: "clang": "C"
// CHECK-DAG: "swift": "E"
// CHECK-DAG: "swift": "G"
// CHECK-DAG: "swift": "SubE"
// CHECK-DAG: "swift": "Swift"
// CHECK-DAG: "swift": "SwiftOnoneSupport"
// CHECK-DAG: "swift": "_Concurrency"
// CHECK-DAG: "swift": "_cross_import_E"
// CHECK: ],
// CHECK: "commandLine":
// CHECK: "casFSRootID":
// CHECK-NOT: "error: cannot open Swift placeholder dependency module map from"
// CHECK: "bridgingHeader":
// CHECK-NEXT: "path":
// CHECK-SAME: Bridging.h
// CHECK-NEXT: "sourceFiles":
// CHECK-NEXT: ChainedBridgingHeader.h
// CHECK-NEXT: Bridging.h
// CHECK-NEXT: BridgingOther.h
// CHECK: "moduleDependencies": [
// CHECK-NEXT: "F"
// CHECK-NEXT: ]
// CHECK: "swiftOverlayDependencies": [
// CHECK-DAG: "swift": "A"
// CHECK-DAG: "swift": "F"
/// --------Clang module C
// CHECK-LABEL: "modulePath": "{{.*}}{{/|\\}}C-{{.*}}.pcm",
// CHECK: "sourceFiles": [
// CHECK-DAG: module.modulemap
// CHECK-DAG: C.h
// CHECK: directDependencies
// CHECK-NEXT: {
// CHECK-NEXT: "clang": "B"
// CHECK: "moduleMapPath"
// CHECK-SAME: module.modulemap
// CHECK: "contextHash"
// CHECK-SAME: "{{.*}}"
/// --------Clang module B
// CHECK-LABEL: "modulePath": "{{.*}}{{/|\\}}B-{{.*}}.pcm",
// CHECK: "contextHash": "[[B_CONTEXT:.*]]",
// CHECK: "-o"
// CHECK-NEXT: B-{{.*}}[[B_CONTEXT]].pcm
// Check make-style dependencies
// CHECK-MAKE-DEPS: module_deps.swift
// CHECK-MAKE-DEPS-SAME: A.swiftinterface
// CHECK-MAKE-DEPS-SAME: G.swiftinterface
// CHECK-MAKE-DEPS-SAME: B.h
// CHECK-MAKE-DEPS-SAME: Bridging.h
// CHECK-MAKE-DEPS-SAME: BridgingOther.h
// CHECK-MAKE-DEPS-SAME: module.modulemap
/// --------Swift module F
// CHECK: "modulePath": "{{.*}}{{/|\\}}F-{{.*}}.swiftmodule",
// CHECK-NEXT: "sourceFiles": [
// CHECK-NEXT: ],
// CHECK-NEXT: "directDependencies": [
// CHECK-NEXT: {
// CHECK-DAG: "clang": "F"
// CHECK-DAG: "swift": "Swift"
// CHECK-DAG: "swift": "SwiftOnoneSupport"
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK: "details":
// CHECK: "moduleCacheKey":
/// --------Swift module A
// CHECK-LABEL: "modulePath": "{{.*}}{{/|\\}}A-{{.*}}.swiftmodule",
// CHECK: directDependencies
// CHECK-NEXT: {
// CHECK-DAG: "clang": "A"
// CHECK-DAG: "swift": "Swift"
// CHECK-DAG: "swift": "SwiftOnoneSupport"
// CHECK-NEXT: }
// CHECK: "details":
// CHECK: "moduleCacheKey":
/// --------Swift module G
// CHECK-LABEL: "modulePath": "{{.*}}{{/|\\}}G-{{.*}}.swiftmodule"
// CHECK: "directDependencies"
// CHECK-NEXT: {
// CHECK-DAG: "clang": "G"
// CHECK-DAG: "swift": "Swift"
// CHECK-DAG: "swift": "SwiftOnoneSupport"
// CHECK: ],
// CHECK-NEXT: "linkLibraries": [
// CHECK: "details": {
// CHECK: "commandLine": [
// CHECK: "-compile-module-from-interface"
// CHECK: "-target"
// CHECK: "-cache-compile-job"
// CHECK: "-cas-path"
// CHECK: "-module-name"
// CHECK: "G"
// CHECK: "-swift-version"
// CHECK: "5"
// CHECK: ],
// CHECK: "contextHash": "{{.*}}",
/// --------Swift module E
// CHECK: "swift": "E"
// CHECK-LABEL: modulePath": "{{.*}}{{/|\\}}E-{{.*}}.swiftmodule"
// CHECK: "directDependencies"
// CHECK-NEXT: {
// CHECK-NEXT: "swift": "Swift"
// CHECK: "moduleInterfacePath"
// CHECK-SAME: E.swiftinterface
/// --------Swift module Swift
// CHECK-LABEL: "modulePath": "{{.*}}{{/|\\}}Swift-{{.*}}.swiftmodule",
// CHECK: directDependencies
// CHECK-NEXT: {
// CHECK-NEXT: "clang": "SwiftShims"
/// --------Clang module SwiftShims
// CHECK-LABEL: "modulePath": "{{.*}}{{/|\\}}SwiftShims-{{.*}}.pcm",
// CHECK: "contextHash": "[[SHIMS_CONTEXT:.*]]",
// CHECK: "-o"
// CHECK-NEXT: SwiftShims-{{.*}}[[SHIMS_CONTEXT]].pcm
// CHECK-NO-SEARCH-PATHS-NOT: "-prebuilt-module-cache-path"

View File

@@ -4,46 +4,99 @@
// RUN: mkdir -p %t/clang-module-cache
// RUN: mkdir -p %t/cas
// RUN: split-file %s %t
// RUN: %hmaptool write %t/hmap.json %t/empty.hmap
// RUN: sed "s|DIR|%/t|g" %t/hmap.json.template > %t/hmap.json
// RUN: sed "s|DIR|%/t|g" %t/test.yaml.template > %t/test.yaml
// RUN: %hmaptool write %t/hmap.json %t/test.hmap
// RUN: %target-swift-frontend -scan-dependencies -module-cache-path %t/clang-module-cache \
// RUN: %t/Test.swift -o %t/deps.json -cache-compile-job -cas-path %t/cas \
// RUN: -Xcc -fmodule-map-file=%t/module.modulemap -Xcc -ivfsoverlay -Xcc %t/empty.yaml \
// RUN: -Xcc -I%t/empty.hmap
// RUN: %t/Test.swift -module-name Test -o %t/deps.json -cache-compile-job -cas-path %t/cas \
// RUN: -disable-implicit-string-processing-module-import -disable-implicit-concurrency-module-import \
// RUN: -Xcc -fmodule-map-file=%t/include/module.modulemap -Xcc -ivfsoverlay -Xcc %t/test.yaml \
// RUN: -Xcc -I%t/test.hmap -module-load-mode prefer-serialized -scanner-output-dir %t \
// RUN: -import-objc-header %t/Bridge.h -auto-bridging-header-chaining
// RUN: %validate-json %t/deps.json &>/dev/null
// RUN: %{python} %S/Inputs/SwiftDepsExtractor.py %t/deps.json deps casFSRootID > %t/fs.casid
// RUN: %{python} %S/Inputs/SwiftDepsExtractor.py %t/deps.json Test casFSRootID > %t/fs.casid
// RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-include-tree-list @%t/fs.casid | %FileCheck %s -DDIR=%basename_t -check-prefix FS_ROOT
// RUN: %{python} %S/Inputs/SwiftDepsExtractor.py %t/deps.json clang:Dummy clangIncludeTree > %t/tree.casid
// RUN: clang-cas-test --cas %t/cas --print-include-tree @%t/tree.casid | %FileCheck %s -DDIR=%basename_t -check-prefix INCLUDE_TREE
// FS_ROOT: [[DIR]].tmp/empty.hmap
// FS_ROOT: [[DIR]].tmp/empty.yaml
// FS_ROOT: [[DIR]].tmp/hidden/Dummy.h
// FS_ROOT: [[DIR]].tmp/hidden/a.h
// FS_ROOT: [[DIR]].tmp/hidden/b.h
// INCLUDE_TREE: [[DIR]].tmp/Dummy.h
// 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 clang:Dummy > %t/dummy.cmd
// RUN: %swift_frontend_plain @%t/dummy.cmd
// 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
// RUN: %cache-tool -cas-path %t/cas -cache-tool-action print-output-keys -- \
// 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
// 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/objc.pch\"" >> %t/MyApp.cmd
// RUN: echo "\"-bridging-header-pch-key\"" >> %t/MyApp.cmd
// RUN: echo "\"@%t/key\"" >> %t/MyApp.cmd
// RUN: echo "\"-explicit-swift-module-map-file\"" >> %t/MyApp.cmd
// RUN: echo "\"@%t/map.casid\"" >> %t/MyApp.cmd
// RUN: %target-swift-frontend -cache-compile-job -module-name Test -O -cas-path %t/cas @%t/MyApp.cmd %t/Test.swift \
// RUN: -emit-module -o %t/test.swiftmodule
//--- Test.swift
import Dummy
func test() {}
//--- module.modulemap
//--- Bridge.h
#include "b.h"
//--- hidden/module.modulemap
module Dummy {
umbrella header "Dummy.h"
}
//--- Dummy.h
//--- hidden/Dummy.h
#include "a.h"
void dummy(void);
//--- hmap.json
//--- hidden/a.h
/* empty file */
//--- hidden/b.h
/* empty file */
//--- hmap.json.template
{
"mappings": {}
"mappings": {
"a.h": "DIR/hidden/a.h",
"b.h": "DIR/hidden/b.h"
}
}
//--- empty.yaml
//--- test.yaml.template
{
"version": 0,
"case-sensitive": "false",
"use-external-names": true,
"roots": []
"roots": [
{
"type": "file",
"name": "DIR/include/module.modulemap",
"external-contents": "DIR/hidden/module.modulemap"
},
{
"type": "file",
"name": "DIR/include/Dummy.h",
"external-contents": "DIR/hidden/Dummy.h"
},
]
}

View File

@@ -41,7 +41,6 @@
// INCLUDE_TREE_F-NEXT: CHeaders/F.h
// MAIN_CMD: -direct-clang-cc1-module-build
// MAIN_CMD: -clang-include-tree-root
// MAIN_CMD: -clang-include-tree-filelist
import C

View File

@@ -1,17 +1,45 @@
// REQUIRES: objc_interop
// RUN: %empty-directory(%t)
// RUN: %empty-directory(%t/module-cache)
// RUN: %empty-directory(%t/redirects)
// RUN: %empty-directory(%t/inputs)
// RUN: split-file %s %t
// RUN: sed -e "s|OUT_DIR|%t/redirects|g" -e "s|IN_DIR|%S/Inputs/CHeaders|g" %t/overlay_template.yaml > %t/overlay.yaml
// RUN: sed -e "s|OUT_DIR|%t/redirects|g" -e "s|IN_DIR|%t/inputs|g" %t/overlay_template.yaml > %t/overlay.yaml
// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-interface -module-cache-path %t/module-cache %t/test.swift -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -Xcc -ivfsoverlay -Xcc %t/overlay.yaml
// RUN: %target-swift-frontend -scan-dependencies -module-load-mode prefer-serialized -module-cache-path %t/module-cache %t/test.swift -o %t/deps.json -I %t/inputs -I %S/Inputs/Swift -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -Xcc -ivfsoverlay -Xcc %t/overlay.yaml
// RUN: %validate-json %t/deps.json | %FileCheck %s
// 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 SwiftOnoneSupport > %t/onone.cmd
// RUN: %swift_frontend_plain @%t/onone.cmd
// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps.json clang:F > %t/F.cmd
// RUN: %swift_frontend_plain @%t/F.cmd
// RUN: %{python} %S/../CAS/Inputs/BuildCommandExtractor.py %t/deps.json F > %t/SwiftF.cmd
// RUN: %swift_frontend_plain @%t/SwiftF.cmd
// RUN: %{python} %S/../CAS/Inputs/GenerateExplicitModuleMap.py %t/deps.json > %t/map.json
// 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 "\"-explicit-swift-module-map-file\"" >> %t/MyApp.cmd
// RUN: echo "\"%t/map.json\"" >> %t/MyApp.cmd
// RUN: %target-swift-frontend @%t/MyApp.cmd %t/test.swift -Xcc -ivfsoverlay -Xcc %t/overlay.yaml \
// RUN: -emit-module -o %t/Test.swiftmodule
//--- redirects/RedirectedF.h
void funcRedirectedF(void);
//--- redirects/modulemap
module F {
header "F_2.h"
export *
}
//--- overlay_template.yaml
{
'version': 0,
@@ -20,8 +48,11 @@ void funcRedirectedF(void);
{
'name': 'IN_DIR', 'type': 'directory',
'contents': [
{ 'name': 'F.h', 'type': 'file',
{ 'name': 'F_2.h', 'type': 'file',
'external-contents': 'OUT_DIR/RedirectedF.h'
},
{ 'name': 'module.modulemap', 'type': 'file',
'external-contents': 'OUT_DIR/modulemap'
}
]
},
@@ -31,6 +62,8 @@ void funcRedirectedF(void);
//--- test.swift
import F
func testF() { funcRedirectedF() }
// CHECK: "mainModuleName": "deps"
/// --------Main module
// CHECK-LABEL: "modulePath": "deps.swiftmodule",
@@ -68,7 +101,4 @@ import F
// CHECK: "commandLine": [
// CHECK: "-vfsoverlay",
// CHECK-NEXT: "{{.*}}{{/|\\}}preserve_used_vfs.swift.tmp{{/|\\}}overlay.yaml",
// CHECK: "-ivfsoverlay",
// CHECK-NEXT: "-Xcc",
// CHECK-NEXT: "{{.*}}{{/|\\}}preserve_used_vfs.swift.tmp{{/|\\}}overlay.yaml",
// CHECK: ],