4 use std::path::{Path, PathBuf};
5 use std::process::Command;
7 use super::rustc_info::{get_file_name, get_rustc_path, get_rustc_version};
8 use super::utils::{cargo_command, copy_dir_recursively, spawn_and_wait};
10 pub(crate) const ABI_CAFE: GitRepo =
11 GitRepo::github("Gankra", "abi-cafe", "4c6dc8c9c687e2b3a760ff2176ce236872b37212", "abi-cafe");
13 pub(crate) const RAND: GitRepo =
14 GitRepo::github("rust-random", "rand", "0f933f9c7176e53b2a3c7952ded484e1783f0bf1", "rand");
16 pub(crate) const REGEX: GitRepo =
17 GitRepo::github("rust-lang", "regex", "341f207c1071f7290e3f228c710817c280c8dca1", "regex");
19 pub(crate) const PORTABLE_SIMD: GitRepo = GitRepo::github(
22 "d5cd4a8112d958bd3a252327e0d069a6363249bd",
26 pub(crate) const SIMPLE_RAYTRACER: GitRepo = GitRepo::github(
29 "804a7a21b9e673a482797aa289a18ed480e4d813",
33 pub(crate) fn prepare() {
34 if Path::new("download").exists() {
35 std::fs::remove_dir_all(Path::new("download")).unwrap();
37 std::fs::create_dir_all(Path::new("download")).unwrap();
41 // FIXME maybe install this only locally?
42 eprintln!("[INSTALL] hyperfine");
43 Command::new("cargo").arg("install").arg("hyperfine").spawn().unwrap().wait().unwrap();
48 PORTABLE_SIMD.fetch();
49 SIMPLE_RAYTRACER.fetch();
51 eprintln!("[LLVM BUILD] simple-raytracer");
52 let build_cmd = cargo_command("cargo", "build", None, &SIMPLE_RAYTRACER.source_dir());
53 spawn_and_wait(build_cmd);
59 .join(get_file_name("main", "bin")),
60 SIMPLE_RAYTRACER.source_dir().join(get_file_name("raytracer_cg_llvm", "bin")),
65 fn prepare_sysroot() {
66 let rustc_path = get_rustc_path();
67 let sysroot_src_orig = rustc_path.parent().unwrap().join("../lib/rustlib/src/rust");
68 let sysroot_src = env::current_dir().unwrap().join("build_sysroot").join("sysroot_src");
70 assert!(sysroot_src_orig.exists());
72 if sysroot_src.exists() {
73 fs::remove_dir_all(&sysroot_src).unwrap();
75 fs::create_dir_all(sysroot_src.join("library")).unwrap();
76 eprintln!("[COPY] sysroot src");
77 copy_dir_recursively(&sysroot_src_orig.join("library"), &sysroot_src.join("library"));
79 let rustc_version = get_rustc_version();
80 fs::write(Path::new("build_sysroot").join("rustc_version"), &rustc_version).unwrap();
82 eprintln!("[GIT] init");
83 let mut git_init_cmd = Command::new("git");
84 git_init_cmd.arg("init").arg("-q").current_dir(&sysroot_src);
85 spawn_and_wait(git_init_cmd);
87 init_git_repo(&sysroot_src);
89 apply_patches("sysroot", &sysroot_src);
92 pub(crate) struct GitRepo {
95 patch_name: &'static str,
99 Github { user: &'static str, repo: &'static str },
107 patch_name: &'static str,
109 GitRepo { url: GitRepoUrl::Github { user, repo }, rev, patch_name }
112 pub(crate) fn source_dir(&self) -> PathBuf {
114 GitRepoUrl::Github { user: _, repo } => {
115 std::env::current_dir().unwrap().join("download").join(repo)
122 GitRepoUrl::Github { user, repo } => {
123 clone_repo_shallow_github(&self.source_dir(), user, repo, self.rev);
126 apply_patches(self.patch_name, &self.source_dir());
131 fn clone_repo(download_dir: &Path, repo: &str, rev: &str) {
132 eprintln!("[CLONE] {}", repo);
133 // Ignore exit code as the repo may already have been checked out
134 Command::new("git").arg("clone").arg(repo).arg(&download_dir).spawn().unwrap().wait().unwrap();
136 let mut clean_cmd = Command::new("git");
137 clean_cmd.arg("checkout").arg("--").arg(".").current_dir(&download_dir);
138 spawn_and_wait(clean_cmd);
140 let mut checkout_cmd = Command::new("git");
141 checkout_cmd.arg("checkout").arg("-q").arg(rev).current_dir(download_dir);
142 spawn_and_wait(checkout_cmd);
145 fn clone_repo_shallow_github(download_dir: &Path, user: &str, repo: &str, rev: &str) {
147 // Older windows doesn't have tar or curl by default. Fall back to using git.
148 clone_repo(download_dir, &format!("https://github.com/{}/{}.git", user, repo), rev);
152 let downloads_dir = std::env::current_dir().unwrap().join("download");
154 let archive_url = format!("https://github.com/{}/{}/archive/{}.tar.gz", user, repo, rev);
155 let archive_file = downloads_dir.join(format!("{}.tar.gz", rev));
156 let archive_dir = downloads_dir.join(format!("{}-{}", repo, rev));
158 eprintln!("[DOWNLOAD] {}/{} from {}", user, repo, archive_url);
160 // Remove previous results if they exists
161 let _ = std::fs::remove_file(&archive_file);
162 let _ = std::fs::remove_dir_all(&archive_dir);
163 let _ = std::fs::remove_dir_all(&download_dir);
165 // Download zip archive
166 let mut download_cmd = Command::new("curl");
167 download_cmd.arg("--location").arg("--output").arg(&archive_file).arg(archive_url);
168 spawn_and_wait(download_cmd);
170 // Unpack tar archive
171 let mut unpack_cmd = Command::new("tar");
172 unpack_cmd.arg("xf").arg(&archive_file).current_dir(downloads_dir);
173 spawn_and_wait(unpack_cmd);
175 // Rename unpacked dir to the expected name
176 std::fs::rename(archive_dir, &download_dir).unwrap();
178 init_git_repo(&download_dir);
181 std::fs::remove_file(archive_file).unwrap();
184 fn init_git_repo(repo_dir: &Path) {
185 let mut git_init_cmd = Command::new("git");
186 git_init_cmd.arg("init").arg("-q").current_dir(repo_dir);
187 spawn_and_wait(git_init_cmd);
189 let mut git_add_cmd = Command::new("git");
190 git_add_cmd.arg("add").arg(".").current_dir(repo_dir);
191 spawn_and_wait(git_add_cmd);
193 let mut git_commit_cmd = Command::new("git");
194 git_commit_cmd.arg("commit").arg("-m").arg("Initial commit").arg("-q").current_dir(repo_dir);
195 spawn_and_wait(git_commit_cmd);
198 fn get_patches(source_dir: &Path, crate_name: &str) -> Vec<PathBuf> {
199 let mut patches: Vec<_> = fs::read_dir(source_dir.join("patches"))
201 .map(|entry| entry.unwrap().path())
202 .filter(|path| path.extension() == Some(OsStr::new("patch")))
211 .starts_with(crate_name)
218 fn apply_patches(crate_name: &str, target_dir: &Path) {
219 if crate_name == "<none>" {
223 for patch in get_patches(&std::env::current_dir().unwrap(), crate_name) {
225 "[PATCH] {:?} <- {:?}",
226 target_dir.file_name().unwrap(),
227 patch.file_name().unwrap()
229 let mut apply_patch_cmd = Command::new("git");
230 apply_patch_cmd.arg("am").arg(patch).arg("-q").current_dir(target_dir);
231 spawn_and_wait(apply_patch_cmd);