Skip to content

Instantly share code, notes, and snippets.

@leostera
Created January 3, 2021 09:38
Show Gist options
  • Save leostera/3e42a685ee1a6c33d8f796e1038b0146 to your computer and use it in GitHub Desktop.
Save leostera/3e42a685ee1a6c33d8f796e1038b0146 to your computer and use it in GitHub Desktop.
use super::archive::Archive;
use super::IntoToolchainBuilder;
use super::ToolchainBuilder;
use anyhow::{anyhow, Context};
use log::debug;
use std::collections::HashMap;
use std::collections::HashSet;
use std::io::{BufRead, BufReader, Write};
use std::path::PathBuf;
use std::process::{Command, Stdio};
#[derive(Debug, Clone)]
pub struct Toolchain {
archive: Archive,
root: PathBuf,
erl: PathBuf,
erlc: PathBuf,
}
impl Default for Toolchain {
fn default() -> Toolchain {
let archive = Archive::default()
.with_url("https://github.com/erlang/otp/archive/OTP-23.1.tar.gz".to_string())
.with_sha1("2d6eaefe960f52cc79d7614c11256b73174e4161".to_string())
.with_prefix("otp-OTP-23.1".to_string());
let erl = PathBuf::from("erl");
let erlc = PathBuf::from("erlc");
let root = PathBuf::from(".");
Toolchain {
archive,
erl,
erlc,
root,
}
}
}
impl Toolchain {
pub fn root(&self) -> &PathBuf {
&self.root
}
pub fn archive(&self) -> &Archive {
&self.archive
}
pub fn with_archive(self, archive: Archive) -> Toolchain {
Toolchain { archive, ..self }
}
pub fn with_root(self, root: PathBuf) -> Toolchain {
let root = root
.join(self.name())
.join(self.archive().hash())
.join(self.archive().prefix());
let erl = root.join("bin").join("erl");
let erlc = root.join("bin").join("erlc");
Toolchain {
root,
erl,
erlc,
..self
}
}
pub fn name(&self) -> String {
"erlang".to_string()
}
}
impl IntoToolchainBuilder for Toolchain {
fn toolchain_builder(&self) -> ToolchainBuilder {
let root = self.root.clone();
let erlc = self.erlc.clone();
let is_cached = Box::new(move || Ok(std::fs::metadata(erlc.clone()).is_ok()));
let build_toolchain = Box::new(move || {
let root = root.clone();
debug!("Starting to build Erlang toolchain at: {:?}", root);
let otp_build = std::fs::canonicalize(root.join("otp_build"))
.context("Could not find otp_build!")?;
let otp_build = Command::new(otp_build)
.args(&["autoconf"])
.current_dir(&root)
.output()
.context("Could not spawn otp_build")?;
if otp_build.status.success() {
Ok(())
} else {
std::io::stdout().write_all(&otp_build.stdout).unwrap();
std::io::stderr().write_all(&otp_build.stderr).unwrap();
Err(anyhow!("Error running otp_build"))
}?;
let configure = std::fs::canonicalize(root.join("configure"))
.context("Could not find configure!")?;
let configure = Command::new(configure)
.current_dir(&root)
.output()
.context("Could not spawn configure")?;
if configure.status.success() {
Ok(())
} else {
std::io::stdout().write_all(&configure.stdout).unwrap();
std::io::stderr().write_all(&configure.stderr).unwrap();
Err(anyhow!("Error running configure"))
}?;
debug!("Erlang: running make -j32 in {:?}", &root);
let make = Command::new("make")
.stdout(Stdio::piped())
.args(&["-j32"])
.current_dir(&root)
.output()
.context("Could not spawn make")?;
debug!("Erlang: {:?}", &make.status.success());
if make.status.success() {
Ok(())
} else {
std::io::stdout().write_all(&make.stdout).unwrap();
std::io::stderr().write_all(&make.stderr).unwrap();
Err(anyhow!("Error running make"))
}
});
ToolchainBuilder {
name: self.name(),
archive: self.archive().clone(),
is_cached,
build_toolchain,
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment