}
static void
-printMemberHeader(raw_fd_ostream &Out, StringRef Name,
+printMemberHeader(raw_fd_ostream &Out, object::Archive::Kind Kind,
+ StringRef Name,
std::vector<unsigned>::iterator &StringMapIndexIter,
const sys::TimeValue &ModTime, unsigned UID, unsigned GID,
unsigned Perms, unsigned Size) {
+ if (Kind == object::Archive::K_BSD) {
+ uint64_t PosAfterHeader = Out.tell() + 60 + Name.size();
+ // Pad so that even 64 bit object files are aligned.
+ unsigned Pad = OffsetToAlignment(PosAfterHeader, 8);
+ unsigned NameWithPadding = Name.size() + Pad;
+ printWithSpacePadding(Out, Twine("#1/") + Twine(NameWithPadding), 16);
+ printRestOfMemberHeader(Out, ModTime, UID, GID, Perms,
+ NameWithPadding + Size);
+ Out << Name;
+ assert(PosAfterHeader == Out.tell());
+ while (Pad--)
+ Out.write(uint8_t(0));
+ return;
+ }
if (Name.size() < 16) {
printMemberHeader(Out, Name, ModTime, UID, GID, Perms, Size);
return;
// Returns the offset of the first reference to a member offset.
static ErrorOr<unsigned>
-writeSymbolTable(raw_fd_ostream &Out, ArrayRef<NewArchiveIterator> Members,
+writeSymbolTable(raw_fd_ostream &Out, object::Archive::Kind Kind,
+ ArrayRef<NewArchiveIterator> Members,
ArrayRef<MemoryBufferRef> Buffers,
std::vector<unsigned> &MemberOffsetRefs) {
+ if (Kind != object::Archive::K_GNU)
+ return 0;
+
unsigned StartOffset = 0;
unsigned MemberNum = 0;
std::string NameBuf;
std::pair<StringRef, std::error_code>
llvm::writeArchive(StringRef ArcName,
std::vector<NewArchiveIterator> &NewMembers,
- bool WriteSymtab) {
+ bool WriteSymtab, object::Archive::Kind Kind) {
SmallString<128> TmpArchive;
int TmpArchiveFD;
if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a",
unsigned MemberReferenceOffset = 0;
if (WriteSymtab) {
ErrorOr<unsigned> MemberReferenceOffsetOrErr =
- writeSymbolTable(Out, NewMembers, Members, MemberOffsetRefs);
+ writeSymbolTable(Out, Kind, NewMembers, Members, MemberOffsetRefs);
if (auto EC = MemberReferenceOffsetOrErr.getError())
return std::make_pair(ArcName, EC);
MemberReferenceOffset = MemberReferenceOffsetOrErr.get();
}
std::vector<unsigned> StringMapIndexes;
- writeStringTable(Out, NewMembers, StringMapIndexes);
+ if (Kind != object::Archive::K_BSD)
+ writeStringTable(Out, NewMembers, StringMapIndexes);
unsigned MemberNum = 0;
unsigned NewMemberNum = 0;
if (I.isNewMember()) {
StringRef FileName = I.getNew();
const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum++];
- printMemberHeader(Out, sys::path::filename(FileName), StringMapIndexIter,
- Status.getLastModificationTime(), Status.getUser(),
- Status.getGroup(), Status.permissions(),
- Status.getSize());
+ printMemberHeader(Out, Kind, sys::path::filename(FileName),
+ StringMapIndexIter, Status.getLastModificationTime(),
+ Status.getUser(), Status.getGroup(),
+ Status.permissions(), Status.getSize());
} else {
object::Archive::child_iterator OldMember = I.getOld();
- printMemberHeader(Out, I.getName(), StringMapIndexIter,
+ printMemberHeader(Out, Kind, I.getName(), StringMapIndexIter,
OldMember->getLastModified(), OldMember->getUID(),
OldMember->getGID(), OldMember->getAccessMode(),
OldMember->getSize());
static cl::opt<bool> MRI("M", cl::desc(""));
+namespace {
+enum Format { Default, GNU, BSD };
+}
+
+static cl::opt<Format>
+ FormatOpt("format", cl::desc("Archive format to create"),
+ cl::values(clEnumValN(Default, "defalut", "default"),
+ clEnumValN(GNU, "gnu", "gnu"),
+ clEnumValN(BSD, "bsd", "bsd"), clEnumValEnd));
+
std::string Options;
// Provide additional help output explaining the operations and modifiers of
static void
performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive,
std::vector<NewArchiveIterator> *NewMembersP) {
+ object::Archive::Kind Kind;
+ switch (FormatOpt) {
+ case Default:
+ // FIXME: change as the support for other formats improve.
+ Kind = object::Archive::K_GNU;
+ case GNU:
+ Kind = object::Archive::K_GNU;
+ break;
+ case BSD:
+ Kind = object::Archive::K_BSD;
+ break;
+ }
if (NewMembersP) {
std::pair<StringRef, std::error_code> Result =
- writeArchive(ArchiveName, *NewMembersP, Symtab);
+ writeArchive(ArchiveName, *NewMembersP, Symtab, Kind);
failIfError(Result.second, Result.first);
return;
}
std::vector<NewArchiveIterator> NewMembers =
computeNewArchiveMembers(Operation, OldArchive);
- auto Result = writeArchive(ArchiveName, NewMembers, Symtab);
+ auto Result = writeArchive(ArchiveName, NewMembers, Symtab, Kind);
failIfError(Result.second, Result.first);
}