blob: b99eba3c0131fa56d7493b27cc64b1b9c8bdeed9 [file] [log] [blame] [edit]
use crate::code::version_manager::{
get_enzyme_compilation_checkfile_path, get_rust_compilation_checkfile_path,
};
use super::utils;
use super::utils::{run_and_printerror, Cli};
use super::version_manager;
use std::{path::PathBuf, process::Command};
#[allow(unused)]
fn print_llvm_version() {
let mut cmake = Command::new("cmake");
cmake.args(&["-version"]);
run_and_printerror(&mut cmake);
}
/// A support function to build Enzyme and Rust such that they can be used together.
///
/// The Rust repository must be build first.
/// It will build a nightly version of Rust, together with LLVM and Clang.
/// Building the Enzyme repository will always run tests to verify that it is working correctly.
pub fn build(args: Cli) -> Result<(), String> {
let rust_repo = utils::get_local_rust_repo_path(args.rust.clone()); // Default
if !version_manager::is_compiled_rust(&args) {
build_rustc(rust_repo.clone());
version_manager::set_compiled_rust(&args)?;
} else {
println!(
"Skipped compiling rust since the checkfile {} exists",
get_rust_compilation_checkfile_path(&args).to_string_lossy()
);
}
if !version_manager::is_compiled_enzyme(&args) {
let enzyme_repo = utils::get_local_enzyme_repo_path(args.enzyme.clone());
build_enzyme(enzyme_repo, rust_repo);
version_manager::set_compiled_enzyme(&args)?;
} else {
println!(
"Skipped compiling enzyme since the checkfile {} exists",
get_enzyme_compilation_checkfile_path(&args).to_string_lossy()
);
}
Ok(())
}
fn build_enzyme(enzyme_repo: PathBuf, rust_repo: PathBuf) {
let build_path = utils::get_enzyme_build_path(enzyme_repo);
let llvm_dir = utils::get_llvm_build_path(rust_repo.clone())
.join("lib")
.join("cmake")
.join("llvm");
let llvm_dir = "-DLLVM_DIR=".to_owned() + llvm_dir.to_str().unwrap();
let llvm_external_lit = rust_repo
.join("src")
.join("llvm-project")
.join("llvm")
.join("utils")
.join("lit")
.join("lit.py");
let llvm_external_lit = "-DLLVM_EXTERNAL_LIT=".to_owned() + llvm_external_lit.to_str().unwrap();
let llvm_external_lib = "-DENZYME_EXTERNAL_SHARED_LIB=ON".to_owned();
let build_type = "-DCMAKE_BUILD_TYPE=Release";
let mut cmake = Command::new("cmake");
let mut ninja = Command::new("ninja");
let mut ninja_check = Command::new("ninja");
if !std::path::Path::new(&build_path).exists() {
std::fs::create_dir(&build_path).unwrap();
}
cmake
.args(&[
"-G",
"Ninja",
"..",
build_type,
&llvm_external_lib,
&llvm_dir,
&llvm_external_lit,
])
.current_dir(&build_path.to_str().unwrap());
ninja.current_dir(&build_path.to_str().unwrap());
ninja_check
.args(&["check-enzyme"])
.current_dir(&build_path.to_str().unwrap());
run_and_printerror(&mut cmake);
run_and_printerror(&mut ninja);
run_and_printerror(&mut ninja_check);
}
fn build_rustc(repo_path: PathBuf) {
let mut cargo = Command::new("cargo");
let mut configure = Command::new("./configure");
let mut x = Command::new("x");
let mut rustup = Command::new("rustup");
let build_path = utils::get_rustc_build_path(repo_path.clone());
if !std::path::Path::new(&build_path).exists() {
std::fs::create_dir(&build_path).unwrap();
}
let x_path = std::path::Path::new("src").join("tools").join("x");
let toolchain_path = utils::get_rustc_stage2_path(repo_path.clone());
cargo
.args(&["install", "--path", x_path.to_str().unwrap()])
.current_dir(&repo_path.to_str().unwrap());
configure
.args(&[
"--enable-llvm-link-shared",
"--enable-llvm-plugins",
"--release-channel=nightly", // TODO: Do we still need this? how about nightly?
"--enable-llvm-assertions",
"--enable-clang",
"--enable-lld",
"--enable-option-checking",
"--enable-ninja",
])
.current_dir(&repo_path.to_str().unwrap());
x.args(&["build", "--stage", "2"])
.current_dir(&build_path.to_str().unwrap());
rustup
.args(&[
"toolchain",
"link",
"enzyme",
toolchain_path.to_str().unwrap(),
])
.current_dir(&build_path.to_str().unwrap());
run_and_printerror(&mut cargo);
run_and_printerror(&mut configure);
run_and_printerror(&mut x);
run_and_printerror(&mut rustup);
}