Introduce a package interface.

It has an extension .package.swiftinterface and contains package decls
as well as SPIs and public/inlinable decls. When a module is loaded
from interface, it now looks up the package-name in the interface
and checks if the importer is in the same package. If so, it uses
that package interface found to load the module. If not, uses the existing
logic to load modules.

Resolves rdar://104617854
This commit is contained in:
Ellie Shin
2023-10-27 17:40:49 -07:00
parent 24dc3721bd
commit aba3b6c24e
27 changed files with 367 additions and 64 deletions

View File

@@ -524,7 +524,7 @@ std::error_code ImplicitSerializedModuleLoader::findModuleFilesInDirectory(
if (ModuleInterfaceSourcePath) {
if (auto InterfacePath =
BaseName.findInterfacePath(*Ctx.SourceMgr.getFileSystem()))
BaseName.findInterfacePath(*Ctx.SourceMgr.getFileSystem(), Ctx))
ModuleInterfaceSourcePath->assign(InterfacePath->begin(),
InterfacePath->end());
}
@@ -596,17 +596,56 @@ std::string SerializedModuleBaseName::getName(file_types::ID fileTy) const {
return std::string(result.str());
}
llvm::Optional<std::string> SerializedModuleLoaderBase::getPackageInterfacePathIfInSamePackage(llvm::vfs::FileSystem &fs, ASTContext &ctx) {
std::string packagePath{
getName(file_types::TY_PackageSwiftModuleInterfaceFile)};
if (fs.exists(packagePath)) {
// Read the interface file and extract its package-name argument value
StringRef result;
if (auto packageFile = llvm::MemoryBuffer::getFile(packagePath)) {
llvm::BumpPtrAllocator alloc;
llvm::StringSaver argSaver(alloc);
SmallVector<const char*, 8> args;
(void)extractCompilerFlagsFromInterface(packagePath,
(*packageFile)->getBuffer(), argSaver, args);
for (unsigned I = 0, N = args.size(); I + 1 < N; I++) {
StringRef current(args[I]), next(args[I + 1]);
if (current == "-package-name") {
result = next;
break;
}
}
}
// Return the .package.swiftinterface path if the package name applies to
// the importer module.
if (!result.empty() && result == ctx.LangOpts.PackageName)
return packagePath;
}
return {};
}
llvm::Optional<std::string>
SerializedModuleBaseName::findInterfacePath(llvm::vfs::FileSystem &fs) const {
SerializedModuleBaseName::findInterfacePath(llvm::vfs::FileSystem &fs, ASTContext &ctx) const {
std::string interfacePath{getName(file_types::TY_SwiftModuleInterfaceFile)};
// Ensure the public swiftinterface already exists, otherwise bail early.
if (!fs.exists(interfacePath))
return {};
// Check if a package interface exists and if the package name applies to
// the importer module.
auto packagePath = getPackageInterfacePathIfInSamePackage(fs, ctx);
if (fs.exists(packagePath))
return packagePath;
// If above fails, use the existing logic.
// If present, use the private interface instead of the public one.
std::string privatePath{
getName(file_types::TY_PrivateSwiftModuleInterfaceFile)};
if (fs.exists(privatePath))
return privatePath;
// Otherwise return the public .swiftinterface path
return interfacePath;
}
@@ -688,6 +727,7 @@ bool SerializedModuleLoaderBase::findModule(
(moduleName + ".framework").str(),
genericBaseName.getName(file_types::TY_SwiftModuleInterfaceFile),
genericBaseName.getName(file_types::TY_PrivateSwiftModuleInterfaceFile),
genericBaseName.getName(file_types::TY_PackageSwiftModuleInterfaceFile),
genericBaseName.getName(file_types::TY_SwiftModuleFile)};
auto searchPaths = Ctx.SearchPathOpts.moduleSearchPathsContainingFile(