diff --git a/substrate/frame/contracts/fixtures/Cargo.toml b/substrate/frame/contracts/fixtures/Cargo.toml
index 565adc6f6e8d94257a23273f1df2702dc67db95c..58f20f0b8f5a406e5cbe5311ba2d4d95ca193c29 100644
--- a/substrate/frame/contracts/fixtures/Cargo.toml
+++ b/substrate/frame/contracts/fixtures/Cargo.toml
@@ -23,3 +23,7 @@ toml = "0.8.2"
 twox-hash = "1.6.3"
 polkavm-linker = "0.3.0"
 anyhow = "1.0.0"
+
+[features]
+# Enable experimental RISCV fixtures build
+riscv-experimental = []
diff --git a/substrate/frame/contracts/fixtures/build.rs b/substrate/frame/contracts/fixtures/build.rs
index de95d199b44865f82f4ae15fbe074302257a73b1..84eb4219c251c4b016a3ae415b644995981c6f68 100644
--- a/substrate/frame/contracts/fixtures/build.rs
+++ b/substrate/frame/contracts/fixtures/build.rs
@@ -16,7 +16,7 @@
 // limitations under the License.
 
 //! Compile contracts to wasm and RISC-V binaries.
-use anyhow::{bail, format_err, Context, Result};
+use anyhow::{bail, Context, Result};
 use parity_wasm::elements::{deserialize_file, serialize_to_file, Internal};
 use std::{
 	env, fs,
@@ -91,6 +91,7 @@ impl Entry {
 	}
 
 	/// Return the name of the RISC-V polkavm file.
+	#[cfg(feature = "riscv-experimental")]
 	fn out_riscv_filename(&self) -> String {
 		format!("{}.polkavm", self.name())
 	}
@@ -231,6 +232,7 @@ fn post_process_wasm(input_path: &Path, output_path: &Path) -> Result<()> {
 }
 
 /// Build contracts for RISC-V.
+#[cfg(feature = "riscv-experimental")]
 fn invoke_riscv_build(current_dir: &Path) -> Result<()> {
 	let encoded_rustflags =
 		["-Crelocation-model=pie", "-Clink-arg=--emit-relocs", "-Clink-arg=-Tmemory.ld"]
@@ -241,10 +243,10 @@ fn invoke_riscv_build(current_dir: &Path) -> Result<()> {
 	let build_res = Command::new(env::var("CARGO")?)
 		.current_dir(current_dir)
 		.env_clear()
-		.env("PATH", env::var("PATH").unwrap())
+		.env("PATH", env::var("PATH").unwrap_or_default())
 		.env("CARGO_ENCODED_RUSTFLAGS", encoded_rustflags)
 		.env("RUSTUP_TOOLCHAIN", "rve-nightly")
-		.env("RUSTUP_HOME", env::var("RUSTUP_HOME").unwrap())
+		.env("RUSTUP_HOME", env::var("RUSTUP_HOME").unwrap_or_default())
 		.args(["build", "--release", "--target=riscv32em-unknown-none-elf"])
 		.output()
 		.expect("failed to execute process");
@@ -265,12 +267,13 @@ fn invoke_riscv_build(current_dir: &Path) -> Result<()> {
 	bail!("Failed to build contracts");
 }
 /// Post-process the compiled wasm contracts.
+#[cfg(feature = "riscv-experimental")]
 fn post_process_riscv(input_path: &Path, output_path: &Path) -> Result<()> {
 	let mut config = polkavm_linker::Config::default();
 	config.set_strip(true);
 	let orig = fs::read(input_path).with_context(|| format!("Failed to read {:?}", input_path))?;
 	let linked = polkavm_linker::program_from_elf(config, orig.as_ref())
-		.map_err(|err| format_err!("Failed to link polkavm program: {}", err))?;
+		.map_err(|err| anyhow::format_err!("Failed to link polkavm program: {}", err))?;
 	fs::write(output_path, linked.as_bytes()).map_err(Into::into)
 }
 
@@ -283,6 +286,7 @@ fn write_output(build_dir: &Path, out_dir: &Path, entries: Vec<Entry>) -> Result
 			&out_dir.join(&wasm_output),
 		)?;
 
+		#[cfg(feature = "riscv-experimental")]
 		post_process_riscv(
 			&build_dir.join("target/riscv32em-unknown-none-elf/release").join(entry.name()),
 			&out_dir.join(entry.out_riscv_filename()),
@@ -335,6 +339,8 @@ fn main() -> Result<()> {
 	)?;
 
 	invoke_wasm_build(tmp_dir_path)?;
+
+	#[cfg(feature = "riscv-experimental")]
 	invoke_riscv_build(tmp_dir_path)?;
 
 	write_output(tmp_dir_path, &out_dir, entries)?;