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
107
108
109
110
111
112
113
114
mod config;
use std::path::*;
use std::io::*;
use std::{fs, env, process};
use glob::glob;
pub fn compile(kernel: &str) -> String {
let work = work_dir();
create_dir(&work);
install_builder(&work);
install_file(&work.join("src"), kernel, "lib.rs");
compile_builder(&work);
load_str(&get_ptx_path(&work))
}
const PTX_BUILDER_XARGO: &'static str = include_str!("Xargo.toml");
const PTX_BUILDER_TARGET: &'static str = include_str!("nvptx64-nvidia-cuda.json");
const NIGHTLY: &'static str = "nightly-2017-11-18";
fn install_file(work_dir: &Path, contents: &str, filename: &str) {
let mut f = fs::File::create(work_dir.join(filename)).unwrap();
f.write(contents.as_bytes()).unwrap();
}
fn install_builder(work: &Path) {
install_rustup_nightly();
let mut dep = config::default_dependencies();
if let Ok(home) = env::var("ACCEL_HOME") {
let core_path = Path::new(&home)
.join("accel-core")
.to_str()
.unwrap()
.to_string();
dep.get_mut("accel-core").unwrap().path = Some(core_path);
}
install_file(work, &config::into_config(dep).to_string(), "Cargo.toml");
install_file(work, PTX_BUILDER_XARGO, "Xargo.toml");
install_file(work, PTX_BUILDER_TARGET, "nvptx64-nvidia-cuda.json");
}
fn install_rustup_nightly() {
process::Command::new("rustup")
.args(&["toolchain", "install", NIGHTLY])
.stdout(process::Stdio::null())
.status()
.unwrap();
process::Command::new("rustup")
.args(&["component", "add", "rust-src"])
.stdout(process::Stdio::null())
.env("RUSTUP_TOOLCHAIN", NIGHTLY)
.status()
.unwrap();
}
fn compile_builder(work_dir: &Path) {
process::Command::new("rm")
.args(&["-rf", "target"])
.current_dir(work_dir)
.status()
.unwrap();
process::Command::new("xargo")
.args(
&[
"rustc",
"--release",
"--target",
"nvptx64-nvidia-cuda",
"--",
"--emit=asm",
],
)
.current_dir(work_dir)
.env("RUSTUP_TOOLCHAIN", NIGHTLY)
.status()
.unwrap();
}
fn get_ptx_path(work_dir: &Path) -> PathBuf {
let pattern = work_dir.join("target/**/*.s");
for entry in glob(pattern.to_str().unwrap()).unwrap() {
match entry {
Ok(path) => return path,
Err(_) => unreachable!(""),
}
}
unreachable!("");
}
fn load_str(path: &Path) -> String {
let f = fs::File::open(path).unwrap();
let mut buf = BufReader::new(f);
let mut v = String::new();
buf.read_to_string(&mut v).unwrap();
v
}
fn work_dir() -> PathBuf {
let home = env::home_dir().unwrap();
let work = home.join(".rust2ptx");
work.into()
}
fn create_dir(work: &Path) {
if !work.exists() {
fs::create_dir_all(&work).unwrap();
fs::create_dir_all(work.join("src")).unwrap();
}
}