From 88b4093646f60e680dc3fa3be9877c2ad77257a0 Mon Sep 17 00:00:00 2001
From: Mark McCaskey <mark@wasmer.io>
Date: Tue, 12 Jan 2021 13:07:07 -0800
Subject: [PATCH 01/12] Add packaging of headless wasmer to CI

---
 .github/workflows/main.yaml | 22 ++++++++++++++++++++++
 Makefile                    | 18 ++++++++++++++++--
 Xargo.toml                  |  2 ++
 lib/cli/Cargo.toml          |  2 ++
 lib/cli/src/bin/wasmer.rs   | 19 +++++++++++++++++--
 lib/cli/src/commands.rs     |  5 ++++-
 6 files changed, 63 insertions(+), 5 deletions(-)
 create mode 100644 Xargo.toml

diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml
index be03ee03f62..3b273a37d44 100644
--- a/.github/workflows/main.yaml
+++ b/.github/workflows/main.yaml
@@ -191,6 +191,28 @@ jobs:
         run: |
           make build-wapm
         if: needs.setup.outputs.DOING_RELEASE == '1'
+      - name: Install Nightly Rust for Headless
+        uses: actions-rs/toolchain@v1
+        with:
+          toolchain: 'nightly-2020-12-22'
+          target: ${{ matrix.target }}
+          override: true
+          components: "rust-src"
+        if: needs.setup.outputs.DOING_RELEASE == '1'
+      - name: Build Minimal Wasmer Headless
+        run: |
+          echo "\n[profile.release]
+opt-level = 'z'
+debug = false
+debug-assertions = false
+overflow-checks = false
+lto = true
+panic = 'abort'
+incremental = false
+codegen-units = 1
+rpath = false" >> Cargo.toml
+          make build-wasmer-headless-minimal
+        if: needs.setup.outputs.DOING_RELEASE == '1'
       - name: Copy target binaries
         run: |
           mkdir -p target/release
diff --git a/Makefile b/Makefile
index ae9a8a1c6c4..e9d9fc77484 100644
--- a/Makefile
+++ b/Makefile
@@ -54,6 +54,7 @@ endif
 # Using filter as a logical OR
 # https://stackoverflow.com/questions/7656425/makefile-ifeq-logical-or
 use_system_ffi =
+cross_compiling_to_mac_aarch64 =
 ifneq (,$(filter $(ARCH),aarch64 arm64))
 	test_compilers_engines += cranelift-jit
 	ifneq (, $(findstring llvm,$(compilers)))
@@ -62,6 +63,7 @@ ifneq (,$(filter $(ARCH),aarch64 arm64))
 	# if we are in macos arm64, we use the system libffi for the capi
 	ifeq ($(UNAME_S), Darwin)
 		use_system_ffi = yes
+		cross_compiling_to_mac_aarch64 = yes
 	endif
 endif
 
@@ -121,7 +123,7 @@ build-wasmer-debug:
 build-wasmer-headless-minimal:
 	HOST_TARGET=$$(rustup show | grep 'Default host: ' | cut -d':' -f2 | tr -d ' ') ;\
   echo $$HOST_TARGET ;\
-	xargo build -v --target $$HOST_TARGET --release --manifest-path=lib/cli/Cargo.toml --no-default-features --features disable-all-logging,native,wasi ;\
+	xargo build -v --target $$HOST_TARGET --release --manifest-path=lib/cli/Cargo.toml --no-default-features --features headless-minimal ;\
 	strip target/$$HOST_TARGET/release/wasmer
 
 WAPM_VERSION = master # v0.5.0
@@ -326,6 +328,18 @@ ifeq ($(UNAME_S), Darwin)
 endif
 endif
 
+package-minimal-headless-wasmer:
+ifdef cross_compiling_to_mac_aarch64
+	if [ -f "target/aarch64-apple-darwin/release/wasmer" ]; then \
+		cp target/aarch64-apple-darwin/release/wasmer package/bin/wasmer-headless ;\
+	fi
+else
+	HOST_TARGET=$$(rustup show | grep 'Default host: ' | cut -d':' -f2 | tr -d ' ') ;\
+	if [ -f "target/$$HOST_TARGET/release/wasmer" ]; then \
+		cp target/$$HOST_TARGET/release/wasmer package/bin/wasmer-headless ;\
+	fi
+endif
+
 package-wasmer:
 	mkdir -p "package/bin"
 ifeq ($(OS), Windows_NT)
@@ -369,7 +383,7 @@ package-docs: build-docs build-docs-capi
 	echo '<!-- Build $(SOURCE_VERSION) --><meta http-equiv="refresh" content="0; url=rust/wasmer_vm/index.html">' > package/docs/index.html
 	echo '<!-- Build $(SOURCE_VERSION) --><meta http-equiv="refresh" content="0; url=wasmer_vm/index.html">' > package/docs/crates/index.html
 
