diff --git a/llvm/include/llvm/TextAPI/InterfaceFile.h b/llvm/include/llvm/TextAPI/InterfaceFile.h index ae2bf78403f4f1..d5e3e7e4c0a7c3 100644 --- a/llvm/include/llvm/TextAPI/InterfaceFile.h +++ b/llvm/include/llvm/TextAPI/InterfaceFile.h @@ -248,6 +248,14 @@ class InterfaceFile { /// 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 @@ class InterfaceFile { PackedVersion CompatibilityVersion; uint8_t SwiftABIVersion{0}; bool IsTwoLevelNamespace{false}; + bool IsOSLibNotForSharedCache{false}; bool IsAppExtensionSafe{false}; bool HasSimSupport{false}; ObjCConstraintType ObjcConstraint = ObjCConstraintType::None; diff --git a/llvm/lib/TextAPI/InterfaceFile.cpp b/llvm/lib/TextAPI/InterfaceFile.cpp index f1c6add67b97b9..3689ab9191915a 100644 --- a/llvm/lib/TextAPI/InterfaceFile.cpp +++ b/llvm/lib/TextAPI/InterfaceFile.cpp @@ -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) diff --git a/llvm/lib/TextAPI/TextStub.cpp b/llvm/lib/TextAPI/TextStub.cpp index cbb185fd51c5dc..635f6b3a3df6dd 100644 --- a/llvm/lib/TextAPI/TextStub.cpp +++ b/llvm/lib/TextAPI/TextStub.cpp @@ -360,6 +360,8 @@ template <> struct ScalarBitSetTraits { 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 { if (!File->isTwoLevelNamespace()) Flags |= TBDFlags::FlatNamespace; + if (File->isOSLibNotForSharedCache()) + Flags |= TBDFlags::OSLibNotForSharedCache; + { std::map valueToTargetList; for (const auto &it : File->umbrellas()) @@ -872,6 +877,8 @@ template <> struct MappingTraits { 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) diff --git a/llvm/lib/TextAPI/TextStubCommon.h b/llvm/lib/TextAPI/TextStubCommon.h index 5faba09fa1bbff..360910c48d4fe5 100644 --- a/llvm/lib/TextAPI/TextStubCommon.h +++ b/llvm/lib/TextAPI/TextStubCommon.h @@ -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 diff --git a/llvm/lib/TextAPI/TextStubV5.cpp b/llvm/lib/TextAPI/TextStubV5.cpp index f6a3fef088e464..3546c699bce0ea 100644 --- a/llvm/lib/TextAPI/TextStubV5.cpp +++ b/llvm/lib/TextAPI/TextStubV5.cpp @@ -564,6 +564,8 @@ Expected 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 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)); } diff --git a/llvm/test/tools/llvm-readtapi/compare-flags.test b/llvm/test/tools/llvm-readtapi/compare-flags.test new file mode 100644 index 00000000000000..06184eeb7661e1 --- /dev/null +++ b/llvm/test/tools/llvm-readtapi/compare-flags.test @@ -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 +} + diff --git a/llvm/tools/llvm-readtapi/DiffEngine.cpp b/llvm/tools/llvm-readtapi/DiffEngine.cpp index 0dd0d91616b135..5f4b25ca6c0b2d 100644 --- a/llvm/tools/llvm-readtapi/DiffEngine.cpp +++ b/llvm/tools/llvm-readtapi/DiffEngine.cpp @@ -370,6 +370,14 @@ DiffEngine::findDifferences(const InterfaceFile *IFLHS, rhs, IFRHS->hasSimulatorSupport()), "Simulator Support")); + if (IFLHS->isOSLibNotForSharedCache() != IFRHS->isOSLibNotForSharedCache()) + Output.push_back( + recordDifferences(DiffScalarVal( + lhs, IFLHS->isOSLibNotForSharedCache()), + DiffScalarVal( + rhs, IFRHS->isOSLibNotForSharedCache()), + "Shared Cache Ineligible")); + if (IFLHS->reexportedLibraries() != IFRHS->reexportedLibraries()) Output.push_back(recordDifferences(IFLHS->reexportedLibraries(), IFRHS->reexportedLibraries(), diff --git a/llvm/unittests/TextAPI/TextStubV4Tests.cpp b/llvm/unittests/TextAPI/TextStubV4Tests.cpp index 43b3c4adadbddd..2fefd7910a70c2 100644 --- a/llvm/unittests/TextAPI/TextStubV4Tests.cpp +++ b/llvm/unittests/TextAPI/TextStubV4Tests.cpp @@ -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 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" diff --git a/llvm/unittests/TextAPI/TextStubV5Tests.cpp b/llvm/unittests/TextAPI/TextStubV5Tests.cpp index 60976a5f064818..ac979a81bfc348 100644 --- a/llvm/unittests/TextAPI/TextStubV5Tests.cpp +++ b/llvm/unittests/TextAPI/TextStubV5Tests.cpp @@ -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 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,