diff --git a/Cargo.toml b/Cargo.toml index 6704a74f..1c6eb7c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "packages/ociswap-adapter-v1", "packages/caviarnine-adapter-v1", # Libraries + "libraries/package-loader", "libraries/scrypto-interface", "libraries/adapters-interface" ] @@ -24,8 +25,8 @@ radix-engine-common = { git = "https://github.com/radixdlt/radixdlt-scrypto", re radix-engine-stores = { git = "https://github.com/radixdlt/radixdlt-scrypto", rev = "9663c7c7dbcb91309b01f0b931195194b75b2718" } radix-engine-derive = { git = "https://github.com/radixdlt/radixdlt-scrypto", rev = "9663c7c7dbcb91309b01f0b931195194b75b2718" } radix-engine-queries = { git = "https://github.com/radixdlt/radixdlt-scrypto", rev = "9663c7c7dbcb91309b01f0b931195194b75b2718" } -radix-engine-store-interface = { git = "https://github.com/radixdlt/radixdlt-scrypto", rev = "9663c7c7dbcb91309b01f0b931195194b75b2718" } radix-engine-interface = { git = "https://github.com/radixdlt/radixdlt-scrypto", rev = "9663c7c7dbcb91309b01f0b931195194b75b2718" } +radix-engine-store-interface = { git = "https://github.com/radixdlt/radixdlt-scrypto", rev = "9663c7c7dbcb91309b01f0b931195194b75b2718" } scrypto-unit = { git = "https://github.com/radixdlt/radixdlt-scrypto", rev = "9663c7c7dbcb91309b01f0b931195194b75b2718" } scrypto-test = { git = "https://github.com/radixdlt/radixdlt-scrypto", rev = "9663c7c7dbcb91309b01f0b931195194b75b2718" } diff --git a/libraries/package-loader/Cargo.toml b/libraries/package-loader/Cargo.toml new file mode 100644 index 00000000..17d5ae7d --- /dev/null +++ b/libraries/package-loader/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "package-loader" +description = "The implementaton of a package builder and loader for efficient runtime package loading." +version.workspace = true +edition.workspace = true +build = "build.rs" + +[dependencies] +radix-engine-common = { workspace = true } +radix-engine-queries = { workspace = true } + +lazy_static = { verison = "1.4.0", optional = true } +getrandom = { version = "0.2.12", features = ["js"] } + +[build-dependencies] +walkdir = { version = "2.3.3", optional = true } +cargo_toml = { version = "0.18.0", optional = true } + +scrypto-unit = { workspace = true, optional = true } +radix-engine-interface = { workspace = true, optional = true } + +[features] +default = ["build-time-blueprints"] +build-time-blueprints = [ + "dep:lazy_static", + "dep:walkdir", + "dep:cargo_toml", + "dep:radix-engine-interface", + "dep:scrypto-unit", +] + +[lib] +crate-type = ["cdylib", "lib"] diff --git a/libraries/package-loader/build.rs b/libraries/package-loader/build.rs new file mode 100644 index 00000000..18898ea0 --- /dev/null +++ b/libraries/package-loader/build.rs @@ -0,0 +1,63 @@ +fn main() { + build_blueprints(); +} + +#[cfg(not(feature = "build-time-blueprints"))] +fn build_blueprints() {} + +#[cfg(feature = "build-time-blueprints")] +fn build_blueprints() { + use std::env; + use std::path::PathBuf; + + use cargo_toml::{Manifest, Package}; + use radix_engine_interface::prelude::*; + + let manifest_dir = PathBuf::from_str(env!("CARGO_MANIFEST_DIR")).unwrap(); + let blueprints_dir = manifest_dir.parent().unwrap(); + println!("cargo:rerun-if-changed=\"{:?}\"", blueprints_dir); + + let mut packages = HashMap::new(); + for entry in walkdir::WalkDir::new(blueprints_dir) { + let Ok(entry) = entry else { + continue; + }; + let path = entry.path(); + if !path + .file_name() + .map_or(false, |file_name| file_name == "Cargo.toml") + { + continue; + } + + let manifest = Manifest::from_path(path).unwrap(); + if !manifest + .dependencies + .into_iter() + .any(|(name, _)| name == "scrypto") + { + continue; + } + + let Some(Package { name, .. }) = manifest.package else { + continue; + }; + + let (code, definition) = scrypto_unit::Compile::compile_with_env_vars( + path.parent().unwrap(), + btreemap! { + "RUSTFLAGS".to_owned() => "".to_owned(), + "CARGO_ENCODED_RUSTFLAGS".to_owned() => "".to_owned(), + "LLVM_PROFILE_FILE".to_owned() => "".to_owned() + }, + ); + packages.insert(name, (code, definition)); + } + + let out_dir = + PathBuf::from_str(env::var("OUT_DIR").unwrap().as_str()).unwrap(); + let compilation_path = out_dir.join("compiled_packages.bin"); + + let encoded_packages = scrypto_encode(&packages).unwrap(); + std::fs::write(compilation_path, encoded_packages).unwrap(); +} diff --git a/libraries/package-loader/src/lib.rs b/libraries/package-loader/src/lib.rs new file mode 100644 index 00000000..bac51587 --- /dev/null +++ b/libraries/package-loader/src/lib.rs @@ -0,0 +1,48 @@ +#[cfg(feature = "build-time-blueprints")] +#[allow(unused, clippy::module_inception)] +mod package_loader { + use radix_engine_common::prelude::*; + use radix_engine_queries::typed_substate_layout::*; + + const PACKAGES_BINARY: &[u8] = + include_bytes!(concat!(env!("OUT_DIR"), "/compiled_packages.bin")); + + lazy_static::lazy_static! { + static ref PACKAGES: HashMap, PackageDefinition)> = { + scrypto_decode(PACKAGES_BINARY).unwrap() + }; + } + + pub struct PackageLoader; + impl PackageLoader { + pub fn get(name: &str) -> (Vec, PackageDefinition) { + if let Some(rtn) = PACKAGES.get(name) { + rtn.clone() + } else { + panic!("Package \"{}\" not found. Are you sure that this package is: a) in the blueprints folder, b) that this is the same as the package name in the Cargo.toml file?", name) + } + } + } +} + +#[cfg(not(feature = "build-time-blueprints"))] +#[allow(unused, clippy::module_inception)] +mod package_loader { + use radix_engine_common::prelude::*; + use radix_engine_queries::typed_substate_layout::*; + use std::path::PathBuf; + + pub struct PackageLoader; + impl PackageLoader { + pub fn get(name: &str) -> (Vec, PackageDefinition) { + let package_dir = PathBuf::from_str(env!("CARGO_MANIFEST_DIR")) + .unwrap() + .parent() + .unwrap() + .join(name); + scrypto_unit::Compile::compile(package_dir) + } + } +} + +pub use package_loader::PackageLoader;