-package: package-wapm package-wasmer package-capi
+package: package-wapm package-wasmer package-minimal-headless-wasmer package-capi
 
 distribution: package
 	cp LICENSE package/LICENSE
diff --git a/Xargo.toml b/Xargo.toml
new file mode 100644
index 00000000000..01cf5eb2f4f
--- /dev/null
+++ b/Xargo.toml
@@ -0,0 +1,2 @@
+[dependencies]
+std = {default-features=false, features=["panic_immediate_abort"]}
diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml
index f8614795e57..bb98a574769 100644
--- a/lib/cli/Cargo.toml
+++ b/lib/cli/Cargo.toml
@@ -107,3 +107,5 @@ llvm = [
 ]
 debug = ["fern", "log", "wasmer-wasi/logging"]
 disable-all-logging = ["wasmer-wasi/disable-all-logging"]
+headless = []
+headless-minimal = ["headless", "disable-all-logging", "wasi", "native", "jit"]
diff --git a/lib/cli/src/bin/wasmer.rs b/lib/cli/src/bin/wasmer.rs
index e0e51ed2d5b..79ff745e28a 100644
--- a/lib/cli/src/bin/wasmer.rs
+++ b/lib/cli/src/bin/wasmer.rs
@@ -1,15 +1,28 @@
 use anyhow::Result;
+#[cfg(feature = "compile")]
+use wasmer_cli::commands::Compile;
 #[cfg(all(feature = "object-file", feature = "compiler"))]
 use wasmer_cli::commands::CreateExe;
 #[cfg(feature = "wast")]
 use wasmer_cli::commands::Wast;
-use wasmer_cli::commands::{Cache, Compile, Config, Inspect, Run, SelfUpdate, Validate};
+use wasmer_cli::commands::{Cache, Config, Inspect, Run, SelfUpdate, Validate};
 use wasmer_cli::error::PrettyError;
 
 use structopt::{clap::ErrorKind, StructOpt};
 
 #[derive(Debug, StructOpt)]
-#[structopt(name = "wasmer", about = "WebAssembly standalone runtime.", author)]
+#[cfg_attr(
+    not(feature = "headless"),
+    structopt(name = "wasmer", about = "WebAssembly standalone runtime.", author)
+)]
+#[cfg_attr(
+    feature = "headless",
+    structopt(
+        name = "wasmer-headless",
+        about = "Headless WebAssembly standalone runtime.",
+        author
+    )
+)]
 /// The options for the wasmer Command Line Interface
 enum WasmerCLIOptions {
     /// Run a WebAssembly file. Formats accepted: wasm, wat
@@ -25,6 +38,7 @@ enum WasmerCLIOptions {
     Validate(Validate),
 
     /// Compile a WebAssembly binary
+    #[cfg(feature = "compiler")]
     #[structopt(name = "compile")]
     Compile(Compile),
 
@@ -59,6 +73,7 @@ impl WasmerCLIOptions {
             Self::SelfUpdate(options) => options.execute(),
             Self::Cache(cache) => cache.execute(),
             Self::Validate(validate) => validate.execute(),
+            #[cfg(feature = "compiler")]
             Self::Compile(compile) => compile.execute(),
             #[cfg(all(feature = "object-file", feature = "compiler"))]
             Self::CreateExe(create_exe) => create_exe.execute(),
diff --git a/lib/cli/src/commands.rs b/lib/cli/src/commands.rs
index 7107150ccf4..f3791ef61e2 100644
--- a/lib/cli/src/commands.rs
+++ b/lib/cli/src/commands.rs
@@ -1,5 +1,6 @@
 //! The commands available in the Wasmer binary.
 mod cache;
+#[cfg(feature = "compile")]
 mod compile;
 mod config;
 #[cfg(all(feature = "object-file", feature = "compiler"))]
@@ -11,8 +12,10 @@ mod validate;
 #[cfg(feature = "wast")]
 mod wast;
 
+#[cfg(feature = "compile")]
+pub use compile::*;
 #[cfg(all(feature = "object-file", feature = "compiler"))]
 pub use create_exe::*;
 #[cfg(feature = "wast")]
 pub use wast::*;
-pub use {cache::*, compile::*, config::*, inspect::*, run::*, self_update::*, validate::*};
+pub use {cache::*, config::*, inspect::*, run::*, self_update::*, validate::*};

From ba52b4553ecbb3dc189028facbf2c29b722da345 Mon Sep 17 00:00:00 2001
From: Mark McCaskey <mark@wasmer.io>
Date: Tue, 12 Jan 2021 13:10:11 -0800
Subject: [PATCH 02/12] Fix typo feature "compile" -> "compiler"

---
 lib/cli/src/bin/wasmer.rs | 2 +-
 lib/cli/src/commands.rs   | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/cli/src/bin/wasmer.rs b/lib/cli/src/bin/wasmer.rs
index 79ff745e28a..fe227411819 100644
--- a/lib/cli/src/bin/wasmer.rs
+++ b/lib/cli/src/bin/wasmer.rs
@@ -1,5 +1,5 @@
 use anyhow::Result;
-#[cfg(feature = "compile")]
+#[cfg(feature = "compiler")]
 use wasmer_cli::commands::Compile;
 #[cfg(all(feature = "object-file", feature = "compiler"))]
 use wasmer_cli::commands::CreateExe;
diff --git a/lib/cli/src/commands.rs b/lib/cli/src/commands.rs
index f3791ef61e2..5e80631d7e0 100644
--- a/lib/cli/src/commands.rs
+++ b/lib/cli/src/commands.rs
@@ -1,6 +1,6 @@
 //! The commands available in the Wasmer binary.
 mod cache;
-#[cfg(feature = "compile")]
+#[cfg(feature = "compiler")]
 mod compile;
 mod config;
 #[cfg(all(feature = "object-file", feature = "compiler"))]
@@ -12,7 +12,7 @@ mod validate;
 #[cfg(feature = "wast")]
 mod wast;
 
-#[cfg(feature = "compile")]
+#[cfg(feature = "compiler")]
 pub use compile::*;
 #[cfg(all(feature = "object-file", feature = "compiler"))]
 pub use create_exe::*;

From ecc15b5c8c264a4e1d9af137218479bb1f92225a Mon Sep 17 00:00:00 2001
From: Mark McCaskey <mark@wasmer.io>
Date: Tue, 12 Jan 2021 13:24:15 -0800
Subject: [PATCH 03/12] Ensure `panic=abort` is always true when building with
 xargo

---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index e9d9fc77484..325d9efea9c 100644
--- a/Makefile
+++ b/Makefile
@@ -123,7 +123,7 @@ build-wasmer-debug:
 build-wasmer-headless-minimal:
 	HOST_TARGET=$$(rustup show | grep 'Default host: ' | cut -d':' -f2 | tr -d ' ') ;\
   echo $$HOST_TARGET ;\
-	xargo build -v --target $$HOST_TARGET --release --manifest-path=lib/cli/Cargo.toml --no-default-features --features headless-minimal ;\
+	RUSTFLAGS="-C panic=abort" xargo build -v --target $$HOST_TARGET --release --manifest-path=lib/cli/Cargo.toml --no-default-features --features headless-minimal ;\
 	strip target/$$HOST_TARGET/release/wasmer
 
 WAPM_VERSION = master # v0.5.0

From d63490e70ef6a09c1b9d09924f6304b4f675b12b Mon Sep 17 00:00:00 2001
From: Syrus Akbary <me@syrusakbary.com>
Date: Tue, 12 Jan 2021 13:29:05 -0800
Subject: [PATCH 04/12] Move HOST_TARGET up

---
 Makefile | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/Makefile b/Makefile
index e9d9fc77484..6014d9ba750 100644
--- a/Makefile
+++ b/Makefile
@@ -90,6 +90,9 @@ endif
 compiler_features_spaced := $(foreach compiler,$(compilers),$(compiler))
 compiler_features := --features "$(compiler_features_spaced)"
 
+HOST_TARGET=$(shell rustup show | grep 'Default host: ' | cut -d':' -f2 | tr -d ' ')
+
+$(info Host target: $(bold)$(green)$(HOST_TARGET)$(reset))
 $(info Available compilers: $(bold)$(green)${compilers}$(reset))
 $(info Compilers features: $(bold)$(green)${compiler_features}$(reset))
 $(info Available compilers + engines for test: $(bold)$(green)${test_compilers_engines}$(reset))
@@ -121,10 +124,8 @@ build-wasmer-debug:
 # codegen-units = 1
 # rpath = false
 build-wasmer-headless-minimal:
-	HOST_TARGET=$$(rustup show | grep 'Default host: ' | cut -d':' -f2 | tr -d ' ') ;\
-  echo $$HOST_TARGET ;\
-	xargo build -v --target $$HOST_TARGET --release --manifest-path=lib/cli/Cargo.toml --no-default-features --features headless-minimal ;\
-	strip target/$$HOST_TARGET/release/wasmer
+	RUSTFLAGS="-C panic=abort" xargo build -v --target $(HOST_TARGET) --release --manifest-path=lib/cli/Cargo.toml --no-default-features --features headless-minimal ;\
+	strip target/$(HOST_TARGET)/release/wasmer
 
 WAPM_VERSION = master # v0.5.0
 get-wapm:

From f0c7f5bc437a61c37fd22222addc53b3efe7988b Mon Sep 17 00:00:00 2001
From: Mark McCaskey <mark@wasmer.io>
Date: Tue, 12 Jan 2021 13:32:05 -0800
Subject: [PATCH 05/12] Temporarily unconditionally build headless wasmer

---
 .github/workflows/main.yaml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml
index 3b273a37d44..fb21b1f56b7 100644
--- a/.github/workflows/main.yaml
+++ b/.github/workflows/main.yaml
@@ -198,7 +198,7 @@ jobs:
           target: ${{ matrix.target }}
           override: true
           components: "rust-src"
-        if: needs.setup.outputs.DOING_RELEASE == '1'
+        #if: needs.setup.outputs.DOING_RELEASE == '1'
       - name: Build Minimal Wasmer Headless
         run: |
           echo "\n[profile.release]
@@ -212,7 +212,7 @@ incremental = false
 codegen-units = 1
 rpath = false" >> Cargo.toml
           make build-wasmer-headless-minimal
-        if: needs.setup.outputs.DOING_RELEASE == '1'
+        #if: needs.setup.outputs.DOING_RELEASE == '1'
       - name: Copy target binaries
         run: |
           mkdir -p target/release

From a9bba97c75226936b3529cba5b3d1f31fc0c9d88 Mon Sep 17 00:00:00 2001
From: Syrus Akbary <me@syrusakbary.com>
Date: Tue, 12 Jan 2021 14:13:09 -0800
Subject: [PATCH 06/12] Improved strip command

---
 Makefile | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index d1d71115910..f1f280aaae7 100644
--- a/Makefile
+++ b/Makefile
@@ -123,7 +123,11 @@ build-wasmer-debug:
 # rpath = false
 build-wasmer-headless-minimal:
 	RUSTFLAGS="-C panic=abort" xargo build -v --target $(HOST_TARGET) --release --manifest-path=lib/cli/Cargo.toml --no-default-features --features headless --bin wasmer-headless
-	strip target/$(HOST_TARGET)/release/wasmer-headless
+ifeq ($(UNAME_S), Darwin)
+	strip -u target/$(HOST_TARGET)/release/wasmer-headless
+else
+	strip --keep-file-symbols target/$(HOST_TARGET)/release/wasmer-headless
+endif
 
 WAPM_VERSION = master # v0.5.0
 get-wapm:

From 1aa6da06201ddde2661544043c0276c16c7bf749 Mon Sep 17 00:00:00 2001
From: Syrus Akbary <me@syrusakbary.com>
Date: Tue, 12 Jan 2021 14:18:29 -0800
Subject: [PATCH 07/12] Improved Linux strip command

---
 Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index f1f280aaae7..871a7b2cbf0 100644
--- a/Makefile
+++ b/Makefile
@@ -126,7 +126,7 @@ build-wasmer-headless-minimal:
 ifeq ($(UNAME_S), Darwin)
 	strip -u target/$(HOST_TARGET)/release/wasmer-headless
 else
-	strip --keep-file-symbols target/$(HOST_TARGET)/release/wasmer-headless
+	strip --strip-unneeded target/$(HOST_TARGET)/release/wasmer-headless
 endif
 
 WAPM_VERSION = master # v0.5.0

From 470dd80a3fe38488986280df5cd4a9617878e526 Mon Sep 17 00:00:00 2001
From: Mark McCaskey <mark@wasmer.io>
Date: Tue, 12 Jan 2021 14:40:55 -0800
Subject: [PATCH 08/12] Create separate wasmer-headless binary

---
 Makefile                           |  12 +--
 lib/cli/Cargo.toml                 |   6 ++
 lib/cli/src/bin/wasmer.rs          | 115 +---------------------------
 lib/cli/src/bin/wasmer_headless.rs |   5 ++
 lib/cli/src/cli.rs                 | 119 +++++++++++++++++++++++++++++
 lib/cli/src/lib.rs                 |   1 +
 6 files changed, 139 insertions(+), 119 deletions(-)
 create mode 100644 lib/cli/src/bin/wasmer_headless.rs
 create mode 100644 lib/cli/src/cli.rs

diff --git a/Makefile b/Makefile
index 325d9efea9c..3745478edf5 100644
--- a/Makefile
+++ b/Makefile
@@ -123,8 +123,8 @@ build-wasmer-debug:
 build-wasmer-headless-minimal:
 	HOST_TARGET=$$(rustup show | grep 'Default host: ' | cut -d':' -f2 | tr -d ' ') ;\
   echo $$HOST_TARGET ;\
-	RUSTFLAGS="-C panic=abort" xargo build -v --target $$HOST_TARGET --release --manifest-path=lib/cli/Cargo.toml --no-default-features --features headless-minimal ;\
-	strip target/$$HOST_TARGET/release/wasmer
+	RUSTFLAGS="-C panic=abort" xargo build --target $$HOST_TARGET --release --manifest-path=lib/cli/Cargo.toml --no-default-features --features headless-minimal --bin wasmer-headless ;\
+	strip -s required_symbols.txt target/$$HOST_TARGET/release/wasmer-headless
 
 WAPM_VERSION = master # v0.5.0
 get-wapm:
@@ -330,13 +330,13 @@ endif
 
 package-minimal-headless-wasmer:
 ifdef cross_compiling_to_mac_aarch64
-	if [ -f "target/aarch64-apple-darwin/release/wasmer" ]; then \
-		cp target/aarch64-apple-darwin/release/wasmer package/bin/wasmer-headless ;\
+	if [ -f "target/aarch64-apple-darwin/release/wasmer-headless" ]; then \
+		cp target/aarch64-apple-darwin/release/wasmer-headless package/bin/ ;\
 	fi
 else
 	HOST_TARGET=$$(rustup show | grep 'Default host: ' | cut -d':' -f2 | tr -d ' ') ;\
-	if [ -f "target/$$HOST_TARGET/release/wasmer" ]; then \
-		cp target/$$HOST_TARGET/release/wasmer package/bin/wasmer-headless ;\
+	if [ -f "target/$$HOST_TARGET/release/wasmer-headless" ]; then \
+		cp target/$$HOST_TARGET/release/wasmer-headless package/bin/ ;\
 	fi
 endif
 
diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml
index bb98a574769..b2a378f3227 100644
--- a/lib/cli/Cargo.toml
+++ b/lib/cli/Cargo.toml
@@ -16,6 +16,12 @@ name = "wasmer"
 path = "src/bin/wasmer.rs"
 doc = false
 
+[[bin]]
+name = "wasmer-headless"
+path = "src/bin/wasmer_headless.rs"
+doc = false
+required-features = ["headless"]
+
 [dependencies]
 wasmer = { version = "1.0.1", path = "../api", default-features = false }
 wasmer-compiler = { version = "1.0.1", path = "../compiler" }
diff --git a/lib/cli/src/bin/wasmer.rs b/lib/cli/src/bin/wasmer.rs
index fe227411819..ccd9aa9bf80 100644
--- a/lib/cli/src/bin/wasmer.rs
+++ b/lib/cli/src/bin/wasmer.rs
@@ -1,116 +1,5 @@
-use anyhow::Result;
-#[cfg(feature = "compiler")]
-use wasmer_cli::commands::Compile;
-#[cfg(all(feature = "object-file", feature = "compiler"))]
-use wasmer_cli::commands::CreateExe;
-#[cfg(feature = "wast")]
-use wasmer_cli::commands::Wast;
-use wasmer_cli::commands::{Cache, Config, Inspect, Run, SelfUpdate, Validate};
-use wasmer_cli::error::PrettyError;
-
-use structopt::{clap::ErrorKind, StructOpt};
-
-#[derive(Debug, StructOpt)]
-#[cfg_attr(
-    not(feature = "headless"),
-    structopt(name = "wasmer", about = "WebAssembly standalone runtime.", author)
-)]
-#[cfg_attr(
-    feature = "headless",
-    structopt(
-        name = "wasmer-headless",
-        about = "Headless WebAssembly standalone runtime.",
-        author
-    )
-)]
-/// The options for the wasmer Command Line Interface
-enum WasmerCLIOptions {
-    /// Run a WebAssembly file. Formats accepted: wasm, wat
-    #[structopt(name = "run")]
-    Run(Run),
-
-    /// Wasmer cache
-    #[structopt(name = "cache")]
-    Cache(Cache),
-
-    /// Validate a WebAssembly binary
-    #[structopt(name = "validate")]
-    Validate(Validate),
-
-    /// Compile a WebAssembly binary
-    #[cfg(feature = "compiler")]
-    #[structopt(name = "compile")]
-    Compile(Compile),
-
-    /// Compile a WebAssembly binary into a native executable
-    #[cfg(all(feature = "object-file", feature = "compiler"))]
-    #[structopt(name = "create-exe")]
-    CreateExe(CreateExe),
-
-    /// Get various configuration information needed
-    /// to compile programs which use Wasmer
-    #[structopt(name = "config")]
-    Config(Config),
-
-    /// Update wasmer to the latest version
-    #[structopt(name = "self-update")]
-    SelfUpdate(SelfUpdate),
-
-    /// Inspect a WebAssembly file
-    #[structopt(name = "inspect")]
-    Inspect(Inspect),
-
-    /// Run spec testsuite
-    #[cfg(feature = "wast")]
-    #[structopt(name = "wast")]
-    Wast(Wast),
-}
-
-impl WasmerCLIOptions {
-    fn execute(&self) -> Result<()> {
-        match self {
-            Self::Run(options) => options.execute(),
-            Self::SelfUpdate(options) => options.execute(),
-            Self::Cache(cache) => cache.execute(),
-            Self::Validate(validate) => validate.execute(),
-            #[cfg(feature = "compiler")]
-            Self::Compile(compile) => compile.execute(),
-            #[cfg(all(feature = "object-file", feature = "compiler"))]
-            Self::CreateExe(create_exe) => create_exe.execute(),
-            Self::Config(config) => config.execute(),
-            Self::Inspect(inspect) => inspect.execute(),
-            #[cfg(feature = "wast")]
-            Self::Wast(wast) => wast.execute(),
-        }
-    }
-}
+use wasmer_cli::cli::wasmer_main;
 
 fn main() {
-    // We allow windows to print properly colors
-    #[cfg(windows)]
-    colored::control::set_virtual_terminal(true).unwrap();
-
-    // We try to run wasmer with the normal arguments.
-    // Eg. `wasmer <SUBCOMMAND>`
-    // In case that fails, we fallback trying the Run subcommand directly.
-    // Eg. `wasmer myfile.wasm --dir=.`
-    let args = std::env::args().collect::<Vec<_>>();
-    let command = args.get(1);
-    let options = match command.unwrap_or(&"".to_string()).as_ref() {
-        "cache" | "compile" | "config" | "create-exe" | "help" | "inspect" | "run"
-        | "self-update" | "validate" | "wast" => WasmerCLIOptions::from_args(),
-        _ => {
-            WasmerCLIOptions::from_iter_safe(args.iter()).unwrap_or_else(|e| {
-                match e.kind {
-                    // This fixes a issue that:
-                    // 1. Shows the version twice when doing `wasmer -V`
-                    // 2. Shows the run help (instead of normal help) when doing `wasmer --help`
-                    ErrorKind::VersionDisplayed | ErrorKind::HelpDisplayed => e.exit(),
-                    _ => WasmerCLIOptions::Run(Run::from_args()),
-                }
-            })
-        }
-    };
-
-    PrettyError::report(options.execute());
+    wasmer_main();
 }
diff --git a/lib/cli/src/bin/wasmer_headless.rs b/lib/cli/src/bin/wasmer_headless.rs
new file mode 100644
index 00000000000..ccd9aa9bf80
--- /dev/null
+++ b/lib/cli/src/bin/wasmer_headless.rs
@@ -0,0 +1,5 @@
+use wasmer_cli::cli::wasmer_main;
+
+fn main() {
+    wasmer_main();
+}
diff --git a/lib/cli/src/cli.rs b/lib/cli/src/cli.rs
new file mode 100644
index 00000000000..26e21eafa61
--- /dev/null
+++ b/lib/cli/src/cli.rs
@@ -0,0 +1,119 @@
+//! The logic for the Wasmer CLI tool.
+
+#[cfg(feature = "compiler")]
+use crate::commands::Compile;
+#[cfg(all(feature = "object-file", feature = "compiler"))]
+use crate::commands::CreateExe;
+#[cfg(feature = "wast")]
+use crate::commands::Wast;
+use crate::commands::{Cache, Config, Inspect, Run, SelfUpdate, Validate};
+use crate::error::PrettyError;
+use anyhow::Result;
+
+use structopt::{clap::ErrorKind, StructOpt};
+
+#[derive(Debug, StructOpt)]
+#[cfg_attr(
+    not(feature = "headless"),
+    structopt(name = "wasmer", about = "WebAssembly standalone runtime.", author)
+)]
+#[cfg_attr(
+    feature = "headless",
+    structopt(
+        name = "wasmer-headless",
+        about = "Headless WebAssembly standalone runtime.",
+        author
+    )
+)]
+/// The options for the wasmer Command Line Interface
+enum WasmerCLIOptions {
+    /// Run a WebAssembly file. Formats accepted: wasm, wat
+    #[structopt(name = "run")]
+    Run(Run),
+
+    /// Wasmer cache
+    #[structopt(name = "cache")]
+    Cache(Cache),
+
+    /// Validate a WebAssembly binary
+    #[structopt(name = "validate")]
+    Validate(Validate),
+
+    /// Compile a WebAssembly binary
+    #[cfg(feature = "compiler")]
+    #[structopt(name = "compile")]
+    Compile(Compile),
+
+    /// Compile a WebAssembly binary into a native executable
+    #[cfg(all(feature = "object-file", feature = "compiler"))]
+    #[structopt(name = "create-exe")]
+    CreateExe(CreateExe),
+
+    /// Get various configuration information needed
+    /// to compile programs which use Wasmer
+    #[structopt(name = "config")]
+    Config(Config),
+
+    /// Update wasmer to the latest version
+    #[structopt(name = "self-update")]
+    SelfUpdate(SelfUpdate),
+
+    /// Inspect a WebAssembly file
+    #[structopt(name = "inspect")]
+    Inspect(Inspect),
+
+    /// Run spec testsuite
+    #[cfg(feature = "wast")]
+    #[structopt(name = "wast")]
+    Wast(Wast),
+}
+
+impl WasmerCLIOptions {
+    fn execute(&self) -> Result<()> {
+        match self {
+            Self::Run(options) => options.execute(),
+            Self::SelfUpdate(options) => options.execute(),
+            Self::Cache(cache) => cache.execute(),
+            Self::Validate(validate) => validate.execute(),
+            #[cfg(feature = "compiler")]
+            Self::Compile(compile) => compile.execute(),
+            #[cfg(all(feature = "object-file", feature = "compiler"))]
+            Self::CreateExe(create_exe) => create_exe.execute(),
+            Self::Config(config) => config.execute(),
+            Self::Inspect(inspect) => inspect.execute(),
+            #[cfg(feature = "wast")]
+            Self::Wast(wast) => wast.execute(),
+        }
+    }
+}
+
+/// The main function for the Wasmer CLI tool.
+pub fn wasmer_main() {
+    // We allow windows to print properly colors
+    #[cfg(windows)]
+    colored::control::set_virtual_terminal(true).unwrap();
+
+    // We try to run wasmer with the normal arguments.
+    // Eg. `wasmer <SUBCOMMAND>`
+    // In case that fails, we fallback trying the Run subcommand directly.
+    // Eg. `wasmer myfile.wasm --dir=.`
+    let args = std::env::args().collect::<Vec<_>>();
+    let command = args.get(1);
+    let options = match command.unwrap_or(&"".to_string()).as_ref() {
+        "cache" | "compile" | "config" | "create-exe" | "help" | "inspect" | "run"
+        | "self-update" | "validate" | "wast" => WasmerCLIOptions::from_args(),
+        _ => {
+            WasmerCLIOptions::from_iter_safe(args.iter()).unwrap_or_else(|e| {
+                match e.kind {
+                    // This fixes a issue that:
+                    // 1. Shows the version twice when doing `wasmer -V`
+                    // 2. Shows the run help (instead of normal help) when doing `wasmer --help`
+                    ErrorKind::VersionDisplayed | ErrorKind::HelpDisplayed => e.exit(),
+                    _ => WasmerCLIOptions::Run(Run::from_args()),
+                }
+            })
+        }
+    };
+
+    PrettyError::report(options.execute());
+}
diff --git a/lib/cli/src/lib.rs b/lib/cli/src/lib.rs
index bd8b30171ac..abb23aac40c 100644
--- a/lib/cli/src/lib.rs
+++ b/lib/cli/src/lib.rs
@@ -21,6 +21,7 @@ pub mod common;
 #[macro_use]
 pub mod error;
 pub mod c_gen;
+pub mod cli;
 #[cfg(feature = "debug")]
 pub mod logging;
 pub mod store;

From 3178121be8c5f81e07602b046007d37a1fe1fb50 Mon Sep 17 00:00:00 2001
From: Mark McCaskey <mark@wasmer.io>
Date: Tue, 12 Jan 2021 14:45:17 -0800
Subject: [PATCH 09/12] Make headless wasmer build in release only

---
 .github/workflows/main.yaml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml
index fb21b1f56b7..3b273a37d44 100644
--- a/.github/workflows/main.yaml
+++ b/.github/workflows/main.yaml
@@ -198,7 +198,7 @@ jobs:
           target: ${{ matrix.target }}
           override: true
           components: "rust-src"
-        #if: needs.setup.outputs.DOING_RELEASE == '1'
+        if: needs.setup.outputs.DOING_RELEASE == '1'
       - name: Build Minimal Wasmer Headless
         run: |
           echo "\n[profile.release]
@@ -212,7 +212,7 @@ incremental = false
 codegen-units = 1
 rpath = false" >> Cargo.toml
           make build-wasmer-headless-minimal
-        #if: needs.setup.outputs.DOING_RELEASE == '1'
+        if: needs.setup.outputs.DOING_RELEASE == '1'
       - name: Copy target binaries
         run: |
           mkdir -p target/release

