1#![deny(
4 missing_debug_implementations,
5 trivial_numeric_casts,
6 unstable_features,
7 unused_import_braces,
8 unused_qualifications
9)]
10
11#[macro_use]
12extern crate structopt;
13extern crate clap;
14extern crate digest;
15extern crate futures;
16extern crate http;
17extern crate hyper;
18extern crate libflate;
19extern crate notify;
20extern crate pbr;
21extern crate reqwest;
22extern crate serde;
23extern crate sha1;
24extern crate sha2;
25extern crate tar;
26extern crate tempfile;
27extern crate toml;
28#[macro_use]
29extern crate serde_derive;
30#[macro_use]
31extern crate serde_json;
32extern crate base_x;
33extern crate handlebars;
34extern crate indexmap;
35extern crate regex;
36extern crate unicode_categories;
37extern crate walkdir;
38extern crate websocket;
39#[macro_use]
40extern crate lazy_static;
41extern crate directories;
42extern crate percent_encoding;
43
44extern crate parity_wasm;
45#[macro_use]
46extern crate log;
47extern crate env_logger;
48extern crate rustc_demangle;
49
50extern crate ansi_term;
51extern crate cargo_metadata;
52
53extern crate memmap;
54extern crate semver;
55
56extern crate atty;
57extern crate open;
58#[macro_use]
59extern crate failure;
60extern crate mime_guess;
61
62mod cargo_shim;
63
64#[macro_use]
65mod utils;
66mod build;
67mod chrome_devtools;
68mod cmd_build;
69mod cmd_deploy;
70mod cmd_prepare_emscripten;
71mod cmd_start;
72mod cmd_test;
73mod config;
74mod deployment;
75mod emscripten;
76mod error;
77mod http_utils;
78mod package;
79mod project_dirs;
80mod test_chromium;
81mod wasm;
82mod wasm_context;
83mod wasm_export_main;
84mod wasm_export_table;
85mod wasm_gc;
86mod wasm_hook_grow;
87mod wasm_inline_js;
88mod wasm_intrinsics;
89mod wasm_js_export;
90mod wasm_js_snippet;
91mod wasm_runtime;
92
93use std::ffi::OsStr;
94use std::net::{IpAddr, ToSocketAddrs};
95use std::path::PathBuf;
96
97use build::{Backend, BuildArgs};
98use cargo_shim::MessageFormat;
99use error::Error;
100use wasm_runtime::RuntimeKind;
101
102#[derive(Debug, StructOpt)]
104#[structopt(name = "cargo-web")]
105#[structopt(about = "A `cargo` subcommand for the client-side web.")]
106#[structopt(raw(global_setting = "structopt::clap::AppSettings::ColoredHelp"))]
107#[structopt(raw(setting = "structopt::clap::AppSettings::VersionlessSubcommands"))]
108#[structopt(rename_all = "kebab-case")]
109pub enum CargoWebOpts {
110 Build(BuildOpts),
112 Check(CheckOpts),
114 Deploy(DeployOpts),
116 PrepareEmscripten(PrepareEmscriptenOpts),
118 Start(StartOpts),
120 Test(TestOpts),
122 #[doc(hidden)]
123 #[structopt(raw(setting = "structopt::clap::AppSettings::Hidden"))]
124 __Nonexhaustive,
125}
126
127pub fn run(cfg: CargoWebOpts) -> Result<(), Error> {
129 match cfg {
130 CargoWebOpts::Build(BuildOpts {
131 build_args,
132 build_target,
133 ext,
134 }) => cmd_build::command_build(BuildArgs::new(build_args, ext, build_target)?),
135 CargoWebOpts::Check(CheckOpts {
136 build_args,
137 build_target,
138 ext,
139 }) => cmd_build::command_check(BuildArgs::new(build_args, ext, build_target)?),
140 CargoWebOpts::Deploy(DeployOpts { build_args, output }) => {
141 cmd_deploy::command_deploy(build_args.into(), output)
142 }
143 CargoWebOpts::PrepareEmscripten(_) => cmd_prepare_emscripten::command_prepare_emscripten(),
144 CargoWebOpts::Start(StartOpts {
145 build_args,
146 build_target,
147 auto_reload,
148 open,
149 port,
150 host,
151 }) => cmd_start::command_start(
152 BuildArgs::from(build_args).with_target(build_target),
153 host,
154 port,
155 open,
156 auto_reload,
157 ),
158 CargoWebOpts::Test(TestOpts {
159 build_args,
160 nodejs,
161 no_run,
162 passthrough,
163 }) => {
164 let pass_os = passthrough.iter().map(OsStr::new).collect::<Vec<_>>();
165 cmd_test::command_test(build_args.into(), nodejs, no_run, &pass_os)
166 }
167 CargoWebOpts::__Nonexhaustive => unreachable!(),
168 }
169}
170
171#[derive(Debug, StructOpt)]
173#[structopt(rename_all = "kebab-case")]
174pub struct BuildOpts {
175 #[structopt(flatten)]
176 build_args: Build,
177 #[structopt(flatten)]
178 ext: BuildExt,
179 #[structopt(flatten)]
180 build_target: Target,
181}
182
183#[derive(Debug, StructOpt)]
185#[structopt(rename_all = "kebab-case")]
186pub struct CheckOpts {
187 #[structopt(flatten)]
188 build_args: Build,
189 #[structopt(flatten)]
190 ext: BuildExt,
191 #[structopt(flatten)]
192 build_target: Target,
193}
194
195#[derive(Debug, StructOpt)]
197#[structopt(rename_all = "kebab-case")]
198pub struct DeployOpts {
199 #[structopt(short = "o", long, parse(from_os_str))]
201 output: Option<PathBuf>,
202 #[structopt(flatten)]
203 build_args: Build,
204}
205
206#[derive(Debug, StructOpt)]
208#[structopt(rename_all = "kebab-case")]
209pub struct PrepareEmscriptenOpts {
210 #[doc(hidden)]
211 #[structopt(raw(set = "structopt::clap::ArgSettings::Hidden"))]
212 __reserved: bool,
213}
214
215#[derive(Debug, StructOpt)]
217#[structopt(rename_all = "kebab-case")]
218pub struct StartOpts {
219 #[structopt(
221 long,
222 parse(try_from_str = "resolve_host"),
223 default_value = "localhost"
224 )]
225 host: IpAddr,
226 #[structopt(long, default_value = "8000")]
228 port: u16,
229 #[structopt(long)]
231 open: bool,
232 #[structopt(long)]
234 auto_reload: bool,
235 #[structopt(flatten)]
236 build_target: Target,
237 #[structopt(flatten)]
238 build_args: Build,
239}
240
241#[derive(Debug, StructOpt)]
243#[structopt(rename_all = "kebab-case")]
244pub struct TestOpts {
245 #[structopt(long)]
247 no_run: bool,
248 #[structopt(long)]
250 nodejs: bool,
251 #[structopt(flatten)]
252 build_args: Build,
253 passthrough: Vec<String>,
255}
256
257#[derive(Debug, StructOpt)]
259#[structopt(rename_all = "kebab-case")]
260struct Target {
261 #[structopt(long, group = "target_type")]
263 lib: bool,
264 #[structopt(long, group = "target_type")]
266 bin: Option<String>,
267 #[structopt(long, group = "target_type")]
269 example: Option<String>,
270 #[structopt(long, group = "target_type")]
272 test: Option<String>,
273 #[structopt(long, group = "target_type")]
275 bench: Option<String>,
276}
277
278impl Default for Target {
279 fn default() -> Self {
280 Self {
281 lib: false,
282 bin: None,
283 example: None,
284 test: None,
285 bench: None,
286 }
287 }
288}
289
290#[derive(Debug, StructOpt)]
292#[structopt(rename_all = "kebab-case")]
293struct BuildExt {
294 #[structopt(
296 long,
297 default_value = "human",
298 parse(try_from_str),
299 raw(possible_values = "&[\"human\", \"json\"]"),
300 raw(set = "structopt::clap::ArgSettings::NextLineHelp")
301 )]
302 message_format: MessageFormat,
303 #[structopt(
307 long,
308 parse(try_from_str),
309 raw(set = "structopt::clap::ArgSettings::NextLineHelp")
310 )]
311 runtime: Option<RuntimeKind>,
312}
313
314impl Default for BuildExt {
315 fn default() -> Self {
316 Self {
317 message_format: MessageFormat::Json,
318 runtime: None,
319 }
320 }
321}
322
323#[derive(Debug, StructOpt)]
325#[structopt(rename_all = "kebab-case")]
326struct Build {
327 #[structopt(short = "p", long)]
329 pub package: Option<String>,
330 #[structopt(long, group = "build_features")]
332 pub features: Option<String>,
333 #[structopt(long, group = "build_features")]
335 pub all_features: bool,
336 #[structopt(long)]
338 pub no_default_features: bool,
339 #[structopt(long)]
341 pub use_system_emscripten: bool,
342 #[structopt(long)]
344 pub release: bool,
345 #[structopt(
348 long,
349 parse(try_from_str),
350 raw(
351 possible_values = "&[\"wasm32-unknown-unknown\", \"wasm32-unknown-emscripten\", \"asmjs-unknown-emscripten\"]"
352 ),
353 raw(set = "structopt::clap::ArgSettings::NextLineHelp")
354 )]
355 pub target: Option<Backend>,
356 #[structopt(short = "v", long)]
358 pub verbose: bool,
359}
360
361impl Default for Build {
362 fn default() -> Self {
368 Self {
369 package: None,
370 features: None,
371 all_features: false,
372 no_default_features: false,
373 use_system_emscripten: false,
374 release: false,
375 target: None,
376 verbose: false,
377 }
378 }
379}
380
381fn resolve_host(host: &str) -> std::io::Result<IpAddr> {
383 (host, 0)
384 .to_socket_addrs()
385 .map(|itr| itr.map(|a| a.ip()).collect::<Vec<_>>()[0])
386}