From 9ab0475d940342a670ad323c151db565e6318e08 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 14 Apr 2015 16:28:50 -0700 Subject: 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. --- src/rustllvm/RustWrapper.cpp | 79 ++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 24 deletions(-) (limited to 'src/rustllvm/RustWrapper.cpp') diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 31f75ae03b0..492993ec9a9 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -770,37 +770,68 @@ LLVMRustOpenArchive(char *path) { return ret; } -extern "C" const char* #if LLVM_VERSION_MINOR >= 6 -LLVMRustArchiveReadSection(OwningBinary *ob, char *name, size_t *size) { - - Archive *ar = ob->getBinary(); +typedef OwningBinary 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 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 *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 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 -- cgit 1.4.1-3-g733a5