Author: Cyndy Ishida Date: 2023-02-16T13:53:38-08:00 New Revision: 7f254605c66e0260f8b169cd62b094e8a56ddb70
URL: https://github.com/llvm/llvm-project/commit/7f254605c66e0260f8b169cd62b094e8a56ddb70 DIFF: https://github.com/llvm/llvm-project/commit/7f254605c66e0260f8b169cd62b094e8a56ddb70.diff LOG: [text] WIP writerf Added: Modified: llvm/lib/TextAPI/TextStub.cpp llvm/lib/TextAPI/TextStubCommon.h llvm/lib/TextAPI/TextStubV5.cpp llvm/unittests/TextAPI/TextStubV5Tests.cpp Removed: ################################################################################ diff --git a/llvm/lib/TextAPI/TextStub.cpp b/llvm/lib/TextAPI/TextStub.cpp index 73cb61472bff..af60bd794e2d 100644 --- a/llvm/lib/TextAPI/TextStub.cpp +++ b/llvm/lib/TextAPI/TextStub.cpp @@ -1163,6 +1163,12 @@ 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); + } + llvm::yaml::Output YAMLOut(OS, &Ctx, /*WrapColumn=*/80); std::vector<const InterfaceFile *> Files; diff --git a/llvm/lib/TextAPI/TextStubCommon.h b/llvm/lib/TextAPI/TextStubCommon.h index 51b423137f4e..6ee5b3931831 100644 --- a/llvm/lib/TextAPI/TextStubCommon.h +++ b/llvm/lib/TextAPI/TextStubCommon.h @@ -45,6 +45,8 @@ class PackedVersion; Expected<std::unique_ptr<InterfaceFile>> getInterfaceFileFromJSON(StringRef JSON); + +Error serializeInterfaceFileToJSON(raw_ostream &OS, const InterfaceFile &File); } // namespace MachO namespace yaml { diff --git a/llvm/lib/TextAPI/TextStubV5.cpp b/llvm/lib/TextAPI/TextStubV5.cpp index d19f7dd457f3..abd3f6030e96 100644 --- a/llvm/lib/TextAPI/TextStubV5.cpp +++ b/llvm/lib/TextAPI/TextStubV5.cpp @@ -155,6 +155,10 @@ 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<llvm::json::ParseError> { public: JSONStubError(Twine ErrMsg) : Message(ErrMsg.str()) {} @@ -710,3 +714,78 @@ MachO::getInterfaceFileFromJSON(StringRef JSON) { } return std::move(IF); } + +namespace { + +bool insertNonEmptyArray(Object &Obj, TBDKey Key, Array &&Contents) { + if (Contents.empty()) + return false; + Obj[Keys[Key]] = std::move(Contents); + return true; +} + +Array serializeTargets(const InterfaceFile *File) { + Array Targets; + for (const auto Targ : File->targets()) { + Object TargetInfo; + TargetInfo[Keys[TBDKey::Deployment]] = Targ.MinDeployment.getAsString(); + TargetInfo[Keys[TBDKey::Target]] = + (getArchitectureName(Targ.Arch) + "-" + getPlatformName(Targ.Platform)) + .str(); + Targets.emplace_back(std::move(TargetInfo)); + } + return Targets; +} + +Array serializeInstallNames(const InterfaceFile *File) { + Array Names; + return Names; +} + +Expected<Object> serializeIF(const InterfaceFile *File) { + Object Library; + + // Handle required keys. + if (!insertNonEmptyArray(Library, TBDKey::TargetInfo, serializeTargets(File))) + return make_error<JSONStubError>(getSerializeErrorMsg(TBDKey::TargetInfo)); + + // if (!insertNonEmptyArray(Library, TBDKey::InstallName, + // serializeInstallNames(File))) + // return + // make_error<JSONStubError>(getSerializeErrorMsg(TBDKey::InstallName)); + + return Library; +} + +Expected<Object> getJSON(const InterfaceFile *File) { + assert(File->getFileType() == FileType::TBD_V5 && + "unexpected json file format version"); + Object Root; + + Array Documents; + auto MainLibOrErr = serializeIF(File); + if (!MainLibOrErr) + return MainLibOrErr; + Documents.emplace_back(std::move(*MainLibOrErr)); + 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; + Root[Keys[TBDKey::Document]] = std::move(Documents); + return Root; +} + +} // namespace + +Error MachO::serializeInterfaceFileToJSON(raw_ostream &OS, + const InterfaceFile &File) { + auto TextFile = getJSON(&File); + if (!TextFile) + return TextFile.takeError(); + 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 5b0b596b1cd1..8ccde0c79483 100644 --- a/llvm/unittests/TextAPI/TextStubV5Tests.cpp +++ b/llvm/unittests/TextAPI/TextStubV5Tests.cpp @@ -519,4 +519,154 @@ TEST(TBDv5, ReadMultipleDocuments) { std::equal(Exports.begin(), Exports.end(), std::begin(ExpectedExports))); } +TEST(TBDv5, WriteFile) { + static const char TBDv5File[] = R"({ +"tapi_tbd_version": 5, +"files": [ + { + "target_info": [ + { + "target": "x86_64-macos", + "min_deployment": "10.14" + }, + { + "target": "arm64-macos", + "min_deployment": "10.14" + }, + { + "target": "arm64-maccatalyst", + "min_deployment": "12.1" + } + ], + "flags":[ + { + "attributes": ["flat_namespace"] + } + ], + "install_names":[ + { + "name":"/S/L/F/Foo.framework/Foo" + } + ], + "current_versions":[ + { + "version": "1.2" + } + ], + "compatibility_versions":[ + { + "version": "1.1" + } + ], + "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": { + "globals": [ "_global" ], + "objc_classes": [ "ClassA" ], + "weaks": [], + "thread-locals": [] + }, + "text": { + "globals": [ "_func" ] + } + }, + { + "targets": [ + "x86_64-macos" + ], + "data": { + "globals": [ "_globalVar" ], + "objc_classes": [ "ClassData" ], + "objc_eh_types": [ "ClassA", "ClassB" ], + "objc_ivars": [ "ClassA.ivar1", "ClassA.ivar2", "ClassC.ivar1" ] + }, + "text": { + "globals": [ "_funcFoo" ] + } + } + ], + "reexported_symbols": [ + { + "targets": [ "x86_64-macos", "arm64-macos" ], + "data": { + "globals": [ "_globalRe" ], + "objc_classes": [ "ClassRexport" ] + }, + "text": { + "globals": [ "_funcA" ] + } + } + ], + "undefined_symbols": [ + { + "targets": [ "x86_64-macos" ], + "data": { + "globals": [ "_globalBind" ], + "weaks": [ "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("Umbrella.framework/Umbrella"); + // File.addUUID(uuids[0].first, uuids[0].second); + // File.addUUID(uuids[1].first, uuids[1].second); + // File.setCurrentVersion(PackedVersion(1, 2, 3)); + // File.setTwoLevelNamespace(); + // File.setInstallAPI(true); + // File.setApplicationExtensionSafe(true); + // File.setSwiftABIVersion(5); + // File.addAllowableClient("ClientA", Targets[0]); + // File.addParentUmbrella(Targets[0], "System"); + // File.addParentUmbrella(Targets[1], "System"); + // File.addSymbol(SymbolKind::GlobalSymbol, "_symA", {Targets[0]}); + // File.addSymbol(SymbolKind::GlobalSymbol, "_symB", {Targets[1]}); + // File.addSymbol(SymbolKind::GlobalSymbol, "_symC", {Targets[0]}, + // SymbolFlags::WeakDefined); + // File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", {Targets[0]}); + + SmallString<4096> Buffer; + raw_svector_ostream OS(Buffer); + Error Result = TextAPIWriter::writeToStream(OS, File); + EXPECT_FALSE(Result); + llvm::outs() << Buffer; + EXPECT_STREQ(TBDv5File, Buffer.c_str()); +} + } // end namespace TBDv5 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits