Repository: bytecodealliance/wasmtime
Pull request #2119 (2020-08-07 19:14:59)

Making caching support optional in Wasmtime
This commit moves all of the caching support that currently lives in
`wasmtime-environ` into a `wasmtime-cache` crate and makes it optional. The
goal here is to slim down the `wasmtime-environ` crate and clearly separate
boundaries where caching is a standalone and optional feature, not intertwined
with other crates.


github-actions[bot]: #### Subscribe to Label Action

cc @peterhuene

<details>
This issue or pull request has been labeled: "wasmtime:api"

Thus the following users have been cc'd because of the following labels:

* peterhuene: wasmtime:api

To subscribe or unsubscribe from this label, edit the <code>.github/subscribe-to-label.json</code> configuration file.

[Learn more.](https://github.com/bytecodealliance/subscribe-to-label-action)
</details>
github-actions[bot]: #### Subscribe to Label Action

cc @peterhuene

<details>
This issue or pull request has been labeled: "wasmtime:c-api"

Thus the following users have been cc'd because of the following labels:

* peterhuene: wasmtime:c-api

To subscribe or unsubscribe from this label, edit the <code>.github/subscribe-to-label.json</code> configuration file.

[Learn more.](https://github.com/bytecodealliance/subscribe-to-label-action)
</details>

Patch:
diff --git a/Cargo.lock b/Cargo.lock
index dc4d2d228..4cf980b0f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2373,6 +2373,7 @@ dependencies = [
  "target-lexicon",
  "tempfile",
  "wasmparser 0.59.0",
+ "wasmtime-cache",
  "wasmtime-environ",
  "wasmtime-jit",
  "wasmtime-profiling",
@@ -2404,6 +2405,30 @@ dependencies = [
  "quote",
 ]
 
+[[package]]
+name = "wasmtime-cache"
+version = "0.19.0"
+dependencies = [
+ "anyhow",
+ "base64 0.12.3",
+ "bincode",
+ "directories",
+ "errno",
+ "file-per-thread-logger",
+ "filetime",
+ "lazy_static",
+ "libc",
+ "log",
+ "more-asserts",
+ "pretty_env_logger",
+ "serde",
+ "sha2",
+ "tempfile",
+ "toml",
+ "winapi",
+ "zstd",
+]
+
 [[package]]
 name = "wasmtime-cli"
 version = "0.19.0"
@@ -2425,6 +2450,7 @@ dependencies = [
  "test-programs",
  "wasi-common",
  "wasmtime",
+ "wasmtime-cache",
  "wasmtime-debug",
  "wasmtime-environ",
  "wasmtime-fuzzing",
@@ -2455,33 +2481,19 @@ name = "wasmtime-environ"
 version = "0.19.0"
 dependencies = [
  "anyhow",
- "base64 0.12.3",
- "bincode",
  "cfg-if",
  "cranelift-codegen",
  "cranelift-entity",
  "cranelift-frontend",
  "cranelift-wasm",
- "directories",
- "errno",
- "file-per-thread-logger",
- "filetime",
  "gimli 0.21.0",
  "indexmap",
- "lazy_static",
- "libc",
  "lightbeam",
  "log",
  "more-asserts",
- "pretty_env_logger",
  "serde",
- "sha2",
- "tempfile",
  "thiserror",
- "toml",
  "wasmparser 0.59.0",
- "winapi",
- "zstd",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index c7b56dc0e..4e665313e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,7 +22,8 @@ doc = false
 
 [dependencies]
 # Enable all supported architectures by default.
-wasmtime = { path = "crates/wasmtime", version = "0.19.0", default-features = false }
+wasmtime = { path = "crates/wasmtime", version = "0.19.0", default-features = false, features = ['cache'] }
+wasmtime-cache = { path = "crates/cache", version = "0.19.0" }
 wasmtime-debug = { path = "crates/debug", version = "0.19.0" }
 wasmtime-environ = { path = "crates/environ", version = "0.19.0" }
 wasmtime-jit = { path = "crates/jit", version = "0.19.0" }
diff --git a/crates/c-api/Cargo.toml b/crates/c-api/Cargo.toml
index e59532cd9..fc4704e28 100644
--- a/crates/c-api/Cargo.toml
+++ b/crates/c-api/Cargo.toml
@@ -31,7 +31,8 @@ wasi-common = { path = "../wasi-common", optional = true }
 wasmtime-wasi = { path = "../wasi", optional = true }
 
 [features]
-default = ['jitdump', 'wat', 'wasi']
+default = ['jitdump', 'wat', 'wasi', 'cache']
 lightbeam = ["wasmtime/lightbeam"]
 jitdump = ["wasmtime/jitdump"]
+cache = ["wasmtime/cache"]
 wasi = ['wasi-common', 'wasmtime-wasi']
diff --git a/crates/c-api/src/config.rs b/crates/c-api/src/config.rs
index aaee8c4b3..49dce1984 100644
--- a/crates/c-api/src/config.rs
+++ b/crates/c-api/src/config.rs
@@ -1,3 +1,7 @@
+// Don't worry about unused imports if we're frobbing features, only worry about
+// them with the default set of features enabled.
+#![cfg_attr(not(feature = "cache"), allow(unused_imports))]
+
 use crate::{handle_result, wasmtime_error_t};
 use std::ffi::CStr;
 use std::os::raw::c_char;
@@ -130,6 +134,7 @@ pub extern "C" fn wasmtime_config_profiler_set(
 }
 
 #[no_mangle]
+#[cfg(feature = "cache")]
 pub unsafe extern "C" fn wasmtime_config_cache_config_load(
     c: &mut wasm_config_t,
     filename: *const c_char,
diff --git a/crates/cache/Cargo.toml b/crates/cache/Cargo.toml
new file mode 100644
index 000000000..b4c736772
--- /dev/null
+++ b/crates/cache/Cargo.toml
@@ -0,0 +1,35 @@
+[package]
+name = "wasmtime-cache"
+version = "0.19.0"
+authors = ["The Wasmtime Project Developers"]
+description = "Support for automatic module caching with Wasmtime"
+license = "Apache-2.0 WITH LLVM-exception"
+repository = "https://github.com/bytecodealliance/wasmtime"
+documentation = "https://docs.rs/wasmtime-cache/"
+edition = "2018"
+
+[dependencies]
+anyhow = "1.0"
+base64 = "0.12.0"
+bincode = "1.1.4"
+directories = "2.0.1"
+file-per-thread-logger = "0.1.1"
+log = { version = "0.4.8", default-features = false }
+serde = { version = "1.0.94", features = ["derive"] }
+sha2 = "0.8.0"
+toml = "0.5.5"
+zstd = "0.5"
+
+[target.'cfg(target_os = "windows")'.dependencies]
+winapi = "0.3.7"
+
+[target.'cfg(not(target_os = "windows"))'.dependencies]
+errno = "0.2.4"
+libc = "0.2.60"
+
+[dev-dependencies]
+filetime = "0.2.7"
+lazy_static = "1.3.0"
+more-asserts = "0.2.1"
+pretty_env_logger = "0.4.0"
+tempfile = "3"
diff --git a/crates/environ/Cargo.toml b/crates/environ/Cargo.toml
index 19b8f08d0..0dac39f98 100644
--- a/crates/environ/Cargo.toml
+++ b/crates/environ/Cargo.toml
@@ -21,31 +21,11 @@ wasmparser = "0.59.0"
 lightbeam = { path = "../lightbeam", optional = true, version = "0.19.0" }
 indexmap = { version = "1.0.2", features = ["serde-1"] }
 thiserror = "1.0.4"
-directories = "2.0.1"
-sha2 = "0.8.0"
-base64 = "0.12.0"
 serde = { version = "1.0.94", features = ["derive"] }
-bincode = "1.1.4"
 log = { version = "0.4.8", default-features = false }
-zstd = "0.5"
-toml = "0.5.5"
-file-per-thread-logger = "0.1.1"
 more-asserts = "0.2.1"
 cfg-if = "0.1.9"
 gimli = "0.21"
 
-[target.'cfg(target_os = "windows")'.dependencies]
-winapi = "0.3.7"
-
-[target.'cfg(not(target_os = "windows"))'.dependencies]
-libc = "0.2.60"
-errno = "0.2.4"
-
-[dev-dependencies]
-tempfile = "3"
-pretty_env_logger = "0.4.0"
-filetime = "0.2.7"
-lazy_static = "1.3.0"
-
 [badges]
 maintenance = { status = "actively-developed" }
diff --git a/crates/environ/src/lib.rs b/crates/environ/src/lib.rs
index a0148ff7f..d07792632 100644
--- a/crates/environ/src/lib.rs
+++ b/crates/environ/src/lib.rs
@@ -33,15 +33,11 @@ mod module_environ;
 mod tunables;
 mod vmoffsets;
 
-mod cache;
-
 pub mod cranelift;
 #[cfg(feature = "lightbeam")]
 pub mod lightbeam;
 
 pub use crate::address_map::*;
-pub use crate::cache::create_new_config as cache_create_new_config;
-pub use crate::cache::{CacheConfig, ModuleCacheEntry};
 pub use crate::compilation::*;
 pub use crate::cranelift::Cranelift;
 pub use crate::data_structures::*;
diff --git a/crates/wasmtime/Cargo.toml b/crates/wasmtime/Cargo.toml
index 54a15a42f..83efbb8e1 100644
--- a/crates/wasmtime/Cargo.toml
+++ b/crates/wasmtime/Cargo.toml
@@ -13,6 +13,7 @@ edition = "2018"
 wasmtime-runtime = { path = "../runtime", version = "0.19.0" }
 wasmtime-environ = { path = "../environ", version = "0.19.0" }
 wasmtime-jit = { path = "../jit", version = "0.19.0" }
+wasmtime-cache = { path = "../cache", version = "0.19.0", optional = true }
 wasmtime-profiling = { path = "../profiling", version = "0.19.0" }
 wasmparser = "0.59.0"
 target-lexicon = { version = "0.10.0", default-features = false }
@@ -40,7 +41,7 @@ wasmtime-wasi = { path = "../wasi" }
 maintenance = { status = "actively-developed" }
 
 [features]
-default = ['wat', 'jitdump', 'parallel-compilation']
+default = ['cache', 'wat', 'jitdump', 'parallel-compilation']
 
 # Enables experimental support for the lightbeam codegen backend, an alternative
 # to cranelift. Requires Nightly Rust currently, and this is not enabled by
@@ -55,3 +56,6 @@ vtune = ["wasmtime-jit/vtune"]
 
 # Enables parallel compilation of WebAssembly code
 parallel-compilation = ["wasmtime-jit/parallel-compilation"]
+
+# Enables support for automatic cache configuration to be enabled in `Config`.
+cache = ["wasmtime-cache"]
diff --git a/crates/wasmtime/src/module.rs b/crates/wasmtime/src/module.rs
index 40f346cba..dd306289f 100644
--- a/crates/wasmtime/src/module.rs
+++ b/crates/wasmtime/src/module.rs
@@ -4,7 +4,8 @@ use crate::types::{EntityType, ExportType, ExternType, ImportType};
 use anyhow::{bail, Context, Result};
 use std::path::Path;
 use std::sync::{Arc, Mutex};
-use wasmtime_environ::ModuleCacheEntry;
+#[cfg(feature = "cache")]
+use wasmtime_cache::ModuleCacheEntry;
 use wasmtime_jit::{CompilationArtifacts, CompiledModule};
 
 /// A compiled WebAssembly module, ready to be instantiated.
@@ -301,11 +302,13 @@ impl Module {
     }
 
     unsafe fn compile(engine: &Engine, binary: &[u8]) -> Result<Self> {
-        let cache_entry = ModuleCacheEntry::new("wasmtime", engine.cache_config());
-        let artifacts = cache_entry
+        #[cfg(feature = "cache")]
+        let artifacts = ModuleCacheEntry::new("wasmtime", engine.cache_config())
             .get_data((engine.compiler(), binary), |(compiler, binary)| {
                 CompilationArtifacts::build(compiler, binary)
             })?;
+        #[cfg(not(feature = "cache"))]
+        let artifacts = CompilationArtifacts::build(engine.compiler(), binary)?;
 
         let compiled = CompiledModule::from_artifacts(
             artifacts,
diff --git a/crates/wasmtime/src/runtime.rs b/crates/wasmtime/src/runtime.rs
index 8315c9edb..c45098f58 100644
--- a/crates/wasmtime/src/runtime.rs
+++ b/crates/wasmtime/src/runtime.rs
@@ -7,13 +7,16 @@ use std::cmp;
 use std::convert::TryFrom;
 use std::fmt;
 use std::hash::{Hash, Hasher};
+#[cfg(feature = "cache")]
 use std::path::Path;
 use std::rc::{Rc, Weak};
 use std::sync::Arc;
 use target_lexicon::Triple;
 use wasmparser::Validator;
+#[cfg(feature = "cache")]
+use wasmtime_cache::CacheConfig;
 use wasmtime_environ::settings::{self, Configurable, SetError};
-use wasmtime_environ::{ir, isa, isa::TargetIsa, wasm, CacheConfig, Tunables};
+use wasmtime_environ::{ir, isa, isa::TargetIsa, wasm, Tunables};
 use wasmtime_jit::{native, CompilationStrategy, Compiler};
 use wasmtime_profiling::{JitDumpAgent, NullProfilerAgent, ProfilingAgent, VTuneAgent};
 use wasmtime_runtime::{
@@ -37,6 +40,7 @@ pub struct Config {
     pub(crate) isa_flags: isa::Builder,
     pub(crate) tunables: Tunables,
     pub(crate) strategy: CompilationStrategy,
+    #[cfg(feature = "cache")]
     pub(crate) cache_config: CacheConfig,
     pub(crate) profiler: Arc<dyn ProfilingAgent>,
     pub(crate) memory_creator: Option<MemoryCreatorProxy>,
@@ -89,6 +93,7 @@ impl Config {
             flags,
             isa_flags: native::builder(),
             strategy: CompilationStrategy::Auto,
+            #[cfg(feature = "cache")]
             cache_config: CacheConfig::new_cache_disabled(),
             profiler: Arc::new(NullProfilerAgent),
             memory_creator: None,
@@ -395,14 +400,18 @@ impl Config {
     ///
     /// By default cache configuration is not enabled or loaded.
     ///
+    /// This method is only available when the `cache` feature of this crate is
+    /// enabled.
+    ///
     /// # Errors
     ///
     /// This method can fail due to any error that happens when loading the file
     /// pointed to by `path` and attempting to load the cache configuration.
     ///
     /// [docs]: https://bytecodealliance.github.io/wasmtime/cli-cache.html
+    #[cfg(feature = "cache")]
     pub fn cache_config_load(&mut self, path: impl AsRef<Path>) -> Result<&mut Self> {
-        self.cache_config = wasmtime_environ::CacheConfig::from_file(Some(path.as_ref()))?;
+        self.cache_config = CacheConfig::from_file(Some(path.as_ref()))?;
         Ok(self)
     }
 
@@ -416,6 +425,9 @@ impl Config {
     ///
     /// By default cache configuration is not enabled or loaded.
     ///
+    /// This method is only available when the `cache` feature of this crate is
+    /// enabled.
+    ///
     /// # Errors
     ///
     /// This method can fail due to any error that happens when loading the
@@ -424,8 +436,9 @@ impl Config {
     /// for an enabled cache are applied.
     ///
     /// [docs]: https://bytecodealliance.github.io/wasmtime/cli-cache.html
+    #[cfg(feature = "cache")]
     pub fn cache_config_load_default(&mut self) -> Result<&mut Self> {
-        self.cache_config = wasmtime_environ::CacheConfig::from_file(None)?;
+        self.cache_config = CacheConfig::from_file(None)?;
         Ok(self)
     }
 
@@ -793,6 +806,7 @@ impl Engine {
         &self.inner.compiler
     }
 
+    #[cfg(feature = "cache")]
     pub(crate) fn cache_config(&self) -> &CacheConfig {
         &self.config().cache_config
     }
diff --git a/scripts/publish.rs b/scripts/publish.rs
index af2f694b3..c61870edb 100644
--- a/scripts/publish.rs
+++ b/scripts/publish.rs
@@ -58,6 +58,7 @@ const CRATES_TO_PUBLISH: &[&str] = &[
     "wasmtime-profiling",
     "wasmtime-obj",
     "wasmtime-jit",
+    "wasmtime-cache",
     "wasmtime",
     "wasmtime-wiggle",
     "wasmtime-wasi",
diff --git a/src/commands/config.rs b/src/commands/config.rs
index 5507bf502..14184bd8e 100644
--- a/src/commands/config.rs
+++ b/src/commands/config.rs
@@ -1,8 +1,7 @@
 //! The module that implements the `wasmtime config` command.
 
-use anyhow::{anyhow, Result};
+use anyhow::Result;
 use structopt::StructOpt;
-use wasmtime_environ::cache_create_new_config;
 
 const CONFIG_NEW_AFTER_HELP: &str =
     "If no file path is specified, the system configuration file path will be used.";
@@ -37,7 +36,7 @@ pub struct ConfigNewCommand {
 impl ConfigNewCommand {
     /// Executes the command.
     pub fn execute(&self) -> Result<()> {
-        let path = cache_create_new_config(self.path.as_ref()).map_err(|e| anyhow!(e))?;
+        let path = wasmtime_cache::create_new_config(self.path.as_ref())?;
 
         println!(
             "Successfully created a new configuation file at '{}'.",


Test patch:
diff --git a/crates/environ/build.rs b/crates/cache/build.rs
similarity index 100%
rename from crates/environ/build.rs
rename to crates/cache/build.rs
diff --git a/crates/environ/src/cache/config.rs b/crates/cache/src/config.rs
similarity index 100%
rename from crates/environ/src/cache/config.rs
rename to crates/cache/src/config.rs
diff --git a/crates/environ/src/cache/config/tests.rs b/crates/cache/src/config/tests.rs
similarity index 100%
rename from crates/environ/src/cache/config/tests.rs
rename to crates/cache/src/config/tests.rs
diff --git a/crates/environ/src/cache.rs b/crates/cache/src/lib.rs
similarity index 100%
rename from crates/environ/src/cache.rs
rename to crates/cache/src/lib.rs
diff --git a/crates/environ/src/cache/tests.rs b/crates/cache/src/tests.rs
similarity index 100%
rename from crates/environ/src/cache/tests.rs
rename to crates/cache/src/tests.rs
diff --git a/crates/environ/src/cache/worker.rs b/crates/cache/src/worker.rs
similarity index 100%
rename from crates/environ/src/cache/worker.rs
rename to crates/cache/src/worker.rs
diff --git a/crates/environ/src/cache/worker/tests.rs b/crates/cache/src/worker/tests.rs
similarity index 99%
rename from crates/environ/src/cache/worker/tests.rs
rename to crates/cache/src/worker/tests.rs
index 43f0c0671..493973de8 100644
--- a/crates/environ/src/cache/worker/tests.rs
+++ b/crates/cache/src/worker/tests.rs
@@ -1,5 +1,5 @@
 use super::*;
-use crate::cache::config::tests::test_prolog;
+use crate::config::tests::test_prolog;
 use more_asserts::{assert_ge, assert_gt, assert_lt};
 use std::iter::repeat;
 use std::process;
diff --git a/crates/environ/src/cache/worker/tests/system_time_stub.rs b/crates/cache/src/worker/tests/system_time_stub.rs
similarity index 100%
rename from crates/environ/src/cache/worker/tests/system_time_stub.rs
rename to crates/cache/src/worker/tests/system_time_stub.rs
diff --git a/crates/environ/tests/cache_write_default_config.rs b/crates/cache/tests/cache_write_default_config.rs
similarity index 70%
rename from crates/environ/tests/cache_write_default_config.rs
rename to crates/cache/tests/cache_write_default_config.rs
index 1f1592fdb..6ef0b19a7 100644
--- a/crates/environ/tests/cache_write_default_config.rs
+++ b/crates/cache/tests/cache_write_default_config.rs
@@ -1,12 +1,11 @@
-use tempfile;
-use wasmtime_environ::cache_create_new_config;
+use wasmtime_cache::create_new_config;
 
 #[test]
 fn test_cache_write_default_config() {
     let dir = tempfile::tempdir().expect("Can't create temporary directory");
     let config_path = dir.path().join("cache-config.toml");
 
-    let result = cache_create_new_config(Some(&config_path));
+    let result = create_new_config(Some(&config_path));
     assert!(result.is_ok());
     assert!(config_path.exists());
     assert_eq!(config_path, result.unwrap());