diff --git a/platformio/builder/tools/piobuild.py b/platformio/builder/tools/piobuild.py index 8ef2522cf7..c3867e5908 100644 --- a/platformio/builder/tools/piobuild.py +++ b/platformio/builder/tools/piobuild.py @@ -240,17 +240,51 @@ def ProcessFlags(env, flags): # pylint: disable=too-many-branches # Cancel any previous definition of name, either built in or # provided with a -U option // Issue #191 - undefines = [ - u - for u in env.get("CCFLAGS", []) - if isinstance(u, string_types) and u.startswith("-U") - ] + ccflags = env.get("CCFLAGS", []) + undefines = [] + + # Handle both "-UMACRO" and "-U MACRO" formats + i = 0 + while i < len(ccflags): + item = ccflags[i] + if isinstance(item, string_types) and item.startswith("-U"): + if len(item) == 2: # Just "-U" by itself + # Next item should be the macro name + if i + 1 < len(ccflags): + macro_name = ccflags[i + 1] + undefines.append(("-U", macro_name)) + i += 2 # Skip both "-U" and the macro name + continue + else: # "-UMACRONAME" format + macro_name = item[2:] + undefines.append(item) + i += 1 + continue + i += 1 + if undefines: for undef in undefines: - env["CCFLAGS"].remove(undef) - if undef[2:] in env["CPPDEFINES"]: - env["CPPDEFINES"].remove(undef[2:]) - env.Append(_CPPDEFFLAGS=" %s" % " ".join(undefines)) + # Handle both formats + if isinstance(undef, tuple): + flag, macro_name = undef + env["CCFLAGS"].remove(flag) + env["CCFLAGS"].remove(macro_name) + else: + macro_name = undef[2:] + env["CCFLAGS"].remove(undef) + + # Remove from CPPDEFINES if it exists + if macro_name in env["CPPDEFINES"]: + env["CPPDEFINES"].remove(macro_name) + + # Build the -U flags string + undef_flags = [] + for undef in undefines: + if isinstance(undef, tuple): + undef_flags.append(f"{undef[0]} {undef[1]}") + else: + undef_flags.append(undef) + env.Append(_CPPDEFFLAGS=" %s" % " ".join(undef_flags)) def ProcessUnFlags(env, flags): diff --git a/platformio/project/config.py b/platformio/project/config.py index 82b76abf09..15cca1d361 100644 --- a/platformio/project/config.py +++ b/platformio/project/config.py @@ -180,9 +180,12 @@ def walk_options(self, root_section): for option in self._parser.options(section): yield (section, option) if self._parser.has_option(section, "extends"): - extends_queue.extend( - self.parse_multi_values(self._parser.get(section, "extends")) - ) + for ext_section in self.parse_multi_values( + self._parser.get(section, "extends") + ): + # Prevent circular dependencies + if ext_section not in extends_done and ext_section not in extends_queue: + extends_queue.append(ext_section) def options(self, section=None, env=None): result = [] diff --git a/platformio/test/cli.py b/platformio/test/cli.py index 78a28490b5..4fac61ef8d 100644 --- a/platformio/test/cli.py +++ b/platformio/test/cli.py @@ -189,17 +189,14 @@ def print_suite_header(test_suite): def print_suite_footer(test_suite): is_error = test_suite.status in (TestStatus.FAILED, TestStatus.ERRORED) + status_color = "red" if is_error else test_suite.status.to_ansi_color() util.print_labeled_bar( "%s [%s] Took %.2f seconds" % ( click.style( "%s:%s" % (test_suite.env_name, test_suite.test_name), bold=True ), - ( - click.style(test_suite.status.name, fg="red", bold=True) - if is_error - else click.style("PASSED", fg="green", bold=True) - ), + click.style(test_suite.status.name, fg=status_color, bold=True), test_suite.duration, ), is_error=is_error,