From 35dee405f78e163bfe36d5a3e34cd33e4ae2062c Mon Sep 17 00:00:00 2001
From: Syrus Akbary <me@syrusakbary.com>
Date: Tue, 12 Jan 2021 15:09:02 -0800
Subject: [PATCH 10/12] Fix flags

---
 lib/cli/Cargo.toml | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml
index 5bb67129c15..b2a378f3227 100644
--- a/lib/cli/Cargo.toml
+++ b/lib/cli/Cargo.toml
@@ -113,4 +113,5 @@ llvm = [
 ]
 debug = ["fern", "log", "wasmer-wasi/logging"]
 disable-all-logging = ["wasmer-wasi/disable-all-logging"]
-headless = ["disable-all-logging", "wasi", "native", "jit"]
+headless = []
+headless-minimal = ["headless", "disable-all-logging", "wasi", "native", "jit"]

From 74a71628f6d7c96e636a2366f2284f5bc2c6b435 Mon Sep 17 00:00:00 2001
From: Syrus Akbary <me@syrusakbary.com>
Date: Tue, 12 Jan 2021 15:09:14 -0800
Subject: [PATCH 11/12] Removed wasmer-headless bin

---
 lib/cli/src/bin/wasmer-headless.rs | 61 ------------------------------
 1 file changed, 61 deletions(-)
 delete mode 100644 lib/cli/src/bin/wasmer-headless.rs

