Skip to content

Commit f52a4f7

Browse files
Rustify prepare.sh command
1 parent 4748fdc commit f52a4f7

File tree

9 files changed

+288
-0
lines changed

9 files changed

+288
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,4 @@ tools/llvmint
2525
tools/llvmint-2
2626
# The `llvm` folder is generated by the `tools/generate_intrinsics.py` script to update intrinsics.
2727
llvm
28+
build_system/target

build_system/Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build_system/Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "y"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[[bin]]
7+
name = "y"
8+
path = "src/main.rs"
9+
10+
[features]
11+
unstable-features = [] # for rust-analyzer

build_system/src/build.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub fn run() -> Result<(), String> {
2+
Ok(())
3+
}

build_system/src/main.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#![feature(exclusive_range_pattern)]
2+
3+
use std::env;
4+
use std::process;
5+
6+
mod build;
7+
mod prepare;
8+
mod rustc_info;
9+
mod utils;
10+
11+
macro_rules! arg_error {
12+
($($err:tt)*) => {{
13+
eprintln!($($err)*);
14+
usage();
15+
std::process::exit(1);
16+
}};
17+
}
18+
19+
fn usage() {
20+
// eprintln!("{}", include_str!("usage.txt"));
21+
}
22+
23+
pub enum Command {
24+
Prepare,
25+
Build,
26+
}
27+
28+
fn main() {
29+
if env::var("RUST_BACKTRACE").is_err() {
30+
env::set_var("RUST_BACKTRACE", "1");
31+
}
32+
33+
let mut args = env::args().skip(1);
34+
let command = match args.next().as_deref() {
35+
Some("prepare") => Command::Prepare,
36+
Some("build") => Command::Build,
37+
Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag),
38+
Some(command) => arg_error!("Unknown command {}", command),
39+
None => {
40+
usage();
41+
process::exit(0);
42+
}
43+
};
44+
45+
if let Err(e) = match command {
46+
Command::Prepare => prepare::run(),
47+
Command::Build => build::run(),
48+
} {
49+
eprintln!("Command failed to run: {e:?}");
50+
process::exit(1);
51+
}
52+
}

