Skip to content

Commit ef5d161

Browse files
authored
Merge pull request rust-lang#144 from bjorn3/wip_linker
Linker
2 parents 104e9ff + 29e1d61 commit ef5d161

File tree

7 files changed

+1499
-33
lines changed

7 files changed

+1499
-33
lines changed

Cargo.lock

+79
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ faerie = "0.6.0"
2525
ar = "0.6.0"
2626
bitflags = "1.0.3"
2727
byteorder = "1.2.6"
28+
cc = "1.0.25"
29+
libc = "0.2.43"
30+
tempfile = "3.0.4"
2831

2932
# Uncomment to use local checkout of cranelift
3033
#[patch."https://github.com/CraneStation/cranelift.git"]

build.sh

+11-11
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,7 @@ fi
1414

1515
build_example_bin() {
1616
$RUSTC $2 --crate-name $1 --crate-type bin
17-
18-
pushd target/out
19-
gcc $1 libmini_core.rlib -o $1_bin
20-
sh -c ./$1_bin || true
21-
popd
17+
sh -c ./target/out/$1 || true
2218
}
2319

2420
if [[ "$1" == "--release" ]]; then
@@ -54,23 +50,27 @@ rm -r target || true
5450
time xargo build
5551
popd
5652

57-
$RUSTC --sysroot ~/.xargo/HOST example/alloc_example.rs --crate-type bin
5853
# TODO linux linker doesn't accept duplicate definitions
59-
#gcc -Wl,--gc-sections target/out/alloc_example ~/.xargo/HOST/lib/rustlib/*/lib/libcore-*.rlib ~/.xargo/HOST/lib/rustlib/*/lib/liballoc-*.rlib ~/.xargo/HOST/lib/rustlib/*/lib/liballoc_system-*.rlib -o target/out/alloc_example_exe
60-
#hyperfine ./target/out/alloc_example_exe
54+
#$RUSTC --sysroot ~/.xargo/HOST example/alloc_example.rs --crate-type bin
55+
#./target/out/alloc_example
6156

6257
$RUSTC --sysroot ~/.xargo/HOST example/mod_bench.rs --crate-type bin
63-
gcc -Wl,--gc-sections target/out/mod_bench -lc -o target/out/mod_bench_exe
58+
59+
echo "[BUILD] RUSTFLAGS=-Zmir-opt-level=3"
60+
pushd xargo
61+
rm -r ~/.xargo/HOST || true
62+
rm -r target || true
63+
time RUSTFLAGS="-Zmir-opt-level=3 $RUSTFLAGS" xargo build
64+
popd
6465

6566
$RUSTC --sysroot ~/.xargo/HOST example/mod_bench.rs --crate-type bin -Zmir-opt-level=3 --crate-name mod_bench_inline
66-
gcc -Wl,--gc-sections target/out/mod_bench_inline -lc -o target/out/mod_bench_inline_exe
6767

6868
rustc example/mod_bench.rs --crate-type bin -Copt-level=0 -o target/out/mod_bench_llvm_0 -Cpanic=abort
6969
rustc example/mod_bench.rs --crate-type bin -Copt-level=1 -o target/out/mod_bench_llvm_1 -Cpanic=abort
7070
rustc example/mod_bench.rs --crate-type bin -Copt-level=2 -o target/out/mod_bench_llvm_2 -Cpanic=abort
7171
rustc example/mod_bench.rs --crate-type bin -Copt-level=3 -o target/out/mod_bench_llvm_3 -Cpanic=abort
7272
echo
7373
echo "[Bench] mod_bench"
74-
hyperfine ./target/out/mod_bench{,_inline}_exe ./target/out/mod_bench_llvm_*
74+
hyperfine ./target/out/mod_bench{,_inline} ./target/out/mod_bench_llvm_*
7575

7676
cat target/out/log.txt | sort | uniq -c

src/archive.rs

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
use std::collections::HashMap;
2+
use std::fs::File;
3+
use std::path::PathBuf;
4+
5+
use crate::prelude::*;
6+
7+
pub struct ArchiveConfig<'a> {
8+
pub sess: &'a Session,
9+
pub dst: PathBuf,
10+
pub src: Option<PathBuf>,
11+
pub lib_search_paths: Vec<PathBuf>,
12+
}
13+
14+
pub struct ArchiveBuilder<'a> {
15+
cfg: ArchiveConfig<'a>,
16+
src_archive: Option<ar::Archive<File>>,
17+
src_entries: HashMap<String, usize>,
18+
builder: ar::Builder<File>,
19+
update_symbols: bool,
20+
}
21+
22+
impl<'a> ArchiveBuilder<'a> {
23+
pub fn new(cfg: ArchiveConfig<'a>) -> Self {
24+
let (src_archive, src_entries) = if let Some(src) = &cfg.src {
25+
let mut archive = ar::Archive::new(File::open(src).unwrap());
26+
let mut entries = HashMap::new();
27+
28+
let mut i = 0;
29+
while let Some(entry) = archive.next_entry() {
30+
let entry = entry.unwrap();
31+
entries.insert(
32+
String::from_utf8(entry.header().identifier().to_vec()).unwrap(),
33+
i,
34+
);
35+
i += 1;
36+
}
37+
38+
(Some(archive), entries)
39+
} else {
40+
(None, HashMap::new())
41+
};
42+
43+
let builder = ar::Builder::new(File::create(&cfg.dst).unwrap());
44+
45+
ArchiveBuilder {
46+
cfg,
47+
src_archive,
48+
src_entries,
49+
builder,
50+
update_symbols: false,
51+
}
52+
}
53+
54+
pub fn src_files(&self) -> Vec<String> {
55+
self.src_entries.keys().cloned().collect()
56+
}
57+
58+
pub fn remove_file(&mut self, name: &str) {
59+
assert!(
60+
self.src_entries.remove(name).is_some(),
61+
"Tried to remove file not existing in src archive",
62+
);
63+
}
64+
65+
pub fn update_symbols(&mut self) {
66+
self.update_symbols = true;
67+
}
68+
69+
pub fn build(mut self) {
70+
// Add files from original archive
71+
if let Some(mut src_archive) = self.src_archive {
72+
for (_entry_name, entry_idx) in self.src_entries.into_iter() {
73+
let entry = src_archive.jump_to_entry(entry_idx).unwrap();
74+
let orig_header = entry.header();
75+
let mut header =
76+
ar::Header::new(orig_header.identifier().to_vec(), orig_header.size());
77+
header.set_mtime(orig_header.mtime());
78+
header.set_uid(orig_header.uid());
79+
header.set_gid(orig_header.gid());
80+
header.set_mode(orig_header.mode());
81+
self.builder.append(&header, entry).unwrap();
82+
}
83+
}
84+
85+
// Finalize archive
86+
std::mem::drop(self.builder);
87+
88+
// Run ranlib to be able to link the archive
89+
let status = std::process::Command::new("ranlib")
90+
.arg(self.cfg.dst)
91+
.status()
92+
.expect("Couldn't run ranlib");
93+
assert!(
94+
status.success(),
95+
"Ranlib exited with code {:?}",
96+
status.code()
97+
);
98+
}
99+
}

0 commit comments

Comments
 (0)