diff --git a/Cargo.toml b/Cargo.toml index 154fbd1a1a..02a2e10491 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ members = [ "crates/env", "crates/storage", "crates/storage/derive", + "crates/build-script-utils", ] exclude = [ "examples/", diff --git a/crates/build-script-utils/Cargo.toml b/crates/build-script-utils/Cargo.toml new file mode 100644 index 0000000000..f02652aa75 --- /dev/null +++ b/crates/build-script-utils/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "ink_build_script_utils" +version = "3.2.0" +authors = ["Petar Ivanov "] +edition = "2021" + +license = "Apache-2.0" +readme = "README.md" +repository = "https://github.com/paritytech/ink" +documentation = "https://docs.rs/ink_build_script_utils/" +homepage = "https://www.parity.io/" +description = "[ink!] Utilities for `build.rs` scripts." +keywords = ["wasm", "parity", "webassembly", "blockchain", "edsl"] +include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"] diff --git a/crates/build-script-utils/README.md b/crates/build-script-utils/README.md new file mode 100644 index 0000000000..1c184f6732 --- /dev/null +++ b/crates/build-script-utils/README.md @@ -0,0 +1,3 @@ +Crate with utility functions for `build.rs` scripts. + +License: Apache-2.0 \ No newline at end of file diff --git a/crates/build-script-utils/src/lib.rs b/crates/build-script-utils/src/lib.rs new file mode 100644 index 0000000000..fb00e2a6f9 --- /dev/null +++ b/crates/build-script-utils/src/lib.rs @@ -0,0 +1,88 @@ +// Copyright 2018-2022 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::{ + env, + fs, + path::Path, +}; + +// Environment variables. +const ENV_ENGINE_STATIC_BUFFER_CAPACITY: &str = "ENV_ENGINE_STATIC_BUFFER_CAPACITY"; + +/// Configure the `StaticBuffer` capacity used in the `env` crate at build time +/// through the `ENV_ENGINE_STATIC_BUFFER_CAPACITY` environment variable. +/// If not explicitly configured, a default value of 16384 is used. +/// +/// `StaticBuffer`: engine/on_chain/buffer.rs +pub fn env_engine_static_buffer_capacity() -> String { + // Make sure that `build.rs` is called if the capacity configuration (env var) changes. + println!( + "cargo:rerun-if-env-changed={}", + ENV_ENGINE_STATIC_BUFFER_CAPACITY + ); + + let capacity = + env::var(ENV_ENGINE_STATIC_BUFFER_CAPACITY).unwrap_or_else(|_| "16384".into()); + let capacity: usize = capacity.parse().unwrap_or_else(|_| { + panic!( + "`{}` must be of type `usize`", + ENV_ENGINE_STATIC_BUFFER_CAPACITY + ) + }); + + format!("const CONFIGURED_CAPACITY: usize = {};", capacity) +} + +/// Write to the given `file` only if the `content` is different. +/// +/// Taken from: +/// https://github.dev/paritytech/substrate/blob/4b48e8ec7dffcb599248040f4da5be3de3c09318/utils/wasm-builder/src/lib.rs#L151 +pub fn write_file_if_changed(file: impl AsRef, content: impl AsRef) { + if fs::read_to_string(file.as_ref()).ok().as_deref() != Some(content.as_ref()) { + fs::write(file.as_ref(), content.as_ref()).unwrap_or_else(|_| { + panic!("Writing `{}` can not fail!", file.as_ref().display()) + }); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn env_engine_static_buffer_capacity_no_env() { + env::remove_var(ENV_ENGINE_STATIC_BUFFER_CAPACITY); + assert_eq!( + env_engine_static_buffer_capacity(), + "const CONFIGURED_CAPACITY: usize = 16384;" + ) + } + + #[test] + fn env_engine_static_buffer_capacity_valid_env() { + env::set_var(ENV_ENGINE_STATIC_BUFFER_CAPACITY, "32768"); + assert_eq!( + env_engine_static_buffer_capacity(), + "const CONFIGURED_CAPACITY: usize = 32768;" + ) + } + + #[test] + #[should_panic] + fn env_engine_static_buffer_capacity_invalid_env() { + env::set_var(ENV_ENGINE_STATIC_BUFFER_CAPACITY, "abc"); + env_engine_static_buffer_capacity(); + } +} diff --git a/crates/env/Cargo.toml b/crates/env/Cargo.toml index 82ab3cc2ea..30b3436bcf 100644 --- a/crates/env/Cargo.toml +++ b/crates/env/Cargo.toml @@ -14,6 +14,9 @@ keywords = ["wasm", "parity", "webassembly", "blockchain", "edsl"] categories = ["no-std", "embedded"] include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"] +[build-dependencies] +ink_build_script_utils = { version = "3.2.0", path = "../build-script-utils/", default-features = false } + [dependencies] ink_metadata = { version = "3.2.0", path = "../metadata/", default-features = false, features = ["derive"], optional = true } ink_allocator = { version = "3.2.0", path = "../allocator/", default-features = false } diff --git a/crates/env/build.rs b/crates/env/build.rs new file mode 100644 index 0000000000..3735bdd2f6 --- /dev/null +++ b/crates/env/build.rs @@ -0,0 +1,34 @@ +// Copyright 2018-2022 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::{ + env, + path::PathBuf, +}; + +use ink_build_script_utils::*; + +/// Write the engine static buffer capacity constant to a file that is then +/// included in the env/src/engine/on_chain/buffer.rs file. +fn write_env_engine_static_buffer_capacity() { + let capacity = env_engine_static_buffer_capacity(); + let out_dir = + PathBuf::from(env::var("OUT_DIR").expect("`OUT_DIR` must be set by cargo!")); + let out_file = out_dir.join("env_engine_static_buffer_capacity.rs"); + write_file_if_changed(out_file, capacity); +} + +fn main() { + write_env_engine_static_buffer_capacity(); +} diff --git a/crates/env/src/engine/on_chain/buffer.rs b/crates/env/src/engine/on_chain/buffer.rs index 469238f252..6df0751d5c 100644 --- a/crates/env/src/engine/on_chain/buffer.rs +++ b/crates/env/src/engine/on_chain/buffer.rs @@ -12,15 +12,23 @@ // See the License for the specific language governing permissions and // limitations under the License. -/// A static buffer with 16 kB of capacity. +// Inlcude the generated configuration file that contains the `CONFIGURED_CAPACITY` +// constant. +include!(concat!( + env!("OUT_DIR"), + "/env_engine_static_buffer_capacity.rs" +)); + +/// A static buffer with a configurable capacity at build-time. +/// If not explicitly configured, a default value of 16384 (16 kB) is used. pub struct StaticBuffer { - /// The static buffer with a total capacity of 16 kB. + /// The static buffer. buffer: [u8; Self::CAPACITY], } impl StaticBuffer { /// The capacity of the static buffer. - const CAPACITY: usize = 1 << 14; // 16 kB + const CAPACITY: usize = CONFIGURED_CAPACITY; /// Creates a new static buffer. pub const fn new() -> Self { diff --git a/crates/env/src/engine/on_chain/mod.rs b/crates/env/src/engine/on_chain/mod.rs index 2bee4c0785..16d6b9ebd4 100644 --- a/crates/env/src/engine/on_chain/mod.rs +++ b/crates/env/src/engine/on_chain/mod.rs @@ -27,7 +27,7 @@ use super::OnInstance; /// The on-chain environment. pub struct EnvInstance { - /// Encode & decode buffer with static size of 16 kB. + /// Encode & decode buffer with a default static capacity of 16 kB. /// /// If operations require more than that they will fail. /// This limit was found to be a sweet spot after running benchmarks @@ -36,6 +36,11 @@ pub struct EnvInstance { /// Please note that this is still an implementation detail and /// might change. Users should generally avoid storing too big values /// into single storage entries. + /// + /// Note: The static capacity of the buffer can be configured at + /// build-time via the `ENV_ENGINE_STATIC_BUFFER_CAPACITY` environment + /// variable. + /// See crates/env/build.rs for more information. buffer: StaticBuffer, }