Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
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
42 changes: 8 additions & 34 deletions crates/build/src/docker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,14 @@ impl From<Option<String>> for ImageVariant {
}
}

pub trait ComposeBuildArgs {
/// Takes CLI args from the host and appends them to the build command inside the
/// docker.
fn compose_build_args() -> Result<Vec<String>>;
}

/// Launches the docker container to execute verifiable build.
pub fn docker_build(args: ExecuteArgs) -> Result<BuildResult> {
pub fn docker_build<T: ComposeBuildArgs>(args: ExecuteArgs) -> Result<BuildResult> {
let ExecuteArgs {
manifest_path,
verbosity,
Expand All @@ -139,7 +145,7 @@ pub fn docker_build(args: ExecuteArgs) -> Result<BuildResult> {
let crate_metadata =
CrateMetadata::collect_with_target_dir(&manifest_path, target_dir)?;
let host_folder = std::env::current_dir()?;
let args = compose_build_args()?;
let args = T::compose_build_args()?;

let client = Docker::connect_with_socket_defaults().map_err(|e| {
anyhow::anyhow!("{e}\nDo you have the docker engine installed in path?")
Expand Down Expand Up @@ -511,38 +517,6 @@ async fn run_build(
}
}

/// Takes CLI args from the host and appends them to the build command inside the docker.
fn compose_build_args() -> Result<Vec<String>> {
use regex::Regex;
let mut args: Vec<String> = Vec::new();
// match `--image` or `verify` with arg with 1 or more white spaces surrounded
let rex = Regex::new(r#"(--image|verify)[ ]*[^ ]*[ ]*"#)?;
// we join the args together, so we can remove `--image <arg>`
// We skip the first captured argument (binary name), to allow other binaries use
// docker_build.
let args_string: String = std::env::args().skip(1).collect::<Vec<String>>().join(" ");
let args_string = rex.replace_all(&args_string, "").to_string();

// and then we turn it back to the vec, filtering out commands and arguments
// that should not be passed to the docker build command
let mut os_args: Vec<String> = args_string
.split_ascii_whitespace()
.filter(|a| {
a != &"--verifiable"
&& !a.contains("cargo-contract")
&& a != &"cargo"
&& a != &"contract"
&& a != &"build"
&& a != &"--output-json"
})
.map(|s| s.to_string())
.collect();

args.append(&mut os_args);

Ok(args)
}

/// Pulls the docker image from the registry.
async fn pull_image(client: &Docker, image: String, verbosity: &Verbosity) -> Result<()> {
let mut pull_image_stream = client.create_image(
Expand Down
5 changes: 3 additions & 2 deletions crates/build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ pub use self::{
VerbosityFlags,
},
crate_metadata::CrateMetadata,
docker::ComposeBuildArgs,
metadata::{
BuildInfo,
InkMetadataArtifacts,
Expand Down Expand Up @@ -575,7 +576,7 @@ fn validate_metadata_spec_for_abi(
/// deploying.
///
/// It does so by invoking `cargo build` and then post-processing the final binary.
pub fn execute(args: ExecuteArgs) -> Result<BuildResult> {
pub fn execute<T: ComposeBuildArgs>(args: ExecuteArgs) -> Result<BuildResult> {
let ExecuteArgs {
manifest_path,
verbosity,
Expand All @@ -592,7 +593,7 @@ pub fn execute(args: ExecuteArgs) -> Result<BuildResult> {

// if image exists, then --verifiable was called and we need to build inside docker.
if build_mode == &BuildMode::Verifiable {
return docker_build(args)
return docker_build::<T>(args)
}

let crate_metadata =
Expand Down
43 changes: 27 additions & 16 deletions crates/build/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::{
BuildArtifacts,
BuildMode,
BuildResult,
ComposeBuildArgs,
CrateMetadata,
ExecuteArgs,
InkMetadataArtifacts,
Expand Down Expand Up @@ -46,6 +47,13 @@ use std::{
time::SystemTime,
};

struct MockComposeBuildArgs;
impl ComposeBuildArgs for MockComposeBuildArgs {
fn compose_build_args() -> Result<Vec<String>> {
Ok(Vec::new())
}
}

// All functions provided here are run sequentially as part of the same `#[test]`
// sharing build artifacts (but nothing else) using the [`BuildTestContext`].
//
Expand Down Expand Up @@ -108,7 +116,7 @@ fn build_code_only(manifest_path: &ManifestPath) -> Result<()> {
..Default::default()
};

let res = super::execute(args).expect("build failed");
let res = super::execute::<MockComposeBuildArgs>(args).expect("build failed");

// our ci has set `CARGO_TARGET_DIR` to cache artifacts.
// this dir does not include `/target/` as a path, hence
Expand Down Expand Up @@ -161,7 +169,7 @@ fn check_must_not_output_contract_artifacts_in_project_dir(
};

// when
super::execute(args).expect("build failed");
super::execute::<MockComposeBuildArgs>(args).expect("build failed");

// then
let project_dir = project_path(
Expand Down Expand Up @@ -195,7 +203,7 @@ fn building_template_in_debug_mode_must_work(manifest_path: &ManifestPath) -> Re
};

// when
let res = super::execute(args);
let res = super::execute::<MockComposeBuildArgs>(args);

// then
assert!(res.is_ok(), "building template in debug mode failed!");
Expand All @@ -214,7 +222,7 @@ fn building_template_in_release_mode_must_work(
};

// when
let res = super::execute(args);
let res = super::execute::<MockComposeBuildArgs>(args);

// then
assert!(res.is_ok(), "building template in release mode failed!");
Expand Down Expand Up @@ -244,7 +252,7 @@ fn building_contract_with_source_file_in_subfolder_must_work(
};

// when
let res = super::execute(args);
let res = super::execute::<MockComposeBuildArgs>(args);

// then
assert!(res.is_ok(), "building contract failed!");
Expand Down Expand Up @@ -273,7 +281,7 @@ fn building_contract_with_build_rs_must_work(manifest_path: &ManifestPath) -> Re
};

// when
let res = super::execute(args);
let res = super::execute::<MockComposeBuildArgs>(args);

// then
assert!(res.is_ok(), "building contract failed!");
Expand All @@ -291,7 +299,7 @@ fn keep_debug_symbols_in_debug_mode(manifest_path: &ManifestPath) -> Result<()>
};

// todo
let _res = super::execute(args).expect("build failed");
let _res = super::execute::<MockComposeBuildArgs>(args).expect("build failed");

// we specified that debug symbols should be kept
// assert!(has_debug_symbols(res.dest_binary.unwrap()));
Expand All @@ -310,7 +318,7 @@ fn keep_debug_symbols_in_release_mode(manifest_path: &ManifestPath) -> Result<()
};

// todo
let _res = super::execute(args).expect("build failed");
let _res = super::execute::<MockComposeBuildArgs>(args).expect("build failed");

// we specified that debug symbols should be kept
// assert!(has_debug_symbols(res.dest_binary.unwrap()));
Expand All @@ -328,7 +336,7 @@ fn build_with_json_output_works(manifest_path: &ManifestPath) -> Result<()> {
};

// when
let res = super::execute(args).expect("build failed");
let res = super::execute::<MockComposeBuildArgs>(args).expect("build failed");

// then
assert!(res.serialize_json().is_ok());
Expand All @@ -355,7 +363,9 @@ fn missing_linting_toolchain_installation_must_be_detected(
extra_lints: true,
..Default::default()
};
let res = super::execute(args).map(|_| ()).unwrap_err();
let res = super::execute::<MockComposeBuildArgs>(args)
.map(|_| ())
.unwrap_err();

// then
assert!(format!("{res:?}").contains("` was not found!"));
Expand Down Expand Up @@ -418,7 +428,7 @@ fn generates_metadata(manifest_path: &ManifestPath) -> Result<()> {
};
args.manifest_path = manifest_path.clone();

let build_result = crate::execute(args)?;
let build_result = crate::execute::<MockComposeBuildArgs>(args)?;
let dest_bundle = &ink_metadata_artifacts(
build_result
.metadata_result
Expand Down Expand Up @@ -539,7 +549,7 @@ fn generates_solidity_metadata(manifest_path: &ManifestPath) -> Result<()> {
};
args.manifest_path = manifest_path.clone();

let build_result = crate::execute(args)?;
let build_result = crate::execute::<MockComposeBuildArgs>(args)?;
let metadata_result = solidity_metadata_artifacts(
build_result
.metadata_result
Expand Down Expand Up @@ -684,10 +694,11 @@ fn unchanged_contract_skips_optimization_and_metadata_steps(
}

// when
let res1 = super::execute(args.clone()).expect("build failed");
let res1 =
super::execute::<MockComposeBuildArgs>(args.clone()).expect("build failed");
let (opt_result_modified1, metadata_modified1, contract_bundle_modified1) =
get_last_modified(&res1);
let res2 = super::execute(args).expect("build failed");
let res2 = super::execute::<MockComposeBuildArgs>(args).expect("build failed");
let (opt_result_modified2, metadata_modified2, contract_bundle_modified2) =
get_last_modified(&res2);

Expand All @@ -711,7 +722,7 @@ fn unchanged_contract_skips_optimization_and_metadata_steps(
fn unchanged_contract_no_metadata_artifacts_generates_metadata(
manifest_path: &ManifestPath,
) -> Result<()> {
let res1 = super::execute(ExecuteArgs {
let res1 = super::execute::<MockComposeBuildArgs>(ExecuteArgs {
manifest_path: manifest_path.clone(),
build_artifact: BuildArtifacts::CodeOnly,
..Default::default()
Expand All @@ -724,7 +735,7 @@ fn unchanged_contract_no_metadata_artifacts_generates_metadata(

let dest_binary_modified_pre = file_last_modified(&res1.dest_binary.unwrap());

let res2 = super::execute(ExecuteArgs {
let res2 = super::execute::<MockComposeBuildArgs>(ExecuteArgs {
manifest_path: manifest_path.clone(),
build_artifact: BuildArtifacts::All,
..Default::default()
Expand Down
37 changes: 35 additions & 2 deletions crates/cargo-contract/src/cmd/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use contract_build::{
BuildArtifacts,
BuildMode,
BuildResult,
ComposeBuildArgs,
ExecuteArgs,
Features,
ImageVariant,
Expand All @@ -36,6 +37,38 @@ use std::{
path::PathBuf,
};

pub(crate) struct CargoContractComposeBuildArgs;
impl ComposeBuildArgs for CargoContractComposeBuildArgs {
fn compose_build_args() -> Result<Vec<String>> {
use regex::Regex;
let mut args: Vec<String> = Vec::new();
// match `--image` or `verify` with arg with 1 or more white spaces surrounded
let rex = Regex::new(r#"(--image|verify)[ ]*[^ ]*[ ]*"#)?;
// we join the args together, so we can remove `--image <arg>`
let args_string: String = std::env::args().collect::<Vec<String>>().join(" ");
let args_string = rex.replace_all(&args_string, "").to_string();

// and then we turn it back to the vec, filtering out commands and arguments
// that should not be passed to the docker build command
let mut os_args: Vec<String> = args_string
.split_ascii_whitespace()
.filter(|a| {
a != &"--verifiable"
&& !a.contains("cargo-contract")
&& a != &"cargo"
&& a != &"contract"
&& a != &"build"
&& a != &"--output-json"
})
.map(|s| s.to_string())
.collect();

args.append(&mut os_args);

Ok(args)
}
}

/// Executes build of the smart contract which produces a PolkaVM binary that is ready for
/// deploying.
///
Expand Down Expand Up @@ -146,7 +179,7 @@ impl BuildCommand {
metadata_spec: self.metadata,
target_dir: None,
};
contract_build::execute(args)
contract_build::execute::<CargoContractComposeBuildArgs>(args)
}
}

Expand Down Expand Up @@ -181,6 +214,6 @@ impl CheckCommand {
target_dir: None,
};

contract_build::execute(args)
contract_build::execute::<CargoContractComposeBuildArgs>(args)
}
}
5 changes: 3 additions & 2 deletions crates/cargo-contract/src/cmd/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with cargo-contract. If not, see <http://www.gnu.org/licenses/>.

use crate::cmd::build::CargoContractComposeBuildArgs;
use anyhow::{
Context,
Result,
Expand Down Expand Up @@ -109,7 +110,7 @@ impl VerifyCommand {
..Default::default()
};

let build_result = execute(args)?;
let build_result = execute::<CargoContractComposeBuildArgs>(args)?;

// 4. Grab the code hash from the built contract and compare it with the reference
// one.
Expand Down Expand Up @@ -245,7 +246,7 @@ impl VerifyCommand {
..Default::default()
};

let build_result = execute(args)?;
let build_result = execute::<CargoContractComposeBuildArgs>(args)?;

// 4. Grab the code hash from the built contract and compare it with the reference
// code hash.
Expand Down
Loading