diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 38108868..97a5225d 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -5,54 +5,54 @@ name: build on: pull_request: - branches: [ main, feat/* ] + branches: [main, feat/*] workflow_dispatch: jobs: build: name: Build and Test mxpy for ${{ matrix.os }}, python ${{ matrix.python-version }} - + runs-on: ${{ matrix.os }} strategy: matrix: os: [windows-2019] - python-version: [3.8] + python-version: [3.11] steps: - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - shell: bash - run: | - python3 -m pip install --upgrade pip - pip3 install -r requirements.txt - pip3 install pytest - - name: Set github_api_token - shell: bash - run: | - mkdir ~/multiversx-sdk - export PYTHONPATH=. - python3 -m multiversx_sdk_cli.cli config new test - python3 -m multiversx_sdk_cli.cli config set github_api_token ${{ secrets.GITHUB_TOKEN }} - - name: Setup test dependencies - shell: bash - run: | - python3 -m multiversx_sdk_cli.cli deps install testwallets - - name: Run unit tests - shell: bash - run: | - export PYTHONPATH=. - pytest -m "not skip_on_windows" . - - name: Run CLI tests - shell: bash - run: | - export PROXY=https://testnet-gateway.multiversx.com - export CHAIN_ID=T - cd ./multiversx_sdk_cli/tests - source ./test_cli_tx.sh && testAll || return 1 - source ./test_cli_dns.sh && testOffline || return 1 - source ./test_cli_validators.sh && testAll || return 1 + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + shell: bash + run: | + python3 -m pip install --upgrade pip + pip3 install -r requirements.txt + pip3 install pytest + - name: Set github_api_token + shell: bash + run: | + mkdir ~/multiversx-sdk + export PYTHONPATH=. + python3 -m multiversx_sdk_cli.cli config new test + python3 -m multiversx_sdk_cli.cli config set github_api_token ${{ secrets.GITHUB_TOKEN }} + - name: Setup test dependencies + shell: bash + run: | + python3 -m multiversx_sdk_cli.cli deps install testwallets + - name: Run unit tests + shell: bash + run: | + export PYTHONPATH=. + pytest -m "not skip_on_windows" . + - name: Run CLI tests + shell: bash + run: | + export PROXY=https://testnet-gateway.multiversx.com + export CHAIN_ID=T + cd ./multiversx_sdk_cli/tests + source ./test_cli_tx.sh && testAll || return 1 + source ./test_cli_dns.sh && testOffline || return 1 + source ./test_cli_validators.sh && testAll || return 1 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8dd1900f..d4825988 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,53 +5,52 @@ name: build on: pull_request: - branches: [ main, feat/* ] + branches: [main, feat/*] workflow_dispatch: jobs: build: name: Build and Test mxpy for ${{ matrix.os }}, python ${{ matrix.python-version }} - + runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, macos-latest] - python-version: [3.8, 3.11] + python-version: [3.11] steps: - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python3 -m pip install --upgrade pip - pip3 install -r requirements.txt - pip3 install pytest - - name: Install libtinfo5 - if: ${{ matrix.os != 'macos-latest' }} - run: | - sudo apt update - sudo apt install -y libtinfo5 - - name: Set github_api_token - run: | - mkdir ~/multiversx-sdk - export PYTHONPATH=. - python3 -m multiversx_sdk_cli.cli config new test - python3 -m multiversx_sdk_cli.cli config set github_api_token ${{ secrets.GITHUB_TOKEN }} - - name: Setup test dependencies - run: | - python3 -m multiversx_sdk_cli.cli deps install testwallets - python3 -m multiversx_sdk_cli.cli deps install wasm-opt - - name: Run unit tests - run: | - export PYTHONPATH=. - pytest . - - name: Run CLI tests - run: | - python3 -m multiversx_sdk_cli.cli config set dependencies.vmtools.tag v1.4.60 - cd ./multiversx_sdk_cli/tests - source ./test_cli_contracts.sh && testAll || return 1 - source ./test_cli_dns.sh && testOffline || return 1 + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python3 -m pip install --upgrade pip + pip3 install -r requirements.txt + pip3 install pytest + - name: Install libtinfo5 + if: ${{ matrix.os != 'macos-latest' }} + run: | + sudo apt update + sudo apt install -y libtinfo5 + - name: Set github_api_token + run: | + mkdir ~/multiversx-sdk + export PYTHONPATH=. + python3 -m multiversx_sdk_cli.cli config new test + python3 -m multiversx_sdk_cli.cli config set github_api_token ${{ secrets.GITHUB_TOKEN }} + - name: Setup test dependencies + run: | + python3 -m multiversx_sdk_cli.cli deps install testwallets + - name: Run unit tests + run: | + export PYTHONPATH=. + pytest . + - name: Run CLI tests + run: | + python3 -m multiversx_sdk_cli.cli config set dependencies.vmtools.tag v1.4.60 + cd ./multiversx_sdk_cli/tests + source ./test_cli_contracts.sh && testAll || return 1 + source ./test_cli_dns.sh && testOffline || return 1 diff --git a/.github/workflows/install-macos.yml b/.github/workflows/install-macos.yml index 39966e83..b815c17c 100644 --- a/.github/workflows/install-macos.yml +++ b/.github/workflows/install-macos.yml @@ -6,7 +6,7 @@ on: workflow_dispatch: env: - BRANCH_NAME: ${{ github.head_ref || github.ref_name }} + BRANCH_NAME: ${{ github.head_ref || github.ref_name }} jobs: install: @@ -14,7 +14,7 @@ jobs: strategy: matrix: - python-version: [3.8] + python-version: [3.11] steps: - name: Set up Python ${{ matrix.python-version }} diff --git a/.github/workflows/install-ubuntu.yml b/.github/workflows/install-ubuntu.yml index 1615a19d..734e3593 100644 --- a/.github/workflows/install-ubuntu.yml +++ b/.github/workflows/install-ubuntu.yml @@ -6,7 +6,7 @@ on: workflow_dispatch: env: - BRANCH_NAME: ${{ github.head_ref || github.ref_name }} + BRANCH_NAME: ${{ github.head_ref || github.ref_name }} jobs: install: @@ -14,7 +14,7 @@ jobs: strategy: matrix: - python-version: [3.8] + python-version: [3.11] steps: - name: Set up Python ${{ matrix.python-version }} diff --git a/.github/workflows/install-windows.yml b/.github/workflows/install-windows.yml index eef56de0..0e7d6dca 100644 --- a/.github/workflows/install-windows.yml +++ b/.github/workflows/install-windows.yml @@ -6,7 +6,7 @@ on: workflow_dispatch: env: - BRANCH_NAME: ${{ github.head_ref || github.ref_name }} + BRANCH_NAME: ${{ github.head_ref || github.ref_name }} jobs: install: @@ -14,7 +14,7 @@ jobs: strategy: matrix: - python-version: [3.8] + python-version: [3.11] steps: - name: Set up Python ${{ matrix.python-version }} diff --git a/multiversx_sdk_cli/cli_deps.py b/multiversx_sdk_cli/cli_deps.py index 701c3866..471e0610 100644 --- a/multiversx_sdk_cli/cli_deps.py +++ b/multiversx_sdk_cli/cli_deps.py @@ -16,7 +16,6 @@ def setup_parser(subparsers: Any) -> Any: sub = cli_shared.add_command_subparser(subparsers, "deps", "install", "Install dependencies or multiversx-sdk modules.") sub.add_argument("name", choices=choices, help="the dependency to install") sub.add_argument("--overwrite", action="store_true", default=False, help="whether to overwrite an existing installation") - sub.add_argument("--tag", help="the tag or version to install") sub.set_defaults(func=install) sub = cli_shared.add_command_subparser(subparsers, "deps", "check", "Check whether a dependency is installed.") @@ -30,9 +29,8 @@ def setup_parser(subparsers: Any) -> Any: def install(args: Any): name: str = args.name - tag: str = args.tag overwrite: bool = args.overwrite - dependencies.install_module(name, tag, overwrite) + dependencies.install_module(name, overwrite) def check(args: Any): @@ -42,6 +40,7 @@ def check(args: Any): default_tag: str = config.get_dependency_tag(module.key) tag_to_check = tag or default_tag resolution: str = config.get_dependency_resolution(module.key) + resolution = resolution if resolution else "HOST" logger.info(f"Checking dependency: module = {module.key}, tag = {tag_to_check}; default tag = {default_tag}, resolution = {resolution}") diff --git a/multiversx_sdk_cli/config.py b/multiversx_sdk_cli/config.py index 863e64f7..3cf89ba4 100644 --- a/multiversx_sdk_cli/config.py +++ b/multiversx_sdk_cli/config.py @@ -150,28 +150,19 @@ def get_defaults() -> Dict[str, Any]: "dependencies.vmtools.urlTemplate.linux": "https://github.com/multiversx/mx-chain-vm-go/archive/{TAG}.tar.gz", "dependencies.vmtools.urlTemplate.osx": "https://github.com/multiversx/mx-chain-vm-go/archive/{TAG}.tar.gz", "dependencies.vmtools.urlTemplate.windows": "https://github.com/multiversx/mx-chain-vm-go/archive/{TAG}.tar.gz", - "dependencies.llvm.tag": "v9-19feb", - # ide.elrond.com will be removed, TBD if clang will still be downloaded - "dependencies.llvm.urlTemplate.linux": "https://ide.elrond.com/vendor-llvm/{TAG}/linux-amd64.tar.gz?t=19feb", - "dependencies.llvm.urlTemplate.osx": "https://ide.elrond.com/vendor-llvm/{TAG}/darwin-amd64.tar.gz?t=19feb", - "dependencies.rust.resolution": "SDK", "dependencies.rust.tag": "nightly-2023-05-26", "dependencies.golang.resolution": "SDK", "dependencies.golang.tag": "go1.20.7", "dependencies.golang.urlTemplate.linux": "https://golang.org/dl/{TAG}.linux-amd64.tar.gz", "dependencies.golang.urlTemplate.osx": "https://golang.org/dl/{TAG}.darwin-amd64.tar.gz", "dependencies.golang.urlTemplate.windows": "https://golang.org/dl/{TAG}.windows-amd64.zip", - "dependencies.wasm-opt.tag": "latest", "dependencies.twiggy.tag": "latest", + "dependencies.sc-meta.tag": "latest", "dependencies.testwallets.tag": "latest", "dependencies.testwallets.urlTemplate.linux": "https://github.com/multiversx/mx-sdk-testwallets/archive/{TAG}.tar.gz", "dependencies.testwallets.urlTemplate.osx": "https://github.com/multiversx/mx-sdk-testwallets/archive/{TAG}.tar.gz", "dependencies.testwallets.urlTemplate.windows": "https://github.com/multiversx/mx-sdk-testwallets/archive/{TAG}.tar.gz", - "dependencies.wasm-opt.resolution": "SDK", - "dependencies.wasm-opt.tag": "version_112", - "dependencies.wasm-opt.urlTemplate.linux": "https://github.com/WebAssembly/binaryen/releases/download/{TAG}/binaryen-{TAG}-x86_64-linux.tar.gz", - "dependencies.wasm-opt.urlTemplate.osx": "https://github.com/WebAssembly/binaryen/releases/download/{TAG}/binaryen-{TAG}-x86_64-macos.tar.gz", - "dependencies.wasm-opt.urlTemplate.windows": "https://github.com/WebAssembly/binaryen/releases/download/{TAG}/binaryen-{TAG}-x86_64-windows.tar.gz", + "dependencies.wasm-opt.tag": "0.112.0", "github_api_token": "", } diff --git a/multiversx_sdk_cli/dependencies/install.py b/multiversx_sdk_cli/dependencies/install.py index 9d340de1..64945e4f 100644 --- a/multiversx_sdk_cli/dependencies/install.py +++ b/multiversx_sdk_cli/dependencies/install.py @@ -3,20 +3,22 @@ from typing import Dict, List from multiversx_sdk_cli import config, errors -from multiversx_sdk_cli.dependencies.modules import (CargoModule, TestWalletsModule, VMToolsModule, - DependencyModule, GolangModule, Rust, StandaloneModule, WasmOptModule) +from multiversx_sdk_cli.dependencies.modules import (DependencyModule, + GolangModule, Rust, + TestWalletsModule, + VMToolsModule) logger = logging.getLogger("install") -def install_module(key: str, tag: str = "", overwrite: bool = False): +def install_module(key: str, overwrite: bool = False): if key == 'all': - modules = _get_implicitly_installable_deps() + modules = _get_all_deps() else: modules = [get_module_by_key(key)] for module in modules: - module.install(tag, overwrite) + module.install(overwrite) def get_module_directory(key: str) -> Path: @@ -46,26 +48,10 @@ def get_deps_dict() -> Dict[str, DependencyModule]: def _get_all_deps() -> List[DependencyModule]: - return _get_explicitly_installable_deps() + _get_implicitly_installable_deps() - - -def _get_explicitly_installable_deps() -> List[DependencyModule]: return [ - StandaloneModule(key="llvm", aliases=["clang", "cpp"]), Rust(key="rust"), - GolangModule(key="golang") - ] - - -def _get_implicitly_installable_deps() -> List[DependencyModule]: - # See: https://github.com/multiversx/mx-sdk-py-cli/pull/55 - - return [ + GolangModule(key="golang"), VMToolsModule(key="vmtools"), - StandaloneModule(key="mx_chain_go", repo_name="mx-chain-go", organisation="multiversx"), - StandaloneModule(key="mx_chain_proxy_go", repo_name="mx-chain-proxy-go", organisation="multiversx"), - WasmOptModule(key="wasm-opt"), - CargoModule(key="twiggy"), TestWalletsModule(key="testwallets") ] diff --git a/multiversx_sdk_cli/dependencies/modules.py b/multiversx_sdk_cli/dependencies/modules.py index 2e367fc2..19224462 100644 --- a/multiversx_sdk_cli/dependencies/modules.py +++ b/multiversx_sdk_cli/dependencies/modules.py @@ -9,6 +9,7 @@ myprocess, utils, workstation) from multiversx_sdk_cli.dependencies.resolution import ( DependencyResolution, get_dependency_resolution) +from multiversx_sdk_cli.ux import show_warning logger = logging.getLogger("modules") @@ -21,9 +22,9 @@ def __init__(self, key: str, aliases: List[str] = []): def get_directory(self, tag: str) -> Path: raise NotImplementedError() - def install(self, tag: str, overwrite: bool) -> None: - # Fallback to default tag if not provided - tag = tag or config.get_dependency_tag(self.key) + def install(self, overwrite: bool) -> None: + # We install the default tag + tag = config.get_dependency_tag(self.key) if tag == 'latest': tag = self.get_latest_release() @@ -34,7 +35,6 @@ def install(self, tag: str, overwrite: bool) -> None: logger.info("Already exists. Skip install.") return - self._guard_cannot_install_on_host() self.uninstall(tag) self._do_install(tag) @@ -66,10 +66,6 @@ def get_latest_release(self) -> str: def get_resolution(self) -> DependencyResolution: return get_dependency_resolution(self.key) - def _guard_cannot_install_on_host(self): - if self.get_resolution() == DependencyResolution.Host: - raise errors.KnownError(f"Installation of {self.key} on the host machine is not supported. Perhaps set 'dependencies.{self.key}.resolution' to 'SDK' in config?") - class StandaloneModule(DependencyModule): def __init__(self, @@ -256,7 +252,39 @@ def get_latest_release(self) -> str: class Rust(DependencyModule): - def _do_install(self, tag: str) -> None: + def is_installed(self, tag: str) -> bool: + which_rustc = shutil.which("rustc") + which_cargo = shutil.which("cargo") + which_sc_meta = shutil.which("sc-meta") + which_wasm_opt = shutil.which("wasm-opt") + which_twiggy = shutil.which("twiggy") + logger.info(f"which rustc: {which_rustc}") + logger.info(f"which cargo: {which_cargo}") + logger.info(f"which sc-meta: {which_sc_meta}") + logger.info(f"which wasm-opt: {which_wasm_opt}") + logger.info(f"which twiggy: {which_twiggy}") + + dependencies = [which_rustc, which_cargo, which_sc_meta, which_wasm_opt, which_twiggy] + return all(dependency is not None for dependency in dependencies) + + def install(self, overwrite: bool) -> None: + module = dependencies.get_module_by_key("rust") + tag: str = config.get_dependency_tag(module.key) + + show_warning(f"We recommend using rust {tag}. If you'd like to overwrite your current version please run `mxpy deps install rust --overwrite`.") + logger.info(f"install: key={self.key}, tag={tag}, overwrite={overwrite}") + + if overwrite: + logger.info("Overwriting the current rust version...") + elif self.is_installed(""): + return + + self._install_rust(tag) + self._install_sc_meta() + self._install_wasm_opt() + self._install_twiggy() + + def _install_rust(self, tag: str) -> None: installer_url = self._get_installer_url() installer_path = self._get_installer_path() @@ -269,12 +297,36 @@ def _do_install(self, tag: str) -> None: toolchain = "nightly" args = [str(installer_path), "--verbose", "--default-toolchain", toolchain, "--profile", - "minimal", "--target", "wasm32-unknown-unknown", "--no-modify-path", "-y"] - output = myprocess.run_process(args, env=self.get_env_for_install()) + "minimal", "--target", "wasm32-unknown-unknown", "-y"] - if output: - sc_meta_args = ["cargo", "install", "multiversx-sc-meta"] - myprocess.run_process(sc_meta_args, env=self.get_env_for_install()) + logger.info("Installing rust.") + myprocess.run_process(args) + + def _install_sc_meta(self): + logger.info("Installing multiversx-sc-meta.") + tag = config.get_dependency_tag("sc-meta") + args = ["cargo", "install", "multiversx-sc-meta"] + + if tag != "latest": + args.extend(["--version", tag]) + + myprocess.run_process(args) + + def _install_wasm_opt(self): + logger.info("Installing wasm-opt. This may take a while.") + tag = config.get_dependency_tag("wasm-opt") + args = ["cargo", "install", "wasm-opt", "--version", tag] + myprocess.run_process(args) + + def _install_twiggy(self): + logger.info("Installing twiggy.") + tag = config.get_dependency_tag("twiggy") + args = ["cargo", "install", "twiggy"] + + if tag != "latest": + args.extend(["--version", tag]) + + myprocess.run_process(args) def _get_installer_url(self) -> str: if workstation.is_windows(): @@ -293,102 +345,17 @@ def uninstall(self, tag: str): if os.path.isdir(directory): shutil.rmtree(directory) - def is_installed(self, tag: str) -> bool: - resolution = self.get_resolution() - - if resolution == DependencyResolution.Host: - which_rustc = shutil.which("rustc") - which_cargo = shutil.which("cargo") - logger.info(f"which rustc: {which_rustc}") - logger.info(f"which cargo: {which_cargo}") - - return which_rustc is not None and which_cargo is not None - if resolution == DependencyResolution.SDK: - try: - env = self._get_env_for_is_installed_in_sdk() - myprocess.run_process(["rustc", "--version"], env=env) - return True - except Exception: - return False - - raise errors.BadDependencyResolution(self.key, resolution) - def get_directory(self, tag: str) -> Path: tools_folder = workstation.get_tools_folder() return tools_folder / "vendor-rust" - def get_env(self): - directory = self.get_directory("") - resolution = self.get_resolution() - - if resolution == DependencyResolution.Host: - return { - "PATH": os.environ.get("PATH", ""), - "RUSTUP_HOME": os.environ.get("RUSTUP_HOME", ""), - "CARGO_HOME": os.environ.get("CARGO_HOME", "") - } - if resolution == DependencyResolution.SDK: - return { - # At this moment, cc (build-essential) is sometimes required by the meta crate (e.g. for reports) - "PATH": f"{path.join(directory, 'bin')}:{os.environ['PATH']}", - "RUSTUP_HOME": str(directory), - "CARGO_HOME": str(directory) - } - - raise errors.BadDependencyResolution(self.key, resolution) - - def _get_env_for_is_installed_in_sdk(self) -> Dict[str, str]: - directory = self.get_directory("") - - return { - "PATH": str(directory / "bin"), - "RUSTUP_HOME": str(directory), - "CARGO_HOME": str(directory) - } - - def get_env_for_install(self): - directory = self.get_directory("") - - env = { - # For installation, wget (or curl) and cc (build-essential) are also required. - "PATH": f"{path.join(directory, 'bin')}:{os.environ['PATH']}", - "RUSTUP_HOME": str(directory), - "CARGO_HOME": str(directory) - } - - if workstation.is_windows(): - env["RUSTUP_USE_HYPER"] = "1" - - return env + def get_env(self) -> Dict[str, str]: + return dict(os.environ) def get_latest_release(self) -> str: raise errors.UnsupportedConfigurationValue("Rust tag must either be explicit, empty or 'nightly'") -class CargoModule(DependencyModule): - def _do_install(self, tag: str) -> None: - self._run_command_with_rust_env(["cargo", "install", self.key]) - - def is_installed(self, tag: str) -> bool: - rust = dependencies.get_module_by_key("rust") - output = myprocess.run_process(["cargo", "install", "--list"], rust.get_env()) - for line in output.splitlines(): - if self.key == line.strip(): - return True - return False - - def uninstall(self, tag: str): - if self.is_installed(tag): - self._run_command_with_rust_env(["cargo", "uninstall", self.key]) - - def get_latest_release(self) -> str: - return "latest" - - def _run_command_with_rust_env(self, args: List[str]) -> str: - rust = dependencies.get_module_by_key("rust") - return myprocess.run_process(args, rust.get_env()) - - class TestWalletsModule(StandaloneModule): def __init__(self, key: str): super().__init__(key, []) @@ -400,48 +367,3 @@ def _post_install(self, tag: str): target = self.get_source_directory(tag) link = path.join(self.get_parent_directory(), "latest") utils.symlink(str(target), link) - - -class WasmOptModule(StandaloneModule): - def __init__(self, key: str): - super().__init__(key, []) - self.organisation = "WebAssembly" - self.repo_name = "binaryen" - - def _post_install(self, tag: str): - # Bit of cleanup, we don't need the rest of the binaries. - bin_to_remove = list(self._get_bin_directory(tag).glob("*")) - bin_to_remove = [file for file in bin_to_remove if file.name != "wasm-opt"] - lib_to_remove = list((self.get_source_directory(tag) / "lib").glob("*")) - lib_to_remove = [file for file in lib_to_remove if file.suffix != ".dylib"] - - for file in bin_to_remove + lib_to_remove: - file.unlink() - - def _get_bin_directory(self, tag: str) -> Path: - return self.get_source_directory(tag) / "bin" - - def is_installed(self, tag: str) -> bool: - resolution = self.get_resolution() - tag = tag or config.get_dependency_tag(self.key) - bin_file = self._get_bin_directory(tag) / "wasm-opt" - - if resolution == DependencyResolution.Host: - which_wasm_opt = shutil.which("wasm-opt") - logger.info(f"which wasm-opt: {which_wasm_opt}") - - return shutil.which("wasm-opt") is not None - if resolution == DependencyResolution.SDK: - return bin_file.exists() - raise errors.BadDependencyResolution(self.key, resolution) - - def get_env(self): - tag = config.get_dependency_tag(self.key) - bin_directory = self._get_bin_directory(tag) - - return { - "PATH": f"{bin_directory}:{os.environ['PATH']}", - } - - def get_latest_release(self) -> str: - raise errors.UnsupportedConfigurationValue("wasm-opt tag must either be explicit") diff --git a/multiversx_sdk_cli/localnet/step_prerequisites.py b/multiversx_sdk_cli/localnet/step_prerequisites.py index c372e3ee..bff27822 100644 --- a/multiversx_sdk_cli/localnet/step_prerequisites.py +++ b/multiversx_sdk_cli/localnet/step_prerequisites.py @@ -16,7 +16,7 @@ def fetch_prerequisites(configfile: Path): config = ConfigRoot.from_file(configfile) - dependencies.install_module("testwallets", tag="", overwrite=True) + dependencies.install_module("testwallets", overwrite=True) if config.software.mx_chain_go.resolution == SoftwareResolution.Remote: download_software_component(config.software.mx_chain_go) diff --git a/multiversx_sdk_cli/projects/project_base.py b/multiversx_sdk_cli/projects/project_base.py index aadd5ebc..74777af1 100644 --- a/multiversx_sdk_cli/projects/project_base.py +++ b/multiversx_sdk_cli/projects/project_base.py @@ -38,6 +38,8 @@ def clean(self): def _ensure_dependencies_installed(self): module_keys = self.get_dependencies() for module_key in module_keys: + if module_key == "": + continue dependencies.install_module(module_key) def get_dependencies(self) -> List[str]: diff --git a/multiversx_sdk_cli/projects/project_clang.py b/multiversx_sdk_cli/projects/project_clang.py index 3985955c..1b800b7c 100644 --- a/multiversx_sdk_cli/projects/project_clang.py +++ b/multiversx_sdk_cli/projects/project_clang.py @@ -6,6 +6,8 @@ from multiversx_sdk_cli import dependencies, errors, myprocess, utils from multiversx_sdk_cli.projects.project_base import Project, rename_wasm_files +from multiversx_sdk_cli.projects.shared import \ + check_clang_and_cpp_dependencies_installed logger = logging.getLogger('ProjectClang') @@ -26,6 +28,8 @@ def perform_build(self): self.file_output = self.unit.with_suffix('.wasm') try: + check_clang_and_cpp_dependencies_installed() + self.do_clang() self.do_llvm_link() self.do_llc() @@ -151,4 +155,4 @@ def get_source_files_from_folder(self): return list(map(str, self.path.rglob('*.c'))) def get_dependencies(self): - return ['llvm'] + return [""] diff --git a/multiversx_sdk_cli/projects/project_cpp.py b/multiversx_sdk_cli/projects/project_cpp.py index 12b62dc5..eb2dafef 100644 --- a/multiversx_sdk_cli/projects/project_cpp.py +++ b/multiversx_sdk_cli/projects/project_cpp.py @@ -1,12 +1,14 @@ import logging import os -from pathlib import Path import subprocess from os import path +from pathlib import Path from typing import List from multiversx_sdk_cli import dependencies, errors, myprocess, utils from multiversx_sdk_cli.projects.project_base import Project, rename_wasm_files +from multiversx_sdk_cli.projects.shared import \ + check_clang_and_cpp_dependencies_installed logger = logging.getLogger("ProjectCpp") @@ -23,6 +25,8 @@ def perform_build(self): self.file_export = self.unit.with_suffix(".export") try: + check_clang_and_cpp_dependencies_installed() + self._do_clang() self._do_llc() self._do_wasm() @@ -87,7 +91,7 @@ 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")) - + paths = rename_wasm_files([output_wasm_file], self.options.get("wasm-name")) return paths @@ -95,7 +99,7 @@ def _get_llvm_path(self): return dependencies.get_module_directory("llvm") def get_dependencies(self): - return ["llvm"] + return [""] class CppBuildConfiguration: diff --git a/multiversx_sdk_cli/projects/project_rust.py b/multiversx_sdk_cli/projects/project_rust.py index 498dae16..cc837eb1 100644 --- a/multiversx_sdk_cli/projects/project_rust.py +++ b/multiversx_sdk_cli/projects/project_rust.py @@ -5,6 +5,7 @@ from multiversx_sdk_cli import dependencies, errors, utils, workstation from multiversx_sdk_cli.constants import DEFAULT_CARGO_TARGET_DIR_NAME +from multiversx_sdk_cli.dependencies.modules import Rust from multiversx_sdk_cli.projects.project_base import Project logger = logging.getLogger("ProjectRust") @@ -56,12 +57,6 @@ def prepare_build_wasm_args(self, args: List[str]): def run_meta(self): env = self.get_env() - with_wasm_opt = not self.options.get("no-wasm-opt") - if with_wasm_opt: - check_wasm_opt_installed() - wasm_opt = dependencies.get_module_by_key("wasm-opt") - env = merge_env(env, wasm_opt.get_env()) - args = [ "sc-meta", "all", @@ -123,6 +118,9 @@ def get_env(self): return dependencies.get_module_by_key("rust").get_env() def build_wasm_with_debug_symbols(self, build_options: Dict[str, Any]): + rust_module = Rust("rust") + rust_module.install(overwrite=False) + cwd = self.path env = self.get_env() target_dir: str = build_options.get("target-dir", "") @@ -253,18 +251,3 @@ def merge_env(first: Dict[str, str], second: Dict[str, str]) -> Dict[str, str]: values = paths_of(first, key).union(paths_of(second, key)) merged[key] = ":".join(sorted(values)) return merged - - -def check_wasm_opt_installed() -> None: - wasm_opt = dependencies.get_module_by_key("wasm-opt") - if not wasm_opt.is_installed(""): - logger.warn(""" - Skipping optimization because wasm-opt is not installed. - - To install it run: - mxpy deps install wasm-opt - - Alternatively, pass the "--no-wasm-opt" argument in order to skip the optimization step. - """) - else: - logger.info("wasm-opt is installed.") diff --git a/multiversx_sdk_cli/projects/shared.py b/multiversx_sdk_cli/projects/shared.py index ef7f375d..83e52585 100644 --- a/multiversx_sdk_cli/projects/shared.py +++ b/multiversx_sdk_cli/projects/shared.py @@ -1,5 +1,12 @@ +import logging +import shutil from pathlib import Path +from multiversx_sdk_cli.errors import KnownError +from multiversx_sdk_cli.ux import show_critical_error + +logger = logging.getLogger("projects.shared") + def is_source_clang(directory: Path) -> bool: return _directory_contains_file(directory, ".c") @@ -22,3 +29,27 @@ def _directory_contains_file(directory: Path, name_suffix: str) -> bool: if str(file).lower().endswith(name_suffix.lower()): return True return False + + +def check_clang_and_cpp_dependencies_installed() -> None: + which_clang = shutil.which("clang") + which_llc = shutil.which("llc") + which_wasm_ld = shutil.which("wasm-ld") + which_llvm_link = shutil.which("llvm-link") + + logger.info(f"which_clang: {which_clang}") + logger.info(f"which_llc: {which_llc}") + logger.info(f"which_wasm_ld: {which_wasm_ld}") + logger.info(f"which_llvm_link: {which_llvm_link}") + + dependencies = [which_clang, which_llc, which_wasm_ld, which_llvm_link] + is_installed = all(dependency is not None for dependency in dependencies) + + if is_installed is False: + message = """ +`clang` is not installed. Please install it manually, then try again. +Check out the cookbook: https://docs.multiversx.com/sdk-and-tools/sdk-py/mxpy-cli +For more details check out this page: https://clang.llvm.org/get_started.html""" + + show_critical_error(message) + raise KnownError("The required dependencies are not installed. Please check the above message.") diff --git a/multiversx_sdk_cli/tests/shared.sh b/multiversx_sdk_cli/tests/shared.sh index 57f3dda8..8ca40072 100755 --- a/multiversx_sdk_cli/tests/shared.sh +++ b/multiversx_sdk_cli/tests/shared.sh @@ -16,7 +16,7 @@ PROXY="${PROXY:-http://localhost:7950}" CHAIN_ID="${CHAIN_ID:-localnet}" TestUser=./testdata/testUser.pem TestUser2=./testdata/testUser2.pem -RUST_VERSION="nightly-2023-04-24" +RUST_VERSION="nightly-2023-05-26" cleanSandbox() { rm -rf ${SANDBOX} diff --git a/multiversx_sdk_cli/tests/test_cli_contracts.py b/multiversx_sdk_cli/tests/test_cli_contracts.py index 774bab25..46f5cddd 100644 --- a/multiversx_sdk_cli/tests/test_cli_contracts.py +++ b/multiversx_sdk_cli/tests/test_cli_contracts.py @@ -38,7 +38,7 @@ def test_contract_new_with_bad_code(): def replace_variable_with_unknown_variable(): - # this is done in order to replace the value added in the adder contract witha unknown variable + # this is done in order to replace the value added in the adder contract with a unknown variable with open(parent / "testdata-out" / "SANDBOX" / "adder-bad-src" / "src" / "adder.rs", "r") as f: contract_lines = f.readlines() @@ -60,7 +60,7 @@ def test_contract_build(): f"{parent}/testdata-out/SANDBOX/adder" ]) - assert Path.is_file(Path(Path(parent) / "testdata-out" / "SANDBOX" / "adder" / "output" / "adder.wasm")) + assert Path.is_file(parent / "testdata-out" / "SANDBOX" / "adder" / "output" / "adder.wasm") @pytest.mark.skip_on_windows diff --git a/multiversx_sdk_cli/tests/test_cli_deps.py b/multiversx_sdk_cli/tests/test_cli_deps.py new file mode 100644 index 00000000..3859505b --- /dev/null +++ b/multiversx_sdk_cli/tests/test_cli_deps.py @@ -0,0 +1,43 @@ +import shutil +from pathlib import Path + +import pytest + +from multiversx_sdk_cli.cli import main + + +def test_deps_install_rust(): + return_code = main(["deps", "install", "rust", "--overwrite"]) + assert return_code == 0 + + +def test_deps_check_rust(): + return_code = main(["deps", "check", "rust"]) + assert True if return_code == 0 else False + + which_rustc = shutil.which("rustc") + assert which_rustc and Path.is_file(Path(which_rustc)) + + which_cargo = shutil.which("cargo") + assert which_cargo and Path.is_file(Path(which_cargo)) + + which_sc_meta = shutil.which("sc-meta") + assert which_sc_meta and Path.is_file(Path(which_sc_meta)) + + which_wasm_opt = shutil.which("wasm-opt") + assert which_wasm_opt and Path.is_file(Path(which_wasm_opt)) + + which_twiggy = shutil.which("twiggy") + assert which_twiggy and Path.is_file(Path(which_twiggy)) + + +@pytest.mark.skip_on_windows +def test_deps_install_vmtools(): + return_code = main(["deps", "install", "vmtools"]) + assert return_code == 0 + + +@pytest.mark.skip_on_windows +def test_deps_check_vmtools(): + return_code = main(["deps", "check", "vmtools"]) + assert return_code == 0 diff --git a/multiversx_sdk_cli/tests/test_cli_deps.sh b/multiversx_sdk_cli/tests/test_cli_deps.sh deleted file mode 100644 index e191201b..00000000 --- a/multiversx_sdk_cli/tests/test_cli_deps.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -source "./shared.sh" - -testAll() { - set -x - - ${CLI} --verbose deps install rust --tag=${RUST_VERSION} - ${CLI} --verbose deps install vmtools --overwrite - - ${CLI} --verbose deps check rust - ${CLI} --verbose deps check vmtools - - set +x -} diff --git a/pyproject.toml b/pyproject.toml index b4476a0e..61b18480 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "multiversx-sdk-cli" -version = "8.1.2" +version = "8.2.0" authors = [ { name="MultiversX" }, ] diff --git a/pytest.ini b/pytest.ini index 81836503..6669f27f 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,3 +1,6 @@ [pytest] markers = skip_on_windows: marks tests as being skiped when running on windows (deselect with '-m "skip_on_windows"') + only: only run a specific test (run using: pytest -m "only") + +log_cli = True