diff --git a/.github/workflows/fast-checks.yml b/.github/workflows/fast-checks.yml index 183b7879..e7096ff3 100644 --- a/.github/workflows/fast-checks.yml +++ b/.github/workflows/fast-checks.yml @@ -63,4 +63,4 @@ jobs: with: builtin: clear,rare check_filenames: true - ignore_words_list: assertIn, \ No newline at end of file + ignore_words_list: assertIn,crate, \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index fd26e6b1..c678014f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.23.0] - 2024-07-25 + +### Changed + +- Rust app: get target directory from cargo metadata (workspace compatible) + ## [1.22.1] - 2024-07-23 ### Fixed diff --git a/src/ragger/utils/misc.py b/src/ragger/utils/misc.py index c6172a63..e12943a4 100644 --- a/src/ragger/utils/misc.py +++ b/src/ragger/utils/misc.py @@ -17,6 +17,8 @@ from typing import Optional, Tuple, List from pathlib import Path from ragger.error import ExceptionRAPDU +import subprocess +import json ERROR_BOLOS_DEVICE_LOCKED = 0x5515 ERROR_DENIED_BY_USER = 0x5501 @@ -69,10 +71,23 @@ def find_application(base_dir: Path, device: str, sdk: str) -> Path: raise AssertionError(f"{base_dir} is not a directory") app = base_dir.resolve() if sdk.lower() == "rust": + """ + When building a Rust app, the resulting binary is located in a target + directory target//release/. app is the Path to the + build directory, where is stored the app's Cargo.toml file. + If the app repository is organized as a workspace crate (several packages, + each package in its own directory with its own Cargo.toml), the binaries are + all stored in the same target directory. 'cargo metadata' is used to get the + target directory full path. + """ if device == "nanos2": device = "nanosplus" app_name = toml.load(base_dir / "Cargo.toml")["package"]["name"] - app = app / "target" / device / "release" / app_name + cmd = ["cargo", "metadata", "--no-deps"] + output = subprocess.check_output(cmd, cwd=base_dir) + metadata = json.loads(output) + target = Path(metadata["target_directory"]) + app = target / device / "release" / app_name else: app = app / "build" / device / "bin" / "app.elf" if not app.is_file(): diff --git a/tests/unit/utils/test_misc.py b/tests/unit/utils/test_misc.py index cef8b60f..a04d1b64 100644 --- a/tests/unit/utils/test_misc.py +++ b/tests/unit/utils/test_misc.py @@ -1,4 +1,5 @@ import os +import subprocess from pathlib import Path from unittest import TestCase from unittest.mock import MagicMock, patch @@ -40,13 +41,14 @@ def test_find_application_ok_c(self): def test_find_application_ok_rust(self): device, sdk, appname = "device", "rust", "rustapp" with temporary_directory() as dir_path: - tmp_dir = (dir_path / "target" / device / "release") + cmd = ["cargo", "new", appname] + subprocess.check_output(cmd, cwd=dir_path) + app_path = dir_path / appname + tmp_dir = (app_path / "target" / device / "release") tmp_dir.mkdir(parents=True, exist_ok=True) expected = tmp_dir / appname expected.touch() - with patch("ragger.utils.misc.toml") as toml_patch: - toml_patch.load.return_value = {"package": {"name": appname}} - result = misc.find_application(dir_path, device, sdk) + result = misc.find_application(app_path, device, sdk) self.assertEqual(result, expected) def test_find_application_nok_not_dir(self):