Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ concurrency:

env:
ARTIFACT_RETENTION_DAYS_FOR_TEST_WASMS: 7
SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2: 1

defaults:
run:
Expand Down
16 changes: 2 additions & 14 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,9 @@ build: build-libs build-test-wasms
build-libs: fmt
cargo hack build --release $(foreach c,$(LIB_CRATES),--package $(c))

# First, build crate used as WASM deps to other test crates.
# Then, build `test_spec_shaking_v2` without the spec shaking v2 env var to verify
# that it falls back to spec_shaking_v1 behaviour.
# Then, build the test wasms with MSRV by default, with some meta disabled for
# binary stability for tests.
build-test-wasms: fmt
SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2=1 \
RUSTUP_TOOLCHAIN=$(TEST_CRATES_RUSTUP_TOOLCHAIN) \
RUSTFLAGS='--cfg soroban_sdk_internal_no_rssdkver_meta' \
cargo build --release --target wasm32v1-none --package test_spec_import
RUSTUP_TOOLCHAIN=$(TEST_CRATES_RUSTUP_TOOLCHAIN) \
RUSTFLAGS='--cfg soroban_sdk_internal_no_rssdkver_meta' \
cargo build --release --target wasm32v1-none --package test_spec_shaking_v2
cp target/wasm32v1-none/release/test_spec_shaking_v2.wasm \
target/wasm32v1-none/release/test_spec_shaking_v2_no_env.wasm
# Build the test wasms with MSRV by default, with some meta disabled for
# binary stability for tests.
SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2=1 \
RUSTUP_TOOLCHAIN=$(TEST_CRATES_RUSTUP_TOOLCHAIN) \
RUSTFLAGS='--cfg soroban_sdk_internal_no_rssdkver_meta' \
Expand Down
11 changes: 4 additions & 7 deletions soroban-sdk-macros/src/derive_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ use stellar_xdr::{
ScSpecUdtUnionCaseVoidV0, ScSpecUdtUnionV0, StringM, VecM, WriteXdr, SCSYMBOL_LIMIT,
};

use crate::{
doc::docs_from_attrs, map_type::map_type, shaking, spec_shaking_v2_enabled,
DEFAULT_XDR_RW_LIMITS,
};
use crate::{doc::docs_from_attrs, map_type::map_type, shaking, DEFAULT_XDR_RW_LIMITS};

