yggdrasil/xtask/src/build/toolchain.rs

174 lines
4.5 KiB
Rust
Raw Normal View History

2024-03-12 18:17:47 +02:00
// use std::{collections::HashMap, path::Path};
2024-08-10 20:41:32 +03:00
use std::{
collections::HashMap, fs::OpenOptions, os::unix::fs::OpenOptionsExt, path::Path,
process::Command,
};
2024-03-12 18:17:47 +02:00
2024-11-13 16:31:26 +02:00
use crate::{
env::BuildEnv,
error::Error,
util::{self, git_clone},
};
2024-03-12 18:17:47 +02:00
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)
}
}
2024-08-10 20:41:32 +03:00
fn install_shims<P: AsRef<Path>>(env: &BuildEnv, toolchain_root: P) -> Result<(), Error> {
use std::io::Write;
let toolchain_root = toolchain_root.as_ref();
let build_dir = toolchain_root.join("build").join(&env.host_triple);
let stage1_rustlib = build_dir
.join("stage1/lib/rustlib/")
.join(&env.host_triple)
.join("lib");
let stage1_tools_bin = build_dir.join("stage1-tools-bin");
let stage1_bin = build_dir.join("stage1/bin");
let rust_analyzer = stage1_bin.join("rust-analyzer");
let mut file = OpenOptions::new()
.write(true)
.truncate(true)
.create(true)
.mode(0o755)
.open(rust_analyzer)?;
writeln!(file, "#!/bin/sh")?;
writeln!(
file,
"LD_LIBRARY_PATH={} {}/rust-analyzer",
stage1_rustlib.display(),
stage1_tools_bin.display()
)?;
Ok(())
}
2024-03-12 18:17:47 +02:00
pub fn fetch(env: &BuildEnv, branch: &str) -> Result<(), Error> {
let path = env.workspace_root.join("toolchain");
2024-11-13 16:31:26 +02:00
git_clone(path, TOOLCHAIN_URL, branch)
2024-03-12 18:17:47 +02:00
}
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)?;
2024-08-10 20:41:32 +03:00
log::info!("Installing rust tool shims");
install_shims(env, &toolchain_path)?;
2024-03-12 18:17:47 +02:00
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(())
}