-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4748fdc
commit 31bc169
Showing
9 changed files
with
285 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[package] | ||
name = "y" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[[bin]] | ||
name = "y" | ||
path = "src/main.rs" | ||
|
||
[features] | ||
unstable-features = [] # for rust-analyzer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
pub fn run() -> Result<(), String> { | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
#![feature(exclusive_range_pattern)] | ||
|
||
use std::env; | ||
use std::process; | ||
|
||
mod build; | ||
mod prepare; | ||
mod rustc_info; | ||
mod utils; | ||
|
||
macro_rules! arg_error { | ||
($($err:tt)*) => {{ | ||
eprintln!($($err)*); | ||
usage(); | ||
std::process::exit(1); | ||
}}; | ||
} | ||
|
||
fn usage() { | ||
// eprintln!("{}", include_str!("usage.txt")); | ||
} | ||
|
||
pub enum Command { | ||
Prepare, | ||
Build, | ||
} | ||
|
||
fn main() { | ||
if env::var("RUST_BACKTRACE").is_err() { | ||
env::set_var("RUST_BACKTRACE", "1"); | ||
} | ||
|
||
let mut args = env::args().skip(1); | ||
let command = match args.next().as_deref() { | ||
Some("prepare") => Command::Prepare, | ||
Some("build") => Command::Build, | ||
Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), | ||
Some(command) => arg_error!("Unknown command {}", command), | ||
None => { | ||
usage(); | ||
process::exit(0); | ||
} | ||
}; | ||
|
||
if let Err(e) = match command { | ||
Command::Prepare => prepare::run(), | ||
Command::Build => build::run(), | ||
} { | ||
eprintln!("Command failed to run: {e:?}"); | ||
process::exit(1); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
use crate::rustc_info::get_rustc_path; | ||
use crate::utils::{cargo_install, git_clone, run_command, walk_dir}; | ||
|
||
use std::fs; | ||
use std::path::Path; | ||
|
||
fn prepare_libcore() -> Result<(), String> { | ||
let rustc_path = match get_rustc_path() { | ||
Some(path) => path, | ||
None => return Err("`rustc` path not found".to_owned()), | ||
}; | ||
|
||
let parent = match rustc_path.parent() { | ||
Some(path) => path, | ||
None => return Err(format!("No parent for `{}`", rustc_path.display())), | ||
}; | ||
|
||
let src_dir = parent.join("../lib/rustlib/src/rust"); | ||
if !src_dir.is_dir() { | ||
return Err("Please install `rust-src` component".to_owned()); | ||
} | ||
|
||
let dst_dir = Path::new("sysroot_src"); | ||
if dst_dir.is_dir() { | ||
if let Err(e) = fs::remove_dir_all(dst_dir) { | ||
return Err(format!("Failed to remove `{}`: {:?}", dst_dir.display(), e)); | ||
} | ||
} | ||
|
||
let dst_dir = dst_dir.join("library"); | ||
fs::create_dir_all(&dst_dir) | ||
.map_err(|e| format!("Failed to folder `{}`: {e:?}", dst_dir.display()))?; | ||
|
||
run_command(&[&"cp", &"-r", &src_dir, &dst_dir], None)?; | ||
|
||
println!("[GIT] init (cwd): `{}`", dst_dir.display()); | ||
run_command(&[&"git", &"init"], Some(&dst_dir))?; | ||
println!("[GIT] add (cwd): `{}`", dst_dir.display()); | ||
run_command(&[&"git", &"add", &"."], Some(&dst_dir))?; | ||
println!("[GIT] commit (cwd): `{}`", dst_dir.display()); | ||
|
||
// This is needed on systems where nothing is configured. | ||
// git really needs something here, or it will fail. | ||
// Even using --author is not enough. | ||
run_command(&[&"git", &"config", &"user.email", &"[email protected]"], Some(&dst_dir))?; | ||
run_command(&[&"git", &"config", &"user.name", &"None"], Some(&dst_dir))?; | ||
run_command(&[&"git", &"commit", &"-m", &"Initial commit", &"-q"], Some(&dst_dir))?; | ||
|
||
walk_dir("patches", |_| Ok(()), |file_path: &Path| { | ||
println!("[GIT] apply `{}`", file_path.display()); | ||
let path = Path::new("../..").join(file_path); | ||
run_command(&[&"git", &"apply", &path], Some(&dst_dir))?; | ||
run_command(&[&"git", &"add", &"-A"], Some(&dst_dir))?; | ||
run_command( | ||
&[&"git", &"commit", &"--no-gpg-sign", &"-m", &format!("Patch {}", path.display())], | ||
Some(&dst_dir), | ||
)?; | ||
Ok(()) | ||
})?; | ||
println!("Successfully prepared libcore for building"); | ||
Ok(()) | ||
} | ||
|
||
// build with cg_llvm for perf comparison | ||
fn build_raytracer(repo_dir: &Path) -> Result<(), String> { | ||
run_command(&[&"cargo", &"build"], Some(repo_dir))?; | ||
run_command(&[&"mv", &"target/debug/main", &"raytracer_cg_llvm"], Some(repo_dir))?; | ||
Ok(()) | ||
} | ||
|
||
fn clone_and_setup<F>(repo_url: &str, checkout_commit: &str, extra: Option<F>) -> Result<(), String> | ||
where | ||
F: Fn(&Path) -> Result<(), String>, | ||
{ | ||
let res = git_clone(repo_url, None)?; | ||
if !res.ran_clone { | ||
println!("`{}` has already been cloned", res.repo_name); | ||
} | ||
let repo_path = Path::new(&res.repo_name); | ||
run_command(&[&"git", &"checkout", &"--", &"."], Some(repo_path))?; | ||
run_command(&[&"git", &"checkout", &checkout_commit], Some(repo_path))?; | ||
let filter = format!("-{}-", res.repo_name); | ||
walk_dir("crate_patches", |_| Ok(()), |file_path| { | ||
let s = file_path.as_os_str().to_str().unwrap(); | ||
if s.contains(&filter) && s.ends_with(".patch") { | ||
run_command(&[&"git", &"am", &s], Some(repo_path))?; | ||
} | ||
Ok(()) | ||
})?; | ||
if let Some(extra) = extra { | ||
extra(repo_path)?; | ||
} | ||
Ok(()) | ||
} | ||
|
||
pub fn run() -> Result<(), String> { | ||
prepare_libcore()?; | ||
|
||
cargo_install("hyperfine")?; | ||
|
||
let to_clone = &[ | ||
("https://github.com/rust-random/rand.git", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", None), | ||
("https://github.com/rust-lang/regex.git", "341f207c1071f7290e3f228c710817c280c8dca1", None), | ||
("https://github.com/ebobby/simple-raytracer", "804a7a21b9e673a482797aa289a18ed480e4d813", Some(build_raytracer)), | ||
]; | ||
|
||
for (repo_url, checkout_commit, cb) in to_clone { | ||
clone_and_setup(repo_url, checkout_commit, *cb)?; | ||
} | ||
|
||
println!("Successfully ran `prepare`"); | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
use std::path::{Path, PathBuf}; | ||
|
||
use crate::utils::run_command; | ||
|
||
pub fn get_rustc_path() -> Option<PathBuf> { | ||
if let Ok(rustc) = std::env::var("RUSTC") { | ||
return Some(PathBuf::from(rustc)); | ||
} | ||
run_command(&[&"rustup", &"which", &"rustc"], None) | ||
.ok() | ||
.map(|out| Path::new(String::from_utf8(out.stdout).unwrap().trim()).to_owned()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
use std::ffi::OsStr; | ||
use std::fs; | ||
use std::path::Path; | ||
use std::process::{Command, Output}; | ||
|
||
pub fn run_command(input: &[&dyn AsRef<OsStr>], cwd: Option<&Path>) -> Result<Output, String> { | ||
let (cmd, args) = match input { | ||
[] => panic!("empty command"), | ||
[cmd, args @ ..] => (cmd, args), | ||
}; | ||
let mut c = Command::new(cmd); | ||
c.args(args); | ||
if let Some(cwd) = cwd { | ||
c.current_dir(cwd); | ||
} | ||
c.output() | ||
.map_err(|e| format!( | ||
"Command `{}` failed to run: {e:?}", | ||
input.iter().fold(String::new(), |mut acc, s| { | ||
if !acc.is_empty() { | ||
acc.push(' '); | ||
} | ||
acc.push_str(s.as_ref().to_str().unwrap()); | ||
acc | ||
}) | ||
)) | ||
} | ||
|
||
pub fn cargo_install(to_install: &str) -> Result<(), String> { | ||
let output = run_command(&[&"cargo", &"install", &"--list"], None)?; | ||
|
||
let to_install = format!("{to_install} "); | ||
if String::from_utf8(output.stdout).unwrap().lines().any(|line| line.ends_with(':') && line.starts_with(&to_install)) { | ||
return Ok(()); | ||
} | ||
run_command(&[&"cargo", &"install", &to_install], None)?; | ||
Ok(()) | ||
} | ||
|
||
pub struct CloneResult { | ||
pub ran_clone: bool, | ||
pub repo_name: String, | ||
} | ||
|
||
/// Returns `Ok(true)` if the repository was already cloned. | ||
pub fn git_clone(to_clone: &str, dest: Option<&Path>) -> Result<CloneResult, String> { | ||
let repo_name = to_clone.split('/').last().unwrap(); | ||
let repo_name = match repo_name.strip_suffix(".git") { | ||
Some(n) => n.to_owned(), | ||
None => repo_name.to_owned(), | ||
}; | ||
|
||
let dest = dest.unwrap_or_else(|| Path::new(&repo_name)); | ||
if dest.is_dir() { | ||
return Ok(CloneResult { ran_clone: false, repo_name }); | ||
} | ||
|
||
run_command(&[&"git", &"clone", &to_clone, &dest], None)?; | ||
Ok(CloneResult { ran_clone: true, repo_name }) | ||
} | ||
|
||
pub fn walk_dir<P, D, F>(dir: P, dir_cb: D, file_cb: F) -> Result<(), String> | ||
where | ||
P: AsRef<Path>, | ||
D: Fn(&Path) -> Result<(), String>, | ||
F: Fn(&Path) -> Result<(), String>, | ||
{ | ||
let dir = dir.as_ref(); | ||
for entry in fs::read_dir(dir).map_err(|e| format!("Failed to read dir `{}`: {e:?}", dir.display()))? { | ||
let entry = entry.map_err(|e| format!("Failed to read entry in `{}`: {e:?}", dir.display()))?; | ||
let entry_path = entry.path(); | ||
if entry_path.is_dir() { | ||
dir_cb(&entry_path)?; | ||
} else { | ||
file_cb(&entry_path)?; | ||
} | ||
} | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#!/usr/bin/env bash | ||
|
||
set -e | ||
echo "[BUILD] build system" 1>&2 | ||
mkdir -p build_system/target | ||
rustc build_system/src/main.rs -o build_system/target/y -Cdebuginfo=1 --edition 2021 | ||
exec ./build_system/target/y "$@" |