From f219f35ac8bac251f0bc28fba862e0b6a82856be Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 20 Jun 2023 20:55:00 +0300 Subject: [PATCH] Updated the "pio project metadata" command to return C/C++ flags as parsed Unix shell arguments --- HISTORY.rst | 1 + docs | 2 +- platformio/builder/tools/piointegration.py | 9 +++- platformio/check/tools/base.py | 4 +- platformio/compat.py | 8 +++ platformio/project/commands/metadata.py | 1 + .../tpls/clion/CMakeListsPrivate.txt.tpl | 14 ++--- .../.settings/language.settings.xml.tpl | 4 +- .../project/integration/tpls/emacs/.ccls.tpl | 6 ++- .../tpls/qtcreator/platformio.cflags.tpl | 4 +- .../tpls/qtcreator/platformio.cxxflags.tpl | 4 +- .../integration/tpls/sublimetext/.ccls.tpl | 6 ++- .../project/integration/tpls/vim/.ccls.tpl | 6 ++- .../vscode/.vscode/c_cpp_properties.json.tpl | 53 ++++++++----------- tests/commands/test_init.py | 2 +- 15 files changed, 69 insertions(+), 55 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index adf42844..7aa40fde 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -23,6 +23,7 @@ PlatformIO Core 6 * Optimized project integration templates to address the issue of long paths on Windows (`issue #4652 `_) * Refactored |UNITTESTING| engine to resolve compiler warnings with "-Wpedantic" option (`pull #4671 `_) * Eliminated erroneous warning regarding the use of obsolete PlatformIO Core when downgrading to the stable version (`issue #4664 `_) +* Updated the `pio project metadata `__ command to return C/C++ flags as parsed Unix shell arguments when dumping project build metadata * Removed PlatformIO IDE for Atom from the documentation as `Atom has been deprecated `__ 6.1.7 (2023-05-08) diff --git a/docs b/docs index 7b024165..45e6fad5 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 7b02416590fed8484ee9c6fbefcc2f9901ddb325 +Subproject commit 45e6fad5dcd601e88aec0411c0ed76e9849ef7a6 diff --git a/platformio/builder/tools/piointegration.py b/platformio/builder/tools/piointegration.py index 3e27dd36..25ca1eb0 100644 --- a/platformio/builder/tools/piointegration.py +++ b/platformio/builder/tools/piointegration.py @@ -16,6 +16,7 @@ import glob import os +import click import SCons.Defaults # pylint: disable=import-error import SCons.Subst # pylint: disable=import-error from SCons.Script import COMMAND_LINE_TARGETS # pylint: disable=import-error @@ -154,8 +155,12 @@ def DumpIntegrationData(*args): ], "defines": dump_defines(projenv), "includes": projenv.DumpIntegrationIncludes(), - "cc_flags": _subst_cmd(projenv, "$CFLAGS $CCFLAGS $CPPFLAGS"), - "cxx_flags": _subst_cmd(projenv, "$CXXFLAGS $CCFLAGS $CPPFLAGS"), + "cc_flags": click.parser.split_arg_string( + _subst_cmd(projenv, "$CFLAGS $CCFLAGS $CPPFLAGS") + ), + "cxx_flags": click.parser.split_arg_string( + _subst_cmd(projenv, "$CXXFLAGS $CCFLAGS $CPPFLAGS") + ), "cc_path": where_is_program( globalenv.subst("$CC"), globalenv.subst("${ENV['PATH']}") ), diff --git a/platformio/check/tools/base.py b/platformio/check/tools/base.py index 77f0e55c..ccf331f4 100644 --- a/platformio/check/tools/base.py +++ b/platformio/check/tools/base.py @@ -60,8 +60,8 @@ class CheckToolBase: # pylint: disable=too-many-instance-attributes data = load_build_metadata(self.project_dir, self.envname) if not data: return - self.cc_flags = click.parser.split_arg_string(data.get("cc_flags", "")) - self.cxx_flags = click.parser.split_arg_string(data.get("cxx_flags", "")) + self.cc_flags = data.get("cc_flags", []) + self.cxx_flags = data.get("cxx_flags", []) self.cpp_includes = self._dump_includes(data.get("includes", {})) self.cpp_defines = data.get("defines", []) self.cc_path = data.get("cc_path") diff --git a/platformio/compat.py b/platformio/compat.py index 17b4cc0a..694783c2 100644 --- a/platformio/compat.py +++ b/platformio/compat.py @@ -17,6 +17,7 @@ import importlib.util import inspect import locale +import shlex import sys from platformio.exception import UserSideException @@ -36,6 +37,13 @@ IS_MACOS = sys.platform.startswith("darwin") MISSING = object() string_types = (str,) +try: + from shlex import join as shlex_join +except ImportError: + + def shlex_join(split_command): + return " ".join(shlex.quote(arg) for arg in split_command) + def is_bytes(x): return isinstance(x, (bytes, memoryview, bytearray)) diff --git a/platformio/project/commands/metadata.py b/platformio/project/commands/metadata.py index fbf71b8b..ee9f5b19 100644 --- a/platformio/project/commands/metadata.py +++ b/platformio/project/commands/metadata.py @@ -37,6 +37,7 @@ from platformio.project.helpers import load_build_metadata @click.option("--json-output", is_flag=True) @click.option("--json-output-path", type=click.Path()) def project_metadata_cmd(project_dir, environments, json_output, json_output_path): + project_dir = os.path.abspath(project_dir) with fs.cd(project_dir): config = ProjectConfig.get_instance() config.validate(environments) diff --git a/platformio/project/integration/tpls/clion/CMakeListsPrivate.txt.tpl b/platformio/project/integration/tpls/clion/CMakeListsPrivate.txt.tpl index 6297706f..c65848f6 100644 --- a/platformio/project/integration/tpls/clion/CMakeListsPrivate.txt.tpl +++ b/platformio/project/integration/tpls/clion/CMakeListsPrivate.txt.tpl @@ -8,6 +8,7 @@ % import os % import re % +% from platformio.compat import shlex_join % from platformio.project.helpers import load_build_metadata % % def _normalize_path(path): @@ -64,17 +65,16 @@ set(CLION_SVD_FILE_PATH "{{ _normalize_path(svd_path) }}" CACHE FILEPATH "Periph SET(CMAKE_C_COMPILER "{{ _normalize_path(cc_path) }}") SET(CMAKE_CXX_COMPILER "{{ _normalize_path(cxx_path) }}") -SET(CMAKE_CXX_FLAGS "{{ _normalize_path(to_unix_path(cxx_flags)) }}") -SET(CMAKE_C_FLAGS "{{ _normalize_path(to_unix_path(cc_flags)) }}") +SET(CMAKE_CXX_FLAGS {{ _normalize_path(to_unix_path(shlex_join(cxx_flags))) }}) +SET(CMAKE_C_FLAGS {{ _normalize_path(to_unix_path(shlex_join(cc_flags))) }}) -% STD_RE = re.compile(r"\-std=[a-z\+]+(\w+)") -% cc_stds = STD_RE.findall(cc_flags) -% cxx_stds = STD_RE.findall(cxx_flags) +% cc_stds = [arg for arg in cc_flags if arg.startswith("-std=")] +% cxx_stds = [arg for arg in cxx_flags if arg.startswith("-std=")] % if cc_stds: -SET(CMAKE_C_STANDARD {{ cc_stds[-1] }}) +SET(CMAKE_C_STANDARD {{ cc_stds[-1][-2:] }}) % end % if cxx_stds: -set(CMAKE_CXX_STANDARD {{ cxx_stds[-1] }}) +set(CMAKE_CXX_STANDARD {{ cxx_stds[-1][-2:] }}) % end if (CMAKE_BUILD_TYPE MATCHES "{{ env_name }}") diff --git a/platformio/project/integration/tpls/eclipse/.settings/language.settings.xml.tpl b/platformio/project/integration/tpls/eclipse/.settings/language.settings.xml.tpl index d8826fca..f2123be6 100644 --- a/platformio/project/integration/tpls/eclipse/.settings/language.settings.xml.tpl +++ b/platformio/project/integration/tpls/eclipse/.settings/language.settings.xml.tpl @@ -1,6 +1,4 @@ -% import re -% STD_RE = re.compile(r"(\-std=[a-z\+]+\w+)") -% cxx_stds = STD_RE.findall(cxx_flags) +% cxx_stds = [arg for arg in cxx_flags if arg.startswith("-std=")] % cxx_std = cxx_stds[-1] if cxx_stds else "" % % if cxx_path.startswith(user_home_dir): diff --git a/platformio/project/integration/tpls/emacs/.ccls.tpl b/platformio/project/integration/tpls/emacs/.ccls.tpl index a747bb61..94d37680 100644 --- a/platformio/project/integration/tpls/emacs/.ccls.tpl +++ b/platformio/project/integration/tpls/emacs/.ccls.tpl @@ -1,7 +1,9 @@ +% from platformio.compat import shlex_join +% clang -{{"%c"}} {{ !cc_flags }} -{{"%cpp"}} {{ !cxx_flags }} +{{"%c"}} {{ shlex_join(cc_flags) }} +{{"%cpp"}} {{ shlex_join(cxx_flags) }} % for include in filter_includes(includes): -I{{ !include }} diff --git a/platformio/project/integration/tpls/qtcreator/platformio.cflags.tpl b/platformio/project/integration/tpls/qtcreator/platformio.cflags.tpl index f09a94f9..024c813d 100644 --- a/platformio/project/integration/tpls/qtcreator/platformio.cflags.tpl +++ b/platformio/project/integration/tpls/qtcreator/platformio.cflags.tpl @@ -1 +1,3 @@ -{{cc_flags.replace('-mlongcalls', '-mlong-calls')}} +% from platformio.compat import shlex_join +% +{{shlex_join(cc_flags).replace('-mlongcalls', '-mlong-calls')}} diff --git a/platformio/project/integration/tpls/qtcreator/platformio.cxxflags.tpl b/platformio/project/integration/tpls/qtcreator/platformio.cxxflags.tpl index c5b30511..551f02e1 100644 --- a/platformio/project/integration/tpls/qtcreator/platformio.cxxflags.tpl +++ b/platformio/project/integration/tpls/qtcreator/platformio.cxxflags.tpl @@ -1 +1,3 @@ -{{cxx_flags.replace('-mlongcalls', '-mlong-calls')}} +% from platformio.compat import shlex_join +% +{{shlex_join(cxx_flags).replace('-mlongcalls', '-mlong-calls')}} diff --git a/platformio/project/integration/tpls/sublimetext/.ccls.tpl b/platformio/project/integration/tpls/sublimetext/.ccls.tpl index a747bb61..94d37680 100644 --- a/platformio/project/integration/tpls/sublimetext/.ccls.tpl +++ b/platformio/project/integration/tpls/sublimetext/.ccls.tpl @@ -1,7 +1,9 @@ +% from platformio.compat import shlex_join +% clang -{{"%c"}} {{ !cc_flags }} -{{"%cpp"}} {{ !cxx_flags }} +{{"%c"}} {{ shlex_join(cc_flags) }} +{{"%cpp"}} {{ shlex_join(cxx_flags) }} % for include in filter_includes(includes): -I{{ !include }} diff --git a/platformio/project/integration/tpls/vim/.ccls.tpl b/platformio/project/integration/tpls/vim/.ccls.tpl index a747bb61..94d37680 100644 --- a/platformio/project/integration/tpls/vim/.ccls.tpl +++ b/platformio/project/integration/tpls/vim/.ccls.tpl @@ -1,7 +1,9 @@ +% from platformio.compat import shlex_join +% clang -{{"%c"}} {{ !cc_flags }} -{{"%cpp"}} {{ !cxx_flags }} +{{"%c"}} {{ shlex_join(cc_flags) }} +{{"%cpp"}} {{ shlex_join(cxx_flags) }} % for include in filter_includes(includes): -I{{ !include }} diff --git a/platformio/project/integration/tpls/vscode/.vscode/c_cpp_properties.json.tpl b/platformio/project/integration/tpls/vscode/.vscode/c_cpp_properties.json.tpl index ac525e56..9abadeef 100644 --- a/platformio/project/integration/tpls/vscode/.vscode/c_cpp_properties.json.tpl +++ b/platformio/project/integration/tpls/vscode/.vscode/c_cpp_properties.json.tpl @@ -1,27 +1,20 @@ % import os % import platform -% import re -% -% import click % % systype = platform.system().lower() % % cpp_standards_remap = { -% "0x": "11", -% "1y": "14", -% "1z": "17", -% "2a": "20", -% "2b": "23" +% "c++0x": "c++11", +% "c++1y": "c++14", +% "c++1z": "c++17", +% "c++2a": "c++20", +% "c++2b": "c++23" % } % % def _escape(text): % return to_unix_path(text).replace('"', '\\"') % end % -% def split_args(args_string): -% return click.parser.split_arg_string(to_unix_path(args_string)) -% end -% % def filter_args(args, allowed, ignore=None): % if not allowed: % return [] @@ -31,18 +24,18 @@ % result = [] % i = 0 % length = len(args) -% while(i < length): -% if any(args[i].startswith(f) for f in allowed) and not any( -% args[i].startswith(f) for f in ignore): -% result.append(args[i]) -% if i + 1 < length and not args[i + 1].startswith("-"): -% i += 1 -% result.append(args[i]) -% end +% while(i < length): +% if any(args[i].startswith(f) for f in allowed) and not any( +% args[i].startswith(f) for f in ignore): +% result.append(args[i]) +% if i + 1 < length and not args[i + 1].startswith("-"): +% i += 1 +% result.append(args[i]) % end -% i += 1 -% end -% return result +% end +% i += 1 +% end +% return result % end % % def _find_abs_path(inc, inc_paths): @@ -76,12 +69,10 @@ % % cleaned_includes = filter_includes(includes, ["toolchain"]) % -% STD_RE = re.compile(r"\-std=[a-z\+]+(\w+)") -% cc_stds = STD_RE.findall(cc_flags) -% cxx_stds = STD_RE.findall(cxx_flags) -% cc_m_flags = split_args(cc_flags) +% cc_stds = [arg[5:] for arg in cc_flags if arg.startswith("-std=")] +% cxx_stds = [arg[5:] for arg in cxx_flags if arg.startswith("-std=")] % forced_includes = _find_forced_includes( -% filter_args(cc_m_flags, ["-include", "-imacros"]), cleaned_includes) +% filter_args(cc_flags, ["-include", "-imacros"]), cleaned_includes) % // // !!! WARNING !!! AUTO-GENERATED FILE! @@ -114,10 +105,10 @@ "" ], % if cc_stds: - "cStandard": "c{{ cc_stds[-1] }}", + "cStandard": "{{ cc_stds[-1] }}", % end % if cxx_stds: - "cppStandard": "c++{{ cpp_standards_remap.get(cxx_stds[-1], cxx_stds[-1]) }}", + "cppStandard": "{{ cpp_standards_remap.get(cxx_stds[-1], cxx_stds[-1]) }}", % end % if forced_includes: "forcedInclude": [ @@ -130,7 +121,7 @@ "compilerPath": "{{ cc_path }}", "compilerArgs": [ % for flag in [ -% f for f in filter_args(cc_m_flags, ["-m", "-i", "@"], ["-include", "-imacros"]) +% f for f in filter_args(cc_flags, ["-m", "-i", "@"], ["-include", "-imacros"]) % ]: "{{ flag }}", % end diff --git a/tests/commands/test_init.py b/tests/commands/test_init.py index b3d9f013..80ef0d91 100644 --- a/tests/commands/test_init.py +++ b/tests/commands/test_init.py @@ -62,7 +62,7 @@ def test_init_duplicated_boards(clirunner, validate_cliresult, tmpdir): def test_init_ide_without_board(clirunner, tmpdir): with tmpdir.as_cwd(): - result = clirunner.invoke(project_init_cmd, ["--ide", "atom"]) + result = clirunner.invoke(project_init_cmd, ["--ide", "vscode"]) assert result.exit_code != 0 assert isinstance(result.exception, ProjectEnvsNotAvailableError)