Commit 9ca094a1 authored by Westly Ward's avatar Westly Ward
Browse files

Initial commit

parents
[package]
name = "rustbstrap"
version = "0.2.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.44"
ctrlc = "3.2.0"
exitcode = "1.1.2"
nix = "0.23.0"
ureq = "2.2.0"
fn main() {
println!("cargo:rustc-env=TARGET={}", std::env::var("TARGET").unwrap());
}
use std::io::Write;
use std::io::BufReader;
use std::io::Read;
use std::path::PathBuf;
//use path_absolutize::*;
pub struct VersionData {
pub rustc: PathBuf,
pub cargo: PathBuf,
pub url: String,
pub config: String,
pub output_file: PathBuf,
pub output_dir: PathBuf,
pub git_command: String,
}
impl VersionData {
pub fn new(version: impl Into<String>, rustc_versions: Vec<impl Into<String>>, base_directory: impl Into<PathBuf>, target_triple: impl Into<String>) -> Self {
let ver = version.into();
let base_dir = base_directory.into();
let mut versions: Vec<String> = Vec::new();
let mut cargo_init = base_dir.clone();
cargo_init.push("/usr/bin/cargo");
let mut cargo = cargo_init.clone();
let triple = target_triple.into();
let mut rustc_init = base_dir.clone();
rustc_init.push("/usr/bin/rustc");
let mut rustc = rustc_init.clone();
let url = format!("https://static.rust-lang.org/dist/rustc-{}-src.tar.gz", ver);
let git_command = format!("git clone https://github.com/smaeul/rust.git -b bootstrap-{} --depth 1 bootstrap-{}", ver, ver);
let mut output_file = base_dir.clone();
output_file.push(format!("rustc-{}-src.tar.gz", ver).as_str());
let mut output_dir = base_dir.clone();
output_dir.push(format!("bootstrap-{}", ver).as_str());
for vers in rustc_versions {
let vrsn = vers.into();
versions.push(vrsn);
}
for (num, vers) in versions.clone().into_iter().enumerate() {
let rustc_version: String = vers.into();
if rustc_version == ver {
if num != 0 {
let mut cargo_start = base_dir.clone();
cargo_start.push(format!("bootstrap-{}/build/{}/stage2-tools-bin/cargo", versions.clone()[num - 1], triple));
cargo = cargo_start.clone();//PathBuf::new(format!().as_str().absolutize.unwrap().into_owned())
let mut rustc_start = base_dir.clone();
rustc_start.push(format!("bootstrap-{}/build/{}/stage2/bin/rustc", versions.clone()[num - 1], triple).as_str());
rustc = rustc_start.clone();
}
}
}
let config = format!(r#"[build]
cargo = "{}"
rustc = "{}"
docs = false
vendor = true
extended = true
tools = ["cargo"]
build = "{}"
[rust]
channel = "stable"
#[target.{}]
#crt-static = false"#, cargo.clone().to_str().unwrap(), rustc.clone().to_str().unwrap(), triple, triple);
Self {
rustc: rustc,
cargo: cargo,
url: url,
config: config,
output_file: output_file,
output_dir: output_dir,
git_command: git_command,
}
}
}
pub fn buffered_download(url: impl Into<String>, output: impl Into<PathBuf>) -> Result<(), anyhow::Error> {
let url_string = url.into();
let out_path = output.into();
let mut outfile = std::fs::File::create(out_path)?;
let response = ureq::get(url_string.as_str()).call()?;
let mut reader = BufReader::new(response.into_reader());
let mut keep_going = true;
while keep_going {
let buf = read_bytes(&mut reader)?;
if !buf.is_empty() {
outfile.write_all(&buf)?;
} else {
keep_going = false;
}
}
Ok(())
}
fn read_bytes(reader: &mut (impl Read + Send)) -> Result<Vec<u8>, anyhow::Error> {
let mut chunk = reader.take(409600000);
let mut buf: Vec<u8> = Vec::new();
chunk.read_to_end(&mut buf)?;
Ok(buf)
}
use std::collections::HashMap;
use std::io::Write;
use std::fs::OpenOptions;
//use std::thread;
use std::process::{Command, Stdio};
use std::sync::mpsc::{TryRecvError, channel};
//use std::path::{Path, PathBuf};
fn main() {
const TARGET: &str = env!("TARGET");
const RUSTC_VERSIONS: &[&str; 12] = &["1.39.0",
"1.40.0",
"1.41.1",
"1.42.0",
"1.43.1",
"1.44.1",
"1.45.2",
"1.46.0",
"1.47.0",
"1.48.0",
"1.49.0",
"1.50.0"];
/*
"1.51.0",
"1.52.0",
"1.52.1",
"1.53.0",
"1.54.0",
"1.55.0"];
*/
// const CARGO_CONFIG: &str = r#"[target.x86_64-unknown-linux-musl]
//linker = "x86_64-foxkit-musl-gcc""#;
let versions = RUSTC_VERSIONS.to_vec();
let mut version_info: HashMap<&str, rustbstrap::VersionData> = HashMap::new();
//let versions = RUSTC_VERSIONS.to_vec();
let base_dir = std::env::current_dir().unwrap();
let mut compiled_versions: Vec<String> = Vec::new();
let mut extracted_versions: Vec<String> = Vec::new();
let mut downloaded_versions: Vec<String> = Vec::new();
let mut downloaded_log = base_dir.clone();
let mut compiled_log = base_dir.clone();
let mut extracted_log = base_dir.clone();
downloaded_log.push("downloaded.log");
compiled_log.push("compiled.log");
extracted_log.push("extracted.log");
if compiled_log.exists(){
let compiled_data = std::fs::read_to_string(compiled_log.clone()).unwrap();
for version in compiled_data.replace("\r", "").split("\n") {
if version.trim() != "" {
compiled_versions.push(version.to_string());
}
}
}
if extracted_log.exists(){
let extracted_data = std::fs::read_to_string(extracted_log.clone()).unwrap();
for version in extracted_data.replace("\r", "").split("\n") {
if version.trim() != "" {
extracted_versions.push(version.to_string());
}
}
}
if downloaded_log.exists(){
let downloaded_data = std::fs::read_to_string(downloaded_log.clone()).unwrap();
for version in downloaded_data.replace("\r", "").split("\n") {
if version.trim() != "" {
downloaded_versions.push(version.to_string());
}
}
}
for version in RUSTC_VERSIONS.clone() {
version_info.insert(version, rustbstrap::VersionData::new(version, versions.clone(), base_dir.clone(), TARGET));
}
let (tx, rx) = channel();
let tx_clone = tx.clone();
ctrlc::set_handler(move || tx_clone.send("ctrlc").expect("Could not send signal on channel."))
.expect("Error setting Ctrl-C handler");
/*
for version in RUSTC_VERSIONS { //.clone() {
if !downloaded_versions.contains(&version.to_string()) {
println!("Downloading rust version {}...", version);
if version_info.get(version).unwrap().output_file.clone().exists() {
std::fs::remove_file(version_info.get(version).unwrap().output_file.clone()).unwrap();
}
rustbstrap::buffered_download(version_info.get(version).unwrap().url.clone(), version_info.get(version).unwrap().output_file.clone()).unwrap();
{
let mut out_file = OpenOptions::new().append(true).create(true).open(downloaded_log.clone()).unwrap();
out_file.write_all(format!("{}\n", version).as_bytes()).expect("Unable to write to downloaded files log.");
}
} else {
println!("Skipping downloading rust version {} because it's already downloaded...", version);
}
}
let mut tar_commands: Vec<(String, Vec<String>)> = Vec::new();
for version in RUSTC_VERSIONS { //.clone() {
let out_dir = version_info.get(version).unwrap().output_dir.clone().to_str().unwrap().to_string();
let out_file = version_info.get(version).unwrap().output_file.clone().to_str().unwrap().to_string();
if !version_info.get(version).unwrap().output_dir.clone().exists() {
std::fs::create_dir(version_info.get(version).unwrap().output_dir.clone()).unwrap();
}
let mut config_path = version_info.get(version).unwrap().output_dir.clone();
config_path.push("config.toml");
if config_path.exists() {
std::fs::remove_file(config_path.clone()).unwrap();
}
let mut config_file = std::fs::File::create(config_path).unwrap();
config_file.write_all(version_info.get(version).unwrap().config.as_bytes()).unwrap();
if extracted_versions.contains(&version.to_string()) {
println!("Skipping extracting rust version {} because it's already extracted...", version);
continue;
}
let command = vec!["tar".to_string(), "xzf".to_string(), out_file, "-C".to_string(), out_dir, "--strip-components".to_string(), "1".to_string()];
tar_commands.push((version.to_string(), command));
}
for cmd in tar_commands {
let command = cmd.clone().1.clone();
let version = cmd.clone().0.clone();
println!("{}", command.clone().join(" "));
let mut child = Command::new(command[0].clone()).args(command[1..].into_iter()).stdout(Stdio::inherit()).stderr(Stdio::inherit()).stdin(Stdio::inherit()).spawn().unwrap();
let child_id = child.id() as i32;
//let (tx2, rx2) = channel();
let tx_clone2 = tx.clone();
//let tx2_clone = tx2.clone();
std::thread::spawn(move || {
child.wait().unwrap();
//tx2_clone.send(child.wait().expect("abuild not running").success()).unwrap();
tx_clone2.send("done").unwrap();
});
let mut status = match rx.try_recv() {
Ok(rx) => rx,
Err(TryRecvError::Empty) => "empty",
Err(TryRecvError::Disconnected) => "disconnected",
};
while status != "ctrlc" && status != "done" {
status = match rx.try_recv() {
Ok(rx) => rx,
Err(TryRecvError::Empty) => "empty",
Err(TryRecvError::Disconnected) => "disconnected",
};
std::thread::sleep(std::time::Duration::from_micros(1));
}
if status == "ctrlc" {
//tx2.send("quit").unwrap();
nix::sys::signal::kill(
nix::unistd::Pid::from_raw(child_id),
nix::sys::signal::Signal::SIGINT
).expect("cannot send ctrl-c");
return;
//std::process::exit(exitcode::TEMPFAIL);
} else {
let mut out_file = OpenOptions::new().append(true).create(true).open(extracted_log.clone()).unwrap();
out_file.write_all(format!("{}\n", version).as_bytes()).expect("Unable to write to extracted versions log.");
}
}
*/
for version in RUSTC_VERSIONS {
let command_string = version_info.get(version).unwrap().git_command.clone();
let command = command_string.split(" ").collect::<Vec<&str>>();
//let command = cmd.clone().1.clone();
//let version = cmd.clone().0.clone();
println!("{}", command.clone().join(" "));
let mut child = Command::new(command[0].clone()).args(command[1..].into_iter()).stdout(Stdio::inherit()).stderr(Stdio::inherit()).stdin(Stdio::inherit()).spawn().unwrap();
let child_id = child.id() as i32;
//let (tx2, rx2) = channel();
let tx_clone2 = tx.clone();
//let tx2_clone = tx2.clone();
std::thread::spawn(move || {
child.wait().unwrap();
//tx2_clone.send(child.wait().expect("abuild not running").success()).unwrap();
tx_clone2.send("done").unwrap();
});
let mut status = match rx.try_recv() {
Ok(rx) => rx,
Err(TryRecvError::Empty) => "empty",
Err(TryRecvError::Disconnected) => "disconnected",
};
while status != "ctrlc" && status != "done" {
status = match rx.try_recv() {
Ok(rx) => rx,
Err(TryRecvError::Empty) => "empty",
Err(TryRecvError::Disconnected) => "disconnected",
};
std::thread::sleep(std::time::Duration::from_micros(1));
}
if status == "ctrlc" {
//tx2.send("quit").unwrap();
nix::sys::signal::kill(
nix::unistd::Pid::from_raw(child_id),
nix::sys::signal::Signal::SIGINT
).expect("cannot send ctrl-c");
return;
//std::process::exit(exitcode::TEMPFAIL);
} else {
let mut out_file = OpenOptions::new().append(true).create(true).open(downloaded_log.clone()).unwrap();
out_file.write_all(format!("{}\n", version).as_bytes()).expect("Unable to write to downloaded versions log.");
}
let mut config_path = version_info.get(version).unwrap().output_dir.clone();
config_path.push("config.toml");
if config_path.exists() {
std::fs::remove_file(config_path.clone()).unwrap();
}
let mut config_file = std::fs::File::create(config_path).unwrap();
config_file.write_all(version_info.get(version).unwrap().config.as_bytes()).unwrap();
}
let mut cargo_home = base_dir.clone();
cargo_home.push(".cargo");
std::env::set_var("CARGO_HOME", cargo_home.to_str().unwrap());
for version in RUSTC_VERSIONS { //.clone() {
std::env::set_current_dir(version_info.get(version).unwrap().output_dir.clone()).unwrap();
println!("Building rust version {}", version);
let mut child = Command::new("python3").arg("x.py").arg("build").stdout(Stdio::inherit()).stderr(Stdio::inherit()).stdin(Stdio::inherit()).spawn().unwrap();
let child_id = child.id() as i32;
let (tx2, rx2) = channel();
let tx_clone2 = tx.clone();
let tx2_clone = tx2.clone();
std::thread::spawn(move || {
//child.wait().unwrap();
tx2_clone.send(child.wait().expect("command not running")).unwrap();
tx_clone2.send("done").unwrap();
});
let mut status = match rx.try_recv() {
Ok(rx) => rx,
Err(TryRecvError::Empty) => "empty",
Err(TryRecvError::Disconnected) => "disconnected",
};
while status != "ctrlc" && status != "done" {
status = match rx.try_recv() {
Ok(rx) => rx,
Err(TryRecvError::Empty) => "empty",
Err(TryRecvError::Disconnected) => "disconnected",
};
std::thread::sleep(std::time::Duration::from_micros(1));
}
if status == "ctrlc" {
//tx2.send("quit").unwrap();
nix::sys::signal::kill(
nix::unistd::Pid::from_raw(child_id),
nix::sys::signal::Signal::SIGINT
).expect("cannot send ctrl-c");
return;
//std::process::exit(exitcode::TEMPFAIL);
}
let command_status = rx2.recv().unwrap();
if !command_status.success() {
if command_status.code().is_some() {
std::process::exit(command_status.code().unwrap());
}
std::process::exit(exitcode::TEMPFAIL);
} else {
let mut out_file = OpenOptions::new().append(true).create(true).open(compiled_log.clone()).unwrap();
out_file.write_all(format!("{}\n", version).as_bytes()).expect("Unable to write to compiled versions log.");
}
}
std::env::set_current_dir(base_dir).unwrap();
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment