1
Fork 0

rustc: Handle duplicate names merging archives

When linking an archive statically to an rlib, the compiler will extract all
contents of the archive and add them all to the rlib being generated. The
current method of extraction is to run `ar x`, dumping all files into a
temporary directory. Object archives, however, are allowed to have multiple
entries with the same file name, so there is no method for them to extract their
contents into a directory in a lossless fashion.

This commit adds iterator support to the `ArchiveRO` structure which hooks into
LLVM's support for reading object archives. This iterator is then used to
inspect each object in turn and extract it to a unique location for later
assembly.
This commit is contained in:
Alex Crichton 2015-04-14 16:28:50 -07:00
parent 77acda1c8e
commit 9ab0475d94
12 changed files with 265 additions and 85 deletions

View file

@ -770,37 +770,68 @@ LLVMRustOpenArchive(char *path) {
return ret;
}
extern "C" const char*
#if LLVM_VERSION_MINOR >= 6
LLVMRustArchiveReadSection(OwningBinary<Archive> *ob, char *name, size_t *size) {
Archive *ar = ob->getBinary();
typedef OwningBinary<Archive> RustArchive;
#define GET_ARCHIVE(a) ((a)->getBinary())
#else
LLVMRustArchiveReadSection(Archive *ar, char *name, size_t *size) {
typedef Archive RustArchive;
#define GET_ARCHIVE(a) (a)
#endif
Archive::child_iterator child = ar->child_begin(),
end = ar->child_end();
for (; child != end; ++child) {
ErrorOr<StringRef> name_or_err = child->getName();
if (name_or_err.getError()) continue;
StringRef sect_name = name_or_err.get();
if (sect_name.trim(" ") == name) {
StringRef buf = child->getBuffer();
*size = buf.size();
return buf.data();
}
}
return NULL;
extern "C" void
LLVMRustDestroyArchive(RustArchive *ar) {
delete ar;
}
struct RustArchiveIterator {
Archive::child_iterator cur;
Archive::child_iterator end;
};
extern "C" RustArchiveIterator*
LLVMRustArchiveIteratorNew(RustArchive *ra) {
Archive *ar = GET_ARCHIVE(ra);
RustArchiveIterator *rai = new RustArchiveIterator();
rai->cur = ar->child_begin();
rai->end = ar->child_end();
return rai;
}
extern "C" const Archive::Child*
LLVMRustArchiveIteratorCurrent(RustArchiveIterator *rai) {
if (rai->cur == rai->end)
return NULL;
const Archive::Child &ret = *rai->cur;
return &ret;
}
extern "C" void
#if LLVM_VERSION_MINOR >= 6
LLVMRustDestroyArchive(OwningBinary<Archive> *ar) {
#else
LLVMRustDestroyArchive(Archive *ar) {
#endif
delete ar;
LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
if (rai->cur == rai->end)
return;
++rai->cur;
}
extern "C" void
LLVMRustArchiveIteratorFree(RustArchiveIterator *rai) {
delete rai;
}
extern "C" const char*
LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) {
ErrorOr<StringRef> name_or_err = child->getName();
if (name_or_err.getError())
return NULL;
StringRef name = name_or_err.get();
*size = name.size();
return name.data();
}
extern "C" const char*
LLVMRustArchiveChildData(Archive::Child *child, size_t *size) {
StringRef buf = child->getBuffer();
*size = buf.size();
return buf.data();
}
extern "C" void