[llvm][TextAPI] Add new not_for_dyld_shared_cache attribute to file… (#71735)

… format.

Formats >= TBDv4 will now encode new attribute that the system static
linker wil read when tbd files replace binary dylibs.
This commit is contained in:
Cyndy Ishida 2023-11-09 09:22:16 -08:00 committed by GitHub
parent dfecfc7ed0
commit e17efa60b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 139 additions and 1 deletions

View File

@ -248,6 +248,14 @@ public:
/// Check if the library uses two-level namespace.
bool isTwoLevelNamespace() const { return IsTwoLevelNamespace; }
/// Specify if the library is an OS library but not shared cache eligible.
void setOSLibNotForSharedCache(bool V = true) {
IsOSLibNotForSharedCache = V;
}
/// Check if the library is an OS library that is not shared cache eligible.
bool isOSLibNotForSharedCache() const { return IsOSLibNotForSharedCache; }
/// Specify if the library is application extension safe (or not).
void setApplicationExtensionSafe(bool V = true) { IsAppExtensionSafe = V; }
@ -455,6 +463,7 @@ private:
PackedVersion CompatibilityVersion;
uint8_t SwiftABIVersion{0};
bool IsTwoLevelNamespace{false};
bool IsOSLibNotForSharedCache{false};
bool IsAppExtensionSafe{false};
bool HasSimSupport{false};
ObjCConstraintType ObjcConstraint = ObjCConstraintType::None;

View File

@ -361,6 +361,8 @@ bool InterfaceFile::operator==(const InterfaceFile &O) const {
return false;
if (IsAppExtensionSafe != O.IsAppExtensionSafe)
return false;
if (IsOSLibNotForSharedCache != O.IsOSLibNotForSharedCache)
return false;
if (HasSimSupport != O.HasSimSupport)
return false;
if (ParentUmbrellas != O.ParentUmbrellas)

View File

@ -360,6 +360,8 @@ template <> struct ScalarBitSetTraits<TBDFlags> {
IO.bitSetCase(Flags, "not_app_extension_safe",
TBDFlags::NotApplicationExtensionSafe);
IO.bitSetCase(Flags, "installapi", TBDFlags::InstallAPI);
IO.bitSetCase(Flags, "not_for_dyld_shared_cache",
TBDFlags::OSLibNotForSharedCache);
}
};
@ -782,6 +784,9 @@ template <> struct MappingTraits<const InterfaceFile *> {
if (!File->isTwoLevelNamespace())
Flags |= TBDFlags::FlatNamespace;
if (File->isOSLibNotForSharedCache())
Flags |= TBDFlags::OSLibNotForSharedCache;
{
std::map<std::string, TargetList> valueToTargetList;
for (const auto &it : File->umbrellas())
@ -872,6 +877,8 @@ template <> struct MappingTraits<const InterfaceFile *> {
File->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
File->setApplicationExtensionSafe(
!(Flags & TBDFlags::NotApplicationExtensionSafe));
File->setOSLibNotForSharedCache(
(Flags & TBDFlags::OSLibNotForSharedCache));
for (const auto &CurrentSection : AllowableClients) {
for (const auto &lib : CurrentSection.Values)

View File

@ -29,7 +29,8 @@ enum TBDFlags : unsigned {
NotApplicationExtensionSafe = 1U << 1,
InstallAPI = 1U << 2,
SimulatorSupport = 1U << 3,
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/SimulatorSupport),
OSLibNotForSharedCache = 1U << 4,
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OSLibNotForSharedCache),
};
// clang-format on

View File

@ -564,6 +564,8 @@ Expected<TBDFlags> getFlags(const Object *File) {
.Case("not_app_extension_safe",
TBDFlags::NotApplicationExtensionSafe)
.Case("sim_support", TBDFlags::SimulatorSupport)
.Case("not_for_dyld_shared_cache",
TBDFlags::OSLibNotForSharedCache)
.Default(TBDFlags::None);
Flags |= TBDFlag;
});
@ -655,6 +657,7 @@ Expected<IFPtr> parseToInterfaceFile(const Object *File) {
F->setApplicationExtensionSafe(
!(Flags & TBDFlags::NotApplicationExtensionSafe));
F->setSimulatorSupport((Flags & TBDFlags::SimulatorSupport));
F->setOSLibNotForSharedCache((Flags & TBDFlags::OSLibNotForSharedCache));
for (auto &T : Targets)
F->addTarget(T);
for (auto &[Lib, Targets] : Clients)
@ -923,6 +926,8 @@ Array serializeFlags(const InterfaceFile *File) {
Flags.emplace_back("not_app_extension_safe");
if (File->hasSimulatorSupport())
Flags.emplace_back("sim_support");
if (File->isOSLibNotForSharedCache())
Flags.emplace_back("not_for_dyld_shared_cache");
return serializeScalar(TBDKey::Attributes, std::move(Flags));
}

View File

@ -0,0 +1,49 @@
; RUN: rm -rf %t
; RUN: split-file %s %t
; RUN: not llvm-readtapi --compare %t/tbdv4.tbd %t/tbdv5.tbd 2>&1 | FileCheck %s
; CHECK: < {{.*}}tbdv4.tbd
; CHECK: > {{.*}}tbdv5.tbd
CHECK: Two Level Namespace
CHECK-NEXT: < true
CHECK-NEXT: > false
CHECK-NEXT: Shared Cache Ineligible
CHECK-NEXT: < true
CHECK-NEXT: > false
//--- tbdv4.tbd
--- !tapi-tbd
tbd-version: 4
targets: [ arm64-macos ]
flags: [ not_app_extension_safe, not_for_dyld_shared_cache ]
install-name: '/usr/lib/libFake.dylib'
...
//--- tbdv5.tbd
{
"main_library": {
"flags": [
{
"attributes": [
"not_app_extension_safe",
"flat_namespace"
]
}
],
"install_names": [
{
"name": "/usr/lib/libFake.dylib"
}
],
"target_info": [
{
"min_deployment": "13",
"target": "arm64-macos"
}
]
},
"tapi_tbd_version": 5
}

View File

@ -370,6 +370,14 @@ DiffEngine::findDifferences(const InterfaceFile *IFLHS,
rhs, IFRHS->hasSimulatorSupport()),
"Simulator Support"));
if (IFLHS->isOSLibNotForSharedCache() != IFRHS->isOSLibNotForSharedCache())
Output.push_back(
recordDifferences(DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
lhs, IFLHS->isOSLibNotForSharedCache()),
DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
rhs, IFRHS->isOSLibNotForSharedCache()),
"Shared Cache Ineligible"));
if (IFLHS->reexportedLibraries() != IFRHS->reexportedLibraries())
Output.push_back(recordDifferences(IFLHS->reexportedLibraries(),
IFRHS->reexportedLibraries(),

View File

@ -100,6 +100,7 @@ TEST(TBDv4, ReadFile) {
EXPECT_EQ(5U, File->getSwiftABIVersion());
EXPECT_FALSE(File->isTwoLevelNamespace());
EXPECT_TRUE(File->isApplicationExtensionSafe());
EXPECT_FALSE(File->isOSLibNotForSharedCache());
InterfaceFileRef client("ClientA", Targets);
InterfaceFileRef reexport("/System/Library/Frameworks/A.framework/A",
{Targets[0]});
@ -832,6 +833,29 @@ TEST(TBDv4, Swift_99) {
stripWhitespace(Buffer.c_str()));
}
TEST(TBDv4, NotForSharedCache) {
static const char TBDv4NotForSharedCache[] =
"--- !tapi-tbd\n"
"tbd-version: 4\n"
"targets: [ arm64-macos ]\n"
"flags: [ not_for_dyld_shared_cache ]\n"
"install-name: /S/L/F/Foo.framework/Foo\n"
"...\n";
Expected<TBDFile> Result =
TextAPIReader::get(MemoryBufferRef(TBDv4NotForSharedCache, "Test.tbd"));
EXPECT_TRUE(!!Result);
Target ExpectedTarget = Target(AK_arm64, PLATFORM_MACOS);
TBDFile ReadFile = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V4, ReadFile->getFileType());
EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
ReadFile->getInstallName());
EXPECT_TRUE(ReadFile->targets().begin() != ReadFile->targets().end());
EXPECT_EQ(*ReadFile->targets().begin(), ExpectedTarget);
EXPECT_TRUE(ReadFile->isOSLibNotForSharedCache());
}
TEST(TBDv4, InvalidArchitecture) {
static const char TBDv4UnknownArch[] = "--- !tapi-tbd\n"
"tbd-version: 4\n"

View File

@ -218,6 +218,7 @@ TEST(TBDv5, ReadFile) {
EXPECT_EQ(PackedVersion(1, 1, 0), File->getCompatibilityVersion());
EXPECT_TRUE(File->isApplicationExtensionSafe());
EXPECT_FALSE(File->isTwoLevelNamespace());
EXPECT_FALSE(File->isOSLibNotForSharedCache());
EXPECT_EQ(0U, File->documents().size());
InterfaceFileRef ClientA("ClientA", AllTargets);
@ -1197,6 +1198,38 @@ TEST(TBDv5, SimSupport) {
EXPECT_TRUE(ReadFile->hasSimulatorSupport());
}
TEST(TBDv5, NotForSharedCache) {
static const char TBDv5File[] = R"({
"tapi_tbd_version": 5,
"main_library": {
"target_info": [
{
"target": "arm64-macos",
"min_deployment": "11.1"
}
],
"install_names":[
{ "name":"/S/L/F/Foo.framework/Foo" }
],
"flags":[
{ "attributes": ["not_for_dyld_shared_cache"] }
]
}})";
Expected<TBDFile> Result =
TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
EXPECT_TRUE(!!Result);
Target ExpectedTarget = Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 1));
TBDFile ReadFile = std::move(Result.get());
EXPECT_EQ(FileType::TBD_V5, ReadFile->getFileType());
EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
ReadFile->getInstallName());
EXPECT_TRUE(ReadFile->targets().begin() != ReadFile->targets().end());
EXPECT_EQ(*ReadFile->targets().begin(), ExpectedTarget);
EXPECT_FALSE(ReadFile->hasSimulatorSupport());
EXPECT_TRUE(ReadFile->isOSLibNotForSharedCache());
}
TEST(TBDv5, MergeIF) {
static const char TBDv5FileA[] = R"({
"tapi_tbd_version": 5,