Updated the "pio project metadata" command to return C/C++ flags as parsed Unix shell arguments

This commit is contained in:
Ivan Kravets
2023-06-20 20:55:00 +03:00
parent 4d89593b05
commit f219f35ac8
15 changed files with 69 additions and 55 deletions

View File

@ -23,6 +23,7 @@ PlatformIO Core 6
* Optimized project integration templates to address the issue of long paths on Windows (`issue #4652 <https://github.com/platformio/platformio-core/issues/4652>`_) * Optimized project integration templates to address the issue of long paths on Windows (`issue #4652 <https://github.com/platformio/platformio-core/issues/4652>`_)
* Refactored |UNITTESTING| engine to resolve compiler warnings with "-Wpedantic" option (`pull #4671 <https://github.com/platformio/platformio-core/pull/4671>`_) * Refactored |UNITTESTING| engine to resolve compiler warnings with "-Wpedantic" option (`pull #4671 <https://github.com/platformio/platformio-core/pull/4671>`_)
* Eliminated erroneous warning regarding the use of obsolete PlatformIO Core when downgrading to the stable version (`issue #4664 <https://github.com/platformio/platformio-core/issues/4664>`_) * Eliminated erroneous warning regarding the use of obsolete PlatformIO Core when downgrading to the stable version (`issue #4664 <https://github.com/platformio/platformio-core/issues/4664>`_)
* Updated the `pio project metadata <https://docs.platformio.org/en/latest/core/userguide/project/cmd_metadata.html>`__ 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 <https://github.blog/2022-06-08-sunsetting-atom/>`__ * Removed PlatformIO IDE for Atom from the documentation as `Atom has been deprecated <https://github.blog/2022-06-08-sunsetting-atom/>`__
6.1.7 (2023-05-08) 6.1.7 (2023-05-08)

2
docs

Submodule docs updated: 7b02416590...45e6fad5dc

View File

@ -16,6 +16,7 @@
import glob import glob
import os import os
import click
import SCons.Defaults # pylint: disable=import-error import SCons.Defaults # pylint: disable=import-error
import SCons.Subst # pylint: disable=import-error import SCons.Subst # pylint: disable=import-error
from SCons.Script import COMMAND_LINE_TARGETS # 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), "defines": dump_defines(projenv),
"includes": projenv.DumpIntegrationIncludes(), "includes": projenv.DumpIntegrationIncludes(),
"cc_flags": _subst_cmd(projenv, "$CFLAGS $CCFLAGS $CPPFLAGS"), "cc_flags": click.parser.split_arg_string(
"cxx_flags": _subst_cmd(projenv, "$CXXFLAGS $CCFLAGS $CPPFLAGS"), _subst_cmd(projenv, "$CFLAGS $CCFLAGS $CPPFLAGS")
),
"cxx_flags": click.parser.split_arg_string(
_subst_cmd(projenv, "$CXXFLAGS $CCFLAGS $CPPFLAGS")
),
"cc_path": where_is_program( "cc_path": where_is_program(
globalenv.subst("$CC"), globalenv.subst("${ENV['PATH']}") globalenv.subst("$CC"), globalenv.subst("${ENV['PATH']}")
), ),

View File

@ -60,8 +60,8 @@ class CheckToolBase: # pylint: disable=too-many-instance-attributes
data = load_build_metadata(self.project_dir, self.envname) data = load_build_metadata(self.project_dir, self.envname)
if not data: if not data:
return return
self.cc_flags = click.parser.split_arg_string(data.get("cc_flags", "")) self.cc_flags = data.get("cc_flags", [])
self.cxx_flags = click.parser.split_arg_string(data.get("cxx_flags", "")) self.cxx_flags = data.get("cxx_flags", [])
self.cpp_includes = self._dump_includes(data.get("includes", {})) self.cpp_includes = self._dump_includes(data.get("includes", {}))
self.cpp_defines = data.get("defines", []) self.cpp_defines = data.get("defines", [])
self.cc_path = data.get("cc_path") self.cc_path = data.get("cc_path")

View File

