Skip to content

Commit fd4d075

Browse files
committed
[llvm][TextAPI] adding inlining reexported libraries support
Summary: [llvm][TextAPI] adding inlining reexported libraries support * this patch adds reader/writer support for MachO tbd files. The usecase is to represent reexported libraries in top level library that won't need to exist for linker indirection because all of the needed content will be inlined in the same document. Reviewers: ributzka, steven_wu, jhenderson Reviewed By: ributzka Subscribers: JDevlieghere, hiraditya, mgrang, dexonsmith, rupprecht, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D67646
1 parent ea3152b commit fd4d075

File tree

4 files changed

+509
-19
lines changed

4 files changed

+509
-19
lines changed

llvm/include/llvm/TextAPI/MachO/InterfaceFile.h

+20
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,11 @@ class InterfaceFile {
274274
/// \param Target_ The target applicable to Parent
275275
/// \param Parent The name of Parent
276276
void addParentUmbrella(const Target &Target_, StringRef Parent);
277+
278+
/// Get the list of Parent Umbrella frameworks.
279+
///
280+
/// \return Returns a list of target information and install name of parent
281+
/// umbrellas.
277282
const std::vector<std::pair<Target, std::string>> &umbrellas() const {
278283
return ParentUmbrellas;
279284
}
@@ -328,6 +333,20 @@ class InterfaceFile {
328333
return UUIDs;
329334
}
330335

336+
/// Add a library for inlining to top level library.
337+
///
338+
///\param Document The library to inline with top level library.
339+
void addDocument(std::shared_ptr<InterfaceFile> &&Document) {
340+
Documents.emplace_back(std::move(Document));
341+
}
342+
343+
/// Get the list of inlined libraries.
344+
///
345+
/// \return Returns a list of the inlined frameworks.
346+
const std::vector<std::shared_ptr<InterfaceFile>> &documents() const {
347+
return Documents;
348+
}
349+
331350
/// Add a symbol to the symbols list or extend an existing one.
332351
void addSymbol(SymbolKind Kind, StringRef Name, const TargetList &Targets,
333352
SymbolFlags Flags = SymbolFlags::None);
@@ -403,6 +422,7 @@ class InterfaceFile {
403422
std::vector<std::pair<Target, std::string>> ParentUmbrellas;
404423
std::vector<InterfaceFileRef> AllowableClients;
405424
std::vector<InterfaceFileRef> ReexportedLibraries;
425+
std::vector<std::shared_ptr<InterfaceFile>> Documents;
406426
std::vector<std::pair<Target, std::string>> UUIDs;
407427
SymbolMapType Symbols;
408428
};

llvm/lib/TextAPI/MachO/TextStub.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,10 @@ TextAPIReader::get(MemoryBufferRef InputBuffer) {
11181118
auto File = std::unique_ptr<InterfaceFile>(
11191119
const_cast<InterfaceFile *>(Files.front()));
11201120

1121+
for (auto Iter = std::next(Files.begin()); Iter != Files.end(); ++Iter)
1122+
File->addDocument(
1123+
std::shared_ptr<InterfaceFile>(const_cast<InterfaceFile *>(*Iter)));
1124+
11211125
if (YAMLIn.error())
11221126
return make_error<StringError>(Ctx.ErrorMessage, YAMLIn.error());
11231127

@@ -1133,6 +1137,9 @@ Error TextAPIWriter::writeToStream(raw_ostream &OS, const InterfaceFile &File) {
11331137
std::vector<const InterfaceFile *> Files;
11341138
Files.emplace_back(&File);
11351139

1140+
for (auto Document : File.documents())
1141+
Files.emplace_back(Document.get());
1142+
11361143
// Stream out yaml.
11371144
YAMLOut << Files;
11381145

llvm/unittests/TextAPI/TextStubV3Tests.cpp

+202
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,127 @@ TEST(TBDv3, ReadFile) {
117117
std::equal(Exports.begin(), Exports.end(), std::begin(TBDv3Symbols)));
118118
}
119119

120+
TEST(TBDv3, ReadMultipleDocuments) {
121+
static const char TBDv3Inlines[] =
122+
"--- !tapi-tbd-v3\n"
123+
"archs: [ armv7, arm64 ]\n"
124+
"uuids: [ 'armv7: 00000000-0000-0000-0000-000000000000',\n"
125+
" 'arm64: 11111111-1111-1111-1111-111111111111']\n"
126+
"platform: ios\n"
127+
"install-name: Test.dylib\n"
128+
"current-version: 2.3.4\n"
129+
"compatibility-version: 1.0\n"
130+
"swift-abi-version: 1.1\n"
131+
"parent-umbrella: Umbrella.dylib\n"
132+
"exports:\n"
133+
" - archs: [ armv7, arm64 ]\n"
134+
" allowable-clients: [ clientA ]\n"
135+
" re-exports: [ /usr/lib/libfoo.dylib,\n"
136+
" TestInline.dylib ]\n"
137+
" symbols: [ _sym1, _sym2, _sym3, _sym4, $ld$hide$os9.0$_sym1 ]\n"
138+
" objc-classes: [ class1, class2 ]\n"
139+
" objc-eh-types: [ class1 ]\n"
140+
" objc-ivars: [ class1._ivar1, class1._ivar2 ]\n"
141+
" weak-def-symbols: [ _weak1, _weak2 ]\n"
142+
" thread-local-symbols: [ _tlv1, _tlv3 ]\n"
143+
" - archs: [ armv7 ]\n"
144+
" symbols: [ _sym5 ]\n"
145+
" objc-classes: [ class3 ]\n"
146+
" objc-ivars: [ class1._ivar3 ]\n"
147+
" weak-def-symbols: [ _weak3 ]\n"
148+
" thread-local-symbols: [ _tlv3 ]\n"
149+
"--- !tapi-tbd-v3\n"
150+
"archs: [ armv7, arm64 ]\n"
151+
"uuids: [ 'armv7: 00000000-0000-0000-0000-000000000000',\n"
152+
" 'arm64: 11111111-1111-1111-1111-111111111111']\n"
153+
"platform: ios\n"
154+
"install-name: TestInline.dylib\n"
155+
"swift-abi-version: 1.1\n"
156+
"exports:\n"
157+
" - archs: [ armv7, arm64 ]\n"
158+
" symbols: [ _sym5, _sym6 ]\n"
159+
"...\n";
160+
161+
auto Result = TextAPIReader::get(MemoryBufferRef(TBDv3Inlines, "Test.tbd"));
162+
EXPECT_TRUE(!!Result);
163+
auto File = std::move(Result.get());
164+
EXPECT_EQ(File->documents().size(), 1U);
165+
EXPECT_EQ(FileType::TBD_V3, File->getFileType());
166+
auto Archs = AK_armv7 | AK_arm64;
167+
auto Platform = PlatformKind::iOS;
168+
TargetList Targets;
169+
for (auto &&arch : Archs)
170+
Targets.emplace_back(Target(arch, Platform));
171+
EXPECT_EQ(Archs, File->getArchitectures());
172+
UUIDs Uuids = {{Target(AK_armv7, PlatformKind::unknown),
173+
"00000000-0000-0000-0000-000000000000"},
174+
{Target(AK_arm64, PlatformKind::unknown),
175+
"11111111-1111-1111-1111-111111111111"}};
176+
EXPECT_EQ(Uuids, File->uuids());
177+
EXPECT_EQ(File->getPlatforms().size(), 1U);
178+
EXPECT_EQ(Platform, *File->getPlatforms().begin());
179+
EXPECT_EQ(std::string("Test.dylib"), File->getInstallName());
180+
EXPECT_EQ(PackedVersion(2, 3, 4), File->getCurrentVersion());
181+
EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion());
182+
EXPECT_EQ(2U, File->getSwiftABIVersion());
183+
EXPECT_EQ(ObjCConstraintType::Retain_Release, File->getObjCConstraint());
184+
EXPECT_TRUE(File->isTwoLevelNamespace());
185+
EXPECT_TRUE(File->isApplicationExtensionSafe());
186+
EXPECT_FALSE(File->isInstallAPI());
187+
InterfaceFileRef Client("clientA", Targets);
188+
const std::vector<InterfaceFileRef> Reexports = {
189+
InterfaceFileRef("/usr/lib/libfoo.dylib", Targets),
190+
InterfaceFileRef("TestInline.dylib", Targets)};
191+
EXPECT_EQ(1U, File->allowableClients().size());
192+
EXPECT_EQ(Client, File->allowableClients().front());
193+
EXPECT_EQ(2U, File->reexportedLibraries().size());
194+
EXPECT_EQ(Reexports, File->reexportedLibraries());
195+
196+
ExportedSymbolSeq Exports;
197+
for (const auto *Sym : File->symbols()) {
198+
EXPECT_FALSE(Sym->isWeakReferenced());
199+
EXPECT_FALSE(Sym->isUndefined());
200+
Exports.emplace_back(ExportedSymbol{Sym->getKind(), Sym->getName().str(),
201+
Sym->isWeakDefined(),
202+
Sym->isThreadLocalValue()});
203+
}
204+
llvm::sort(Exports.begin(), Exports.end());
205+
206+
EXPECT_EQ(sizeof(TBDv3Symbols) / sizeof(ExportedSymbol), Exports.size());
207+
EXPECT_TRUE(
208+
std::equal(Exports.begin(), Exports.end(), std::begin(TBDv3Symbols)));
209+
210+
// Check Second Document
211+
Exports.clear();
212+
auto Document = File->documents().front();
213+
EXPECT_EQ(FileType::TBD_V3, Document->getFileType());
214+
EXPECT_EQ(Archs, Document->getArchitectures());
215+
EXPECT_EQ(Uuids, Document->uuids());
216+
EXPECT_EQ(Platform, *Document->getPlatforms().begin());
217+
EXPECT_EQ(std::string("TestInline.dylib"), Document->getInstallName());
218+
EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCurrentVersion());
219+
EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCompatibilityVersion());
220+
EXPECT_EQ(2U, Document->getSwiftABIVersion());
221+
222+
for (const auto *Sym : Document->symbols()) {
223+
EXPECT_FALSE(Sym->isWeakReferenced());
224+
EXPECT_FALSE(Sym->isUndefined());
225+
Exports.emplace_back(ExportedSymbol{Sym->getKind(), Sym->getName().str(),
226+
Sym->isWeakDefined(),
227+
Sym->isThreadLocalValue()});
228+
}
229+
llvm::sort(Exports.begin(), Exports.end());
230+
231+
ExportedSymbolSeq DocumentSymbols{
232+
{SymbolKind::GlobalSymbol, "_sym5", false, false},
233+
{SymbolKind::GlobalSymbol, "_sym6", false, false},
234+
};
235+
236+
EXPECT_EQ(DocumentSymbols.size(), Exports.size());
237+
EXPECT_TRUE(
238+
std::equal(Exports.begin(), Exports.end(), DocumentSymbols.begin()));
239+
}
240+
120241
TEST(TBDv3, WriteFile) {
121242
static const char TBDv3File3[] =
122243
"--- !tapi-tbd-v3\n"
@@ -171,6 +292,87 @@ TEST(TBDv3, WriteFile) {
171292
EXPECT_STREQ(TBDv3File3, Buffer.c_str());
172293
}
173294

295+
TEST(TBDv3, WriteMultipleDocuments) {
296+
static const char TBDv3Inlines[] =
297+
"--- !tapi-tbd-v3\n"
298+
"archs: [ i386, x86_64 ]\n"
299+
"platform: zippered\n"
300+
"install-name: '/usr/lib/libfoo.dylib'\n"
301+
"current-version: 1.2.3\n"
302+
"compatibility-version: 0\n"
303+
"swift-abi-version: 5\n"
304+
"exports:\n"
305+
" - archs: [ x86_64 ]\n"
306+
" allowable-clients: [ clientA ]\n"
307+
" re-exports: [ '/usr/lib/libbar.dylib' ]\n"
308+
" - archs: [ i386, x86_64 ]\n"
309+
" symbols: [ _sym1 ]\n"
310+
" objc-classes: [ Class1 ]\n"
311+
" objc-eh-types: [ Class1 ]\n"
312+
" objc-ivars: [ Class1._ivar1 ]\n"
313+
" weak-def-symbols: [ _sym2 ]\n"
314+
" thread-local-symbols: [ _symA ]\n"
315+
"--- !tapi-tbd-v3\n"
316+
"archs: [ i386 ]\n"
317+
"platform: macosx\n"
318+
"install-name: '/usr/lib/libbar.dylib'\n"
319+
"current-version: 0\n"
320+
"compatibility-version: 0\n"
321+
"swift-abi-version: 5\n"
322+
"objc-constraint: none\n"
323+
"exports:\n"
324+
" - archs: [ i386 ]\n"
325+
" symbols: [ _sym3, _sym4 ]\n"
326+
"...\n";
327+
328+
InterfaceFile File;
329+
TargetList Targets;
330+
for (auto &&arch : AK_i386 | AK_x86_64) {
331+
Targets.emplace_back(Target(arch, PlatformKind::macOS));
332+
Targets.emplace_back(Target(arch, PlatformKind::macCatalyst));
333+
}
334+
File.addTargets(Targets);
335+
File.setPath("libfoo.dylib");
336+
File.setInstallName("/usr/lib/libfoo.dylib");
337+
File.setFileType(FileType::TBD_V3);
338+
File.setCurrentVersion(PackedVersion(1, 2, 3));
339+
File.setTwoLevelNamespace();
340+
File.setApplicationExtensionSafe();
341+
File.setSwiftABIVersion(5);
342+
File.setObjCConstraint(ObjCConstraintType::Retain_Release);
343+
File.addAllowableClient("clientA", Targets[2]);
344+
File.addReexportedLibrary("/usr/lib/libbar.dylib", Targets[2]);
345+
File.addSymbol(SymbolKind::GlobalSymbol, "_sym1", Targets);
346+
File.addSymbol(SymbolKind::GlobalSymbol, "_sym2", Targets,
347+
SymbolFlags::WeakDefined);
348+
File.addSymbol(SymbolKind::GlobalSymbol, "_symA", Targets,
349+
SymbolFlags::ThreadLocalValue);
350+
File.addSymbol(SymbolKind::ObjectiveCClass, "Class1", Targets);
351+
File.addSymbol(SymbolKind::ObjectiveCClassEHType, "Class1", Targets);
352+
File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "Class1._ivar1",
353+
Targets);
354+
355+
// Inline document
356+
InterfaceFile Document;
357+
Targets = {Target(AK_i386, PlatformKind::macOS)};
358+
Document.addTargets(Targets);
359+
Document.setPath("libbar.dylib");
360+
Document.setInstallName("/usr/lib/libbar.dylib");
361+
Document.setFileType(FileType::TBD_V3);
362+
Document.setTwoLevelNamespace();
363+
Document.setApplicationExtensionSafe();
364+
Document.setSwiftABIVersion(5);
365+
Document.addSymbol(SymbolKind::GlobalSymbol, "_sym3", Targets);
366+
Document.addSymbol(SymbolKind::GlobalSymbol, "_sym4", Targets);
367+
File.addDocument(std::make_shared<InterfaceFile>(std::move(Document)));
368+
369+
SmallString<4096> Buffer;
370+
raw_svector_ostream OS(Buffer);
371+
auto Result = TextAPIWriter::writeToStream(OS, File);
372+
EXPECT_FALSE(Result);
373+
EXPECT_STREQ(TBDv3Inlines, Buffer.c_str());
374+
}
375+
174376
TEST(TBDv3, Platform_macOS) {
175377
static const char TBDv3PlatformMacOS[] = "--- !tapi-tbd-v3\n"
176378
"archs: [ x86_64 ]\n"

0 commit comments

Comments
 (0)