python: simplify libs()
and headers()
methods in python/package.py
- [x] Rework `headers` to search a sequence of directories and to display all searched locations on error, as opposed to handling each directory with a variable - [x] Make `headers` and `libs` do the same type of search and raise the same sort of errors. Co-authored-by: Todd Gamblin <tgamblin@llnl.gov>
This commit is contained in:
parent
30585890a8
commit
50f8a0f0d6
@ -1044,6 +1044,12 @@ def find_library(self, library):
|
|||||||
win_bin_dir = self.config_vars["BINDIR"]
|
win_bin_dir = self.config_vars["BINDIR"]
|
||||||
|
|
||||||
directories = [libdir, libpl, frameworkprefix, macos_developerdir, win_bin_dir]
|
directories = [libdir, libpl, frameworkprefix, macos_developerdir, win_bin_dir]
|
||||||
|
|
||||||
|
# The Python shipped with Xcode command line tools isn't in any of these locations
|
||||||
|
for subdir in ["lib", "lib64"]:
|
||||||
|
directories.append(os.path.join(self.config_vars["base"], subdir))
|
||||||
|
|
||||||
|
directories = dedupe(directories)
|
||||||
for directory in directories:
|
for directory in directories:
|
||||||
path = os.path.join(directory, library)
|
path = os.path.join(directory, library)
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
@ -1051,52 +1057,64 @@ def find_library(self, library):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def libs(self):
|
def libs(self):
|
||||||
# The +shared variant isn't always reliable, as `spack external find`
|
py_version = self.version.up_to(2)
|
||||||
# currently can't detect it. If +shared, prefer the shared libraries, but check
|
|
||||||
# for static if those aren't found. Vice versa for ~shared.
|
|
||||||
|
|
||||||
# The values of LDLIBRARY and LIBRARY also aren't reliable. Intel Python uses a
|
# The values of LDLIBRARY and LIBRARY aren't reliable. Intel Python uses a
|
||||||
# static binary but installs shared libraries, so sysconfig reports
|
# static binary but installs shared libraries, so sysconfig reports
|
||||||
# libpythonX.Y.a but only libpythonX.Y.so exists.
|
# libpythonX.Y.a but only libpythonX.Y.so exists. So we add our own paths, too.
|
||||||
shared_libs = [
|
shared_libs = [
|
||||||
self.config_vars["LDLIBRARY"],
|
self.config_vars["LDLIBRARY"],
|
||||||
"libpython{}.{}".format(self.version.up_to(2), dso_suffix),
|
"libpython{}.{}".format(py_version, dso_suffix),
|
||||||
]
|
]
|
||||||
static_libs = [
|
static_libs = [
|
||||||
self.config_vars["LIBRARY"],
|
self.config_vars["LIBRARY"],
|
||||||
"libpython{}.a".format(self.version.up_to(2)),
|
"libpython{}.a".format(py_version),
|
||||||
]
|
]
|
||||||
if "+shared" in self.spec:
|
|
||||||
libraries = shared_libs + static_libs
|
|
||||||
else:
|
|
||||||
libraries = static_libs + shared_libs
|
|
||||||
libraries = dedupe(libraries)
|
|
||||||
|
|
||||||
for library in libraries:
|
# The +shared variant isn't reliable, as `spack external find` currently can't
|
||||||
lib = self.find_library(library)
|
# detect it. If +shared, prefer the shared libraries, but check for static if
|
||||||
|
# those aren't found. Vice versa for ~shared.
|
||||||
|
if "+shared" in self.spec:
|
||||||
|
candidates = shared_libs + static_libs
|
||||||
|
else:
|
||||||
|
candidates = static_libs + shared_libs
|
||||||
|
candidates = dedupe(candidates)
|
||||||
|
|
||||||
|
for candidate in candidates:
|
||||||
|
lib = self.find_library(candidate)
|
||||||
if lib:
|
if lib:
|
||||||
return lib
|
return lib
|
||||||
|
|
||||||
msg = "Unable to locate {} libraries in {}"
|
raise spack.error.NoLibrariesError(
|
||||||
libdir = self.config_vars["LIBDIR"]
|
"Unable to find {} libraries with the following names:".format(self.name),
|
||||||
raise spack.error.NoLibrariesError(msg.format(self.name, libdir))
|
"\n".join(candidates),
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def headers(self):
|
def headers(self):
|
||||||
# Location where pyconfig.h is _supposed_ to be
|
# Locations where pyconfig.h could be
|
||||||
config_h = self.config_vars["config_h_filename"]
|
# This varies by system, especially on macOS where the command line tools are
|
||||||
if os.path.exists(config_h):
|
# installed in a very different directory from the system python interpreter.
|
||||||
headers = HeaderList(config_h)
|
py_version = str(self.version.up_to(2))
|
||||||
|
candidates = [
|
||||||
|
os.path.dirname(self.config_vars["config_h_filename"]),
|
||||||
|
self.config_vars["INCLUDEPY"],
|
||||||
|
self.config_vars["CONFINCLUDEPY"],
|
||||||
|
os.path.join(self.config_vars["base"], "include", py_version),
|
||||||
|
os.path.join(self.config_vars["base"], "Headers"),
|
||||||
|
]
|
||||||
|
candidates = list(dedupe(candidates))
|
||||||
|
|
||||||
|
for directory in candidates:
|
||||||
|
headers = find_headers("pyconfig", directory)
|
||||||
|
if headers:
|
||||||
|
config_h = headers[0]
|
||||||
|
break
|
||||||
else:
|
else:
|
||||||
# If not, one of these config vars should contain the right directory
|
raise spack.error.NoHeadersError(
|
||||||
for var in ["INCLUDEPY", "CONFINCLUDEPY"]:
|
"Unable to locate {} headers in any of these locations:".format(self.name),
|
||||||
headers = find_headers("pyconfig", self.config_vars[var])
|
"\n".join(candidates),
|
||||||
if headers:
|
)
|
||||||
config_h = headers[0]
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
msg = "Unable to locate {} headers in {}"
|
|
||||||
raise spack.error.NoHeadersError(msg.format(self.name, directory))
|
|
||||||
|
|
||||||
headers.directories = [os.path.dirname(config_h)]
|
headers.directories = [os.path.dirname(config_h)]
|
||||||
return headers
|
return headers
|
||||||
|
Loading…
Reference in New Issue
Block a user