pub fn derive_type_enum(
path: &Path,
Expand Down Expand Up @@ -184,9 +181,9 @@ pub fn derive_type_enum(
None
};

// SpecShakingMarker impl - only generated when spec is true and
// spec shaking v2 is enabled.
let spec_shaking_impl = if spec_shaking_v2_enabled() {
// SpecShakingMarker impl - only generated when spec is true and the
// experimental_spec_shaking_v2 feature is enabled.
let spec_shaking_impl = if cfg!(feature = "experimental_spec_shaking_v2") {
spec_xdr.as_ref().map(|spec_xdr| {
// Flatten all variant field types for shaking calls, deduplicating
// to avoid redundant calls for types that appear in multiple variants.
Expand Down
8 changes: 4 additions & 4 deletions soroban-sdk-macros/src/derive_enum_int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use syn::{

use stellar_xdr::{ScSpecEntry, ScSpecUdtEnumCaseV0, WriteXdr};

use crate::{doc::docs_from_attrs, shaking, spec_shaking_v2_enabled, DEFAULT_XDR_RW_LIMITS};
use crate::{doc::docs_from_attrs, shaking, DEFAULT_XDR_RW_LIMITS};

// TODO: Add conversions to/from ScVal types.

Expand Down Expand Up @@ -103,9 +103,9 @@ pub fn derive_type_enum_int(
None
};

// SpecShakingMarker impl - only generated when spec is true and
// spec shaking v2 is enabled.
let spec_shaking_impl = if spec_shaking_v2_enabled() {
// SpecShakingMarker impl - only generated when spec is true and the
// experimental_spec_shaking_v2 feature is enabled.
let spec_shaking_impl = if cfg!(feature = "experimental_spec_shaking_v2") {
spec_xdr.as_ref().map(|spec_xdr| {
shaking::generate_marker_impl(
path,
Expand Down
8 changes: 4 additions & 4 deletions soroban-sdk-macros/src/derive_error_enum_int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use syn::{
ext::IdentExt as _, spanned::Spanned, Attribute, DataEnum, Error, ExprLit, Ident, Lit, Path,
};

use crate::{doc::docs_from_attrs, shaking, spec_shaking_v2_enabled, DEFAULT_XDR_RW_LIMITS};
use crate::{doc::docs_from_attrs, shaking, DEFAULT_XDR_RW_LIMITS};

pub fn derive_type_error_enum_int(
path: &Path,
Expand Down Expand Up @@ -100,9 +100,9 @@ pub fn derive_type_error_enum_int(
None
};

// SpecShakingMarker impl - only generated when spec is true and
// spec shaking v2 is enabled.
let spec_shaking_impl = if spec_shaking_v2_enabled() {
// SpecShakingMarker impl - only generated when spec is true and the
// experimental_spec_shaking_v2 feature is enabled.
let spec_shaking_impl = if cfg!(feature = "experimental_spec_shaking_v2") {
spec_xdr.as_ref().map(|spec_xdr| {
shaking::generate_marker_impl(
path,
Expand Down
10 changes: 5 additions & 5 deletions soroban-sdk-macros/src/derive_event.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
attribute::remove_attributes_from_item, default_crate_path, doc::docs_from_attrs,
map_type::map_type, shaking, spec_shaking_v2_enabled, symbol, DEFAULT_XDR_RW_LIMITS,
map_type::map_type, shaking, symbol, DEFAULT_XDR_RW_LIMITS,
};
use darling::{ast::NestedMeta, Error, FromMeta};
use heck::ToSnakeCase;
Expand Down Expand Up @@ -202,7 +202,7 @@ fn derive_impls(args: &ContractEventArgs, input: &DeriveInput) -> Result<TokenSt
"__SPEC_XDR_EVENT_{}",
input.ident.unraw().to_string().to_uppercase()
);
let spec_shaking_call = if export && spec_shaking_v2_enabled() {
let spec_shaking_call = if export && cfg!(feature = "experimental_spec_shaking_v2") {
Some(quote! { <Self as #path::SpecShakingMarker>::spec_shaking_marker(); })
} else {
None
Expand All @@ -220,9 +220,9 @@ fn derive_impls(args: &ContractEventArgs, input: &DeriveInput) -> Result<TokenSt
}
};

// SpecShakingMarker impl - only generated when export is true and
// spec shaking v2 is enabled.
let spec_shaking_impl = if export && spec_shaking_v2_enabled() {
// SpecShakingMarker impl - only generated when export is true and the
// experimental_spec_shaking_v2 feature is enabled.
let spec_shaking_impl = if export && cfg!(feature = "experimental_spec_shaking_v2") {
Some(shaking::generate_marker_impl(
path,
quote!(#ident),
Expand Down
11 changes: 4 additions & 7 deletions soroban-sdk-macros/src/derive_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ use stellar_xdr::{
ScSpecEntry, ScSpecTypeDef, ScSpecUdtStructFieldV0, ScSpecUdtStructV0, StringM, WriteXdr,
};

use crate::{
doc::docs_from_attrs, map_type::map_type, shaking, spec_shaking_v2_enabled,
DEFAULT_XDR_RW_LIMITS,
};
use crate::{doc::docs_from_attrs, map_type::map_type, shaking, DEFAULT_XDR_RW_LIMITS};

// TODO: Add field attribute for including/excluding fields in types.
// TODO: Better handling of partial types and types without all their fields and
Expand Down Expand Up @@ -113,9 +110,9 @@ pub fn derive_type_struct(
None
};

// SpecShakingMarker impl - only generated when spec is true and
// spec shaking v2 is enabled.
let spec_shaking_impl = if spec_shaking_v2_enabled() {
// SpecShakingMarker impl - only generated when spec is true and the
// experimental_spec_shaking_v2 feature is enabled.
let spec_shaking_impl = if cfg!(feature = "experimental_spec_shaking_v2") {
spec_xdr.as_ref().map(|spec_xdr| {
shaking::generate_marker_impl(
path,
Expand Down
11 changes: 4 additions & 7 deletions soroban-sdk-macros/src/derive_struct_tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ use stellar_xdr::{
ScSpecEntry, ScSpecTypeDef, ScSpecUdtStructFieldV0, ScSpecUdtStructV0, StringM, WriteXdr,
};

use crate::{
doc::docs_from_attrs, map_type::map_type, shaking, spec_shaking_v2_enabled,
DEFAULT_XDR_RW_LIMITS,
};
use crate::{doc::docs_from_attrs, map_type::map_type, shaking, DEFAULT_XDR_RW_LIMITS};

pub fn derive_type_struct_tuple(
path: &Path,
Expand Down Expand Up @@ -102,9 +99,9 @@ pub fn derive_type_struct_tuple(
None
};

// SpecShakingMarker impl - only generated when spec is true and
// spec shaking v2 is enabled.
let spec_shaking_impl = if spec_shaking_v2_enabled() {
// SpecShakingMarker impl - only generated when spec is true and the
// experimental_spec_shaking_v2 feature is enabled.
let spec_shaking_impl = if cfg!(feature = "experimental_spec_shaking_v2") {
spec_xdr.as_ref().map(|spec_xdr| {
shaking::generate_marker_impl(
path,
Expand Down
22 changes: 7 additions & 15 deletions soroban-sdk-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,6 @@ pub(crate) fn default_crate_path() -> Path {
parse_str("soroban_sdk").unwrap()
}

/// Returns true if spec shaking v2 should be used. Requires both the
/// `experimental_spec_shaking_v2` feature to be enabled on the macro crate AND
/// the `SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2` env var to be set
/// at the time the macro expands (i.e. when the consumer crate is compiled).
fn spec_shaking_v2_enabled() -> bool {
cfg!(feature = "experimental_spec_shaking_v2")
&& option_env!("SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2").is_some()
}

#[derive(Debug, FromMeta)]
struct ContractSpecArgs {
name: Type,
Expand Down Expand Up @@ -437,10 +428,10 @@ pub fn contracttype(metadata: TokenStream, input: TokenStream) -> TokenStream {
}
// If the export argument has a value, do as it instructs regarding
// exporting. If it does not have a value, export if the type is pub,
// or always export when spec shaking v2 is enabled.
// or always export when spec shaking is enabled.
let gen_spec = if let Some(export) = args.export {
export
} else if spec_shaking_v2_enabled() {
} else if cfg!(feature = "experimental_spec_shaking_v2") {
true
Comment thread
mootz12 marked this conversation as resolved.
} else {
matches!(input.vis, Visibility::Public(_))
Expand Down Expand Up @@ -511,10 +502,10 @@ pub fn contracterror(metadata: TokenStream, input: TokenStream) -> TokenStream {
let attrs = &input.attrs;
// If the export argument has a value, do as it instructs regarding
// exporting. If it does not have a value, export if the type is pub,
// or always export when spec shaking v2 is enabled.
// or always export when spec shaking is enabled.
let gen_spec = if let Some(export) = args.export {
export
} else if spec_shaking_v2_enabled() {
} else if cfg!(feature = "experimental_spec_shaking_v2") {
true
Comment thread
mootz12 marked this conversation as resolved.
} else {
matches!(input.vis, Visibility::Public(_))
Expand Down Expand Up @@ -700,9 +691,10 @@ pub fn contractimport(metadata: TokenStream) -> TokenStream {
}
};

// Generate with options based on whether spec shaking v2 is enabled
// Generate with options based on whether the experimental_spec_shaking_v2
// feature is enabled.
let opts = GenerateOptions {
export: spec_shaking_v2_enabled(),
export: cfg!(feature = "experimental_spec_shaking_v2"),
};
match generate_from_wasm_with_options(&wasm, &args.file, args.sha256.as_deref(), &opts) {
Ok(code) => quote! { #code },
Expand Down
30 changes: 16 additions & 14 deletions soroban-sdk/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,25 @@ pub fn main() {
}

// When the experimental_spec_shaking_v2 feature is enabled, check for an env var from the
// build system (like Stellar CLI) that indicates it supports spec optimization using markers.
// If the env var is set, enable spec_shaking_v2 cfg for the crate. If not, fall back to
// spec shaking v1 behavior and emit a warning on wasm targets.
println!("cargo::rustc-check-cfg=cfg(spec_shaking_v2)");
// build system (Stellar CLI) that indicates it supports spec optimization using markers.
if std::env::var("CARGO_FEATURE_EXPERIMENTAL_SPEC_SHAKING_V2").is_ok() {
let env_name = "SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2";
println!("cargo::rerun-if-env-changed={env_name}");
if std::env::var(env_name).is_ok() {
println!("cargo::rustc-cfg=spec_shaking_v2");
} else if std::env::var("CARGO_CFG_TARGET_FAMILY").unwrap_or_default() == "wasm" {
println!(
"cargo::warning=soroban-sdk: feature 'experimental_spec_shaking_v2' was enabled but not used, \
because this build was not started by a tool that supports spec shaking v2. \
Falling back to spec shaking v1. To use v2, use a build tool that supports \
spec shaking v2 such as stellar-cli v25.2.0+ with `stellar contract build`. \
To manually use v2 without a supporting build tool, set the env var \
SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2 before building."
if std::env::var(env_name).is_err()
&& std::env::var("CARGO_CFG_TARGET_FAMILY").unwrap_or_default() == "wasm"
{
panic!(
"\
\n\nerror: soroban-sdk feature 'experimental_spec_shaking_v2' requires stellar-cli v25.2.0+\
\n\
\nThe soroban-sdk 'experimental_spec_shaking_v2' feature requires building\
\nwith `stellar contract build` from stellar-cli v25.2.0 or newer.\
\n\
\nTo fix, either:\
\n - Build with `stellar contract build` using stellar-cli v25.2.0+\
\n - Disable the feature by removing 'experimental_spec_shaking_v2' from\
\n the soroban-sdk import features list in Cargo.toml.\
Comment thread
mootz12 marked this conversation as resolved.
\n"
);
}
}
Expand Down
15 changes: 5 additions & 10 deletions soroban-sdk/src/_features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,16 +135,11 @@
//!
//! ### Build Requirements
//!
//! Spec shaking v2 requires the
//! `SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2` environment variable to
//! be set at build time. This is automatically set by `stellar contract build`
//! from `stellar-cli` v25.2.0 or newer.
//!
//! When the `experimental_spec_shaking_v2` feature is enabled but the env var
//! is not set, the SDK falls back to spec shaking v1 behavior and emits a
//! build warning on wasm targets. This allows contracts to build with plain
//! `cargo build` without errors, while still benefiting from v2 when built
//! with compatible tooling.
//! This feature requires building with `stellar contract build` from
//! `stellar-cli` v25.2.0 or newer. Building directly with `cargo build` will
//! produce a build error unless the
//! `SOROBAN_SDK_BUILD_SYSTEM_SUPPORTS_SPEC_SHAKING_V2` environment variable is
//! set.
//!
//! [`contracttype`]: crate::contracttype
//! [`contracterror`]: crate::contracterror
Expand Down
4 changes: 2 additions & 2 deletions soroban-sdk/src/into_val_for_contract_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub trait IntoValForContractFn {
fn into_val_for_contract_fn(self, env: &Env) -> Val;
}

#[cfg(spec_shaking_v2)]
#[cfg(feature = "experimental_spec_shaking_v2")]
#[doc(hidden)]
#[allow(deprecated)]
impl<T> IntoValForContractFn for T
Expand All @@ -33,7 +33,7 @@ where
}
}

#[cfg(not(spec_shaking_v2))]
#[cfg(not(feature = "experimental_spec_shaking_v2"))]
#[doc(hidden)]
#[allow(deprecated)]
impl<T> IntoValForContractFn for T
Expand Down
8 changes: 4 additions & 4 deletions soroban-sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,11 @@ const _: () = {
val = concat!(env!("CARGO_PKG_VERSION"), "#", env!("GIT_REVISION")),
);

// An indicator of the spec shaking version in use. Signals to the post-build system that the .wasm
// An indicator of the spec shaking version in use. Signals to the stellar-cli that the .wasm
// needs to have its spec shaken. See soroban_spec::shaking for constants and version detection.
// The contractmeta! macro requires string literals, so we assert the literals match the
// constants defined in soroban_spec::shaking.
#[cfg(spec_shaking_v2)]
#[cfg(feature = "experimental_spec_shaking_v2")]
contractmeta!(key = "rssdk_spec_shaking", val = "2");
};

Expand Down Expand Up @@ -1195,9 +1195,9 @@ mod into_val_for_contract_fn;
#[allow(deprecated)]
pub use into_val_for_contract_fn::IntoValForContractFn;

#[cfg(spec_shaking_v2)]
#[cfg(feature = "experimental_spec_shaking_v2")]
mod spec_shaking;
#[cfg(spec_shaking_v2)]
#[cfg(feature = "experimental_spec_shaking_v2")]
#[doc(hidden)]
pub use spec_shaking::SpecShakingMarker;

Expand Down
4 changes: 2 additions & 2 deletions soroban-sdk/src/try_from_val_for_contract_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub trait TryFromValForContractFn<E: Env, V: ?Sized>: Sized {
fn try_from_val_for_contract_fn(env: &E, v: &V) -> Result<Self, Self::Error>;
}

#[cfg(spec_shaking_v2)]
#[cfg(feature = "experimental_spec_shaking_v2")]
#[doc(hidden)]
#[allow(deprecated)]
impl<E: Env, T, U> TryFromValForContractFn<E, T> for U
Expand All @@ -44,7 +44,7 @@ where
}
}

#[cfg(not(spec_shaking_v2))]
#[cfg(not(feature = "experimental_spec_shaking_v2"))]
#[doc(hidden)]
#[allow(deprecated)]
impl<E: Env, T, U> TryFromValForContractFn<E, T> for U
Expand Down
5 changes: 5 additions & 0 deletions tests-expanded/test_account_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ impl Error {
*b"\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\x05Error\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x04Fail\0\0\0\x01"
}
}
impl soroban_sdk::SpecShakingMarker for Error {
#[doc(hidden)]
#[inline(always)]
fn spec_shaking_marker() {}
}
impl TryFrom<soroban_sdk::Error> for Error {
type Error = soroban_sdk::Error;
#[inline(always)]
Expand Down
10 changes: 10 additions & 0 deletions tests-expanded/test_auth_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,11 @@ mod test_a {
*b"\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\x05Error\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x07Decline\0\0\0\0\x01"
}
}
impl soroban_sdk::SpecShakingMarker for Error {
#[doc(hidden)]
#[inline(always)]
fn spec_shaking_marker() {}
}
impl TryFrom<soroban_sdk::Error> for Error {
type Error = soroban_sdk::Error;
#[inline(always)]
Expand Down Expand Up @@ -2601,6 +2606,11 @@ mod test_b {
*b"\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\x05Error\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x07Decline\0\0\0\0\x01"
}
}
impl soroban_sdk::SpecShakingMarker for Error {
#[doc(hidden)]
#[inline(always)]
fn spec_shaking_marker() {}
}
impl TryFrom<soroban_sdk::Error> for Error {
type Error = soroban_sdk::Error;
#[inline(always)]
Expand Down
Loading
Loading