From 844b75687f82ab8a68e5a9cf4148e95543788a4c Mon Sep 17 00:00:00 2001 From: Valerii Koval Date: Thu, 16 Apr 2020 21:57:06 +0300 Subject: [PATCH] Improve processing of default flags for ESP-IDF build environment Add a dummy component with different file extensions so CMake will generate comprehensive code model --- builder/frameworks/espidf.py | 94 +++++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 27 deletions(-) diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 07cfe97..b8352d5 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -338,35 +338,36 @@ def filter_args(args, allowed, ignore=None): return result -def get_app_flags(app_config): - app_flags = {} - for cg in app_config["compileGroups"]: - app_flags[cg["language"]] = [] +def get_app_flags(app_config, default_config): + def _extract_flags(config): + flags = {} + for cg in config["compileGroups"]: + flags[cg["language"]] = [] for ccfragment in cg["compileCommandFragments"]: fragment = ccfragment.get("fragment", "") if not fragment.strip() or fragment.startswith("-D"): continue - app_flags[cg["language"]].extend( + flags[cg["language"]].extend( click.parser.split_arg_string(fragment.strip()) ) - cflags = app_flags.get("C", []) - cxx_flags = app_flags.get("CXX", []) - ccflags = set(cflags).intersection(cxx_flags) + return flags + + app_flags = _extract_flags(app_config) + default_flags = _extract_flags(default_config) # Flags are sorted because CMake randomly populates build flags in code model return { - "ASFLAGS": sorted(app_flags.get("ASM", [])), - "CFLAGS": sorted(list(set(cflags) - ccflags)), - "CCFLAGS": sorted(list(ccflags)), - "CXXFLAGS": sorted(list(set(cxx_flags) - ccflags)), + "ASFLAGS": sorted(app_flags.get("ASM", default_flags.get("ASM"))), + "CFLAGS": sorted(app_flags.get("C", default_flags.get("C"))), + "CXXFLAGS": sorted(app_flags.get("CXX", default_flags.get("CXX"))), } def get_sdk_configuration(): config_path = join(env.subst("$BUILD_DIR"), "config", "sdkconfig.json") if not isfile(config_path): - print("Warning: Could not find \"sdkconfig.json\" file\n") + print('Warning: Could not find "sdkconfig.json" file\n') try: with open(config_path, "r") as fp: @@ -401,36 +402,41 @@ def find_framework_service_files(search_path, sdk_config): return result -def create_custom_libraries_list(orignial_ldgen_libraries_file, project_target_name): - if not isfile(orignial_ldgen_libraries_file): +def create_custom_libraries_list(ldgen_libraries_file, ignore_targets): + if not isfile(ldgen_libraries_file): sys.stderr.write("Error: Couldn't find the list of framework libraries\n") env.Exit(1) - pio_libraries_file = orignial_ldgen_libraries_file + "_pio" + pio_libraries_file = ldgen_libraries_file + "_pio" if isfile(pio_libraries_file): return pio_libraries_file lib_paths = [] - with open(orignial_ldgen_libraries_file, "r") as fp: + with open(ldgen_libraries_file, "r") as fp: lib_paths = fp.readlines() with open(pio_libraries_file, "w") as fp: for lib_path in lib_paths: - if "lib%s.a" % project_target_name.replace("__idf_", "") not in lib_path: + if all( + "lib%s.a" % t.replace("__idf_", "") not in lib_path + for t in ignore_targets + ): fp.write(lib_path) return pio_libraries_file -def generate_project_ld_script(project_target_name, sdk_config): +def generate_project_ld_script(sdk_config, ignore_targets=None): + ignore_targets = ignore_targets or [] project_files = find_framework_service_files( - join(FRAMEWORK_DIR, "components"), sdk_config) + 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 libraries_list = create_custom_libraries_list( - join(env.subst("$BUILD_DIR"), "ldgen_libraries"), project_target_name + join(env.subst("$BUILD_DIR"), "ldgen_libraries"), ignore_targets ) args = { @@ -698,6 +704,37 @@ def get_project_elf(target_configs): return exec_targets[0] +def generate_default_component(): + # Used to force CMake generate build environments for all supported languages + + prj_cmake_tpl = """# Warning! Do not delete this auto-generated file. +file(GLOB component_sources *.c* *.S) +idf_component_register(SRCS ${component_sources}) +""" + dummy_component_path = join(BUILD_DIR, "__pio_env") + if not isdir(dummy_component_path): + makedirs(dummy_component_path) + + for ext in (".cpp", ".c", ".S"): + dummy_file = join(dummy_component_path, "__dummy" + ext) + if not isfile(dummy_file): + open(dummy_file, "a").close() + + component_cmake = join(dummy_component_path, "CMakeLists.txt") + if not isfile(component_cmake): + with open(component_cmake, "w") as fp: + fp.write(prj_cmake_tpl) + + return dummy_component_path + + +def find_default_component(target_configs): + for config in target_configs: + if "__pio_env" in config: + return config + return "" + + # # Generate final linker script # @@ -778,10 +815,9 @@ if isfile(join(env.subst("$PROJECT_SRC_DIR"), "sdkconfig.h")): # By default 'main' folder is used to store source files. In case when a user has # default 'src' folder we need to add this as an extra component. If there is no 'main' # folder CMake won't generate dependencies properly - -extra_components = [] +extra_components = [generate_default_component()] if env.subst("$PROJECT_SRC_DIR") != join(env.subst("$PROJECT_DIR"), "main"): - extra_components = [env.subst("$PROJECT_SRC_DIR")] + extra_components.append(env.subst("$PROJECT_SRC_DIR")) if "arduino" in env.subst("$PIOFRAMEWORK"): extra_components.append(ARDUINO_FRAMEWORK_DIR) @@ -819,12 +855,15 @@ if project_target_name not in target_configs: sys.stderr.write("Error: Couldn't find the main target of the project!\n") env.Exit(1) -project_ld_scipt = generate_project_ld_script(project_target_name, sdk_config) +project_ld_scipt = generate_project_ld_script(sdk_config, ["__idf_src", "__pio_env"]) env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", project_ld_scipt) elf_config = get_project_elf(target_configs) +default_config_name = find_default_component(target_configs) framework_components_map = get_components_map( - target_configs, ["STATIC_LIBRARY", "OBJECT_LIBRARY"], [project_target_name] + target_configs, + ["STATIC_LIBRARY", "OBJECT_LIBRARY"], + [project_target_name, default_config_name], ) build_components(env, framework_components_map, env.subst("$PROJECT_DIR")) @@ -838,8 +877,9 @@ for component_config in framework_components_map.values(): project_config = target_configs.get(project_target_name, {}) project_includes = get_app_includes(project_config) +default_config = target_configs.get(default_config_name, {}) project_defines = get_app_defines(project_config) -project_flags = get_app_flags(project_config) +project_flags = get_app_flags(project_config, default_config) link_args = extract_link_args(elf_config) app_includes = get_app_includes(elf_config)