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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
use crate::store::CompilerOptions;
use anyhow::Context;
use clap::Parser;
use std::path::PathBuf;
use wasmer_compiler::Artifact;
use wasmer_types::compilation::symbols::ModuleMetadataSymbolRegistry;
use wasmer_types::{CpuFeature, MetadataHeader, Triple};
use webc::WebC;
#[derive(Debug, Parser)]
pub struct GenCHeader {
#[clap(name = "FILE", parse(from_os_str))]
path: PathBuf,
#[clap(long)]
prefix: Option<String>,
#[clap(long)]
atom: Option<String>,
#[clap(name = "OUTPUT PATH", short = 'o', parse(from_os_str))]
output: PathBuf,
#[clap(long = "target")]
target_triple: Option<Triple>,
#[clap(long, short = 'm', multiple = true, number_of_values = 1)]
cpu_features: Vec<CpuFeature>,
}
impl GenCHeader {
pub fn execute(&self) -> Result<(), anyhow::Error> {
let path = crate::common::normalize_path(&format!("{}", self.path.display()));
let mut file = std::fs::read(&path)
.map_err(|e| anyhow::anyhow!("{e}"))
.with_context(|| anyhow::anyhow!("{path}"))?;
let prefix = match self.prefix.as_deref() {
Some(s) => s.to_string(),
None => crate::commands::PrefixMapCompilation::hash_for_bytes(&file),
};
if let Ok(pirita) = WebC::parse(&file, &webc::ParseOptions::default()) {
let atoms = pirita
.manifest
.atoms
.iter()
.map(|a| a.0.clone())
.collect::<Vec<_>>();
if atoms.len() == 1 {
file = pirita
.get_atom(&pirita.get_package_name(), &atoms[0])
.unwrap()
.to_vec();
} else if self.atom.is_none() {
return Err(anyhow::anyhow!("-> note: available atoms are: {}", atoms.join(", ")))
.context(anyhow::anyhow!("file has multiple atoms, please specify which atom to generate the header file for"))?;
} else {
file = pirita
.get_atom(&pirita.get_package_name(), &atoms[0])
.map_err(|_| {
anyhow::anyhow!("-> note: available atoms are: {}", atoms.join(", "))
})
.context(anyhow::anyhow!(
"could not get atom {} from file (invalid atom name)",
&atoms[0]
))?
.to_vec();
}
}
let target_triple = self.target_triple.clone().unwrap_or_else(Triple::host);
let target = crate::commands::create_exe::utils::target_triple_to_target(
&target_triple,
&self.cpu_features,
);
let (store, _) = CompilerOptions::default().get_store_for_target(target.clone())?;
let engine = store.engine();
let engine_inner = engine.inner();
let compiler = engine_inner.compiler()?;
let features = engine_inner.features();
let tunables = store.tunables();
let (metadata, _, _) = Artifact::metadata(
compiler,
&file,
Some(prefix.as_str()),
&target,
tunables,
features,
)
.map_err(|e| anyhow::anyhow!("could not generate metadata: {e}"))?;
let serialized_data = metadata
.serialize()
.map_err(|e| anyhow::anyhow!("failed to serialize: {e}"))?;
let mut metadata_binary = vec![];
metadata_binary.extend(MetadataHeader::new(serialized_data.len()).into_bytes());
metadata_binary.extend(serialized_data);
let metadata_length = metadata_binary.len();
let header_file_src = crate::c_gen::staticlib_header::generate_header_file(
&prefix,
&metadata.compile_info.module,
&ModuleMetadataSymbolRegistry {
prefix: prefix.clone(),
},
metadata_length,
);
let output = crate::common::normalize_path(&self.output.display().to_string());
std::fs::write(&output, &header_file_src)
.map_err(|e| anyhow::anyhow!("{e}"))
.with_context(|| anyhow::anyhow!("{output}"))?;
Ok(())
}
}