forked from hermit-os/kernel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
build.rs
88 lines (73 loc) · 2.09 KB
/
build.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::{env, fs};
use anyhow::{anyhow, Context, Result};
use llvm_tools::LlvmTools;
fn main() -> Result<()> {
if env::var("CARGO_CFG_TARGET_ARCH").unwrap() == "x86_64"
&& env::var_os("CARGO_FEATURE_SMP").is_some()
{
assemble_x86_64_smp_boot()?;
}
Ok(())
}
fn assemble_x86_64_smp_boot() -> Result<()> {
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let boot_s = Path::new("src/arch/x86_64/kernel/boot.s");
let boot_ll = out_dir.join("boot.ll");
let boot_bc = out_dir.join("boot.bc");
let boot_bin = out_dir.join("boot.bin");
let llvm_as = binutil("llvm-as")?;
let rust_lld = binutil("rust-lld")?;
let assembly = fs::read_to_string(boot_s)?;
let mut llvm_file = File::create(&boot_ll)?;
writeln!(
&mut llvm_file,
r#"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-none-elf"
module asm "
{assembly}
"
"#
)?;
llvm_file.flush()?;
drop(llvm_file);
let status = Command::new(&llvm_as)
.arg("-o")
.arg(&boot_bc)
.arg(boot_ll)
.status()
.with_context(|| format!("Failed to run llvm-as from {}", llvm_as.display()))?;
assert!(status.success());
let status = Command::new(&rust_lld)
.arg("-flavor")
.arg("gnu")
.arg("--section-start=.text=0x8000")
.arg("--oformat=binary")
.arg("-o")
.arg(&boot_bin)
.arg(&boot_bc)
.status()
.with_context(|| format!("Failed to run rust-lld from {}", rust_lld.display()))?;
assert!(status.success());
println!("cargo:rerun-if-changed={}", boot_s.display());
Ok(())
}
fn binutil(name: &str) -> Result<PathBuf> {
let exe = format!("{name}{}", env::consts::EXE_SUFFIX);
let path = LlvmTools::new()
.map_err(|err| match err {
llvm_tools::Error::NotFound => anyhow!(
"Could not find llvm-tools component\n\
\n\
Maybe the rustup component `llvm-tools` is missing? Install it through: `rustup component add llvm-tools`"
),
err => anyhow!("{err:?}"),
})?
.tool(&exe)
.ok_or_else(|| anyhow!("could not find {exe}"))?;
Ok(path)
}