Use Package.headers for -I options (#10623)

This restores the use of Package.headers when computing -I options
for building a package that was added in #8136 and reverted in
#10604. #8136 used utility logic that located all header files in
an installation prefix, and calculated the -I options as the
immediate roots containing those header files.

In some cases, for a package containing a directory structure like

  prefix/
    include/
	  ex1.h
	  subdir/
	    ex2.h

dependents may expect to include ex2.h relative to 'include', and
adding 'prefix/include/subdir' as a -I was causing errors,
in particular if ex2.h has the same name as a system header.

This updates header utility logic to by default return the base
"include" directory when it exists, rather than subdirectories.
It also makes it possible for package implementers to override
Package.headers to return the subdirectory when it is required
(for example with libxml2).
This commit is contained in:
Massimiliano Culpo
2019-02-26 19:42:30 +01:00
committed by Peter Scheibel
parent ad25e7f3b0
commit 42386dbe94
7 changed files with 174 additions and 29 deletions

View File

@@ -36,6 +36,7 @@
'filter_file',
'find',
'find_headers',
'find_all_headers',
'find_libraries',
'find_system_libraries',
'fix_darwin_install_name',
@@ -956,10 +957,44 @@ class HeaderList(FileList):
commonly used compiler flags or names.
"""
include_regex = re.compile(r'(.*)(include)(.*)')
def __init__(self, files):
super(HeaderList, self).__init__(files)
self._macro_definitions = []
self._directories = None
@property
def directories(self):
"""Directories to be searched for header files."""
values = self._directories
if values is None:
values = self._default_directories()
return list(dedupe(values))
@directories.setter
def directories(self, value):
value = value or []
# Accept a single directory as input
if isinstance(value, six.string_types):
value = [value]
self._directories = [os.path.normpath(x) for x in value]
def _default_directories(self):
"""Default computation of directories based on the list of
header files.
"""
dir_list = super(HeaderList, self).directories
values = []
for d in dir_list:
# If the path contains a subdirectory named 'include' then stop
# there and don't add anything else to the path.
m = self.include_regex.match(d)
value = os.path.join(*m.group(1, 2)) if m else d
values.append(value)
return values
@property
def headers(self):
@@ -1095,6 +1130,19 @@ def find_headers(headers, root, recursive=False):
return HeaderList(find(root, headers, recursive))
def find_all_headers(root):
"""Convenience function that returns the list of all headers found
in the directory passed as argument.
Args:
root (path): directory where to look recursively for header files
Returns:
List of all headers found in ``root`` and subdirectories.
"""
return find_headers('*', root=root, recursive=True)
class LibraryList(FileList):
"""Sequence of absolute paths to libraries