build_system/src/prepare.rs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
use crate::rustc_info::get_rustc_path;
2+
use crate::utils::{cargo_install, git_clone, run_command, walk_dir};
3+
4+
use std::fs;
5+
use std::path::Path;
6+
7+
fn prepare_libcore() -> Result<(), String> {
8+
let rustc_path = match get_rustc_path() {
9+
Some(path) => path,
10+
None => return Err("`rustc` path not found".to_owned()),
11+
};
12+
13+
let parent = match rustc_path.parent() {
14+
Some(path) => path,
15+
None => return Err(format!("No parent for `{}`", rustc_path.display())),
16+
};
17+
18+
let src_dir = parent.join("../lib/rustlib/src/rust");
19+
if !src_dir.is_dir() {
20+
return Err("Please install `rust-src` component".to_owned());
21+
}
22+
23+
let dst_dir = Path::new("sysroot_src");
24+
if dst_dir.is_dir() {
25+
if let Err(e) = fs::remove_dir_all(dst_dir) {
26+
return Err(format!("Failed to remove `{}`: {:?}", dst_dir.display(), e));
27+
}
28+
}
29+
30+
let dst_dir = dst_dir.join("library");
31+
fs::create_dir_all(&dst_dir)
32+
.map_err(|e| format!("Failed to folder `{}`: {e:?}", dst_dir.display()))?;
33+
34+
run_command(&["cp".as_ref(), "-r".as_ref(), src_dir.as_os_str(), dst_dir.as_os_str()], None)?;
35+
36+
println!("[GIT] init (cwd): `{}`", dst_dir.display());
37+
run_command(&["git", "init"], Some(&dst_dir))?;
38+
println!("[GIT] add (cwd): `{}`", dst_dir.display());
39+
run_command(&["git", "add", "."], Some(&dst_dir))?;
40+
println!("[GIT] commit (cwd): `{}`", dst_dir.display());
41+
42+
// This is needed on systems where nothing is configured.
43+
// git really needs something here, or it will fail.
44+
// Even using --author is not enough.
45+
run_command(&["git", "config", "user.email", "[email protected]"], Some(&dst_dir))?;
46+
run_command(&["git", "config", "user.name", "None"], Some(&dst_dir))?;
47+
run_command(&["git", "commit", "-m", "Initial commit", "-q"], Some(&dst_dir))?;
48+
49+
walk_dir("patches", |_| Ok(()), |file_path: &Path| {
50+
println!("[GIT] apply `{}`", file_path.display());
51+
let path = Path::new("../..").join(file_path);
52+
run_command(&["git".as_ref(), "apply".as_ref(), path.as_os_str()], Some(&dst_dir))?;
53+
run_command(&["git", "add", "-A"], Some(&dst_dir))?;
54+
run_command(
55+
&["git", "commit", "--no-gpg-sign", "-m", &format!("Patch {}", path.display())],
56+
Some(&dst_dir),
57+
)?;
58+
Ok(())
59+
})?;
60+
println!("Successfully prepared libcore for building");
61+
Ok(())
62+
}
63+
64+
// build with cg_llvm for perf comparison
65+
fn build_raytracer(repo_dir: &Path) -> Result<(), String> {
66+
run_command(&["cargo", "build"], Some(repo_dir))?;
67+
run_command(&["mv", "taret/debug/main", "raytracer_cg_llvm"], Some(repo_dir))?;
68+
Ok(())
69+
}
70+
71+
fn clone_and_setup<F>(repo_url: &str, checkout_commit: &str, extra: Option<F>) -> Result<(), String>
72+
where
73+
F: Fn(&Path) -> Result<(), String>,
74+
{
75+
let res = git_clone(repo_url, None)?;
76+
if !res.ran_clone {
77+
println!("`{}` has already been cloned", res.repo_name);
78+
}
79+
let repo_path = Path::new(&res.repo_name);
80+
run_command(&["git", "checkout", "--", "."], Some(repo_path))?;
81+
run_command(&["git", "checkout", checkout_commit], Some(repo_path))?;
82+
let filter = format!("-{}-", res.repo_name);
83+
walk_dir("crate_patches", |_| Ok(()), |file_path| {
84+
let s = file_path.as_os_str().to_str().unwrap();
85+
if s.contains(&filter) && s.ends_with(".patch") {
86+
run_command(&["git", "am", s], Some(repo_path))?;
87+
}
88+
Ok(())
89+
})?;
90+
if let Some(extra) = extra {
91+
extra(repo_path)?;
92+
}
93+
Ok(())
94+
}
95+
96+
pub fn run() -> Result<(), String> {
97+
prepare_libcore()?;
98+
99+
cargo_install("hyperfine")?;
100+
101+
let to_clone = &[
102+
("https://github.com/rust-random/rand.git", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", None),
103+
("https://github.com/rust-lang/regex.git", "341f207c1071f7290e3f228c710817c280c8dca1", None),
104+
("https://github.com/ebobby/simple-raytracer", "804a7a21b9e673a482797aa289a18ed480e4d813", Some(build_raytracer)),
105+
];
106+
107+
for (repo_url, checkout_commit, cb) in to_clone {
108+
clone_and_setup(repo_url, checkout_commit, *cb)?;
109+
}
110+
111+
println!("Successfully ran `prepare`");
112+
Ok(())
113+
}

build_system/src/rustc_info.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use std::path::{Path, PathBuf};
2+
3+
use crate::utils::run_command;
4+
5+
pub fn get_rustc_path() -> Option<PathBuf> {
6+
if let Ok(rustc) = std::env::var("RUSTC") {
7+
return Some(PathBuf::from(rustc));
8+
}
9+
run_command(&["rustup", "which", "rustc"], None)
10+
.ok()
11+
.map(|out| Path::new(String::from_utf8(out.stdout).unwrap().trim()).to_owned())
12+
}

build_system/src/utils.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
use std::ffi::OsStr;
2+
use std::fs;
3+
use std::path::Path;
4+
use std::process::{Command, Output};
5+
6+
pub fn run_command<S>(input: &[S], cwd: Option<&Path>) -> Result<Output, String>
7+
where
8+
S: AsRef<OsStr>,
9+
{
10+
let (cmd, args) = match input {
11+
[] => panic!("empty command"),
12+
[cmd, args @ ..] => (cmd, args),
13+
};
14+
let mut c = Command::new(cmd);
15+
c.args(args);
16+
if let Some(cwd) = cwd {
17+
c.current_dir(cwd);
18+
}
19+
c.output()
20+
.map_err(|e| format!(
21+
"Command `{}` failed to run: {e:?}",
22+
input.iter().fold(String::new(), |mut acc, s| {
23+
if !acc.is_empty() {
24+
acc.push(' ');
25+
}
26+
acc.push_str(s.as_ref().to_str().unwrap());
27+
acc
28+
})
29+
))
30+
}
31+
32+
pub fn cargo_install(to_install: &str) -> Result<(), String> {
33+
let output = run_command(&["cargo", "install", "--list"], None)?;
34+
35+
let to_install = format!("{to_install} ");
36+
if String::from_utf8(output.stdout).unwrap().lines().any(|line| line.ends_with(':') && line.starts_with(&to_install)) {
37+
return Ok(());
38+
}
39+
run_command(&["cargo", "install", &to_install], None)?;
40+
Ok(())
41+
}
42+
43+
pub struct CloneResult {
44+
pub ran_clone: bool,
45+
pub repo_name: String,
46+
}
47+
48+
/// Returns `Ok(true)` if the repository was already cloned.
49+
pub fn git_clone(to_clone: &str, dest: Option<&Path>) -> Result<CloneResult, String> {
50+
let repo_name = to_clone.split('/').last().unwrap();
51+
let repo_name = match repo_name.strip_suffix(".git") {
52+
Some(n) => n.to_owned(),
53+
None => repo_name.to_owned(),
54+
};
55+
56+
let dest = dest.unwrap_or_else(|| Path::new(&repo_name));
57+
if dest.is_dir() {
58+
return Ok(CloneResult { ran_clone: false, repo_name });
59+
}
60+
61+
run_command(&["git", "clone", to_clone, dest.as_os_str().to_str().unwrap()], None)?;
62+
Ok(CloneResult { ran_clone: true, repo_name })
63+
}
64+
65+
pub fn walk_dir<P, D, F>(dir: P, dir_cb: D, file_cb: F) -> Result<(), String>
66+
where
67+
P: AsRef<Path>,
68+
D: Fn(&Path) -> Result<(), String>,
69+
F: Fn(&Path) -> Result<(), String>,
70+
{
71+
let dir = dir.as_ref();
72+
for entry in fs::read_dir(dir).map_err(|e| format!("Failed to read dir `{}`: {e:?}", dir.display()))? {
73+
let entry = entry.map_err(|e| format!("Failed to read entry in `{}`: {e:?}", dir.display()))?;
74+
let entry_path = entry.path();
75+
if entry_path.is_dir() {
76+
dir_cb(&entry_path)?;
77+
} else {
78+
file_cb(&entry_path)?;
79+
}
80+
}
81+
Ok(())
82+
}

y.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
echo "[BUILD] build system" 1>&2
5+
mkdir -p build_system/target
6+
rustc build_system/src/main.rs -o build_system/target/y -Cdebuginfo=1 --edition 2021
7+
exec ./build_system/target/y "$@"

0 commit comments

Comments
 (0)