From 35b29a197fa7c9d7e606faa69ee645961bab0ac1 Mon Sep 17 00:00:00 2001 From: valeros Date: Fri, 10 May 2024 13:50:54 +0300 Subject: [PATCH] Refactor processing of IDF linker fragments The helper function extracts fragments directly from Ninja build script --- builder/frameworks/espidf.py | 57 +++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 2d222e164..1fe5873a3 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -26,6 +26,7 @@ import sys import shutil import os +import re import platform as sys_platform import click @@ -494,7 +495,7 @@ def _scan_components_from_framework(): return components or _scan_components_from_framework() -def extract_linker_script_fragments(framework_components_dir, sdk_config): +def extract_linker_script_fragments_backup(framework_components_dir, sdk_config): # Hardware-specific components are excluded from search and added manually below project_components = load_component_paths( framework_components_dir, ignored_component_prefixes=("esp32", "riscv") @@ -542,6 +543,52 @@ def extract_linker_script_fragments(framework_components_dir, sdk_config): return result +def extract_linker_script_fragments( + ninja_buildfile, framework_components_dir, sdk_config +): + def _normalize_fragment_path(base_dir, fragment_path): + if not os.path.isabs(fragment_path): + fragment_path = os.path.abspath( + os.path.join(base_dir, fragment_path) + ) + if not os.path.isfile(fragment_path): + print("Warning! The `%s` fragment is not found!" % fragment_path) + + return fragment_path + + assert os.path.isfile( + ninja_buildfile + ), "Cannot extract linker fragments! Ninja build file is missing!" + + result = [] + with open(ninja_buildfile, encoding="utf8") as fp: + for line in fp.readlines(): + if "sections.ld: CUSTOM_COMMAND" not in line: + continue + for fragment_match in re.finditer(r"(\S+\.lf\b)+", line): + result.append(_normalize_fragment_path( + BUILD_DIR, fragment_match.group(0).replace("$:", ":") + )) + + break + + # Fall back option if the new algorithm didn't work + if not result: + result = extract_linker_script_fragments_backup( + framework_components_dir, sdk_config + ) + + if board.get("build.esp-idf.extra_lf_files", ""): + for fragment_path in board.get( + "build.esp-idf.extra_lf_files" + ).splitlines(): + if not fragment_path.strip(): + continue + result.append(_normalize_fragment_path(PROJECT_DIR, fragment_path)) + + return result + + def create_custom_libraries_list(ldgen_libraries_file, ignore_targets): if not os.path.isfile(ldgen_libraries_file): sys.stderr.write("Error: Couldn't find the list of framework libraries\n") @@ -570,11 +617,13 @@ def create_custom_libraries_list(ldgen_libraries_file, ignore_targets): def generate_project_ld_script(sdk_config, ignore_targets=None): ignore_targets = ignore_targets or [] linker_script_fragments = extract_linker_script_fragments( - os.path.join(FRAMEWORK_DIR, "components"), sdk_config + os.path.join(BUILD_DIR, "build.ninja"), + os.path.join(FRAMEWORK_DIR, "components"), + sdk_config ) - # Create a new file to avoid automatically generated library entry as files from - # this library are built internally by PlatformIO + # Create a new file to avoid automatically generated library entry as files + # from this library are built internally by PlatformIO libraries_list = create_custom_libraries_list( os.path.join(BUILD_DIR, "ldgen_libraries"), ignore_targets )