abi.py: remove (#46047)
This commit is contained in:
parent
900765901d
commit
297e43b097
@ -1,131 +0,0 @@
|
|||||||
# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
|
|
||||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from llnl.util.lang import memoized
|
|
||||||
|
|
||||||
import spack.spec
|
|
||||||
import spack.version
|
|
||||||
from spack.compilers.clang import Clang
|
|
||||||
from spack.util.executable import Executable, ProcessError
|
|
||||||
|
|
||||||
|
|
||||||
class ABI:
|
|
||||||
"""This class provides methods to test ABI compatibility between specs.
|
|
||||||
The current implementation is rather rough and could be improved."""
|
|
||||||
|
|
||||||
def architecture_compatible(
|
|
||||||
self, target: spack.spec.Spec, constraint: spack.spec.Spec
|
|
||||||
) -> bool:
|
|
||||||
"""Return true if architecture of target spec is ABI compatible
|
|
||||||
to the architecture of constraint spec. If either the target
|
|
||||||
or constraint specs have no architecture, target is also defined
|
|
||||||
as architecture ABI compatible to constraint."""
|
|
||||||
return (
|
|
||||||
not target.architecture
|
|
||||||
or not constraint.architecture
|
|
||||||
or target.architecture.intersects(constraint.architecture)
|
|
||||||
)
|
|
||||||
|
|
||||||
@memoized
|
|
||||||
def _gcc_get_libstdcxx_version(self, version):
|
|
||||||
"""Returns gcc ABI compatibility info by getting the library version of
|
|
||||||
a compiler's libstdc++ or libgcc_s"""
|
|
||||||
from spack.build_environment import dso_suffix
|
|
||||||
|
|
||||||
spec = spack.spec.CompilerSpec("gcc", version)
|
|
||||||
compilers = spack.compilers.compilers_for_spec(spec)
|
|
||||||
if not compilers:
|
|
||||||
return None
|
|
||||||
compiler = compilers[0]
|
|
||||||
rungcc = None
|
|
||||||
libname = None
|
|
||||||
output = None
|
|
||||||
if compiler.cxx:
|
|
||||||
rungcc = Executable(compiler.cxx)
|
|
||||||
libname = "libstdc++." + dso_suffix
|
|
||||||
elif compiler.cc:
|
|
||||||
rungcc = Executable(compiler.cc)
|
|
||||||
libname = "libgcc_s." + dso_suffix
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
try:
|
|
||||||
# Some gcc's are actually clang and don't respond properly to
|
|
||||||
# --print-file-name (they just print the filename, not the
|
|
||||||
# full path). Ignore these and expect them to be handled as clang.
|
|
||||||
if Clang.default_version(rungcc.exe[0]) != "unknown":
|
|
||||||
return None
|
|
||||||
|
|
||||||
output = rungcc("--print-file-name=%s" % libname, output=str)
|
|
||||||
except ProcessError:
|
|
||||||
return None
|
|
||||||
if not output:
|
|
||||||
return None
|
|
||||||
libpath = os.path.realpath(output.strip())
|
|
||||||
if not libpath:
|
|
||||||
return None
|
|
||||||
return os.path.basename(libpath)
|
|
||||||
|
|
||||||
@memoized
|
|
||||||
def _gcc_compiler_compare(self, pversion, cversion):
|
|
||||||
"""Returns true iff the gcc version pversion and cversion
|
|
||||||
are ABI compatible."""
|
|
||||||
plib = self._gcc_get_libstdcxx_version(pversion)
|
|
||||||
clib = self._gcc_get_libstdcxx_version(cversion)
|
|
||||||
if not plib or not clib:
|
|
||||||
return False
|
|
||||||
return plib == clib
|
|
||||||
|
|
||||||
def _intel_compiler_compare(
|
|
||||||
self, pversion: spack.version.ClosedOpenRange, cversion: spack.version.ClosedOpenRange
|
|
||||||
) -> bool:
|
|
||||||
"""Returns true iff the intel version pversion and cversion
|
|
||||||
are ABI compatible"""
|
|
||||||
|
|
||||||
# Test major and minor versions. Ignore build version.
|
|
||||||
pv = pversion.lo
|
|
||||||
cv = cversion.lo
|
|
||||||
return pv.up_to(2) == cv.up_to(2)
|
|
||||||
|
|
||||||
def compiler_compatible(
|
|
||||||
self, parent: spack.spec.Spec, child: spack.spec.Spec, loose: bool = False
|
|
||||||
) -> bool:
|
|
||||||
"""Return true if compilers for parent and child are ABI compatible."""
|
|
||||||
if not parent.compiler or not child.compiler:
|
|
||||||
return True
|
|
||||||
|
|
||||||
if parent.compiler.name != child.compiler.name:
|
|
||||||
# Different compiler families are assumed ABI incompatible
|
|
||||||
return False
|
|
||||||
|
|
||||||
if loose:
|
|
||||||
return True
|
|
||||||
|
|
||||||
# TODO: Can we move the specialized ABI matching stuff
|
|
||||||
# TODO: into compiler classes?
|
|
||||||
for pversion in parent.compiler.versions:
|
|
||||||
for cversion in child.compiler.versions:
|
|
||||||
# For a few compilers use specialized comparisons.
|
|
||||||
# Otherwise match on version match.
|
|
||||||
if pversion.intersects(cversion):
|
|
||||||
return True
|
|
||||||
elif parent.compiler.name == "gcc" and self._gcc_compiler_compare(
|
|
||||||
pversion, cversion
|
|
||||||
):
|
|
||||||
return True
|
|
||||||
elif parent.compiler.name == "intel" and self._intel_compiler_compare(
|
|
||||||
pversion, cversion
|
|
||||||
):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def compatible(
|
|
||||||
self, target: spack.spec.Spec, constraint: spack.spec.Spec, loose: bool = False
|
|
||||||
) -> bool:
|
|
||||||
"""Returns true if target spec is ABI compatible to constraint spec"""
|
|
||||||
return self.architecture_compatible(target, constraint) and self.compiler_compatible(
|
|
||||||
target, constraint, loose=loose
|
|
||||||
)
|
|
@ -8,7 +8,6 @@
|
|||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
import spack.abi
|
|
||||||
import spack.compilers
|
import spack.compilers
|
||||||
import spack.config
|
import spack.config
|
||||||
import spack.environment
|
import spack.environment
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
# Copyright 2013-2024 Lawrence Livermore National Security, LLC and other
|
|
||||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
|
||||||
""" Test ABI compatibility helpers"""
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from spack.abi import ABI
|
|
||||||
from spack.spec import Spec
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"target,constraint,expected",
|
|
||||||
[
|
|
||||||
("foo", "bar", True),
|
|
||||||
("platform=linux", "foo", True),
|
|
||||||
("foo", "arch=linux-fedora31-x86_64", True),
|
|
||||||
("arch=linux-fedora31-skylake", "arch=linux-fedora31-skylake", True),
|
|
||||||
("arch=linux-fedora31-skylake", "arch=linux-fedora31-x86_64", False),
|
|
||||||
("platform=linux os=fedora31", "arch=linux-fedora31-x86_64", True),
|
|
||||||
("platform=linux", "arch=linux-fedora31-x86_64", True),
|
|
||||||
("platform=linux os=fedora31", "platform=linux", True),
|
|
||||||
("platform=darwin", "arch=linux-fedora31-x86_64", False),
|
|
||||||
("os=fedora31", "platform=linux", True),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_architecture_compatibility(target, constraint, expected):
|
|
||||||
assert ABI().architecture_compatible(Spec(target), Spec(constraint)) == expected
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"target,constraint,loose,expected",
|
|
||||||
[
|
|
||||||
("foo", "bar", False, True),
|
|
||||||
("%gcc", "foo", False, True),
|
|
||||||
("foo", "%gcc", False, True),
|
|
||||||
("%gcc", "%gcc", False, True),
|
|
||||||
("%gcc", "%intel", False, False),
|
|
||||||
("%gcc", "%clang", False, False),
|
|
||||||
("%gcc@9.1", "%gcc@9.2", False, False), # TODO should be true ?
|
|
||||||
("%gcc@9.2.1", "%gcc@9.2.2", False, False), # TODO should be true ?
|
|
||||||
("%gcc@4.9", "%gcc@9.2", False, False),
|
|
||||||
("%clang@5", "%clang@6", False, False),
|
|
||||||
("%gcc@9.1", "%gcc@9.2", True, True),
|
|
||||||
("%gcc@9.2.1", "%gcc@9.2.2", True, True),
|
|
||||||
("%gcc@4.9", "%gcc@9.2", True, True),
|
|
||||||
("%clang@5", "%clang@6", True, True),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_compiler_compatibility(target, constraint, loose, expected):
|
|
||||||
assert ABI().compiler_compatible(Spec(target), Spec(constraint), loose=loose) == expected
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
|
||||||
"target,constraint,loose,expected",
|
|
||||||
[
|
|
||||||
("foo", "bar", False, True),
|
|
||||||
("%gcc", "platform=linux", False, True),
|
|
||||||
("%gcc@9.2.1", "%gcc@8.3.1 platform=linux", False, False),
|
|
||||||
("%gcc@9.2.1", "%gcc@8.3.1 platform=linux", True, True),
|
|
||||||
("%gcc@9.2.1 arch=linux-fedora31-skylake", "%gcc@9.2.1 platform=linux", False, True),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
def test_compatibility(target, constraint, loose, expected):
|
|
||||||
assert ABI().compatible(Spec(target), Spec(constraint), loose=loose) == expected
|
|
Loading…
Reference in New Issue
Block a user