diff --git a/crates/build/README.md b/crates/build/README.md index 0409b3340..b743b6827 100644 --- a/crates/build/README.md +++ b/crates/build/README.md @@ -11,6 +11,7 @@ use contract_build::{ Verbosity, BuildArtifacts, BuildMode, + Features, Network, OptimizationPasses, OutputType, @@ -23,6 +24,7 @@ let args = contract_build::ExecuteArgs { manifest_path, verbosity: Verbosity::Default, build_mode: BuildMode::Release, + features: Features::default(), network: Network::Online, build_artifact: BuildArtifacts::All, unstable_flags: UnstableFlags::default(), diff --git a/crates/build/src/args.rs b/crates/build/src/args.rs index 8c2c4580d..ad5485ecc 100644 --- a/crates/build/src/args.rs +++ b/crates/build/src/args.rs @@ -224,3 +224,28 @@ impl TryFrom<&UnstableOptions> for UnstableFlags { }) } } + +/// Define the standard `cargo` features args to be passed through. +#[derive(Default, Clone, Debug, Args)] +pub struct Features { + /// Space or comma separated list of features to activate + #[clap(long)] + features: Vec, +} + +impl Features { + /// Appends a feature. + pub fn push(&mut self, feature: &str) { + self.features.push(feature.to_owned()) + } + + /// Appends the raw features args to pass through to the `cargo` invocation. + pub fn append_to_args<'a>(&'a self, args: &mut Vec<&'a str>) { + if !self.features.is_empty() { + args.push("--features"); + for feature in &self.features { + args.push(feature) + } + } + } +} diff --git a/crates/build/src/lib.rs b/crates/build/src/lib.rs index 893952f92..d13b9efeb 100644 --- a/crates/build/src/lib.rs +++ b/crates/build/src/lib.rs @@ -35,6 +35,7 @@ pub use self::{ BuildArtifacts, BuildMode, BuildSteps, + Features, Network, OutputType, UnstableFlags, @@ -99,6 +100,7 @@ pub struct ExecuteArgs { pub manifest_path: ManifestPath, pub verbosity: Verbosity, pub build_mode: BuildMode, + pub features: Features, pub network: Network, pub build_artifact: BuildArtifacts, pub unstable_flags: UnstableFlags, @@ -232,6 +234,7 @@ impl BuildResult { fn exec_cargo_for_wasm_target( crate_metadata: &CrateMetadata, command: &str, + features: &Features, build_mode: BuildMode, network: Network, verbosity: Verbosity, @@ -248,14 +251,16 @@ fn exec_cargo_for_wasm_target( "--release", &target_dir, ]; + let mut features = features.clone(); if network == Network::Offline { args.push("--offline"); } if build_mode == BuildMode::Debug { - args.push("--features=ink/ink-debug"); + features.push("ink/ink-debug"); } else { args.push("-Zbuild-std-features=panic_immediate_abort"); } + features.append_to_args(&mut args); let mut env = vec![( "RUSTFLAGS", Some("-C link-arg=-zstack-size=65536 -C link-arg=--import-memory -Clinker-plugin-lto -C target-cpu=mvp"), @@ -555,6 +560,7 @@ pub fn execute(args: ExecuteArgs) -> Result { let ExecuteArgs { manifest_path, verbosity, + features, build_mode, network, build_artifact, @@ -619,6 +625,7 @@ pub fn execute(args: ExecuteArgs) -> Result { exec_cargo_for_wasm_target( &crate_metadata, "build", + &features, build_mode, network, verbosity, @@ -683,6 +690,7 @@ pub fn execute(args: ExecuteArgs) -> Result { exec_cargo_for_wasm_target( &crate_metadata, "check", + &features, BuildMode::Release, network, verbosity, diff --git a/crates/build/src/tests.rs b/crates/build/src/tests.rs index 582bf294b..1c333ad7a 100644 --- a/crates/build/src/tests.rs +++ b/crates/build/src/tests.rs @@ -152,6 +152,7 @@ fn optimization_passes_from_cli_must_take_precedence_over_profile( let args = ExecuteArgs { manifest_path: manifest_path.clone(), verbosity: Verbosity::Default, + features: Default::default(), build_mode: Default::default(), network: Default::default(), build_artifact: BuildArtifacts::All, @@ -192,6 +193,7 @@ fn optimization_passes_from_profile_must_be_used( let args = ExecuteArgs { manifest_path: manifest_path.clone(), verbosity: Verbosity::Default, + features: Default::default(), build_mode: Default::default(), network: Default::default(), build_artifact: BuildArtifacts::All, @@ -236,6 +238,7 @@ fn contract_lib_name_different_from_package_name_must_build( let args = ExecuteArgs { manifest_path: manifest_path.clone(), verbosity: Verbosity::Default, + features: Default::default(), build_mode: Default::default(), network: Default::default(), build_artifact: BuildArtifacts::All, diff --git a/crates/cargo-contract/src/cmd/build.rs b/crates/cargo-contract/src/cmd/build.rs index b237c3b02..5913ded8f 100644 --- a/crates/cargo-contract/src/cmd/build.rs +++ b/crates/cargo-contract/src/cmd/build.rs @@ -20,6 +20,7 @@ use contract_build::{ BuildMode, BuildResult, ExecuteArgs, + Features, ManifestPath, Network, OptimizationPasses, @@ -69,6 +70,8 @@ pub struct BuildCommand { #[clap(long = "generate", value_enum, default_value = "all")] build_artifact: BuildArtifacts, #[clap(flatten)] + features: Features, + #[clap(flatten)] verbosity: VerbosityFlags, #[clap(flatten)] unstable_options: UnstableOptions, @@ -140,6 +143,7 @@ impl BuildCommand { manifest_path, verbosity, build_mode, + features: self.features.clone(), network, build_artifact: self.build_artifact, unstable_flags, @@ -163,6 +167,8 @@ pub struct CheckCommand { #[clap(flatten)] verbosity: VerbosityFlags, #[clap(flatten)] + features: Features, + #[clap(flatten)] unstable_options: UnstableOptions, } @@ -177,6 +183,7 @@ impl CheckCommand { manifest_path, verbosity, build_mode: BuildMode::Debug, + features: self.features.clone(), network: Network::default(), build_artifact: BuildArtifacts::CheckOnly, unstable_flags, diff --git a/crates/cargo-contract/src/cmd/test.rs b/crates/cargo-contract/src/cmd/test.rs index 3dcb7a48e..2c5fb1b33 100644 --- a/crates/cargo-contract/src/cmd/test.rs +++ b/crates/cargo-contract/src/cmd/test.rs @@ -19,6 +19,7 @@ use colored::Colorize; use contract_build::{ maybe_println, util, + Features, ManifestPath, Verbosity, VerbosityFlags, @@ -37,6 +38,8 @@ pub struct TestCommand { manifest_path: Option, #[clap(flatten)] verbosity: VerbosityFlags, + #[clap(flatten)] + features: Features, } impl TestCommand { @@ -44,7 +47,7 @@ impl TestCommand { let manifest_path = ManifestPath::try_from(self.manifest_path.as_ref())?; let verbosity = TryFrom::<&VerbosityFlags>::try_from(&self.verbosity)?; - execute(&manifest_path, verbosity) + execute(&manifest_path, verbosity, &self.features) } } @@ -62,10 +65,11 @@ impl TestResult { } } -/// Executes `cargo +nightly test`. +/// Executes `cargo test`. pub(crate) fn execute( manifest_path: &ManifestPath, verbosity: Verbosity, + features: &Features, ) -> Result { maybe_println!( verbosity, @@ -74,8 +78,11 @@ pub(crate) fn execute( "Running tests".bright_green().bold() ); + let mut args = Vec::new(); + features.append_to_args(&mut args); + let stdout = - util::invoke_cargo("test", [""], manifest_path.directory(), verbosity, vec![])?; + util::invoke_cargo("test", args, manifest_path.directory(), verbosity, vec![])?; Ok(TestResult { stdout, verbosity }) } @@ -84,6 +91,7 @@ pub(crate) fn execute( #[cfg(test)] mod tests_ci_only { use contract_build::{ + Features, ManifestPath, Verbosity, }; @@ -107,8 +115,9 @@ mod tests_ci_only { Regex::new(r"test result: ok. \d+ passed; 0 failed; \d+ ignored") .expect("regex pattern compilation failed"); - let res = super::execute(&manifest_path, Verbosity::Default) - .expect("test execution failed"); + let res = + super::execute(&manifest_path, Verbosity::Default, &Features::default()) + .expect("test execution failed"); assert!(ok_output_pattern.is_match(&String::from_utf8_lossy(&res.stdout))); }