Fixed an issue with endless scanning of project dependencies // Resolve #4349

This commit is contained in:
Ivan Kravets
2022-07-09 21:42:47 +03:00
parent 9051677d74
commit d24702eb29
3 changed files with 97 additions and 28 deletions

View File

@ -18,6 +18,7 @@ PlatformIO Core 6
* Show "TimeoutError" only in the verbose mode when can not find a serial port * Show "TimeoutError" only in the verbose mode when can not find a serial port
* Fixed an issue when a serial port was not automatically detected if the board has predefined HWIDs * Fixed an issue when a serial port was not automatically detected if the board has predefined HWIDs
* Fixed an issue with endless scanning of project dependencies (`issue #4349 <https://github.com/platformio/platformio-core/issues/4349>`_)
6.1.0 (2022-07-06) 6.1.0 (2022-07-06)
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~

View File

@ -331,7 +331,7 @@ class LibBuilderBase:
) )
] ]
def _get_found_includes( # pylint: disable=too-many-branches def get_implicit_includes( # pylint: disable=too-many-branches
self, search_files=None self, search_files=None
): ):
# all include directories # all include directories
@ -352,15 +352,17 @@ class LibBuilderBase:
include_dirs.extend(LibBuilderBase._INCLUDE_DIRS_CACHE) include_dirs.extend(LibBuilderBase._INCLUDE_DIRS_CACHE)
result = [] result = []
for path in search_files or []: search_files = search_files or []
if path in self._processed_files: while search_files:
node = self.env.File(search_files.pop(0))
if node.get_abspath() in self._processed_search_files:
continue continue
self._processed_files.append(path) self._processed_search_files.append(node.get_abspath())
try: try:
assert "+" in self.lib_ldf_mode assert "+" in self.lib_ldf_mode
candidates = LibBuilderBase.CCONDITIONAL_SCANNER( candidates = LibBuilderBase.CCONDITIONAL_SCANNER(
self.env.File(path), node,
self.env, self.env,
tuple(include_dirs), tuple(include_dirs),
depth=self.CCONDITIONAL_SCANNER_DEPTH, depth=self.CCONDITIONAL_SCANNER_DEPTH,
@ -370,39 +372,35 @@ class LibBuilderBase:
if self.verbose and "+" in self.lib_ldf_mode: if self.verbose and "+" in self.lib_ldf_mode:
sys.stderr.write( sys.stderr.write(
"Warning! Classic Pre Processor is used for `%s`, " "Warning! Classic Pre Processor is used for `%s`, "
"advanced has failed with `%s`\n" % (path, exc) "advanced has failed with `%s`\n" % (node.get_abspath(), exc)
) )
candidates = self.env.File(path).get_implicit_deps( candidates = LibBuilderBase.CLASSIC_SCANNER(
self.env, node, self.env, tuple(include_dirs)
LibBuilderBase.CLASSIC_SCANNER,
lambda _: tuple(include_dirs),
) )
# mark candidates already processed # print(node.get_abspath(), [c.get_abspath() for c in candidates])
self._processed_files.extend(
[
c.get_abspath()
for c in candidates
if c.get_abspath() not in self._processed_files
]
)
# print(path, [c.get_abspath() for c in candidates])
for item in candidates: for item in candidates:
item_path = item.get_abspath()
# process internal files recursively
if (
item_path not in self._processed_search_files
and item_path not in search_files
and item_path in self
):
search_files.append(item_path)
if item not in result: if item not in result:
result.append(item) result.append(item)
if not self.PARSE_SRC_BY_H_NAME: if not self.PARSE_SRC_BY_H_NAME:
continue continue
_h_path = item.get_abspath() if not fs.path_endswith_ext(item_path, piotool.SRC_HEADER_EXT):
if not fs.path_endswith_ext(_h_path, piotool.SRC_HEADER_EXT):
continue continue
_f_part = _h_path[: _h_path.rindex(".")] item_fname = item_path[: item_path.rindex(".")]
for ext in piotool.SRC_C_EXT + piotool.SRC_CXX_EXT: for ext in piotool.SRC_C_EXT + piotool.SRC_CXX_EXT:
if not os.path.isfile("%s.%s" % (_f_part, ext)): if not os.path.isfile("%s.%s" % (item_fname, ext)):
continue continue
_c_path = self.env.File("%s.%s" % (_f_part, ext)) item_c_node = self.env.File("%s.%s" % (item_fname, ext))
if _c_path not in result: if item_c_node not in result:
result.append(_c_path) result.append(item_c_node)
return result return result
@ -417,7 +415,7 @@ class LibBuilderBase:
search_files = self.get_search_files() search_files = self.get_search_files()
lib_inc_map = {} lib_inc_map = {}
for inc in self._get_found_includes(search_files): for inc in self.get_implicit_includes(search_files):
inc_path = inc.get_abspath() inc_path = inc.get_abspath()
for lb in self.env.GetLibBuilders(): for lb in self.env.GetLibBuilders():
if inc_path in lb: if inc_path in lb:

View File

@ -335,3 +335,73 @@ projenv.Append(CPPDEFINES=[
assert 'MACRO_2=<Text is "Quoted">' in result.output assert 'MACRO_2=<Text is "Quoted">' in result.output
assert 'MACRO_3=<Hello "World"! Isn\'t true?>' in result.output assert 'MACRO_3=<Hello "World"! Isn\'t true?>' in result.output
assert "MACRO_4=<Special chars: ',(,),[,],:>" in result.output assert "MACRO_4=<Special chars: ',(,),[,],:>" in result.output
def test_ldf(clirunner, validate_cliresult, tmp_path: Path):
project_dir = tmp_path / "project"
# libs
lib_dir = project_dir / "lib"
a_lib_dir = lib_dir / "a"
a_lib_dir.mkdir(parents=True)
(a_lib_dir / "a.h").write_text(
"""
#include <some_from_b.h>
"""
)
# b
b_lib_dir = lib_dir / "b"
b_lib_dir.mkdir(parents=True)
(b_lib_dir / "some_from_b.h").write_text("")
# c
c_lib_dir = lib_dir / "c"
c_lib_dir.mkdir(parents=True)
(c_lib_dir / "parse_c_by_name.h").write_text(
"""
void some_func();
"""
)
(c_lib_dir / "parse_c_by_name.c").write_text(
"""
#include <d.h>
#include <parse_c_by_name.h>
void some_func() {
}
"""
)
(c_lib_dir / "some.c").write_text(
"""
#include <d.h>
"""
)
# d
d_lib_dir = lib_dir / "d"
d_lib_dir.mkdir(parents=True)
(d_lib_dir / "d.h").write_text("")
# project
src_dir = project_dir / "src"
src_dir.mkdir(parents=True)
(src_dir / "main.h").write_text(
"""
#include <a.h>
#include <parse_c_by_name.h>
"""
)
(src_dir / "main.c").write_text(
"""
#include <main.h>
int main() {
}
"""
)
(project_dir / "platformio.ini").write_text(
"""
[env:native]
platform = native
"""
)
result = clirunner.invoke(cmd_run, ["--project-dir", str(project_dir)])
validate_cliresult(result)