diff --git a/lib/cli/src/bin/wasmer-headless.rs b/lib/cli/src/bin/wasmer-headless.rs
deleted file mode 100644
index 4d67d876f0b..00000000000
--- a/lib/cli/src/bin/wasmer-headless.rs
+++ /dev/null
@@ -1,61 +0,0 @@
-use anyhow::Result;
-use wasmer_cli::commands::{Config, Run};
-use wasmer_cli::error::PrettyError;
-
-use structopt::{clap::ErrorKind, StructOpt};
-
-#[derive(Debug, StructOpt)]
-#[structopt(
-    name = "wasmer-headless",
-    about = "Headless WebAssembly standalone runtime.",
-    author
-)]
-/// The options for the wasmer Command Line Interface
-enum WasmerCLIOptions {
-    /// Run a WebAssembly file. Formats accepted: wasm, wat
-    #[structopt(name = "run")]
-    Run(Run),
-
-    /// Get various configuration information needed
-    /// to compile programs which use Wasmer
-    #[structopt(name = "config")]
-    Config(Config),
-}
-
-impl WasmerCLIOptions {
-    fn execute(&self) -> Result<()> {
-        match self {
-            Self::Run(options) => options.execute(),
-            Self::Config(config) => config.execute(),
-        }
-    }
-}
-
-fn main() {
-    // We allow windows to print properly colors
-    #[cfg(windows)]
-    colored::control::set_virtual_terminal(true).unwrap();
-
-    // We try to run wasmer with the normal arguments.
-    // Eg. `wasmer <SUBCOMMAND>`
-    // In case that fails, we fallback trying the Run subcommand directly.
-    // Eg. `wasmer myfile.wasm --dir=.`
-    let args = std::env::args().collect::<Vec<_>>();
-    let command = args.get(1);
-    let options = match command.unwrap_or(&"".to_string()).as_ref() {
-        "config" | "run" => WasmerCLIOptions::from_args(),
-        _ => {
-            WasmerCLIOptions::from_iter_safe(args.iter()).unwrap_or_else(|e| {
-                match e.kind {
-                    // This fixes a issue that:
-                    // 1. Shows the version twice when doing `wasmer -V`
-                    // 2. Shows the run help (instead of normal help) when doing `wasmer --help`
-                    ErrorKind::VersionDisplayed | ErrorKind::HelpDisplayed => e.exit(),
-                    _ => WasmerCLIOptions::Run(Run::from_args()),
-                }
-            })
-        }
-    };
-
-    PrettyError::report(options.execute());
-}

From 741afa9ff715cc7889d1d199a4a5c115420ac7d2 Mon Sep 17 00:00:00 2001
From: Mark McCaskey <mark@wasmer.io>
Date: Wed, 13 Jan 2021 06:47:08 -0800
Subject: [PATCH 12/12] Mention `wasmer-headless` in changelog

---
 CHANGELOG.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6e79ee63aba..722f04d4401 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@ This release includes a breaking change in the API (changing the trait `enumset:
 This change is unlikely to affect any users of `wasmer`, but if it does please change uses of the `enumset` crate to the `wasmer_enumset` crate where possible.
 
 ### Added
+- [#2010](https://github.com/wasmerio/wasmer/pull/2010) A new, experimental, minified build of `wasmer` called `wasmer-headless` will now be included with releases. `wasmer-headless` is the `wasmer` VM without any compilers attached, so it can only run precompiled Wasm modules.
 - [#2005](https://github.com/wasmerio/wasmer/pull/2005) Added the arguments `alias` and `optional` to `WasmerEnv` derive's `export` attribute.
 
 ### Changed