@ -17,6 +17,7 @@
import importlib.util import importlib.util
import inspect import inspect
import locale import locale
import shlex
import sys import sys
from platformio.exception import UserSideException from platformio.exception import UserSideException
@ -36,6 +37,13 @@ IS_MACOS = sys.platform.startswith("darwin")
MISSING = object() MISSING = object()
string_types = (str,) 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): def is_bytes(x):
return isinstance(x, (bytes, memoryview, bytearray)) return isinstance(x, (bytes, memoryview, bytearray))

View File

@ -37,6 +37,7 @@ from platformio.project.helpers import load_build_metadata
@click.option("--json-output", is_flag=True) @click.option("--json-output", is_flag=True)
@click.option("--json-output-path", type=click.Path()) @click.option("--json-output-path", type=click.Path())
def project_metadata_cmd(project_dir, environments, json_output, json_output_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): with fs.cd(project_dir):
config = ProjectConfig.get_instance() config = ProjectConfig.get_instance()
config.validate(environments) config.validate(environments)

View File

@ -8,6 +8,7 @@
% import os % import os
% import re % import re
% %
% from platformio.compat import shlex_join
% from platformio.project.helpers import load_build_metadata % from platformio.project.helpers import load_build_metadata
% %
% def _normalize_path(path): % 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_C_COMPILER "{{ _normalize_path(cc_path) }}")
SET(CMAKE_CXX_COMPILER "{{ _normalize_path(cxx_path) }}") SET(CMAKE_CXX_COMPILER "{{ _normalize_path(cxx_path) }}")
SET(CMAKE_CXX_FLAGS "{{ _normalize_path(to_unix_path(cxx_flags)) }}") SET(CMAKE_CXX_FLAGS {{ _normalize_path(to_unix_path(shlex_join(cxx_flags))) }})
SET(CMAKE_C_FLAGS "{{ _normalize_path(to_unix_path(cc_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 = [arg for arg in cc_flags if arg.startswith("-std=")]
% cc_stds = STD_RE.findall(cc_flags) % cxx_stds = [arg for arg in cxx_flags if arg.startswith("-std=")]
% cxx_stds = STD_RE.findall(cxx_flags)
% if cc_stds: % if cc_stds:
SET(CMAKE_C_STANDARD {{ cc_stds[-1] }}) SET(CMAKE_C_STANDARD {{ cc_stds[-1][-2:] }})
% end % end
% if cxx_stds: % if cxx_stds:
set(CMAKE_CXX_STANDARD {{ cxx_stds[-1] }}) set(CMAKE_CXX_STANDARD {{ cxx_stds[-1][-2:] }})
% end % end
if (CMAKE_BUILD_TYPE MATCHES "{{ env_name }}") if (CMAKE_BUILD_TYPE MATCHES "{{ env_name }}")

View File

@ -1,6 +1,4 @@
% import re % cxx_stds = [arg for arg in cxx_flags if arg.startswith("-std=")]
% STD_RE = re.compile(r"(\-std=[a-z\+]+\w+)")
% cxx_stds = STD_RE.findall(cxx_flags)
% cxx_std = cxx_stds[-1] if cxx_stds else "" % cxx_std = cxx_stds[-1] if cxx_stds else ""
% %
% if cxx_path.startswith(user_home_dir): % if cxx_path.startswith(user_home_dir):

View File

@ -1,7 +1,9 @@
% from platformio.compat import shlex_join
%
clang clang
{{"%c"}} {{ !cc_flags }} {{"%c"}} {{ shlex_join(cc_flags) }}
{{"%cpp"}} {{ !cxx_flags }} {{"%cpp"}} {{ shlex_join(cxx_flags) }}
% for include in filter_includes(includes): % for include in filter_includes(includes):
-I{{ !include }} -I{{ !include }}

View File

@ -1 +1,3 @@
{{cc_flags.replace('-mlongcalls', '-mlong-calls')}} % from platformio.compat import shlex_join
%
{{shlex_join(cc_flags).replace('-mlongcalls', '-mlong-calls')}}

View File

@ -1 +1,3 @@
{{cxx_flags.replace('-mlongcalls', '-mlong-calls')}} % from platformio.compat import shlex_join
%
{{shlex_join(cxx_flags).replace('-mlongcalls', '-mlong-calls')}}

View File

@ -1,7 +1,9 @@
% from platformio.compat import shlex_join
%
clang clang
{{"%c"}} {{ !cc_flags }} {{"%c"}} {{ shlex_join(cc_flags) }}
{{"%cpp"}} {{ !cxx_flags }} {{"%cpp"}} {{ shlex_join(cxx_flags) }}
% for include in filter_includes(includes): % for include in filter_includes(includes):
-I{{ !include }} -I{{ !include }}

View File

@ -1,7 +1,9 @@
% from platformio.compat import shlex_join
%
clang clang
{{"%c"}} {{ !cc_flags }} {{"%c"}} {{ shlex_join(cc_flags) }}
{{"%cpp"}} {{ !cxx_flags }} {{"%cpp"}} {{ shlex_join(cxx_flags) }}
% for include in filter_includes(includes): % for include in filter_includes(includes):
-I{{ !include }} -I{{ !include }}

View File

@ -1,27 +1,20 @@
% import os % import os
% import platform % import platform
% import re
%
% import click
% %
% systype = platform.system().lower() % systype = platform.system().lower()
% %
% cpp_standards_remap = { % cpp_standards_remap = {
% "0x": "11", % "c++0x": "c++11",
% "1y": "14", % "c++1y": "c++14",
% "1z": "17", % "c++1z": "c++17",
% "2a": "20", % "c++2a": "c++20",
% "2b": "23" % "c++2b": "c++23"
% } % }
% %
% def _escape(text): % def _escape(text):
% return to_unix_path(text).replace('"', '\\"') % return to_unix_path(text).replace('"', '\\"')
% end % 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): % def filter_args(args, allowed, ignore=None):
% if not allowed: % if not allowed:
% return [] % return []
@ -31,18 +24,18 @@
% result = [] % result = []
% i = 0 % i = 0
% length = len(args) % length = len(args)
% while(i < length): % while(i < length):
% if any(args[i].startswith(f) for f in allowed) and not any( % if any(args[i].startswith(f) for f in allowed) and not any(
% args[i].startswith(f) for f in ignore): % args[i].startswith(f) for f in ignore):
% result.append(args[i]) % result.append(args[i])
% if i + 1 < length and not args[i + 1].startswith("-"): % if i + 1 < length and not args[i + 1].startswith("-"):
% i += 1 % i += 1
% result.append(args[i]) % result.append(args[i])
% end
% end % end
% i += 1 % end
% end % i += 1
% return result % end
% return result
% end % end
% %
% def _find_abs_path(inc, inc_paths): % def _find_abs_path(inc, inc_paths):
@ -76,12 +69,10 @@
% %
% cleaned_includes = filter_includes(includes, ["toolchain"]) % cleaned_includes = filter_includes(includes, ["toolchain"])
% %
% STD_RE = re.compile(r"\-std=[a-z\+]+(\w+)") % cc_stds = [arg[5:] for arg in cc_flags if arg.startswith("-std=")]
% cc_stds = STD_RE.findall(cc_flags) % cxx_stds = [arg[5:] for arg in cxx_flags if arg.startswith("-std=")]
% cxx_stds = STD_RE.findall(cxx_flags)
% cc_m_flags = split_args(cc_flags)
% forced_includes = _find_forced_includes( % 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! // !!! WARNING !!! AUTO-GENERATED FILE!
@ -114,10 +105,10 @@
"" ""
], ],
% if cc_stds: % if cc_stds:
"cStandard": "c{{ cc_stds[-1] }}", "cStandard": "{{ cc_stds[-1] }}",
% end % end
% if cxx_stds: % 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 % end
% if forced_includes: % if forced_includes:
"forcedInclude": [ "forcedInclude": [
@ -130,7 +121,7 @@
"compilerPath": "{{ cc_path }}", "compilerPath": "{{ cc_path }}",
"compilerArgs": [ "compilerArgs": [
% for flag in [ % 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 }}", "{{ flag }}",
% end % end

View File

@ -62,7 +62,7 @@ def test_init_duplicated_boards(clirunner, validate_cliresult, tmpdir):
def test_init_ide_without_board(clirunner, tmpdir): def test_init_ide_without_board(clirunner, tmpdir):
with tmpdir.as_cwd(): 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 result.exit_code != 0
assert isinstance(result.exception, ProjectEnvsNotAvailableError) assert isinstance(result.exception, ProjectEnvsNotAvailableError)