From aeecb45bebc26499ba7382627733e2677fab1af6 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 27 Apr 2019 17:47:15 +0200 Subject: [PATCH] Preserve the order files are added to archives rust.metadata.bin could have been at the start of an .rlib file confusing ld --- example/alloc_example.rs | 2 +- src/archive.rs | 35 ++++++++++++++++++----------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/example/alloc_example.rs b/example/alloc_example.rs index 3dc13452117..20a8642cbd1 100644 --- a/example/alloc_example.rs +++ b/example/alloc_example.rs @@ -1,4 +1,4 @@ -#![feature(start, box_syntax, alloc_system, core_intrinsics, alloc, alloc_prelude, alloc_error_handler)] +#![feature(start, box_syntax, alloc_system, core_intrinsics, alloc_prelude, alloc_error_handler)] #![no_std] extern crate alloc; diff --git a/src/archive.rs b/src/archive.rs index b2553bb59e9..ea6357b539a 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -1,4 +1,3 @@ -use std::collections::HashMap; use std::fs::File; use std::path::{Path, PathBuf}; @@ -24,7 +23,9 @@ enum ArchiveEntry { pub struct ArArchiveBuilder<'a> { config: ArchiveConfig<'a>, src_archives: Vec>, - entries: HashMap, + // Don't use `HashMap` here, as the order is important. `rust.metadata.bin` must always be at + // the end of an archive for linkers to not get confused. + entries: Vec<(String, ArchiveEntry)>, update_symbols: bool, } @@ -42,21 +43,21 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { let (src_archives, entries) = if let Some(src) = &config.src { let mut archive = ar::Archive::new(File::open(src).unwrap()); - let mut entries = HashMap::new(); + let mut entries = Vec::new(); let mut i = 0; while let Some(entry) = archive.next_entry() { let entry = entry.unwrap(); - entries.insert( + entries.push(( String::from_utf8(entry.header().identifier().to_vec()).unwrap(), ArchiveEntry::FromArchive { archive_index: 0, entry_index: i }, - ); + )); i += 1; } (vec![archive], entries) } else { - (vec![], HashMap::new()) + (vec![], Vec::new()) }; ArArchiveBuilder { @@ -68,22 +69,22 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { } fn src_files(&mut self) -> Vec { - self.entries.keys().cloned().collect() + self.entries.iter().map(|(name, _)| name.clone()).collect() } fn remove_file(&mut self, name: &str) { - let file = self.entries.remove(name); - assert!( - file.is_some(), - "Tried to remove file not existing in src archive", - ); + let index = self.entries + .iter() + .position(|(entry_name, _)| entry_name == name) + .expect("Tried to remove file not existing in src archive"); + self.entries.remove(index); } fn add_file(&mut self, file: &Path) { - self.entries.insert( + self.entries.push(( file.file_name().unwrap().to_str().unwrap().to_string(), ArchiveEntry::File(File::open(file).unwrap()), - ); + )); } fn add_native_library(&mut self, name: &str) { @@ -132,7 +133,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> { let mut builder = if self.config.use_gnu_style_archive { BuilderKind::Gnu(ar::GnuBuilder::new( archive_file, - self.entries.keys().map(|key| key.as_bytes().to_vec()).collect(), + self.entries.iter().map(|(name, _)| name.as_bytes().to_vec()).collect(), )) } else { BuilderKind::Bsd(ar::Builder::new(archive_file)) @@ -193,10 +194,10 @@ impl<'a> ArArchiveBuilder<'a> { let entry = entry.unwrap(); let file_name = String::from_utf8(entry.header().identifier().to_vec()).unwrap(); if !skip(&file_name) { - self.entries.insert( + self.entries.push(( file_name, ArchiveEntry::FromArchive { archive_index, entry_index: i }, - ); + )); } i += 1; }