summaryrefslogtreecommitdiff
path: root/cli/main.rs
diff options
context:
space:
mode:
authorLuca Casonato <lucacasonato@yahoo.com>2020-11-30 20:35:12 +0100
committerGitHub <noreply@github.com>2020-11-30 20:35:12 +0100
commit6aa692fece232b83bdfd4ec56150fb5264020697 (patch)
tree9e9c10e9cc6482ca468d68ded39e6ec40187082f /cli/main.rs
parentc7276e15e54b43aa6649ca149d92811059c6415f (diff)
feat: deno compile (#8539)
Diffstat (limited to 'cli/main.rs')
-rw-r--r--cli/main.rs196
1 files changed, 140 insertions, 56 deletions
diff --git a/cli/main.rs b/cli/main.rs
index 6c48a75f6..b4e1f1d2c 100644
--- a/cli/main.rs
+++ b/cli/main.rs
@@ -39,6 +39,7 @@ mod resolve_addr;
mod signal;
mod source_maps;
mod specifier_handler;
+mod standalone;
mod text_encoding;
mod tokio_util;
mod tools;
@@ -51,10 +52,16 @@ mod worker;
use crate::file_fetcher::File;
use crate::file_fetcher::FileFetcher;
use crate::file_watcher::ModuleResolutionResult;
+use crate::flags::DenoSubcommand;
+use crate::flags::Flags;
+use crate::import_map::ImportMap;
use crate::media_type::MediaType;
use crate::permissions::Permissions;
+use crate::program_state::exit_unstable;
use crate::program_state::ProgramState;
use crate::specifier_handler::FetchHandler;
+use crate::standalone::create_standalone_binary;
+use crate::tools::installer::infer_name_from_url;
use crate::worker::MainWorker;
use deno_core::error::generic_error;
use deno_core::error::AnyError;
@@ -66,12 +73,8 @@ use deno_core::v8_set_flags;
use deno_core::ModuleSpecifier;
use deno_doc as doc;
use deno_doc::parser::DocFileLoader;
-use flags::DenoSubcommand;
-use flags::Flags;
-use import_map::ImportMap;
use log::Level;
use log::LevelFilter;
-use program_state::exit_unstable;
use std::cell::RefCell;
use std::env;
use std::io::Read;
@@ -149,6 +152,56 @@ fn get_types(unstable: bool) -> String {
types
}
+async fn compile_command(
+ flags: Flags,
+ source_file: String,
+ out_file: Option<String>,
+) -> Result<(), AnyError> {
+ if !flags.unstable {
+ exit_unstable("compile");
+ }
+
+ let debug = flags.log_level == Some(log::Level::Debug);
+
+ let module_specifier = ModuleSpecifier::resolve_url_or_path(&source_file)?;
+ let program_state = ProgramState::new(flags.clone())?;
+
+ let out_file =
+ out_file.or_else(|| infer_name_from_url(module_specifier.as_url()));
+ let out_file = match out_file {
+ Some(out_file) => out_file,
+ None => return Err(generic_error(
+ "An executable name was not provided. One could not be inferred from the URL. Aborting.",
+ )),
+ };
+
+ let module_graph = create_module_graph_and_maybe_check(
+ module_specifier.clone(),
+ program_state.clone(),
+ debug,
+ )
+ .await?;
+
+ info!(
+ "{} {}",
+ colors::green("Bundle"),
+ module_specifier.to_string()
+ );
+ let bundle_str = bundle_module_graph(module_graph, flags, debug)?;
+
+ info!(
+ "{} {}",
+ colors::green("Compile"),
+ module_specifier.to_string()
+ );
+ create_standalone_binary(bundle_str.as_bytes().to_vec(), out_file.clone())
+ .await?;
+
+ info!("{} {}", colors::green("Emit"), out_file);
+
+ Ok(())
+}
+
async fn info_command(
flags: Flags,
maybe_specifier: Option<String>,
@@ -299,6 +352,73 @@ async fn eval_command(
Ok(())
}
+async fn create_module_graph_and_maybe_check(
+ module_specifier: ModuleSpecifier,
+ program_state: Arc<ProgramState>,
+ debug: bool,
+) -> Result<module_graph::Graph, AnyError> {
+ let handler = Rc::new(RefCell::new(FetchHandler::new(
+ &program_state,
+ // when bundling, dynamic imports are only access for their type safety,
+ // therefore we will allow the graph to access any module.
+ Permissions::allow_all(),
+ )?));
+ let mut builder = module_graph::GraphBuilder::new(
+ handler,
+ program_state.maybe_import_map.clone(),
+ program_state.lockfile.clone(),
+ );
+ builder.add(&module_specifier, false).await?;
+ let module_graph = builder.get_graph();
+
+ if !program_state.flags.no_check {
+ // TODO(@kitsonk) support bundling for workers
+ let lib = if program_state.flags.unstable {
+ module_graph::TypeLib::UnstableDenoWindow
+ } else {
+ module_graph::TypeLib::DenoWindow
+ };
+ let result_info =
+ module_graph.clone().check(module_graph::CheckOptions {
+ debug,
+ emit: false,
+ lib,
+ maybe_config_path: program_state.flags.config_path.clone(),
+ reload: program_state.flags.reload,
+ })?;
+
+ debug!("{}", result_info.stats);
+ if let Some(ignored_options) = result_info.maybe_ignored_options {
+ eprintln!("{}", ignored_options);
+ }
+ if !result_info.diagnostics.is_empty() {
+ return Err(generic_error(result_info.diagnostics.to_string()));
+ }
+ }
+
+ Ok(module_graph)
+}
+
+fn bundle_module_graph(
+ module_graph: module_graph::Graph,
+ flags: Flags,
+ debug: bool,
+) -> Result<String, AnyError> {
+ let (bundle, stats, maybe_ignored_options) =
+ module_graph.bundle(module_graph::BundleOptions {
+ debug,
+ maybe_config_path: flags.config_path,
+ })?;
+ match maybe_ignored_options {
+ Some(ignored_options) if flags.no_check => {
+ eprintln!("{}", ignored_options);
+ }
+ _ => {}
+ }
+ debug!("{}", stats);
+ Ok(bundle)
+}
+
async fn bundle_command(
flags: Flags,
source_file: String,
@@ -323,44 +443,12 @@ async fn bundle_command(
module_specifier.to_string()
);
- let handler = Rc::new(RefCell::new(FetchHandler::new(
- &program_state,
- // when bundling, dynamic imports are only access for their type safety,
- // therefore we will allow the graph to access any module.
- Permissions::allow_all(),
- )?));
- let mut builder = module_graph::GraphBuilder::new(
- handler,
- program_state.maybe_import_map.clone(),
- program_state.lockfile.clone(),
- );
- builder.add(&module_specifier, false).await?;
- let module_graph = builder.get_graph();
-
- if !flags.no_check {
- // TODO(@kitsonk) support bundling for workers
- let lib = if flags.unstable {
- module_graph::TypeLib::UnstableDenoWindow
- } else {
- module_graph::TypeLib::DenoWindow
- };
- let result_info =
- module_graph.clone().check(module_graph::CheckOptions {
- debug,
- emit: false,
- lib,
- maybe_config_path: flags.config_path.clone(),
- reload: flags.reload,
- })?;
-
- debug!("{}", result_info.stats);
- if let Some(ignored_options) = result_info.maybe_ignored_options {
- eprintln!("{}", ignored_options);
- }
- if !result_info.diagnostics.is_empty() {
- return Err(generic_error(result_info.diagnostics.to_string()));
- }
- }
+ let module_graph = create_module_graph_and_maybe_check(
+ module_specifier,
+ program_state.clone(),
+ debug,
+ )
+ .await?;
let mut paths_to_watch: Vec<PathBuf> = module_graph
.get_modules()
@@ -392,19 +480,7 @@ async fn bundle_command(
let flags = flags.clone();
let out_file = out_file.clone();
async move {
- let (output, stats, maybe_ignored_options) =
- module_graph.bundle(module_graph::BundleOptions {
- debug,
- maybe_config_path: flags.config_path,
- })?;
-
- match maybe_ignored_options {
- Some(ignored_options) if flags.no_check => {
- eprintln!("{}", ignored_options);
- }
- _ => {}
- }
- debug!("{}", stats);
+ let output = bundle_module_graph(module_graph, flags, debug)?;
debug!(">>>>> bundle END");
@@ -898,6 +974,10 @@ fn get_subcommand(
DenoSubcommand::Cache { files } => {
cache_command(flags, files).boxed_local()
}
+ DenoSubcommand::Compile {
+ source_file,
+ out_file,
+ } => compile_command(flags, source_file, out_file).boxed_local(),
DenoSubcommand::Fmt {
check,
files,
@@ -968,8 +1048,12 @@ pub fn main() {
colors::enable_ansi(); // For Windows 10
let args: Vec<String> = env::args().collect();
- let flags = flags::flags_from_vec(args);
+ if let Err(err) = standalone::try_run_standalone_binary(args.clone()) {
+ eprintln!("{}: {}", colors::red_bold("error"), err.to_string());
+ std::process::exit(1);
+ }
+ let flags = flags::flags_from_vec(args);
if let Some(ref v8_flags) = flags.v8_flags {
init_v8_flags(v8_flags);
}