summaryrefslogtreecommitdiff
path: root/cli/standalone/binary.rs
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2024-02-13 21:52:30 +0530
committerGitHub <noreply@github.com>2024-02-13 21:52:30 +0530
commita68eb3fcc3997fce8680f87edce46f6450e79635 (patch)
tree6839607033226fdfb2ce1be3187ef93791096507 /cli/standalone/binary.rs
parent492a9fbb9194a24a1f9223f797b4f4df9efde2bd (diff)
feat: denort binary for `deno compile` (#22205)
This introduces the `denort` binary - a slim version of deno without tooling. The binary is used as the default for `deno compile`. Improves `deno compile` final size by ~2.5x (141 MB -> 61 MB) on Linux x86_64.
Diffstat (limited to 'cli/standalone/binary.rs')
-rw-r--r--cli/standalone/binary.rs80
1 files changed, 76 insertions, 4 deletions
diff --git a/cli/standalone/binary.rs b/cli/standalone/binary.rs
index f8bb1e21c..f9d65fdaa 100644
--- a/cli/standalone/binary.rs
+++ b/cli/standalone/binary.rs
@@ -2,12 +2,14 @@
use std::collections::BTreeMap;
use std::env::current_exe;
+use std::fs;
use std::io::Read;
use std::io::Seek;
use std::io::SeekFrom;
use std::io::Write;
use std::path::Path;
use std::path::PathBuf;
+use std::process::Command;
use deno_ast::ModuleSpecifier;
use deno_core::anyhow::bail;
@@ -337,6 +339,71 @@ fn u64_from_bytes(arr: &[u8]) -> Result<u64, AnyError> {
Ok(u64::from_be_bytes(*fixed_arr))
}
+pub fn unpack_into_dir(
+ exe_name: &str,
+ archive_name: &str,
+ archive_data: Vec<u8>,
+ is_windows: bool,
+ temp_dir: &tempfile::TempDir,
+) -> Result<PathBuf, AnyError> {
+ let temp_dir_path = temp_dir.path();
+ let exe_ext = if is_windows { "exe" } else { "" };
+ let archive_path = temp_dir_path.join(exe_name).with_extension("zip");
+ let exe_path = temp_dir_path.join(exe_name).with_extension(exe_ext);
+ assert!(!exe_path.exists());
+
+ let archive_ext = Path::new(archive_name)
+ .extension()
+ .and_then(|ext| ext.to_str())
+ .unwrap();
+ let unpack_status = match archive_ext {
+ "zip" if cfg!(windows) => {
+ fs::write(&archive_path, &archive_data)?;
+ Command::new("tar.exe")
+ .arg("xf")
+ .arg(&archive_path)
+ .arg("-C")
+ .arg(temp_dir_path)
+ .spawn()
+ .map_err(|err| {
+ if err.kind() == std::io::ErrorKind::NotFound {
+ std::io::Error::new(
+ std::io::ErrorKind::NotFound,
+ "`tar.exe` was not found in your PATH",
+ )
+ } else {
+ err
+ }
+ })?
+ .wait()?
+ }
+ "zip" => {
+ fs::write(&archive_path, &archive_data)?;
+ Command::new("unzip")
+ .current_dir(temp_dir_path)
+ .arg(&archive_path)
+ .spawn()
+ .map_err(|err| {
+ if err.kind() == std::io::ErrorKind::NotFound {
+ std::io::Error::new(
+ std::io::ErrorKind::NotFound,
+ "`unzip` was not found in your PATH, please install `unzip`",
+ )
+ } else {
+ err
+ }
+ })?
+ .wait()?
+ }
+ ext => bail!("Unsupported archive type: '{ext}'"),
+ };
+ if !unpack_status.success() {
+ bail!("Failed to unpack archive.");
+ }
+ assert!(exe_path.exists());
+ fs::remove_file(&archive_path)?;
+ Ok(exe_path)
+}
pub struct DenoCompileBinaryWriter<'a> {
file_fetcher: &'a FileFetcher,
client: &'a HttpClient,
@@ -404,13 +471,16 @@ impl<'a> DenoCompileBinaryWriter<'a> {
&self,
compile_flags: &CompileFlags,
) -> Result<Vec<u8>, AnyError> {
- if compile_flags.target.is_none() {
- let path = std::env::current_exe()?;
+ // Used for testing.
+ //
+ // Phase 2 of the 'min sized' deno compile RFC talks
+ // about adding this as a flag.
+ if let Some(path) = std::env::var_os("DENORT_BIN") {
return Ok(std::fs::read(path)?);
}
let target = compile_flags.resolve_target();
- let binary_name = format!("deno-{target}.zip");
+ let binary_name = format!("denort-{target}.zip");
let binary_path_suffix = if crate::version::is_canary() {
format!("canary/{}/{}", crate::version::GIT_COMMIT_HASH, binary_name)
@@ -429,7 +499,9 @@ impl<'a> DenoCompileBinaryWriter<'a> {
let archive_data = std::fs::read(binary_path)?;
let temp_dir = tempfile::TempDir::new()?;
- let base_binary_path = crate::tools::upgrade::unpack_into_dir(
+ let base_binary_path = unpack_into_dir(
+ "denort",
+ &binary_name,
archive_data,
target.contains("windows"),
&temp_dir,