Skip to content

Commit

Permalink
Project based west.yml support for platformio.
Browse files Browse the repository at this point in the history
Adding version management based on state.json.

Signed-off-by: Jean Alinei <[email protected]>
  • Loading branch information
jalinei committed Dec 10, 2024
1 parent c2a98a8 commit ac0af13
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 18 deletions.
55 changes: 50 additions & 5 deletions scripts/platformio/install-deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,19 @@ def load_west_manifest(manifest_path):
sys.stderr.write(str(exc) + "\n")
sys.exit(1)

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):
shutil.rmtree(deprecated_pkg_path)
else:
print("Package path not found")

def process_bundled_projects(platform_name, packages_folder, west_manifest):
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!"
Expand All @@ -192,6 +203,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['manifest']['projects']}
modified = []

# Check for modified entries
for name, state_hash in state_manifest.items():
if name in west_dep:
west_revision = west_dep[name].get('revision')
if state_hash != west_revision:
modified.append({
'name': name,
'state_hash': state_hash,
'west_revision': west_revision,
'path': west_dep[name].get('path')
})
# If deprecated dependency found, clear its folder to download correct version
if modified:
for deprecated_entries in modified:
clear_deprecated_package(deprecated_entries['path'], package_path)

default_remote = west_manifest.get("defaults", {}).get("remote", "")
remotes = {remote["name"]: remote for remote in west_manifest["remotes"]}

Expand Down Expand Up @@ -233,7 +266,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__)), "..", "..")
)
Expand All @@ -252,10 +285,14 @@ def main(platform_name, secondary_installation):
)
sys.exit(1)

west_manifest = load_west_manifest(os.path.join(framework_dir, "west.yml"))
west_manifest = load_west_manifest(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)
Expand All @@ -279,9 +316,17 @@ 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,
default=os.path.join(
os.path.dirname(os.path.abspath(__file__)), "..", "..", "west.yml"
),
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"
Expand Down
33 changes: 20 additions & 13 deletions scripts/platformio/platformio-build.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
manifest_path = project_manifest_path
elif os.path.isfile(framework_manifest_path):
print("Info: No project based dependency manifest found \n \
Default west.yml will be used..")
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")
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -1794,16 +1806,11 @@ def GenerateMCUbootBinaryCmd(env, target, source):
install_python_deps()

#
# Install Zephyr dependencies
#

install_bundled_projects()

#
# Initial targets loading
# Initial targets loading and install Zephyr dependencies
#

west_manifest = load_west_manifest(os.path.join(FRAMEWORK_DIR, "west.yml"))
west_manifest, manifest_path = load_west_manifest()
install_bundled_projects(manifest_path)
codemodel = get_cmake_code_model(west_manifest)
if not codemodel:
sys.stderr.write("Error: Couldn't find code model generated by CMake\n")
Expand Down

0 comments on commit ac0af13

Please sign in to comment.