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