1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
use std::env; use std::path::{Path, PathBuf}; use std::fs::{create_dir_all, metadata, File}; use std::io::{BufWriter, Write}; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use project::{Crate, Project}; use error::*; pub struct ProxyCrate<'a> { project: &'a Project, path: PathBuf, } const DEFAULT_MANIFEST_PREFIX: &str = r#" [package] name = "proxy" version = "0.0.0" [lib] crate_type = ["dylib"] [dependencies] "#; const DEFAULT_LIB_PREFIX: &str = r#" #![feature(lang_items)] #![no_std] "#; const DEFAULT_LIB_SUFFIX: &str = r#" // Needed because we compile `dylib`... #[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} } "#; impl<'a> ProxyCrate<'a> { pub fn new(project: &'a Project) -> Result<Self> { let mut path = env::temp_dir().join("ptx-builder"); path.push(&project.get_rustc_name()); path.push(format!("{:x}", Self::get_project_hash(project))); create_dir_all(&path)?; create_dir_all(&path.join("src"))?; Ok(ProxyCrate { project, path }) } pub fn get_output_path(&self) -> PathBuf { self.path.join("target") } pub fn initialize(&mut self) -> Result<()> { if let Err(_) = metadata(self.path.join("Cargo.toml")) { let mut writer = BufWriter::new(File::create(self.path.join("Cargo.toml"))?); writer.write_all(DEFAULT_MANIFEST_PREFIX.as_bytes())?; writer.write_all( format!( r#"{} = {{ path = {:?} }} "#, self.project.get_name(), self.project.get_path() ).as_bytes(), )?; } if let Err(_) = metadata(self.path.join("src/lib.rs")) { let mut writer = BufWriter::new(File::create(self.path.join("src/lib.rs"))?); writer.write_all(DEFAULT_LIB_PREFIX.as_bytes())?; writer.write_all( format!("extern crate {name};", name = self.project.get_rustc_name()).as_bytes(), )?; writer.write_all(DEFAULT_LIB_SUFFIX.as_bytes())?; } Ok(()) } fn get_project_hash(project: &Project) -> u64 { let mut hasher = DefaultHasher::new(); project.hash(&mut hasher); hasher.finish() } } impl<'a> Crate for ProxyCrate<'a> { fn get_path(&self) -> &Path { &self.path.as_path() } fn get_name(&self) -> &str { "proxy" } fn get_rustc_name(&self) -> &str { "proxy" } }