>>> spack: Building user/spack 0.17.2-r1 (using abuild 3.4.2-r2) started Thu, 28 Jul 2022 15:37:29 +0000>>> spack: Checking sanity of /root/packages/user/spack/APKBUILD...>>> spack: Analyzing dependencies...(1/5) Installing libffi (3.4.2-r0)(2/5) Installing sqlite-libs (3.38.3-r0)(3/5) Installing python3 (3.10.4-r0)(4/5) Installing python3-dev (3.10.4-r0)(5/5) Installing .makedepends-spack (20220728.153730)OK: 477 MiB in 98 packages>>> spack: Cleaning temporary build dirs...>>> spack: Fetching https://git.adelielinux.org/adelie/spack/-/archive/bb8fbb9b589e667f92ce7d56b3802ba44cb188ec/spack-bb8fbb9b589e667f92ce7d56b3802ba44cb188ec.tar.bz2>>> spack: Fetching https://git.adelielinux.org/adelie/spack/-/archive/bb8fbb9b589e667f92ce7d56b3802ba44cb188ec/spack-bb8fbb9b589e667f92ce7d56b3802ba44cb188ec.tar.bz2>>> spack: Checking sha512sums...spack-bb8fbb9b589e667f92ce7d56b3802ba44cb188ec.tar.bz2: OK>>> spack: Unpacking /var/cache/distfiles/spack-bb8fbb9b589e667f92ce7d56b3802ba44cb188ec.tar.bz2...==> "github-actions-v0.1" is now untrusted and will not be used for bootstrapping==> "github-actions-v0.2" is now untrusted and will not be used for bootstrapping==> Error: the "target" field in compilers.yaml accepts only target families [replace "i686" with "x86" in "gcc@8.5.0" specification]>>> ERROR: spack: check failed>>> spack: Uninstalling dependencies...(1/5) Purging .makedepends-spack (20220728.153730)(2/5) Purging python3-dev (3.10.4-r0)(3/5) Purging python3 (3.10.4-r0)(4/5) Purging libffi (3.4.2-r0)(5/5) Purging sqlite-libs (3.38.3-r0)OK: 373 MiB in 93 packages
Note: the easiest way to reproduce this is with setarch i686 $SHELL.
Edited
Designs
Child items
0
Show closed items
No child items are currently assigned. Use child items to break down this issue into smaller parts.
Linked items
0
Link issues together to show that they're related.
Learn more.
Note that any environment variables used to specify configuration file locations do NOT seem to work with the spack compiler find command, and a new compilers.yaml file will be written to ./etc/spack/linux/. This file may have precedence over user-specified configuration locations. (This is a Spack bug, see above).
Anyway, here is what is automatically detected:
builder on x86_64 ~/packages/user/spack/src/spack $ ./bin/spack compiler find==> Added 1 new compiler to /root/packages/user/spack/src/spack/etc/spack/linux/compilers.yaml gcc@8.5.0==> Compilers are defined in the following files: /root/packages/user/spack/src/spack/etc/spack/linux/compilers.yamlbuilder on x86_64 ~/packages/user/spack/src/spack $ cat /root/packages/user/spack/src/spack/etc/spack/linux/compilers.yamlcompilers:- compiler: spec: gcc@8.5.0 paths: cc: /usr/local/bin/gcc cxx: /usr/local/bin/g++ f77: null fc: null flags: {} operating_system: adelie1 target: i686 modules: [] environment: {} extra_rpaths: []
The error comes from here, because i686 is not considered a microarch "family", but belongs to the family we want:
# from lib/spack/spack/compilers/__init__.pydefget_compilers(config,cspec=None,arch_spec=None):compilers=[]foritemsinconfig:items=items["compiler"]ifcspecanditems["spec"]!=str(cspec):continue# If an arch spec is given, confirm that this compiler# is for the given operating systemos=items.get("operating_system",None)ifarch_specandos!=arch_spec.os:continue# If an arch spec is given, confirm that this compiler# is for the given target. If the target is 'any', match# any given arch spec. If the compiler has no assigned# target this is an old compiler config file, skip this logic.target=items.get("target",None)try:current_target=archspec.cpu.TARGETS[str(arch_spec.target)]family=str(current_target.family)exceptKeyError:# TODO: Check if this exception handling makes sense, or if we# TODO: need to change / refactor testsfamily=arch_spec.targetexceptAttributeError:assertarch_specisNoneifarch_specandtargetand(target!=familyandtarget!="any"):# If the family of the target is the family we are seeking,# there's an error in the underlying configurationifarchspec.cpu.TARGETS[target].family==family:msg=('the "target" field in compilers.yaml accepts only ''target families [replace "{0}" with "{1}"'' in "{2}" specification]')msg=msg.format(str(target),family,items.get("spec","??"))raiseValueError(msg)continuecompilers.append(_compiler_from_config_entry(items))returncompilers
Changing i686 (derived) to x86 (family) does work. Or, as suggested in the thread above, clearing the from field in lib/spack/llnl/util/cpu/microarchitectures.json for i686 also works because it tricks Spack into thinking it is a family.
It is confusing because documentation suggests this is a correct way to specify target, which of course is not the literal string x86_64 as would be the family name:
$ spack install zlib target=sandybridge
So does this mean target= is different from the target in compilers.yaml? I'm not sure.
We definitely do not want to edit microarchitectures.json because Spack is a unique package in that our users will be compiling packages on their own systems for their target CPUs.
We also need to consider, if a user installs their own compiler(s), then they are fully permitted to use them with Spack, so distributing a compilers.yaml with our package is not an option.
defhost():"""Detects the host micro-architecture and returns it."""# Retrieve a dictionary with raw information on the host's cpuinfo=raw_info_dictionary()# Get a list of possible candidates for this micro-architecturecandidates=compatible_microarchitectures(info)...
compatible_microarchitectures(info) is implemented here, and seems to rely on a "compatibility check" to decorate based on CPU feature flags what is the correct family:
defcompatible_microarchitectures(info):"""Returns an unordered list of known micro-architectures that are compatible with the info dictionary passed as argument. Args: info (dict): dictionary containing information on the host cpu"""architecture_family=_machine()# If a tester is not registered, be conservative and assume no known# target is compatible with the hosttester=COMPATIBILITY_CHECKS.get(architecture_family,lambdax,y:False)return[xforxinTARGETS.values()iftester(info,x)]or[generic_microarchitecture(architecture_family)]
Note 1: the line architecture_family = _machine() is ... not really precise. More accurately:
diff --git a/lib/spack/external/archspec/cpu/detect.py b/lib/spack/external/archspec/cpu/detect.pyindex a7cc4481f6..a527a3c17d 100644--- a/lib/spack/external/archspec/cpu/detect.py+++ b/lib/spack/external/archspec/cpu/detect.py@@ -222,12 +222,12 @@ def compatible_microarchitectures(info): Args: info (dict): dictionary containing information on the host cpu """- architecture_family = _machine()+ uname = _machine() # If a tester is not registered, be conservative and assume no known # target is compatible with the host- tester = COMPATIBILITY_CHECKS.get(architecture_family, lambda x, y: False)+ tester = COMPATIBILITY_CHECKS.get(uname, lambda x, y: False) return [x for x in TARGETS.values() if tester(info, x)] or [- generic_microarchitecture(architecture_family)+ generic_microarchitecture(uname) ]
Note 2: info contains e.g. /proc/cpuinfo or equivalent, which we will ignore for now:
Let's pretend the generic_microarchitecture() branch is taken.
_machine() is implemented here:
def_machine():""""Return the machine architecture we are on"""operating_system=platform.system()# If we are not on Darwin, trust what Python tells usifoperating_system!="Darwin":returnplatform.machine()...
and this returns either x86_64 or i686. The former is considered a "family", while the latter is not. This is the root cause.
generic_microarchitecture() begins with:
classMicroarchitecture(object):"""Represents a specific CPU micro-architecture. Args: name (str): name of the micro-architecture (e.g. skylake). ...
There is confusion around the terminology involved. As far as I can tell, this is what is intended:
"micro-architecture" refers to skylake or i686
"generic architecture" is synonymous with "family" which means x86_64 or x86
Discussion with @becker33 on Slack has led to this proposed patch:
diff --git a/lib/spack/external/archspec/cpu/detect.py b/lib/spack/external/archspec/cpu/detect.pyindex a7cc4481f6..cadd593ca2 100644--- a/lib/spack/external/archspec/cpu/detect.py+++ b/lib/spack/external/archspec/cpu/detect.py@@ -92,7 +92,8 @@ def _machine(): # If we are not on Darwin, trust what Python tells us if operating_system != "Darwin":- return platform.machine()+ machine = platform.machine()+ return TARGETS[machine].family.name if machine in TARGETS else machine # On Darwin it might happen that we are on M1, but using an interpreter # built for x86_64. In that case "platform.machine() == 'x86_64'", so we