wasmer_cli/commands/
create_obj.rs1#![allow(dead_code)]
2use std::{env, path::PathBuf};
5
6use anyhow::{Context, Result};
7use clap::Parser;
8use wasmer::sys::*;
9use wasmer_package::utils::from_disk;
10
11use crate::backend::RuntimeOptions;
12
13#[derive(Debug, Parser)]
14pub struct CreateObj {
16 #[clap(name = "FILE")]
18 path: PathBuf,
19
20 #[clap(name = "OUTPUT_PATH", short = 'o')]
22 output: PathBuf,
23
24 #[clap(long, name = "DEBUG PATH")]
27 debug_dir: Option<PathBuf>,
28
29 #[clap(long, name = "PREFIX")]
33 prefix: Option<String>,
34
35 #[clap(long, name = "ATOM")]
37 atom: Option<String>,
38
39 #[clap(long = "target")]
52 target_triple: Option<Triple>,
53
54 #[clap(long, short = 'm', number_of_values = 1)]
55 cpu_features: Vec<CpuFeature>,
56
57 #[clap(flatten)]
58 rt: RuntimeOptions,
59}
60
61impl CreateObj {
62 pub fn execute(&self) -> Result<()> {
64 let path = crate::common::normalize_path(&format!("{}", self.path.display()));
65 let target_triple = self.target_triple.clone().unwrap_or_else(Triple::host);
66 let starting_cd = env::current_dir()?;
67 let input_path = starting_cd.join(path);
68 let temp_dir = tempfile::tempdir();
69 let output_directory_path = match self.debug_dir.as_ref() {
70 Some(s) => s.clone(),
71 None => temp_dir?.path().to_path_buf(),
72 };
73 std::fs::create_dir_all(&output_directory_path)?;
74 let prefix = match self.prefix.as_ref() {
75 Some(s) => vec![s.clone()],
76 None => Vec::new(),
77 };
78
79 let target = crate::commands::create_exe::utils::target_triple_to_target(
80 &target_triple,
81 &self.cpu_features,
82 );
83 println!("Target: {}", target.triple());
96
97 let atoms = if let Ok(webc) = from_disk(&input_path) {
98 crate::commands::create_exe::compile_pirita_into_directory(
99 &webc,
100 &output_directory_path,
101 &self.rt,
102 &self.cpu_features,
103 &target_triple,
104 &prefix,
105 crate::commands::AllowMultiWasm::Reject(self.atom.clone()),
106 self.debug_dir.is_some(),
107 )
108 } else {
109 crate::commands::create_exe::prepare_directory_from_single_wasm_file(
110 &input_path,
111 &output_directory_path,
112 &self.rt,
113 &target_triple,
114 &self.cpu_features,
115 &prefix,
116 self.debug_dir.is_some(),
117 )
118 }?;
119
120 let file_paths = std::fs::read_dir(output_directory_path.join("atoms"))
123 .map_err(|e| {
124 anyhow::anyhow!(
125 "could not read {}: {e}",
126 output_directory_path.join("atoms").display()
127 )
128 })?
129 .filter_map(|path| path.ok()?.path().canonicalize().ok())
130 .collect::<Vec<_>>();
131
132 if file_paths.is_empty() {
133 return Err(anyhow::anyhow!(
134 "could not compile object file: no output objects in {}",
135 output_directory_path.join("atoms").display()
136 ));
137 }
138
139 if file_paths.len() == 1 {
140 if let Some(parent) = self.output.parent() {
141 std::fs::create_dir_all(parent)?;
142 }
143 std::fs::copy(
144 std::env::current_dir().unwrap().join(&file_paths[0]),
145 std::env::current_dir().unwrap().join(&self.output),
146 )
147 .map_err(|e| {
148 anyhow::anyhow!(
149 "{} -> {}: {e}",
150 &file_paths[0].display(),
151 self.output.display()
152 )
153 })?;
154 } else {
155 let keys = atoms
156 .iter()
157 .map(|(name, _)| name.clone())
158 .collect::<Vec<_>>();
159 return Err(anyhow::anyhow!(
160 "where <ATOM> is one of: {}",
161 keys.join(", ")
162 ))
163 .context(anyhow::anyhow!(
164 "note: use --atom <ATOM> to specify which atom to compile"
165 ))
166 .context(anyhow::anyhow!(
167 "cannot compile more than one atom at a time"
168 ));
169 }
170
171 let output_file = self.output.canonicalize().unwrap().display().to_string();
172 let output_file = output_file
173 .strip_prefix(r"\\?\")
174 .unwrap_or(&output_file)
175 .to_string();
176
177 eprintln!("✔ Object compiled successfully to `{output_file}`");
178
179 Ok(())
180 }
181}