diff --git a/scripts/platformio/install-deps.py b/scripts/platformio/install-deps.py index dbbb83ae9f04..27e0d3313640 100644 --- a/scripts/platformio/install-deps.py +++ b/scripts/platformio/install-deps.py @@ -183,7 +183,22 @@ def load_west_manifest(manifest_path): sys.exit(1) -def process_bundled_projects(platform_name, packages_folder, west_manifest): +def load_state_json(state_path): + with open(state_path, encoding="utf8") as fp: + return json.load(fp) + + +def clear_deprecated_package(path, packages_folder): + deprecated_pkg_path = os.path.join(packages_folder, path) + if os.path.isdir(deprecated_pkg_path): + clean_up(deprecated_pkg_path) + else: + print("Package path not found") + + +def process_bundled_projects( + platform_name, packages_folder, west_manifest, state_manifest=None +): assert ( "projects" in west_manifest ), "Missing the `projects` field in the package manifest!" @@ -192,6 +207,28 @@ def process_bundled_projects(platform_name, packages_folder, west_manifest): if not os.path.isdir(packages_folder): os.makedirs(packages_folder) + # If there is a state.json manifest, compare it with west.yml + if state_manifest: + # Convert west.yml data into a dictionary for easier comparison + west_dep = {proj["name"]: proj for proj in west_manifest["projects"]} + modified_projects = [ + { + "name": name, + "state_hash": state_hash, + "west_revision": west_dep[name].get("revision"), + "path": west_dep[name].get("path"), + } + for name, state_hash in state_manifest.items() + if name in west_dep and state_hash != west_dep[name].get("revision") + ] + + for project in modified_projects: + print( + f"The version of the `{project['name']}` package changed, " + f"upgrading to `{project['west_revision']}`." + ) + clear_deprecated_package(project["path"], packages_folder) + default_remote = west_manifest.get("defaults", {}).get("remote", "") remotes = {remote["name"]: remote for remote in west_manifest["remotes"]} @@ -233,7 +270,7 @@ def save_state(dst_file, state_data): json.dump(state_data, fp, indent=2) -def main(platform_name, secondary_installation): +def main(platform_name, secondary_installation, manifest_path): framework_dir = os.path.realpath( os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..") ) @@ -252,10 +289,17 @@ def main(platform_name, secondary_installation): ) sys.exit(1) - west_manifest = load_west_manifest(os.path.join(framework_dir, "west.yml")) + if not manifest_path: + manifest_path = os.path.join(framework_dir, "west.yml") + + west_manifest = load_west_manifest(os.path.realpath(manifest_path)) + if os.path.isfile(state_file): + state_manifest = load_state_json(state_file) + else: + state_manifest = None result, state = process_bundled_projects( - platform_name, packages_folder, west_manifest + platform_name, packages_folder, west_manifest, state_manifest ) if result and state: save_state(state_file, state) @@ -279,9 +323,14 @@ def main(platform_name, secondary_installation): action="store_true", help="Ignore the state file while checking Zephyr project dependencies", ) + parser.add_argument( + "--manifest", + type=str, + help="Path to the west.yml manifest file", + ) cargs = parser.parse_args() try: - main(cargs.platform, cargs.secondary_installation) + main(cargs.platform, cargs.secondary_installation, cargs.manifest) except Exception as e: sys.stderr.write( "Error: Unknown exception occured. Failed to install bundled projects!\n" diff --git a/scripts/platformio/platformio-build.py b/scripts/platformio/platformio-build.py index 58cdeff4caab..3d37aba877b2 100644 --- a/scripts/platformio/platformio-build.py +++ b/scripts/platformio/platformio-build.py @@ -1301,14 +1301,24 @@ def _collect_lib_deps(config, libs=None): return _collect_lib_deps(main_config) -def load_west_manifest(manifest_path): - if not os.path.isfile(manifest_path): - sys.stderr.write("Error: Couldn't find `%s`\n" % manifest_path) +def load_west_manifest(): + + project_manifest_path = os.path.join(PROJECT_DIR, "west.yml") + framework_manifest_path = os.path.join(FRAMEWORK_DIR, "west.yml") + + if os.path.isfile(project_manifest_path): + print("Info: Using a project-based dependency manifest file.") + manifest_path = project_manifest_path + elif os.path.isfile(framework_manifest_path): + manifest_path = framework_manifest_path + else: + sys.stderr.write( + "Error: Couldn't find `%s`\n" % framework_manifest_path) env.Exit(1) with open(manifest_path) as fp: try: - return yaml.safe_load(fp).get("manifest", {}) + return yaml.safe_load(fp).get("manifest", {}), manifest_path except yaml.YAMLError as e: sys.stderr.write("Warning! Failed to parse `%s`.\n" % manifest_path) sys.stderr.write(str(e) + "\n") @@ -1663,13 +1673,15 @@ def get_python_exe(): return python_exe_path -def install_bundled_projects(): +def install_bundled_projects(manifest_path): cmd = ( get_python_exe(), os.path.join(FRAMEWORK_DIR, "scripts", "platformio", "install-deps.py"), "--platform", platform.name, "--secondary-installation", + "--manifest", + manifest_path, ) rc = subprocess.call(cmd) @@ -1797,13 +1809,13 @@ def GenerateMCUbootBinaryCmd(env, target, source): # Install Zephyr dependencies # -install_bundled_projects() +west_manifest, manifest_path = load_west_manifest() +install_bundled_projects(manifest_path) # # Initial targets loading # -west_manifest = load_west_manifest(os.path.join(FRAMEWORK_DIR, "west.yml")) codemodel = get_cmake_code_model(west_manifest) if not codemodel: sys.stderr.write("Error: Couldn't find code model generated by CMake\n")