nexus_sdk/compile/
cargo.rs1use crypto_common::generic_array::typenum::{ToInt, U32};
2use std::io;
3use std::io::Write;
4use std::marker::PhantomData;
5use std::path::PathBuf;
6use std::process::Command;
7use std::str::FromStr;
8use uuid::Uuid;
9
10pub use crate::error::BuildError;
11
12use super::{Compile, Compiler, Packager};
13
14pub enum CargoPackager {}
16impl Packager for CargoPackager {
17 type DigestSize = U32;
18
19 fn digest_len() -> usize {
20 let sz: u32 = Self::DigestSize::to_int();
21 sz as usize
22 }
23}
24
25impl Compile for Compiler<CargoPackager> {
26 fn new(package: &str) -> Self {
28 Self {
29 package: package.to_string(),
30 binary: package.to_string(),
31 debug: false,
32 native: false,
33 unique: false,
34 _packager: PhantomData,
35 }
36 }
37
38 fn new_with_custom_binary(package: &str, binary: &str) -> Self {
40 Self {
41 package: package.to_string(),
42 binary: binary.to_string(),
43 debug: false,
44 native: false,
45 unique: false,
46 _packager: PhantomData,
47 }
48 }
49
50 fn set_debug_build(&mut self, debug: bool) {
52 self.debug = debug;
53 }
54
55 fn set_native_build(&mut self, native: bool) {
57 self.native = native;
58 }
59
60 fn set_unique_build(&mut self, unique: bool) {
64 self.unique = unique;
65 }
66
67 fn build(&mut self) -> Result<PathBuf, BuildError> {
69 let linker_path = Compiler::set_linker()?;
70
71 let rust_flags = [
72 "-C",
73 "relocation-model=pic",
74 "-C",
75 &format!("link-arg=-T{}", linker_path.display()),
76 "-C",
77 "panic=abort",
78 ];
79
80 let target = if self.native {
81 "native"
82 } else {
83 "riscv32im-unknown-none-elf"
84 };
85
86 let profile = if self.debug { "debug" } else { "release" };
87
88 let envs = vec![("CARGO_ENCODED_RUSTFLAGS", rust_flags.join("\x1f"))];
89 let prog = self.binary.as_str();
90
91 let mut dest = match std::env::var_os("OUT_DIR") {
92 Some(path) => path.into_string().unwrap(),
93 None => "/tmp/nexus-target".into(),
94 };
95
96 if self.unique {
97 let uuid = Uuid::new_v4();
98 dest = format!("{}-{}", dest, uuid);
99 }
100
101 let cargo_bin = std::env::var("CARGO").unwrap_or_else(|_err| "cargo".into());
102 let mut cmd = Command::new(cargo_bin);
103
104 cmd.envs(envs).args([
106 "build",
107 "--package",
108 self.package.as_str(),
109 "--bin",
110 prog,
111 "--target-dir",
112 &dest,
113 ]);
114
115 if !self.native {
117 cmd.args(["--target", target]);
118 }
119
120 cmd.args(["--profile", profile]);
122
123 let res = cmd.output()?;
124
125 if !res.status.success() {
126 io::stderr().write_all(&res.stderr)?;
127 return Err(BuildError::CompilerError);
128 }
129
130 let elf_path = if self.native {
132 PathBuf::from_str(&format!("{}/{}/{}", dest, profile, prog)).unwrap()
133 } else {
134 PathBuf::from_str(&format!("{}/{}/{}/{}", dest, target, profile, prog)).unwrap()
135 };
136
137 Ok(elf_path)
138 }
139}