mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[ClangImporter] Use TextAPI apis for capturing current-version (#67204)
Use LLVM apis for understanding TBD files instead of parsing the yaml directly. This prevents breaking the compiler when TBD-v5 exists which is in json.
This commit is contained in:
@@ -77,7 +77,8 @@
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/VirtualFileSystem.h"
|
||||
#include "llvm/Support/VirtualOutputBackend.h"
|
||||
#include "llvm/Support/YAMLParser.h"
|
||||
#include "llvm/TextAPI/InterfaceFile.h"
|
||||
#include "llvm/TextAPI/TextAPIReader.h"
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -1934,9 +1935,29 @@ bool ClangImporter::isModuleImported(const clang::Module *M) {
|
||||
return M->NameVisibility == clang::Module::NameVisibilityKind::AllVisible;
|
||||
}
|
||||
|
||||
static std::string getScalaNodeText(llvm::yaml::Node *N) {
|
||||
SmallString<32> Buffer;
|
||||
return cast<llvm::yaml::ScalarNode>(N)->getValue(Buffer).str();
|
||||
static llvm::VersionTuple getCurrentVersionFromTBD(StringRef path,
|
||||
StringRef moduleName) {
|
||||
std::string fwName = (moduleName + ".framework").str();
|
||||
auto pos = path.find(fwName);
|
||||
if (pos == StringRef::npos)
|
||||
return {};
|
||||
llvm::SmallString<256> buffer(path.substr(0, pos + fwName.size()));
|
||||
llvm::sys::path::append(buffer, moduleName + ".tbd");
|
||||
auto tbdPath = buffer.str();
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> tbdBufOrErr =
|
||||
llvm::MemoryBuffer::getFile(tbdPath);
|
||||
// .tbd file doesn't exist, exit.
|
||||
if (!tbdBufOrErr)
|
||||
return {};
|
||||
auto tbdFileOrErr =
|
||||
llvm::MachO::TextAPIReader::get(tbdBufOrErr.get()->getMemBufferRef());
|
||||
if (auto err = tbdFileOrErr.takeError()) {
|
||||
consumeError(std::move(err));
|
||||
return {};
|
||||
}
|
||||
auto tbdCV = (*tbdFileOrErr)->getCurrentVersion();
|
||||
return llvm::VersionTuple(tbdCV.getMajor(), tbdCV.getMinor(),
|
||||
tbdCV.getSubminor());
|
||||
}
|
||||
|
||||
bool ClangImporter::canImportModule(ImportPath::Module modulePath,
|
||||
@@ -1988,49 +2009,13 @@ bool ClangImporter::canImportModule(ImportPath::Module modulePath,
|
||||
return true;
|
||||
|
||||
assert(available);
|
||||
llvm::VersionTuple currentVersion;
|
||||
StringRef path = getClangASTContext().getSourceManager()
|
||||
.getFilename(clangModule->DefinitionLoc);
|
||||
|
||||
// Look for the .tbd file inside .framework dir to get the project version
|
||||
// number.
|
||||
std::string fwName = (llvm::Twine(topModule.Item.str()) + ".framework").str();
|
||||
auto pos = path.find(fwName);
|
||||
while (pos != StringRef::npos) {
|
||||
llvm::SmallString<256> buffer(path.substr(0, pos + fwName.size()));
|
||||
llvm::sys::path::append(buffer, llvm::Twine(topModule.Item.str()) + ".tbd");
|
||||
auto tbdPath = buffer.str();
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> tbdBufOrErr =
|
||||
llvm::MemoryBuffer::getFile(tbdPath);
|
||||
// .tbd file doesn't exist, break.
|
||||
if (!tbdBufOrErr) {
|
||||
break;
|
||||
}
|
||||
StringRef tbdBuffer = tbdBufOrErr->get()->getBuffer();
|
||||
|
||||
// Use a new source manager instead of the one from ASTContext because we
|
||||
// don't want the Json file to be persistent.
|
||||
SourceManager SM;
|
||||
llvm::yaml::Stream Stream(llvm::MemoryBufferRef(tbdBuffer, tbdPath),
|
||||
SM.getLLVMSourceMgr());
|
||||
auto DI = Stream.begin();
|
||||
assert(DI != Stream.end() && "Failed to read a document");
|
||||
llvm::yaml::Node *N = DI->getRoot();
|
||||
assert(N && "Failed to find a root");
|
||||
auto *pairs = dyn_cast_or_null<llvm::yaml::MappingNode>(N);
|
||||
if (!pairs)
|
||||
break;
|
||||
for (auto &keyValue: *pairs) {
|
||||
auto key = getScalaNodeText(keyValue.getKey());
|
||||
// Look for field "current-version" in the .tbd file.
|
||||
if (key == "current-version") {
|
||||
auto ver = getScalaNodeText(keyValue.getValue());
|
||||
currentVersion.tryParse(ver);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
llvm::VersionTuple currentVersion =
|
||||
getCurrentVersionFromTBD(path, topModule.Item.str());
|
||||
versionInfo->setVersion(currentVersion,
|
||||
ModuleVersionSourceKind::ClangModuleTBD);
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
--- !tapi-tbd
|
||||
tbd-version: 4
|
||||
targets: [ arm64-macos, arm64-ios, arm64-watchos, arm64-tvos,
|
||||
arm64-ios-simulator, arm64-watchos-simulator, arm64-tvos-simulator ]
|
||||
flags: [ not_app_extension_safe ]
|
||||
install-name: '/System/Library/Frameworks/Simple.framework/Versions/A/Simple'
|
||||
current-version: 1830.100
|
||||
...
|
||||
@@ -3,9 +3,6 @@
|
||||
// RUN: %empty-directory(%t/frameworks)
|
||||
|
||||
// RUN: cp -rf %S/Inputs/frameworks/Simple.framework %t/frameworks/
|
||||
|
||||
// RUN: echo "current-version: 1830.100" > %t/frameworks/Simple.framework/Simple.tbd
|
||||
|
||||
// RUN: %target-typecheck-verify-swift -disable-implicit-concurrency-module-import -F %t/frameworks
|
||||
|
||||
import Simple
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// conditional, the version in the `.tbd` should be honored. When `_version`
|
||||
// is specified, the version from the `.swiftmodule` should be honored.
|
||||
|
||||
// RUN: echo "current-version: 3" > %t/frameworks/Simple.framework/Simple.tbd
|
||||
// RUN: sed -i -e "s/1830\.100/3/g" %t/frameworks/Simple.framework/Simple.tbd
|
||||
// RUN: echo "@_exported import Simple" > %t.overlay.swift
|
||||
// RUN: echo "public func additional() {}" >> %t.overlay.swift
|
||||
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
// RUN: %empty-directory(%t/frameworks)
|
||||
|
||||
// RUN: cp -rf %S/Inputs/frameworks/Simple.framework %t/frameworks/
|
||||
|
||||
// RUN: echo "" > %t/frameworks/Simple.framework/Simple.tbd
|
||||
// RUN: rm -rf %t/frameworks/Simple.framework/Simple.tbd
|
||||
// RUN: %target-typecheck-verify-swift -disable-implicit-concurrency-module-import -F %t/frameworks
|
||||
|
||||
import Simple
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// should be no diagnostics and the version in the `.swiftmodule` should be
|
||||
// honored.
|
||||
|
||||
// RUN: echo "" > %t/frameworks/Simple.framework/Simple.tbd
|
||||
// RUN: rm -rf %t/frameworks/Simple.framework/Simple.tbd
|
||||
// RUN: echo "@_exported import Simple" > %t.overlay.swift
|
||||
// RUN: echo "public func additional() {}" >> %t.overlay.swift
|
||||
|
||||
|
||||
Reference in New Issue
Block a user