Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate contracts_build.rs instead of multiple *_build.rs files #53

Merged
merged 5 commits into from
Jun 12, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description = "A cargo utility that helps to create, manage and test your smart
keywords = ["wasm", "webassembly", "blockchain"]
categories = ["wasm", "smart contracts"]
name = "cargo-odra"
version = "0.0.7"
version = "0.0.8"
edition = "2021"

[dependencies]
Expand Down
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ prepare:

test-project-generation:
rm -rf testproject
cargo odra new --name testproject --source release/0.3.0
cargo odra new --name testproject --source release/0.4.0
cd testproject && cargo odra generate -c plascoin
cd testproject && cargo odra test
cd testproject && cargo odra test -b casper
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nightly-2023-03-01
nightly-2023-03-01
86 changes: 61 additions & 25 deletions src/actions/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::{
/// BuildAction configuration.
pub struct BuildAction<'a> {
backend: String,
contract_name: Option<String>,
contracts_names: Option<String>,
builder_paths: BuilderPaths,
project: &'a Project,
template_generator: TemplateGenerator,
Expand All @@ -28,10 +28,10 @@ pub struct BuildAction<'a> {
/// BuildAction implementation.
impl<'a> BuildAction<'a> {
/// Crate a new BuildAction for a given backend.
pub fn new(project: &'a Project, backend: String, contract_name: Option<String>) -> Self {
pub fn new(project: &'a Project, backend: String, contracts_names: Option<String>) -> Self {
BuildAction {
backend: backend.clone(),
contract_name,
contracts_names,
builder_paths: BuilderPaths::new(backend, project.project_root.clone()),
project,
template_generator: TemplateGenerator::new(
Expand Down Expand Up @@ -65,23 +65,23 @@ impl BuildAction<'_> {
self.validate_contract_name_argument();
self.prepare_builder();
self.build_wasm_sources();
self.build_wasm_files();
self.format_builder_files();
self.build_wasm_files();
self.copy_wasm_files();
self.optimize_wasm_files();
}

/// Returns list of contract to process.
fn contracts(&self) -> Vec<Contract> {
let names = self.parse_contracts_names();
let odra_toml = self.project.odra_toml();
if let Some(contract_name) = &self.contract_name {
odra_toml
match names.is_empty() {
true => odra_toml.contracts,
false => odra_toml
.contracts
.into_iter()
.filter(|c| c.name == *contract_name)
.collect()
} else {
odra_toml.contracts.into_iter().collect()
.filter(|c| names.contains(&c.name))
.collect(),
}
}

Expand All @@ -96,7 +96,8 @@ impl BuildAction<'_> {

/// Check if contract name argument is valid if set.
fn validate_contract_name_argument(&self) {
if let Some(contract_name) = &self.contract_name {
let names = self.parse_contracts_names();
names.iter().for_each(|contract_name| {
if !self
.project
.odra_toml()
Expand All @@ -106,7 +107,7 @@ impl BuildAction<'_> {
{
Error::ContractNotFound(contract_name.clone()).print_and_die();
}
}
});
}

/// Prepare builder directories and all files.
Expand All @@ -127,22 +128,31 @@ impl BuildAction<'_> {
);

// Build files.
self.create_build_files();
self.create_build_file()
.unwrap_or_else(|err| err.print_and_die());
}

/// Prepare _build.rs files.
fn create_build_files(&self) {
for contract in self.contracts() {
let path = self.builder_paths.wasm_build(&contract.name);
if !path.exists() {
let content = self.template_generator.wasm_source_builder(
&contract.fqn,
&contract.name,
&self.backend_name(),
);
command::write_to_file(path, &content);
}
/// Prepare contracts_build.rs files.
fn create_build_file(&self) -> Result<(), Error> {
let path = self.builder_paths.wasm_build();
if path.exists() {
return Ok(());
}

let contracts_names: Vec<_> = self
.project
.odra_toml()
.contracts
.iter()
.map(|contract| (contract.fqn.to_owned(), contract.name.to_owned()))
.collect();

let content = self
.template_generator
.wasm_source_builder(contracts_names, &self.backend_name())?;

command::write_to_file(path, &content);
Ok(())
}

/// Prepare _wasm.rs file.
Expand Down Expand Up @@ -229,4 +239,30 @@ impl BuildAction<'_> {
..Default::default()
})
}

fn parse_contracts_names(&self) -> Vec<String> {
match &self.contracts_names {
Some(string) => remove_extra_spaces(string)
.map(|string| {
string
.split(' ')
.map(ToString::to_string)
.collect::<Vec<_>>()
})
.unwrap_or_else(|_| {
Error::FailedToParseArgument("contracts_names".to_string()).print_and_die()
}),
None => vec![],
}
}
}

fn remove_extra_spaces(input: &str) -> Result<String, &'static str> {
// Ensure there are no other separators
if input.chars().any(|c| c.is_whitespace() && c != ' ') {
return Err("Input contains non-space whitespace characters");
}

let trimmed = input.split_whitespace().collect::<Vec<&str>>().join(" ");
Ok(trimmed)
}
8 changes: 6 additions & 2 deletions src/actions/generate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ impl GenerateAction<'_> {
/// Crates a new module file in src directory.
fn add_contract_file_to_src(&self) {
// Rename module name.
let contract_body = self.template_generator.module_template(self.module_ident());
let contract_body = self
.template_generator
.module_template(self.module_ident())
.unwrap_or_else(|err| err.print_and_die());

// Make sure the file do not exists.
let path = self.module_file_path();
Expand All @@ -90,7 +93,8 @@ impl GenerateAction<'_> {
// Prepare code to add.
let register_module_code = self
.template_generator
.register_module_snippet(self.contract_name(), self.module_ident());
.register_module_snippet(self.contract_name(), self.module_ident())
.unwrap_or_else(|err| err.print_and_die());

// Write to file.
command::append_file(self.module_root.join("src/lib.rs"), &register_module_code);
Expand Down
18 changes: 8 additions & 10 deletions src/cargo_toml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,15 @@ pub fn builder_cargo_toml(
};

let mut bins = vec![];
for contract in contracts {
let build_name = format!("{}_build", contract.name.clone());
let path = builder_paths
.relative()
.wasm_build_as_string(&contract.name);
bins.push(Product {
path: Some(path),
name: Some(build_name),
..default_bin.clone()
});
let build_name = "contracts_build".to_string();
let path = builder_paths.relative().wasm_build_as_string();

bins.push(Product {
path: Some(path),
name: Some(build_name),
..default_bin.clone()
});
for contract in contracts {
let path = builder_paths
.relative()
.wasm_source_as_string(&contract.name);
Expand Down
6 changes: 3 additions & 3 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ pub struct BuildCommand {
#[clap(value_parser, long, short, value_parser = [consts::ODRA_CASPER_BACKEND])]
pub backend: String,

/// Contract name that matches the name in Odra.toml.
/// Contracts names separated by a space that matches the names in Odra.toml.
#[clap(value_parser, long, short)]
pub contract_name: Option<String>,
pub contracts_names: Option<String>,
}

#[derive(clap::Args, Debug)]
Expand Down Expand Up @@ -129,7 +129,7 @@ pub fn make_action() {
.unwrap_or_else(|_| Error::CouldNotDetermineCurrentDirectory.print_and_die());
match args.subcommand {
OdraSubcommand::Build(build) => {
Project::detect(current_dir).build(build.backend, build.contract_name);
Project::detect(current_dir).build(build.backend, build.contracts_names);
}
OdraSubcommand::Test(test) => {
Project::detect(current_dir).test(test);
Expand Down
4 changes: 3 additions & 1 deletion src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ pub fn cargo_build_wasm_sources(current_dir: PathBuf, contract_name: &str) {
"run",
vec![
"--bin",
format!("{contract_name}_build").as_str(),
"contracts_build",
"--",
contract_name,
"--release",
"--no-default-features",
"--target-dir",
Expand Down
8 changes: 7 additions & 1 deletion src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ pub const ODRA_TEMPLATE_DEFAULT_TEMPLATE: &str = "full";
pub const ODRA_WASM_PATH_ENV_KEY: &str = "ODRA_WASM_PATH";

/// WASM Source builder template.
pub const WASM_SOURCE_BUILDER: &str = "wasm_source_builder";
pub const WASM_SINGLE_SOURCE_BUILDER: &str = "contracts_builder/wasm_source_builder";

/// WASM Source builder helper template.
pub const MATCH_CONTRACT_NAME: &str = "contracts_builder/match_contract_name";

/// WASM Source builder helper template.
pub const GEN_CONTRACT_MOD: &str = "contracts_builder/gen_contract_mod";

/// Module template.
pub const MODULE_TEMPLATE: &str = "module";
Expand Down
4 changes: 4 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ pub enum Error {

#[error("Failed to generate project from template: {0}")]
FailedToGenerateProjectFromTemplate(String),

#[error("Failed to parse the argument: {0}")]
FailedToParseArgument(String),
}

impl Error {
Expand All @@ -88,6 +91,7 @@ impl Error {
Error::ContractNotFound(_) => 17,
Error::OdraNotADependency => 18,
Error::FailedToGenerateProjectFromTemplate(_) => 19,
Error::FailedToParseArgument(_) => 20,
}
}

Expand Down
14 changes: 5 additions & 9 deletions src/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,13 @@ impl BuilderPaths {
self.root().join("src")
}

/// Returns *_build.rs path.
pub fn wasm_build(&self, contract_name: &str) -> PathBuf {
self.src().join(format!("{contract_name}_build.rs"))
pub fn wasm_build(&self) -> PathBuf {
self.src().join("contracts_build.rs")
}

/// Returns *_build.rs path as a String.
pub fn wasm_build_as_string(&self, contract_name: &str) -> String {
self.wasm_build(contract_name)
.into_os_string()
.into_string()
.unwrap()
/// Returns contracts_build.rs path as a String.
pub fn wasm_build_as_string(&self) -> String {
self.wasm_build().into_os_string().into_string().unwrap()
}

/// Returns *_wasm.rs path.
Expand Down
4 changes: 2 additions & 2 deletions src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ impl Project {
}

/// Builds the project
pub fn build(&self, backend: String, contract_name: Option<String>) {
BuildAction::new(self, backend, contract_name).build();
pub fn build(&self, backend: String, contracts_names: Option<String>) {
BuildAction::new(self, backend, contracts_names).build();
}

/// Runs test in the Project.
Expand Down
Loading