From b2b50980de240b3d89e0f9340b51d6d6079fd19d Mon Sep 17 00:00:00 2001 From: Cyndy Ishida Date: Wed, 22 Feb 2023 11:39:23 -0800 Subject: [PATCH] Revert "[TextAPI] Implement TBDv5 Writer" This reverts commit 8217932aabcb271df7eb30e069fdace904299cba. Breaks buildbots. --- llvm/include/llvm/TextAPI/InterfaceFile.h | 11 +- llvm/include/llvm/TextAPI/PackedVersion.h | 2 - llvm/include/llvm/TextAPI/TextAPIWriter.h | 3 +- llvm/lib/TextAPI/PackedVersion.cpp | 7 - llvm/lib/TextAPI/TextStub.cpp | 9 +- llvm/lib/TextAPI/TextStubCommon.h | 3 - llvm/lib/TextAPI/TextStubV5.cpp | 295 ---------------- llvm/unittests/TextAPI/TextStubV5Tests.cpp | 520 ----------------------------- 8 files changed, 3 insertions(+), 847 deletions(-) diff --git a/llvm/include/llvm/TextAPI/InterfaceFile.h b/llvm/include/llvm/TextAPI/InterfaceFile.h index 2ee22ee..c32917d 100644 --- a/llvm/include/llvm/TextAPI/InterfaceFile.h +++ b/llvm/include/llvm/TextAPI/InterfaceFile.h @@ -396,16 +396,7 @@ public: const_filtered_symbol_range exports() const { std::function fn = [](const Symbol *Symbol) { - return !Symbol->isUndefined() && !Symbol->isReexported(); - }; - return make_filter_range( - make_range({Symbols.begin()}, {Symbols.end()}), - fn); - } - - const_filtered_symbol_range reexports() const { - std::function fn = [](const Symbol *Symbol) { - return Symbol->isReexported(); + return !Symbol->isUndefined(); }; return make_filter_range( make_range({Symbols.begin()}, {Symbols.end()}), diff --git a/llvm/include/llvm/TextAPI/PackedVersion.h b/llvm/include/llvm/TextAPI/PackedVersion.h index f9cdf4a..24bec2e 100644 --- a/llvm/include/llvm/TextAPI/PackedVersion.h +++ b/llvm/include/llvm/TextAPI/PackedVersion.h @@ -53,8 +53,6 @@ public: uint32_t rawValue() const { return Version; } - operator std::string() const; - void print(raw_ostream &OS) const; }; diff --git a/llvm/include/llvm/TextAPI/TextAPIWriter.h b/llvm/include/llvm/TextAPI/TextAPIWriter.h index 9bdaaf5..f9857a8 100644 --- a/llvm/include/llvm/TextAPI/TextAPIWriter.h +++ b/llvm/include/llvm/TextAPI/TextAPIWriter.h @@ -22,8 +22,7 @@ class TextAPIWriter { public: TextAPIWriter() = delete; - static Error writeToStream(raw_ostream &OS, const InterfaceFile &File, - bool Compact = false); + static Error writeToStream(raw_ostream &os, const InterfaceFile &); }; } // end namespace MachO. diff --git a/llvm/lib/TextAPI/PackedVersion.cpp b/llvm/lib/TextAPI/PackedVersion.cpp index 22960c3..67fb30a 100644 --- a/llvm/lib/TextAPI/PackedVersion.cpp +++ b/llvm/lib/TextAPI/PackedVersion.cpp @@ -100,13 +100,6 @@ std::pair PackedVersion::parse64(StringRef Str) { return std::make_pair(true, Truncated); } -PackedVersion::operator std::string() const { - SmallString<32> Str; - raw_svector_ostream OS(Str); - print(OS); - return std::string(Str); -} - void PackedVersion::print(raw_ostream &OS) const { OS << format("%d", getMajor()); if (getMinor() || getSubminor()) diff --git a/llvm/lib/TextAPI/TextStub.cpp b/llvm/lib/TextAPI/TextStub.cpp index c51edc1..73cb614 100644 --- a/llvm/lib/TextAPI/TextStub.cpp +++ b/llvm/lib/TextAPI/TextStub.cpp @@ -1159,17 +1159,10 @@ TextAPIReader::get(MemoryBufferRef InputBuffer) { return std::move(File); } -Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File, - bool Compact) { +Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File) { TextAPIContext Ctx; Ctx.Path = std::string(File.getPath()); Ctx.FileKind = File.getFileType(); - - // Write out in JSON format. - if (Ctx.FileKind >= FileType::TBD_V5) { - return serializeInterfaceFileToJSON(OS, File, Compact); - } - llvm::yaml::Output YAMLOut(OS, &Ctx, /*WrapColumn=*/80); std::vector Files; diff --git a/llvm/lib/TextAPI/TextStubCommon.h b/llvm/lib/TextAPI/TextStubCommon.h index 9558bd9..51b4231 100644 --- a/llvm/lib/TextAPI/TextStubCommon.h +++ b/llvm/lib/TextAPI/TextStubCommon.h @@ -45,9 +45,6 @@ class PackedVersion; Expected> getInterfaceFileFromJSON(StringRef JSON); - -Error serializeInterfaceFileToJSON(raw_ostream &OS, const InterfaceFile &File, - bool Compact); } // namespace MachO namespace yaml { diff --git a/llvm/lib/TextAPI/TextStubV5.cpp b/llvm/lib/TextAPI/TextStubV5.cpp index 43519c0..f0ef10d 100644 --- a/llvm/lib/TextAPI/TextStubV5.cpp +++ b/llvm/lib/TextAPI/TextStubV5.cpp @@ -161,10 +161,6 @@ static llvm::SmallString<128> getParseErrorMsg(TBDKey Key) { return {"invalid ", Keys[Key], " section"}; } -static llvm::SmallString<128> getSerializeErrorMsg(TBDKey Key) { - return {"missing ", Keys[Key], " information"}; -} - class JSONStubError : public llvm::ErrorInfo { public: JSONStubError(Twine ErrMsg) : Message(ErrMsg.str()) {} @@ -720,294 +716,3 @@ MachO::getInterfaceFileFromJSON(StringRef JSON) { } return std::move(IF); } - -namespace { - -template -bool insertNonEmptyValues(Object &Obj, TBDKey Key, ContainerT &&Contents) { - if (Contents.empty()) - return false; - Obj[Keys[Key]] = std::move(Contents); - return true; -} - -std::string getFormattedStr(const MachO::Target &Targ) { - std::string PlatformStr = Targ.Platform == PLATFORM_MACCATALYST - ? "maccatalyst" - : getOSAndEnvironmentName(Targ.Platform); - return (getArchitectureName(Targ.Arch) + "-" + PlatformStr).str(); -} - -template -std::vector serializeTargets(const AggregateT Targets, - const TargetList &ActiveTargets) { - std::vector TargetsStr; - if (Targets.size() == ActiveTargets.size()) - return TargetsStr; - - llvm::for_each(Targets, [&TargetsStr](const MachO::Target &Target) { - TargetsStr.emplace_back(getFormattedStr(Target)); - }); - return TargetsStr; -} - -Array serializeTargetInfo(const TargetList &ActiveTargets) { - Array Targets; - for (const auto Targ : ActiveTargets) { - Object TargetInfo; - TargetInfo[Keys[TBDKey::Deployment]] = Targ.MinDeployment.getAsString(); - TargetInfo[Keys[TBDKey::Target]] = getFormattedStr(Targ); - Targets.emplace_back(std::move(TargetInfo)); - } - return Targets; -} - -template -Array serializeScalar(TBDKey Key, ValueT Value, ValueT Default = ValueT()) { - if (Value == Default) - return {}; - Array Container; - Object ScalarObj({Object::KV({Keys[Key], EntryT(Value)})}); - - Container.emplace_back(std::move(ScalarObj)); - return Container; -} - -using TargetsToValuesMap = - std::map, std::vector>; - -template -Array serializeAttrToTargets(AggregateT &Entries, TBDKey Key) { - Array Container; - for (const auto &[Targets, Values] : Entries) { - Object Obj; - insertNonEmptyValues(Obj, TBDKey::Targets, std::move(Targets)); - Obj[Keys[Key]] = Values; - Container.emplace_back(std::move(Obj)); - } - return Container; -} - -template >> -Array serializeField(TBDKey Key, const AggregateT &Values, - const TargetList &ActiveTargets, bool IsArray = true) { - std::map> Entries; - for (const auto &[Target, Val] : Values) - Entries[Val].insert(Target); - - if (!IsArray) { - std::map, std::string> FinalEntries; - for (const auto &[Val, Targets] : Entries) - FinalEntries[serializeTargets(Targets, ActiveTargets)] = Val; - return serializeAttrToTargets(FinalEntries, Key); - } - - TargetsToValuesMap FinalEntries; - for (const auto &[Val, Targets] : Entries) - FinalEntries[serializeTargets(Targets, ActiveTargets)].emplace_back(Val); - return serializeAttrToTargets(FinalEntries, Key); -} - -Array serializeField(TBDKey Key, const std::vector &Values, - const TargetList &ActiveTargets) { - TargetsToValuesMap FinalEntries; - for (const auto &Ref : Values) { - TargetList Targets{Ref.targets().begin(), Ref.targets().end()}; - FinalEntries[serializeTargets(Targets, ActiveTargets)].emplace_back( - Ref.getInstallName()); - } - return serializeAttrToTargets(FinalEntries, Key); -} - -struct SymbolFields { - struct SymbolTypes { - std::vector Weaks; - std::vector Globals; - std::vector TLV; - std::vector ObjCClasses; - std::vector IVars; - std::vector EHTypes; - - bool empty() const { - return Weaks.empty() && Globals.empty() && TLV.empty() && - ObjCClasses.empty() && IVars.empty() && EHTypes.empty(); - } - }; - SymbolTypes Data; - SymbolTypes Text; -}; - -Array serializeSymbols(InterfaceFile::const_filtered_symbol_range Symbols, - const TargetList &ActiveTargets) { - auto AssignForSymbolType = [](SymbolFields::SymbolTypes &Assignment, - const Symbol *Sym) { - switch (Sym->getKind()) { - case SymbolKind::ObjectiveCClass: - Assignment.ObjCClasses.emplace_back(Sym->getName()); - return; - case SymbolKind::ObjectiveCClassEHType: - Assignment.EHTypes.emplace_back(Sym->getName()); - return; - case SymbolKind::ObjectiveCInstanceVariable: - Assignment.IVars.emplace_back(Sym->getName()); - return; - case SymbolKind::GlobalSymbol: { - if (Sym->isWeakReferenced() || Sym->isWeakDefined()) - Assignment.Weaks.emplace_back(Sym->getName()); - else if (Sym->isThreadLocalValue()) - Assignment.TLV.emplace_back(Sym->getName()); - else - Assignment.Globals.emplace_back(Sym->getName()); - return; - } - } - }; - - std::map, SymbolFields> Entries; - for (const auto *Sym : Symbols) { - std::set Targets{Sym->targets().begin(), - Sym->targets().end()}; - auto JSONTargets = serializeTargets(Targets, ActiveTargets); - if (Sym->isData()) - AssignForSymbolType(Entries[std::move(JSONTargets)].Data, Sym); - else if (Sym->isText()) - AssignForSymbolType(Entries[std::move(JSONTargets)].Text, Sym); - else - llvm_unreachable("unexpected symbol type"); - } - - auto InsertSymbolsToJSON = [](Object &SymSection, TBDKey SegmentKey, - SymbolFields::SymbolTypes &SymField) { - if (SymField.empty()) - return; - Object Segment; - insertNonEmptyValues(Segment, TBDKey::Globals, std::move(SymField.Globals)); - insertNonEmptyValues(Segment, TBDKey::ThreadLocal, std::move(SymField.TLV)); - insertNonEmptyValues(Segment, TBDKey::Weak, std::move(SymField.Weaks)); - insertNonEmptyValues(Segment, TBDKey::ObjCClass, - std::move(SymField.ObjCClasses)); - insertNonEmptyValues(Segment, TBDKey::ObjCEHType, - std::move(SymField.EHTypes)); - insertNonEmptyValues(Segment, TBDKey::ObjCIvar, std::move(SymField.IVars)); - insertNonEmptyValues(SymSection, SegmentKey, std::move(Segment)); - }; - - Array SymbolSection; - for (auto &[Targets, Fields] : Entries) { - Object AllSyms; - insertNonEmptyValues(AllSyms, TBDKey::Targets, std::move(Targets)); - InsertSymbolsToJSON(AllSyms, TBDKey::Data, Fields.Data); - InsertSymbolsToJSON(AllSyms, TBDKey::Text, Fields.Text); - SymbolSection.emplace_back(std::move(AllSyms)); - } - - return SymbolSection; -} - -Array serializeFlags(const InterfaceFile *File) { - // TODO: Give all Targets the same flags for now. - Array Flags; - if (!File->isTwoLevelNamespace()) - Flags.emplace_back("flat_namespace"); - if (!File->isApplicationExtensionSafe()) - Flags.emplace_back("not_app_extension_safe"); - return serializeScalar(TBDKey::Attributes, std::move(Flags)); -} - -Expected serializeIF(const InterfaceFile *File) { - Object Library; - - // Handle required keys. - TargetList ActiveTargets{File->targets().begin(), File->targets().end()}; - if (!insertNonEmptyValues(Library, TBDKey::TargetInfo, - serializeTargetInfo(ActiveTargets))) - return make_error(getSerializeErrorMsg(TBDKey::TargetInfo)); - - Array Name = serializeScalar(TBDKey::Name, File->getInstallName()); - if (!insertNonEmptyValues(Library, TBDKey::InstallName, std::move(Name))) - return make_error(getSerializeErrorMsg(TBDKey::InstallName)); - - // Handle optional keys. - Array Flags = serializeFlags(File); - insertNonEmptyValues(Library, TBDKey::Flags, std::move(Flags)); - - Array CurrentV = serializeScalar( - TBDKey::Version, File->getCurrentVersion(), PackedVersion(1, 0, 0)); - insertNonEmptyValues(Library, TBDKey::CurrentVersion, std::move(CurrentV)); - - Array CompatV = serializeScalar( - TBDKey::Version, File->getCompatibilityVersion(), PackedVersion(1, 0, 0)); - insertNonEmptyValues(Library, TBDKey::CompatibilityVersion, - std::move(CompatV)); - - Array SwiftABI = serializeScalar( - TBDKey::ABI, File->getSwiftABIVersion(), 0u); - insertNonEmptyValues(Library, TBDKey::SwiftABI, std::move(SwiftABI)); - - Array RPaths = serializeField(TBDKey::Paths, File->rpaths(), ActiveTargets); - insertNonEmptyValues(Library, TBDKey::RPath, std::move(RPaths)); - - Array Umbrellas = serializeField(TBDKey::Umbrella, File->umbrellas(), - ActiveTargets, /*IsArray=*/false); - insertNonEmptyValues(Library, TBDKey::ParentUmbrella, std::move(Umbrellas)); - - Array Clients = - serializeField(TBDKey::Clients, File->allowableClients(), ActiveTargets); - insertNonEmptyValues(Library, TBDKey::AllowableClients, std::move(Clients)); - - Array ReexportLibs = - serializeField(TBDKey::Names, File->reexportedLibraries(), ActiveTargets); - insertNonEmptyValues(Library, TBDKey::ReexportLibs, std::move(ReexportLibs)); - - // Handle symbols. - Array Exports = serializeSymbols(File->exports(), ActiveTargets); - insertNonEmptyValues(Library, TBDKey::Exports, std::move(Exports)); - - Array Reexports = serializeSymbols(File->reexports(), ActiveTargets); - insertNonEmptyValues(Library, TBDKey::Reexports, std::move(Reexports)); - - if (!File->isTwoLevelNamespace()) { - Array Undefineds = serializeSymbols(File->undefineds(), ActiveTargets); - insertNonEmptyValues(Library, TBDKey::Undefineds, std::move(Undefineds)); - } - - return std::move(Library); -} - -Expected getJSON(const InterfaceFile *File) { - assert(File->getFileType() == FileType::TBD_V5 && - "unexpected json file format version"); - Object Root; - - auto MainLibOrErr = serializeIF(File); - if (!MainLibOrErr) - return MainLibOrErr; - Root[Keys[TBDKey::MainLibrary]] = std::move(*MainLibOrErr); - Array Documents; - for (const auto &Doc : File->documents()) { - auto LibOrErr = serializeIF(Doc.get()); - if (!LibOrErr) - return LibOrErr; - Documents.emplace_back(std::move(*LibOrErr)); - } - - Root[Keys[TBDKey::TBDVersion]] = 5; - insertNonEmptyValues(Root, TBDKey::Documents, std::move(Documents)); - return std::move(Root); -} - -} // namespace - -Error MachO::serializeInterfaceFileToJSON(raw_ostream &OS, - const InterfaceFile &File, - bool Compact) { - auto TextFile = getJSON(&File); - if (!TextFile) - return TextFile.takeError(); - if (Compact) - OS << formatv("{0}", Value(std::move(*TextFile))) << "\n"; - else - OS << formatv("{0:2}", Value(std::move(*TextFile))) << "\n"; - return Error::success(); -} diff --git a/llvm/unittests/TextAPI/TextStubV5Tests.cpp b/llvm/unittests/TextAPI/TextStubV5Tests.cpp index 2536a5a..c9668bb 100644 --- a/llvm/unittests/TextAPI/TextStubV5Tests.cpp +++ b/llvm/unittests/TextAPI/TextStubV5Tests.cpp @@ -520,524 +520,4 @@ TEST(TBDv5, ReadMultipleDocuments) { std::equal(Exports.begin(), Exports.end(), std::begin(ExpectedExports))); } -TEST(TBDv5, WriteFile) { - static const char TBDv5File[] = R"({ -"tapi_tbd_version": 5, -"main_library": { - "target_info": [ - { - "target": "x86_64-macos", - "min_deployment": "10.14" - }, - { - "target": "arm64-macos", - "min_deployment": "10.14" - }, - { - "target": "arm64-maccatalyst", - "min_deployment": "12.1" - } - ], - "install_names": [ - { - "name": "@rpath/S/L/F/Foo.framework/Foo" - } - ], - "current_versions": [ - { - "version": "1.2" - } - ], - "compatibility_versions": [ - { "version": "1.1" } - ], - "flags": [ - { - "attributes": [ - "flat_namespace" - ] - } - ], - "rpaths": [ - { - "targets": [ - "x86_64-macos" - ], - "paths": [ - "@executable_path/.../Frameworks" - ] - } - ], - "parent_umbrellas": [ - { - "umbrella": "System" - } - ], - "allowable_clients": [ - { - "clients": [ - "ClientA", - "ClientB" - ] - } - ], - "reexported_libraries": [ - { - "names": [ - "/u/l/l/libfoo.dylib", - "/u/l/l/libbar.dylib" - ] - } - ], - "exported_symbols": [ - { - "targets": [ - "x86_64-macos", - "arm64-macos" - ], - "data": { - "global": [ - "_global" - ], - "objc_class": [ - "ClassA" - ], - "weak": [], - "thread_local": [] - }, - "text": { - "global": [ - "_func" - ], - "weak": [], - "thread_local": [] - } - }, - { - "targets": [ - "x86_64-macos" - ], - "data": { - "global": [ - "_globalVar" - ], - "objc_class": [ - "ClassData" - ], - "objc_eh_type": [ - "ClassA", - "ClassB" - ], - "objc_ivar": [ - "ClassA.ivar1", - "ClassA.ivar2", - "ClassC.ivar1" - ] - }, - "text": { - "global": [ - "_funcFoo" - ] - } - } - ], - "reexported_symbols": [ - { - "data": { - "global": [ - "_globalRe" - ], - "objc_class": [ - "ClassRexport" - ] - }, - "text": { - "global": [ - "_funcA" - ] - } - } - ], - "undefined_symbols": [ - { - "targets": [ - "x86_64-macos" - ], - "data": { - "global": [ - "_globalBind" - ], - "weak": [ - "referenced_sym" - ] - } - } - ] -}})"; - - InterfaceFile File; - File.setFileType(FileType::TBD_V5); - - TargetList AllTargets = { - Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)), - Target(AK_arm64, PLATFORM_MACOS, VersionTuple(10, 14)), - Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(12, 1)), - }; - File.addTargets(AllTargets); - File.setInstallName("@rpath/S/L/F/Foo.framework/Foo"); - File.setCurrentVersion(PackedVersion(1, 2, 0)); - File.setCompatibilityVersion(PackedVersion(1, 1, 0)); - File.addRPath(AllTargets[0], "@executable_path/.../Frameworks"); - - for (const auto &Targ : AllTargets) { - File.addParentUmbrella(Targ, "System"); - File.addAllowableClient("ClientA", Targ); - File.addAllowableClient("ClientB", Targ); - File.addReexportedLibrary("/u/l/l/libfoo.dylib", Targ); - File.addReexportedLibrary("/u/l/l/libbar.dylib", Targ); - } - - SymbolFlags Flags = SymbolFlags::None; - // Exports. - File.addSymbol(SymbolKind::GlobalSymbol, "_global", - {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Data); - File.addSymbol(SymbolKind::GlobalSymbol, "_func", - {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Text); - File.addSymbol(SymbolKind::ObjectiveCClass, "ClassA", - {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Data); - File.addSymbol(SymbolKind::GlobalSymbol, "_funcFoo", {AllTargets[0]}, - Flags | SymbolFlags::Text); - File.addSymbol(SymbolKind::GlobalSymbol, "_globalVar", {AllTargets[0]}, - Flags | SymbolFlags::Data); - File.addSymbol(SymbolKind::ObjectiveCClass, "ClassData", {AllTargets[0]}, - Flags | SymbolFlags::Data); - File.addSymbol(SymbolKind::ObjectiveCClassEHType, "ClassA", {AllTargets[0]}, - Flags | SymbolFlags::Data); - File.addSymbol(SymbolKind::ObjectiveCClassEHType, "ClassB", {AllTargets[0]}, - Flags | SymbolFlags::Data); - File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "ClassA.ivar1", - {AllTargets[0]}, Flags | SymbolFlags::Data); - File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "ClassA.ivar2", - {AllTargets[0]}, Flags | SymbolFlags::Data); - File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "ClassC.ivar1", - {AllTargets[0]}, Flags | SymbolFlags::Data); - - // Reexports. - Flags = SymbolFlags::Rexported; - File.addSymbol(SymbolKind::GlobalSymbol, "_globalRe", AllTargets, - Flags | SymbolFlags::Data); - File.addSymbol(SymbolKind::GlobalSymbol, "_funcA", AllTargets, - Flags | SymbolFlags::Text); - File.addSymbol(SymbolKind::ObjectiveCClass, "ClassRexport", AllTargets, - Flags | SymbolFlags::Data); - - // Undefineds. - Flags = SymbolFlags::Undefined; - File.addSymbol(SymbolKind::GlobalSymbol, "_globalBind", {AllTargets[0]}, - Flags | SymbolFlags::Data); - File.addSymbol(SymbolKind::GlobalSymbol, "referenced_sym", {AllTargets[0]}, - Flags | SymbolFlags::Data | SymbolFlags::WeakReferenced); - - File.setTwoLevelNamespace(false); - File.setApplicationExtensionSafe(true); - - // Write out file then process it back into IF and compare equality - // against TBDv5File. - SmallString<4096> Buffer; - raw_svector_ostream OS(Buffer); - Error Result = TextAPIWriter::writeToStream(OS, File); - EXPECT_FALSE(Result); - - Expected Input = - TextAPIReader::get(MemoryBufferRef(TBDv5File, "Input.tbd")); - EXPECT_TRUE(!!Input); - TBDFile InputFile = std::move(Input.get()); - - Expected Output = - TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd")); - EXPECT_TRUE(!!Output); - TBDFile OutputFile = std::move(Output.get()); - EXPECT_EQ(*InputFile, *OutputFile); -} - -TEST(TBDv5, WriteMultipleDocuments) { - static const char TBDv5File[] = R"({ -"tapi_tbd_version": 5, -"main_library": { - "target_info": [ - { - "target": "armv7-ios", - "min_deployment": "11.0" - } - ], - "install_names":[ - { "name":"/S/L/F/Foo.framework/Foo" } - ], - "reexported_libraries": [ - { "names": ["/u/l/l/libfoo.dylib"] - } - ] -}, -"libraries": [ - { - "target_info": [ - { - "target": "armv7-ios", - "min_deployment": "11.0" - }, - { - "target": "armv7s-ios", - "min_deployment": "11.0" - } - ], - "install_names":[ - { "name":"/u/l/l/libfoo.dylib" } - ], - "current_versions": [ - { - "version": "2.1.1" - } - ], - "rpaths": [ - { - "targets": [ - "armv7-ios" - ], - "paths": [ - "@executable_path/.../Frameworks" - ] - }], - "reexported_libraries": [ { "names": ["@rpath/libfoo.dylib"] } ], - "flags":[ - { "attributes": ["not_app_extension_safe"] } - ], - "exported_symbols": [ - { - "text": { - "global": [ "_funcFoo" ] - } - } - ] - }, - { - "target_info": [ - { - "target": "armv7-ios", - "min_deployment": "11.0" - } - ], - "install_names":[ - { "name":"@rpath/libfoo.dylib" } - ], - "exported_symbols": [ - { - "data": { - "global": [ "_varFooBaz" ] - } - } - ] - } -]})"; - - InterfaceFile File; - File.setFileType(FileType::TBD_V5); - - TargetList AllTargets = { - Target(AK_armv7, PLATFORM_IOS, VersionTuple(11, 0)), - Target(AK_armv7s, PLATFORM_IOS, VersionTuple(11, 0)), - }; - File.setInstallName("/S/L/F/Foo.framework/Foo"); - File.addTarget(AllTargets[0]); - File.setCurrentVersion(PackedVersion(1, 0, 0)); - File.setCompatibilityVersion(PackedVersion(1, 0, 0)); - File.addReexportedLibrary("/u/l/l/libfoo.dylib", AllTargets[0]); - File.setTwoLevelNamespace(); - File.setApplicationExtensionSafe(true); - - InterfaceFile NestedFile; - NestedFile.setFileType(FileType::TBD_V5); - NestedFile.setInstallName("/u/l/l/libfoo.dylib"); - NestedFile.addTargets(AllTargets); - NestedFile.setCompatibilityVersion(PackedVersion(1, 0, 0)); - NestedFile.setTwoLevelNamespace(); - NestedFile.setApplicationExtensionSafe(false); - NestedFile.setCurrentVersion(PackedVersion(2, 1, 1)); - NestedFile.addRPath(AllTargets[0], "@executable_path/.../Frameworks"); - for (const auto &Targ : AllTargets) - NestedFile.addReexportedLibrary("@rpath/libfoo.dylib", Targ); - NestedFile.addSymbol(SymbolKind::GlobalSymbol, "_funcFoo", AllTargets, - SymbolFlags::Text); - File.addDocument(std::make_shared(std::move(NestedFile))); - - InterfaceFile NestedFileB; - NestedFileB.setFileType(FileType::TBD_V5); - NestedFileB.setInstallName("@rpath/libfoo.dylib"); - NestedFileB.addTarget(AllTargets[0]); - NestedFileB.setCompatibilityVersion(PackedVersion(1, 0, 0)); - NestedFileB.setCurrentVersion(PackedVersion(1, 0, 0)); - NestedFileB.setTwoLevelNamespace(); - NestedFileB.setApplicationExtensionSafe(true); - NestedFileB.addSymbol(SymbolKind::GlobalSymbol, "_varFooBaz", AllTargets, - SymbolFlags::Data); - File.addDocument(std::make_shared(std::move(NestedFileB))); - - // Write out file then process it back into IF and compare equality - // against TBDv5File. - SmallString<4096> Buffer; - raw_svector_ostream OS(Buffer); - Error Result = TextAPIWriter::writeToStream(OS, File, /*Compact=*/true); - EXPECT_FALSE(Result); - - Expected Input = - TextAPIReader::get(MemoryBufferRef(TBDv5File, "Input.tbd")); - EXPECT_TRUE(!!Input); - TBDFile InputFile = std::move(Input.get()); - - Expected Output = - TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd")); - EXPECT_TRUE(!!Output); - TBDFile OutputFile = std::move(Output.get()); - EXPECT_EQ(*InputFile, *OutputFile); -} - -TEST(TBDv5, Target_Simulator) { - static const char TBDv5File[] = R"({ -"tapi_tbd_version": 5, -"main_library": { - "target_info": [ - { - "target": "arm64-ios-simulator", - "min_deployment": "11.0" - }, - { - "target": "x86_64-ios-simulator", - "min_deployment": "11.3" - } - ], - "install_names":[ - { "name":"/S/L/F/Foo.framework/Foo" } - ] -}})"; - - Expected Result = - TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); - EXPECT_TRUE(!!Result); - TBDFile File = std::move(Result.get()); - EXPECT_EQ(FileType::TBD_V5, File->getFileType()); - TargetList ExpectedTargets = { - Target(AK_x86_64, PLATFORM_IOSSIMULATOR, VersionTuple(11, 3)), - Target(AK_arm64, PLATFORM_IOSSIMULATOR, VersionTuple(11, 0)), - }; - TargetList Targets{File->targets().begin(), File->targets().end()}; - llvm::sort(Targets); - EXPECT_EQ(Targets, ExpectedTargets); - - SmallString<4096> Buffer; - raw_svector_ostream OS(Buffer); - Error WriteResult = TextAPIWriter::writeToStream(OS, *File); - EXPECT_TRUE(!WriteResult); - - Expected Output = - TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd")); - EXPECT_TRUE(!!Output); - TBDFile WriteResultFile = std::move(Output.get()); - EXPECT_EQ(*File, *WriteResultFile); -} - -TEST(TBDv5, MisspelledKey) { - static const char TBDv5File[] = R"({ -"tapi_tbd_version": 5, -"main_library": { - "target_info": [ - { - "target": "arm64-ios-simulator", - "min_deployment": "11.0" - } - ], - "intall_names":[ - { "name":"/S/L/F/Foo.framework/Foo" } - ] -}})"; - - Expected Result = - TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); - EXPECT_FALSE(!!Result); - std::string ErrorMessage = toString(Result.takeError()); - EXPECT_EQ("invalid install_names section\n", ErrorMessage); -} - -TEST(TBDv5, InvalidVersion) { - static const char TBDv5File[] = R"({ -"tapi_tbd_version": 11, -"main_library": { - "target_info": [ - { - "target": "arm64-ios-simulator", - "min_deployment": "11.0" - } - ], - "install_names":[ - { "name":"/S/L/F/Foo.framework/Foo" } - ] -}})"; - - Expected Result = - TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); - EXPECT_FALSE(!!Result); - std::string ErrorMessage = toString(Result.takeError()); - EXPECT_EQ("invalid tapi_tbd_version section\n", ErrorMessage); -} - -TEST(TBDv5, MissingRequiredKey) { - static const char TBDv5File[] = R"({ -"main_library": { - "target_info": [ - { - "target": "arm64-ios-simulator", - "min_deployment": "11.0" - } - ], - "install_names":[ - { "name":"/S/L/F/Foo.framework/Foo" } - ] -}})"; - - Expected Result = - TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); - EXPECT_FALSE(!!Result); - std::string ErrorMessage = toString(Result.takeError()); - EXPECT_EQ("invalid tapi_tbd_version section\n", ErrorMessage); -} - -TEST(TBDv5, InvalidSymbols) { - static const char TBDv5File[] = R"({ -"tapi_tbd_version": 5, -"main_library": { - "target_info": [ - { - "target": "arm64-driverkit", - "min_deployment": "11.0" - } - ], - "install_names":[ - { "name":"/S/L/F/Foo.framework/Foo" } - ], - "exported_symbols": [ - { - "daa": { - "global": { - "weak": [] - } - } - } - ] -}})"; - - Expected Result = - TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd")); - EXPECT_FALSE(!!Result); - std::string ErrorMessage = toString(Result.takeError()); - EXPECT_EQ("invalid exported_symbols section\n", ErrorMessage); -} - } // end namespace TBDv5 -- 2.7.4