150 lines
3.9 KiB
Rust
150 lines
3.9 KiB
Rust
|
// use std::{collections::HashMap, path::Path};
|
||
|
|
||
|
use std::{collections::HashMap, path::Path, process::Command};
|
||
|
|
||
|
use crate::{env::BuildEnv, error::Error, util};
|
||
|
|
||
|
const TOOLCHAIN_URL: &str = "https://git.alnyan.me/yggdrasil/yggdrasil-rust";
|
||
|
|
||
|
#[derive(Debug, serde::Serialize)]
|
||
|
struct RustBuildConfig {
|
||
|
host: Vec<String>,
|
||
|
target: Vec<String>,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug, serde::Serialize)]
|
||
|
struct RustTargetConfig {
|
||
|
cc: Option<String>,
|
||
|
cxx: Option<String>,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug, serde::Serialize)]
|
||
|
struct RustRustConfig {
|
||
|
incremental: bool,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug, serde::Serialize)]
|
||
|
#[serde(rename_all = "kebab-case")]
|
||
|
struct RustToolchainConfig {
|
||
|
profile: String,
|
||
|
changelog_seen: u32,
|
||
|
change_id: u32,
|
||
|
|
||
|
build: RustBuildConfig,
|
||
|
target: HashMap<String, RustTargetConfig>,
|
||
|
rust: RustRustConfig,
|
||
|
}
|
||
|
|
||
|
fn configure<P: AsRef<Path>>(env: &BuildEnv, config_toml_path: P) -> Result<(), Error> {
|
||
|
let config = RustToolchainConfig {
|
||
|
profile: "user".into(),
|
||
|
changelog_seen: 2,
|
||
|
change_id: 102579,
|
||
|
|
||
|
build: RustBuildConfig {
|
||
|
host: vec![env.host_triple.clone()],
|
||
|
target: vec![
|
||
|
env.host_triple.clone(),
|
||
|
"x86_64-unknown-yggdrasil".into(),
|
||
|
"aarch64-unknown-yggdrasil".into(),
|
||
|
],
|
||
|
},
|
||
|
target: HashMap::from_iter([(
|
||
|
"aarch64-unknown-yggdrasil".into(),
|
||
|
RustTargetConfig {
|
||
|
cc: Some("aarch64-linux-gnu-gcc".into()),
|
||
|
cxx: Some("aarch64-linux-gnu-g++".into()),
|
||
|
},
|
||
|
)]),
|
||
|
rust: RustRustConfig { incremental: true },
|
||
|
};
|
||
|
|
||
|
let toml = toml::to_string_pretty(&config)?;
|
||
|
std::fs::write(config_toml_path, toml.as_bytes())?;
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
pub fn is_toolchain_linked() -> bool {
|
||
|
util::run_external_command("cargo", ["+ygg-stage1", "--version"], true).is_ok()
|
||
|
}
|
||
|
|
||
|
fn link_rustup_toolchain<P: AsRef<Path>>(env: &BuildEnv, toolchain_root: P) -> Result<(), Error> {
|
||
|
util::run_external_command(
|
||
|
"rustup",
|
||
|
[
|
||
|
"toolchain",
|
||
|
"link",
|
||
|
"ygg-stage1",
|
||
|
&format!(
|
||
|
"{}",
|
||
|
toolchain_root
|
||
|
.as_ref()
|
||
|
.join("build")
|
||
|
.join(&env.host_triple)
|
||
|
.join("stage1")
|
||
|
.display()
|
||
|
),
|
||
|
],
|
||
|
false,
|
||
|
)
|
||
|
}
|
||
|
|
||
|
fn do_build<P: AsRef<Path>>(toolchain_root: P) -> Result<(), Error> {
|
||
|
let status = Command::new("./x")
|
||
|
.current_dir(toolchain_root)
|
||
|
.args(["build", "--stage=1"])
|
||
|
.status()?;
|
||
|
if status.success() {
|
||
|
Ok(())
|
||
|
} else {
|
||
|
Err(Error::ToolchainBuildFailed)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn fetch(env: &BuildEnv, branch: &str) -> Result<(), Error> {
|
||
|
let path = env.workspace_root.join("toolchain");
|
||
|
|
||
|
match git2::Repository::open(&path) {
|
||
|
Ok(_) => {}
|
||
|
Err(err) if err.code() == git2::ErrorCode::NotFound => {
|
||
|
log::info!(
|
||
|
"Fetching toolchain: src={}, branch={}",
|
||
|
TOOLCHAIN_URL,
|
||
|
branch
|
||
|
);
|
||
|
|
||
|
git2::build::RepoBuilder::new()
|
||
|
.branch(branch)
|
||
|
.clone(TOOLCHAIN_URL, &path)?;
|
||
|
}
|
||
|
Err(err) => return Err(err.into()),
|
||
|
}
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
pub fn build(env: &BuildEnv) -> Result<(), Error> {
|
||
|
let toolchain_path = env.workspace_root.join("toolchain");
|
||
|
let config_toml_path = toolchain_path.join("config.toml");
|
||
|
|
||
|
assert!(toolchain_path.exists());
|
||
|
|
||
|
// Write config.toml
|
||
|
if !config_toml_path.exists() {
|
||
|
configure(env, config_toml_path)?;
|
||
|
}
|
||
|
|
||
|
log::info!("Building toolchain");
|
||
|
do_build(&toolchain_path)?;
|
||
|
|
||
|
if !is_toolchain_linked() {
|
||
|
log::info!("Linking the newly built toolchain to +ygg-stage1");
|
||
|
link_rustup_toolchain(env, &toolchain_path)?;
|
||
|
} else {
|
||
|
log::debug!("Toolchain already linked");
|
||
|
}
|
||
|
|
||
|
Ok(())
|
||
|
}
|