From ae6dabc635a7cc86f133afa34748ca596ab2998e Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Wed, 18 May 2022 14:25:39 +0300 Subject: [PATCH 1/7] Fix contract build for Rust contracts. Remove deprecated build flow. --- erdpy/cli_contracts.py | 3 ++ erdpy/myprocess.py | 2 + erdpy/projects/project_rust.py | 81 ++++++++++------------------------ 3 files changed, 29 insertions(+), 57 deletions(-) diff --git a/erdpy/cli_contracts.py b/erdpy/cli_contracts.py index 52f1e0bc..2c7639d0 100644 --- a/erdpy/cli_contracts.py +++ b/erdpy/cli_contracts.py @@ -46,6 +46,8 @@ def setup_parser(args: List[str], subparsers: Any) -> Any: help="for rust projects, does not strip the symbols from the wasm output. Useful for analysing the bytecode. Creates larger wasm files. Avoid in production (default: %(default)s)") sub.add_argument("--wasm-name", type=str, help="for rust projects, optionally specify the name of the wasm bytecode output file") + sub.add_argument("--wasm-suffix", type=str, + help="for rust projects, optionally specify the suffix of the wasm bytecode output file") sub.add_argument("--skip-eei-checks", action="store_true", default=False, help="skip EEI compatibility checks (default: %(default)s)") sub.add_argument("--ignore-eei-checks", action="store_true", default=False, help="ignore EEI compatibility errors (default: %(default)s)") sub.set_defaults(func=build) @@ -214,6 +216,7 @@ def build(args: Any): "cargo_target_dir": args.cargo_target_dir, "wasm_symbols": args.wasm_symbols, "wasm_name": args.wasm_name, + "wasm_suffix": args.wasm_suffix, "skip-eei-checks": args.skip_eei_checks, "ignore-eei-checks": args.ignore_eei_checks } diff --git a/erdpy/myprocess.py b/erdpy/myprocess.py index 48ed6132..50672556 100644 --- a/erdpy/myprocess.py +++ b/erdpy/myprocess.py @@ -32,6 +32,8 @@ def run_process_async( stdout_sink=None, stderr_sink=None ) -> ReturnCode: + logger.info(f"run_process_async: {args}, in folder: {cwd}") + loop = asyncio.get_event_loop() result = loop.run_until_complete(_async_subprocess(args, env, stdout_sink, stderr_sink, cwd)) loop.close() diff --git a/erdpy/projects/project_rust.py b/erdpy/projects/project_rust.py index 7a5955c6..2feaac27 100644 --- a/erdpy/projects/project_rust.py +++ b/erdpy/projects/project_rust.py @@ -32,16 +32,14 @@ def get_wasm_view_folder(self): def perform_build(self): meta = self.has_meta() + if not meta: + raise errors.NotSupportedProject("The project does not have a meta crate") + try: - if meta: - # The meta crate handles the build process, ABI generation and - # allows contract developers to add extra - # preparation steps before building. - self.run_meta() - else: - # For backwards compatibility - build the wasm and generate the ABI - self.run_cargo() - self.generate_abi() + # The meta crate handles the build process, ABI generation and + # allows contract developers to add extra + # preparation steps before building. + self.run_meta() except subprocess.CalledProcessError as err: raise errors.BuildError(err.output) @@ -50,29 +48,9 @@ def prepare_build_wasm_args(self, args: List[str]): "--target=wasm32-unknown-unknown", "--release", "--out-dir", - self.get_output_folder(), - "-Z" - "unstable-options" + self.get_output_folder() ]) - def run_cargo(self): - env = self.get_env() - - args = [ - "cargo", - "build", - ] - self.prepare_build_wasm_args(args) - self.decorate_cargo_args(args) - - if not self.options.get("wasm_symbols"): - env["RUSTFLAGS"] = "-C link-arg=-s" - - cwd = self.path / 'wasm' - return_code = myprocess.run_process_async(args, env=env, cwd=str(cwd)) - if return_code != 0: - raise errors.BuildError(f"error code = {return_code}, see output") - def run_meta(self): cwd = self.get_meta_folder() env = self.get_env() @@ -89,42 +67,31 @@ def run_meta(self): "run", "build", ] - self.prepare_build_wasm_args(args) - for (option, value) in self.options.items(): - if isinstance(value, bool): - if value: - args.extend([f"--{option}"]) - else: - args.extend([f"--{option}", str(value)]) + self.prepare_build_wasm_args(args) + self.decorate_cargo_args(args) return_code = myprocess.run_process_async(args, env=env, cwd=str(cwd)) if return_code != 0: raise errors.BuildError(f"error code = {return_code}, see output") - def decorate_cargo_args(self, args): + def decorate_cargo_args(self, args: List[str]): target_dir = self.options.get("cargo_target_dir") + no_wasm_opt = self.options.get("no_wasm_opt") + wasm_symbols = self.options.get("wasm_symbols") + wasm_name = self.options.get("wasm_name") + wasm_suffix = self.options.get("wasm_suffix") + if target_dir: args.extend(["--target-dir", target_dir]) - - def generate_abi(self): - if not self.has_abi(): - return - - args = [ - "cargo", - "run" - ] - self.decorate_cargo_args(args) - - env = self.get_env() - cwd = path.join(self.directory, "abi") - sink = myprocess.FileOutputSink(self.get_abi_filepath()) - return_code = myprocess.run_process_async(args, env=env, cwd=cwd, stdout_sink=sink) - if return_code != 0: - raise errors.BuildError(f"error code = {return_code}, see output") - - utils.prettify_json_file(self.get_abi_filepath()) + if no_wasm_opt: + args.extend(["--no-wasm-opt"]) + if wasm_symbols: + args.extend(["--wasm-symbols"]) + if wasm_name: + args.extend(["--wasm-name", wasm_name]) + if wasm_suffix: + args.extend(["--wasm-suffix", wasm_suffix]) def has_meta(self): return (self.get_meta_folder() / "Cargo.toml").exists() From 7ecc42f5d69e71a2363921f695de4dc9f94ce72b Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Wed, 18 May 2022 14:26:05 +0300 Subject: [PATCH 2/7] Bump version. --- erdpy/_version.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/erdpy/_version.py b/erdpy/_version.py index 3e8d9f94..5b601886 100644 --- a/erdpy/_version.py +++ b/erdpy/_version.py @@ -1 +1 @@ -__version__ = "1.4.0" +__version__ = "1.5.0" diff --git a/setup.py b/setup.py index f1fb0d06..f1b02291 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ with open("README.md", "r") as fh: long_description = "https://github.com/ElrondNetwork/elrond-sdk-erdpy" -VERSION = "1.4.0" +VERSION = "1.5.0" try: with open('./erdpy/_version.py', 'wt') as versionfile: From 81abaeb076197bcf007c155c299a8c6da56eba01 Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Wed, 18 May 2022 14:29:15 +0300 Subject: [PATCH 3/7] Update changelog. --- erdpy/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erdpy/CHANGELOG.md b/erdpy/CHANGELOG.md index c6a04b18..3d1e79be 100644 --- a/erdpy/CHANGELOG.md +++ b/erdpy/CHANGELOG.md @@ -7,6 +7,9 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how ## [Unreleased] - TBD +## [1.5.0] + - [Improve "contract build" for Rust projects](https://github.com/ElrondNetwork/elrond-sdk-erdpy/pull/140) + ## [1.4.0] - [Add `ledgercomm[hid]`](https://github.com/ElrondNetwork/elrond-sdk-erdpy/pull/139) From 47ce26916eb8e1ed495a554ba3da8ae22e88bd00 Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Wed, 18 May 2022 14:33:46 +0300 Subject: [PATCH 4/7] Update CLI.md. --- erdpy/CLI.md | 1 + 1 file changed, 1 insertion(+) diff --git a/erdpy/CLI.md b/erdpy/CLI.md index 981d7a3c..9c47ea2f 100644 --- a/erdpy/CLI.md +++ b/erdpy/CLI.md @@ -131,6 +131,7 @@ optional arguments: analysing the bytecode. Creates larger wasm files. Avoid in production (default: False) --wasm-name WASM_NAME for rust projects, optionally specify the name of the wasm bytecode output file + --wasm-suffix WASM_SUFFIX for rust projects, optionally specify the suffix of the wasm bytecode output file --skip-eei-checks skip EEI compatibility checks (default: False) --ignore-eei-checks ignore EEI compatibility errors (default: False) From 55db2102b832edbc0a901b59998f150151a41ce2 Mon Sep 17 00:00:00 2001 From: Andrei Bancioiu Date: Wed, 18 May 2022 15:16:17 +0300 Subject: [PATCH 5/7] Undo commit. --- erdpy/projects/project_base.py | 32 ------------------------------- erdpy/tests/test_cli_contracts.sh | 2 +- 2 files changed, 1 insertion(+), 33 deletions(-) diff --git a/erdpy/projects/project_base.py b/erdpy/projects/project_base.py index 17638998..dc9f2fd1 100644 --- a/erdpy/projects/project_base.py +++ b/erdpy/projects/project_base.py @@ -26,7 +26,6 @@ def build(self, options: Union[Dict[str, Any], None] = None) -> List[Path]: self._ensure_dependencies_installed() self.perform_build() contract_paths = self._do_after_build_custom() - contract_paths = rename_wasm_files(contract_paths, self.options.get("wasm_name")) self._do_after_build_core() return contract_paths @@ -155,39 +154,8 @@ def glob_files(folder: Path, pattern: str) -> List[Path]: def exclude_files(files: List[Path], to_exclude: List[Path]) -> List[Path]: return list(set(files).difference(to_exclude)) -def rename_wasm_files(paths: List[Path], name: Union[str, None]) -> List[Path]: - if name is None: - return paths - new_paths = [adjust_wasm_filename(path, name) for path in paths] - for old_path, new_path in zip(paths, new_paths): - old_path.rename(new_path) - return new_paths - -def get_contract_suffix(name: str) -> str: - for suffix in ["-view.wasm", ".wasm"]: - if name.endswith(suffix): - return suffix - return "" def remove_suffix(name: str, suffix: str) -> str: if not name.endswith(suffix) or len(suffix) == 0: return name return name[:-len(suffix)] - -def adjust_wasm_filename(path: Path, name_hint: str) -> Path: - """ - Adjusts the wasm's filename by using a name hint - - >>> adjust_wasm_filename(Path("test/my-contract.wasm"), "hello.wasm") - PosixPath('test/hello.wasm') - >>> adjust_wasm_filename(Path("test/my-contract-view.wasm"), "hello.wasm") - PosixPath('test/hello-view.wasm') - >>> adjust_wasm_filename(Path("test/my-contract-view.wasm"), "hello") - PosixPath('test/hello-view.wasm') - >>> adjust_wasm_filename(Path("test/my-contract.wasm"), "world-view.wasm") - PosixPath('test/world-view.wasm') - >>> adjust_wasm_filename(Path("test/my-contract-view.wasm"), "world-view.wasm") - PosixPath('test/world-view-view.wasm') - """ - new_name = remove_suffix(name_hint, ".wasm") + get_contract_suffix(path.name) - return path.with_name(new_name) diff --git a/erdpy/tests/test_cli_contracts.sh b/erdpy/tests/test_cli_contracts.sh index 987c82c8..bf879728 100755 --- a/erdpy/tests/test_cli_contracts.sh +++ b/erdpy/tests/test_cli_contracts.sh @@ -74,7 +74,7 @@ testWasmName() { ${ERDPY} contract clean ${SANDBOX}/myadder-rs assertFileDoesNotExist ${SANDBOX}/myadder-rs/output/myadder-2-rs.wasm || return 1 - ${ERDPY} contract build ${SANDBOX}/myadder-rs --cargo-target-dir=${TARGET_DIR} --wasm-name myadder-2-rs || return 1 + ${ERDPY} contract build ${SANDBOX}/myadder-rs --cargo-target-dir=${TARGET_DIR} --wasm-name myadder-2-rs.wasm || return 1 assertFileExists ${SANDBOX}/myadder-rs/output/myadder-2-rs.wasm || return 1 assertFileExists ${SANDBOX}/myadder-rs/output/myadder-rs.abi.json || return 1 } From 0a7d35b3b5fa520150af901fbe6903d6983eadc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 18 May 2022 16:50:34 +0300 Subject: [PATCH 6/7] Undo commit. --- erdpy/projects/project_base.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/erdpy/projects/project_base.py b/erdpy/projects/project_base.py index dc9f2fd1..17638998 100644 --- a/erdpy/projects/project_base.py +++ b/erdpy/projects/project_base.py @@ -26,6 +26,7 @@ def build(self, options: Union[Dict[str, Any], None] = None) -> List[Path]: self._ensure_dependencies_installed() self.perform_build() contract_paths = self._do_after_build_custom() + contract_paths = rename_wasm_files(contract_paths, self.options.get("wasm_name")) self._do_after_build_core() return contract_paths @@ -154,8 +155,39 @@ def glob_files(folder: Path, pattern: str) -> List[Path]: def exclude_files(files: List[Path], to_exclude: List[Path]) -> List[Path]: return list(set(files).difference(to_exclude)) +def rename_wasm_files(paths: List[Path], name: Union[str, None]) -> List[Path]: + if name is None: + return paths + new_paths = [adjust_wasm_filename(path, name) for path in paths] + for old_path, new_path in zip(paths, new_paths): + old_path.rename(new_path) + return new_paths + +def get_contract_suffix(name: str) -> str: + for suffix in ["-view.wasm", ".wasm"]: + if name.endswith(suffix): + return suffix + return "" def remove_suffix(name: str, suffix: str) -> str: if not name.endswith(suffix) or len(suffix) == 0: return name return name[:-len(suffix)] + +def adjust_wasm_filename(path: Path, name_hint: str) -> Path: + """ + Adjusts the wasm's filename by using a name hint + + >>> adjust_wasm_filename(Path("test/my-contract.wasm"), "hello.wasm") + PosixPath('test/hello.wasm') + >>> adjust_wasm_filename(Path("test/my-contract-view.wasm"), "hello.wasm") + PosixPath('test/hello-view.wasm') + >>> adjust_wasm_filename(Path("test/my-contract-view.wasm"), "hello") + PosixPath('test/hello-view.wasm') + >>> adjust_wasm_filename(Path("test/my-contract.wasm"), "world-view.wasm") + PosixPath('test/world-view.wasm') + >>> adjust_wasm_filename(Path("test/my-contract-view.wasm"), "world-view.wasm") + PosixPath('test/world-view-view.wasm') + """ + new_name = remove_suffix(name_hint, ".wasm") + get_contract_suffix(path.name) + return path.with_name(new_name) From 4dcd4d78938f2398367e38f85c7d1d8bd3440d27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Wed, 18 May 2022 16:58:04 +0300 Subject: [PATCH 7/7] Do not rename paths in rust projects anymore, after build (already done by the meta crate). --- erdpy/projects/project_base.py | 1 - erdpy/projects/project_clang.py | 6 ++++-- erdpy/projects/project_cpp.py | 6 ++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/erdpy/projects/project_base.py b/erdpy/projects/project_base.py index 17638998..c1d23488 100644 --- a/erdpy/projects/project_base.py +++ b/erdpy/projects/project_base.py @@ -26,7 +26,6 @@ def build(self, options: Union[Dict[str, Any], None] = None) -> List[Path]: self._ensure_dependencies_installed() self.perform_build() contract_paths = self._do_after_build_custom() - contract_paths = rename_wasm_files(contract_paths, self.options.get("wasm_name")) self._do_after_build_core() return contract_paths diff --git a/erdpy/projects/project_clang.py b/erdpy/projects/project_clang.py index 60603002..af89c6ab 100644 --- a/erdpy/projects/project_clang.py +++ b/erdpy/projects/project_clang.py @@ -6,7 +6,7 @@ from typing import List from erdpy import dependencies, errors, myprocess, utils -from erdpy.projects.project_base import Project +from erdpy.projects.project_base import Project, rename_wasm_files logger = logging.getLogger('ProjectClang') @@ -109,7 +109,9 @@ def _do_after_build_custom(self) -> List[Path]: ll_file.unlink() except FileNotFoundError: pass - return [output_wasm_file] + + paths = rename_wasm_files([output_wasm_file], self.options.get("wasm_name")) + return paths def _get_llvm_path(self): return dependencies.get_module_directory('llvm') diff --git a/erdpy/projects/project_cpp.py b/erdpy/projects/project_cpp.py index db78bbb1..60ff98c7 100644 --- a/erdpy/projects/project_cpp.py +++ b/erdpy/projects/project_cpp.py @@ -6,7 +6,7 @@ from typing import List from erdpy import dependencies, errors, myprocess, utils -from erdpy.projects.project_base import Project +from erdpy.projects.project_base import Project, rename_wasm_files logger = logging.getLogger("ProjectCpp") @@ -87,7 +87,9 @@ def _do_after_build_custom(self) -> List[Path]: os.remove(source_file.with_suffix(".wasm")) os.remove(source_file.with_suffix(".ll")) os.remove(source_file.with_suffix(".o")) - return [output_wasm_file] + + paths = rename_wasm_files([output_wasm_file], self.options.get("wasm_name")) + return paths def _get_llvm_path(self): return dependencies.get_module_directory("llvm")