Also move heuristics into find_headers directly
This commit is contained in:
parent
1a8d4e46e4
commit
161b67fd09
@ -1691,6 +1691,7 @@ def find(
|
|||||||
root: Union[Path, Sequence[Path]],
|
root: Union[Path, Sequence[Path]],
|
||||||
files: Union[str, Sequence[str]],
|
files: Union[str, Sequence[str]],
|
||||||
recursive: bool = True,
|
recursive: bool = True,
|
||||||
|
*,
|
||||||
max_depth: Optional[int] = None,
|
max_depth: Optional[int] = None,
|
||||||
) -> List[str]:
|
) -> List[str]:
|
||||||
"""Finds all files matching the patterns from ``files`` starting from ``root``. This function
|
"""Finds all files matching the patterns from ``files`` starting from ``root``. This function
|
||||||
@ -2104,7 +2105,14 @@ def add_macro(self, macro):
|
|||||||
self._macro_definitions.append(macro)
|
self._macro_definitions.append(macro)
|
||||||
|
|
||||||
|
|
||||||
def find_headers(headers, root, recursive=False):
|
def find_headers(
|
||||||
|
headers: Union[List[str], str],
|
||||||
|
root: str,
|
||||||
|
recursive: bool = False,
|
||||||
|
*,
|
||||||
|
heuristic: bool = True,
|
||||||
|
max_depth: Optional[int] = None,
|
||||||
|
) -> HeaderList:
|
||||||
"""Returns an iterable object containing a list of full paths to
|
"""Returns an iterable object containing a list of full paths to
|
||||||
headers if found.
|
headers if found.
|
||||||
|
|
||||||
@ -2120,10 +2128,13 @@ def find_headers(headers, root, recursive=False):
|
|||||||
======= ====================================
|
======= ====================================
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
headers (str or list): Header name(s) to search for
|
headers: Header name(s) to search for
|
||||||
root (str): The root directory to start searching from
|
root: The root directory to start searching from
|
||||||
recursive (bool): if False search only root folder,
|
recursive: if False (default) search only root folder, if True recurse from the root. Note
|
||||||
if True descends top-down from the root. Defaults to False.
|
that recursive search does not imply exhaustive search if heuristic is True.
|
||||||
|
heuristic: if True (default), use a non-exhaustive, faster search. Has no effect
|
||||||
|
if recursive is False.
|
||||||
|
max_depth: if set, don't search below this depth. Cannot be set if recursive is False.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
HeaderList: The headers that have been found
|
HeaderList: The headers that have been found
|
||||||
@ -2131,10 +2142,10 @@ def find_headers(headers, root, recursive=False):
|
|||||||
if isinstance(headers, str):
|
if isinstance(headers, str):
|
||||||
headers = [headers]
|
headers = [headers]
|
||||||
elif not isinstance(headers, collections.abc.Sequence):
|
elif not isinstance(headers, collections.abc.Sequence):
|
||||||
message = "{0} expects a string or sequence of strings as the "
|
raise TypeError(
|
||||||
message += "first argument [got {1} instead]"
|
f"{find_headers.__name__} expects a string or sequence of strings as the "
|
||||||
message = message.format(find_headers.__name__, type(headers))
|
f"first argument [got {type(headers)} instead]"
|
||||||
raise TypeError(message)
|
)
|
||||||
|
|
||||||
# Construct the right suffix for the headers
|
# Construct the right suffix for the headers
|
||||||
suffixes = [
|
suffixes = [
|
||||||
@ -2154,9 +2165,23 @@ def find_headers(headers, root, recursive=False):
|
|||||||
]
|
]
|
||||||
|
|
||||||
# List of headers we are searching with suffixes
|
# List of headers we are searching with suffixes
|
||||||
headers = ["{0}.{1}".format(header, suffix) for header in headers for suffix in suffixes]
|
headers = [f"{header}.{suffix}" for header in headers for suffix in suffixes]
|
||||||
|
|
||||||
return HeaderList(find(root, headers, recursive))
|
if not recursive or not heuristic:
|
||||||
|
return HeaderList(find(root, headers, recursive=recursive))
|
||||||
|
|
||||||
|
# The heuristic here is simpler than the one for libraries: restrict search to <root>/include
|
||||||
|
# (if root isn't an include directory itself) and limit search depth so that headers are found
|
||||||
|
# not deeper than <root>/include/<subdir>/*.
|
||||||
|
|
||||||
|
if max_depth is None:
|
||||||
|
max_depth = 2
|
||||||
|
|
||||||
|
if os.path.basename(root) != "include":
|
||||||
|
root = os.path.join(root, "include")
|
||||||
|
max_depth -= 1
|
||||||
|
|
||||||
|
return HeaderList(find(root, headers, recursive=True, max_depth=max_depth))
|
||||||
|
|
||||||
|
|
||||||
@system_path_filter
|
@system_path_filter
|
||||||
@ -2328,6 +2353,7 @@ def find_libraries(
|
|||||||
shared: bool = True,
|
shared: bool = True,
|
||||||
recursive: bool = False,
|
recursive: bool = False,
|
||||||
runtime: bool = True,
|
runtime: bool = True,
|
||||||
|
heuristic: bool = True,
|
||||||
max_depth: Optional[int] = None,
|
max_depth: Optional[int] = None,
|
||||||
) -> LibraryList:
|
) -> LibraryList:
|
||||||
"""Find libraries in the specified root directory.
|
"""Find libraries in the specified root directory.
|
||||||
@ -2348,12 +2374,12 @@ def find_libraries(
|
|||||||
root: the root directory to start searching from
|
root: the root directory to start searching from
|
||||||
shared: if True searches for shared libraries, otherwise for static. Defaults to True.
|
shared: if True searches for shared libraries, otherwise for static. Defaults to True.
|
||||||
recursive: if False (default) search only root folder, if True recurse from the root. Note
|
recursive: if False (default) search only root folder, if True recurse from the root. Note
|
||||||
that recursive search does not imply exhaustive search. The function returns early if
|
that recursive search does not imply exhaustive search if heuristic is True.
|
||||||
libraries are found in typical, low-depth library directories.
|
|
||||||
max_depth: if set, don't search below this depth. Cannot be set if recursive is False.
|
|
||||||
Defaults to 4.
|
|
||||||
runtime: Windows only option, no-op elsewhere. If True (default), search for runtime shared
|
runtime: Windows only option, no-op elsewhere. If True (default), search for runtime shared
|
||||||
libs (.DLL), otherwise, search for .Lib files. If shared is False, this has no meaning.
|
libs (.DLL), otherwise, search for .Lib files. If shared is False, this has no meaning.
|
||||||
|
heuristic: if True (default), use a non-exhaustive, faster search. Has no effect if
|
||||||
|
recursive is False.
|
||||||
|
max_depth: if set, don't search below this depth. Cannot be set if recursive is False.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
LibraryList: The libraries that have been found
|
LibraryList: The libraries that have been found
|
||||||
@ -2395,13 +2421,17 @@ def find_libraries(
|
|||||||
|
|
||||||
if not recursive:
|
if not recursive:
|
||||||
return LibraryList(find(root, libraries, recursive=False))
|
return LibraryList(find(root, libraries, recursive=False))
|
||||||
|
elif not heuristic:
|
||||||
|
return LibraryList(find(root, libraries, recursive=True, max_depth=max_depth))
|
||||||
|
|
||||||
|
# Heuristic search: a form of non-exhaustive iterative deepening, in order to return early if
|
||||||
|
# libraries are found in their usual locations. This is the default behavior for recursive
|
||||||
|
# searches.
|
||||||
|
|
||||||
if max_depth is None:
|
if max_depth is None:
|
||||||
# this default covers search in <root>/lib/pythonX.Y/site-packages/<package>/*.
|
# this default covers search in <root>/lib/pythonX.Y/site-packages/<package>/*.
|
||||||
max_depth = 4
|
max_depth = 4
|
||||||
|
|
||||||
# Even if recursive is True, we will do some form of targeted, iterative deepening, in order
|
|
||||||
# to return early if libraries are found in common, low-depth library directories.
|
|
||||||
if sys.platform == "win32":
|
if sys.platform == "win32":
|
||||||
common_lib_dirs = ("lib", "lib64", "bin", "Lib")
|
common_lib_dirs = ("lib", "lib64", "bin", "Lib")
|
||||||
else:
|
else:
|
||||||
|
@ -1097,20 +1097,19 @@ def _command_default_handler(spec: "Spec"):
|
|||||||
def _headers_default_handler(spec: "Spec"):
|
def _headers_default_handler(spec: "Spec"):
|
||||||
"""Default handler when looking for the 'headers' attribute.
|
"""Default handler when looking for the 'headers' attribute.
|
||||||
|
|
||||||
Tries to search for ``*.h`` files recursively starting from
|
Tries to search heuristically for header files in ``spec.package.home``.
|
||||||
``spec.package.home.include``.
|
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
spec: spec that is being queried
|
spec: spec that is being queried
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
HeaderList: The headers in ``prefix.include``
|
HeaderList: The headers in ``prefix``
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
NoHeadersError: If no headers are found
|
NoHeadersError: If no headers are found
|
||||||
"""
|
"""
|
||||||
home = getattr(spec.package, "home")
|
home = getattr(spec.package, "home")
|
||||||
headers = fs.find_headers("*", root=home.include, recursive=True)
|
headers = fs.find_headers("*", root=home, recursive=True, heuristic=True)
|
||||||
|
|
||||||
if headers:
|
if headers:
|
||||||
return headers
|
return headers
|
||||||
@ -1160,7 +1159,9 @@ def _libs_default_handler(spec: "Spec"):
|
|||||||
for shared in search_shared:
|
for shared in search_shared:
|
||||||
# Since we are searching for link libraries, on Windows search only for
|
# Since we are searching for link libraries, on Windows search only for
|
||||||
# ".Lib" extensions by default as those represent import libraries for implicit links.
|
# ".Lib" extensions by default as those represent import libraries for implicit links.
|
||||||
libs = fs.find_libraries(name, home, shared=shared, recursive=True, runtime=False)
|
libs = fs.find_libraries(
|
||||||
|
name, home, shared=shared, recursive=True, runtime=False, heuristic=True
|
||||||
|
)
|
||||||
if libs:
|
if libs:
|
||||||
return libs
|
return libs
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user