specs: avoid traversing specs when parsing

The Spec parser currently calls `spec.traverse()` after every parse, in
order to set the platform if it's not set.  We don't need to do a full
traverse -- we can just check the platforrm as new specs are parsed.

This takes about a second off the time required to import all packages in
Spack (from 8s to 7s).

- [x] simplify platform-setting logic in `SpecParser`.
This commit is contained in:
Todd Gamblin 2020-01-28 21:41:35 -08:00
parent a2f8a2321d
commit 3519a17624

View File

@ -1117,6 +1117,18 @@ def _add_dependency(self, spec, deptypes):
self._dependencies[spec.name] = dspec
spec._dependents[self.name] = dspec
def _add_default_platform(self):
"""If a spec has an os or a target and no platform, give it
the default platform.
This is private because it is used by the parser -- it's not
expected to be used outside of ``spec.py``.
"""
arch = self.architecture
if arch and not arch.platform and (arch.os or arch.target):
self._set_architecture(platform=spack.architecture.platform().name)
#
# Public interface
#
@ -4053,14 +4065,6 @@ def do_parse(self):
except spack.parse.ParseError as e:
raise SpecParseError(e)
# If the spec has an os or a target and no platform, give it
# the default platform
platform_default = spack.architecture.platform().name
for spec in specs:
for s in spec.traverse():
if s.architecture and not s.architecture.platform and \
(s.architecture.os or s.architecture.target):
s._set_architecture(platform=platform_default)
return specs
def spec_from_file(self):
@ -4192,6 +4196,7 @@ def spec(self, name):
else:
break
spec._add_default_platform()
return spec
def variant(self, name=None):