concretizer: add basic semantics for compilers
- This handles setting the compiler and falling back to a default compiler, as well as providing default values for compilers/compiler versions. - Versions still aren't quite right -- you can't properly override versions on compiler specs.
This commit is contained in:
parent
f7dce19754
commit
60cf3fdb34
3 changed files with 112 additions and 7 deletions
|
@ -20,6 +20,7 @@
|
||||||
import spack.cmd
|
import spack.cmd
|
||||||
import spack.spec
|
import spack.spec
|
||||||
import spack.package
|
import spack.package
|
||||||
|
import spack.package_prefs
|
||||||
import spack.repo
|
import spack.repo
|
||||||
from spack.util.executable import which
|
from spack.util.executable import which
|
||||||
from spack.version import ver
|
from spack.version import ver
|
||||||
|
@ -187,6 +188,45 @@ def spec_versions(self, spec):
|
||||||
self._or(fn.version(spec.name, v) for v in possible),
|
self._or(fn.version(spec.name, v) for v in possible),
|
||||||
fn.node(spec.name))
|
fn.node(spec.name))
|
||||||
|
|
||||||
|
def compiler_defaults(self):
|
||||||
|
"""Facts about available compilers."""
|
||||||
|
compilers = spack.compilers.all_compiler_specs()
|
||||||
|
|
||||||
|
compiler_versions = collections.defaultdict(lambda: set())
|
||||||
|
for compiler in compilers:
|
||||||
|
compiler_versions[compiler.name].add(compiler.version)
|
||||||
|
|
||||||
|
for compiler in compiler_versions:
|
||||||
|
self.fact(fn.compiler(compiler))
|
||||||
|
self.rule(
|
||||||
|
self._or(
|
||||||
|
fn.compiler_version(compiler, v)
|
||||||
|
for v in sorted(compiler_versions[compiler])),
|
||||||
|
fn.compiler(compiler))
|
||||||
|
|
||||||
|
def package_compiler_defaults(self, pkg):
|
||||||
|
"""Add facts about the default compiler.
|
||||||
|
|
||||||
|
TODO: integrate full set of preferences into the solve (this only
|
||||||
|
TODO: considers the top preference)
|
||||||
|
"""
|
||||||
|
# get list of all compilers
|
||||||
|
compiler_list = spack.compilers.all_compiler_specs()
|
||||||
|
if not compiler_list:
|
||||||
|
raise spack.compilers.NoCompilersError()
|
||||||
|
|
||||||
|
# prefer package preferences, then latest version
|
||||||
|
ppk = spack.package_prefs.PackagePrefs(pkg.name, 'compiler')
|
||||||
|
compiler_list = sorted(
|
||||||
|
compiler_list, key=lambda x: (x.name, x.version), reverse=True)
|
||||||
|
compiler_list = sorted(compiler_list, key=ppk)
|
||||||
|
|
||||||
|
# write out default rules for this package's compilers
|
||||||
|
default_compiler = compiler_list[0]
|
||||||
|
self.fact(fn.node_compiler_default(pkg.name, default_compiler.name))
|
||||||
|
self.fact(fn.node_compiler_default_version(
|
||||||
|
pkg.name, default_compiler.name, default_compiler.version))
|
||||||
|
|
||||||
def pkg_rules(self, pkg):
|
def pkg_rules(self, pkg):
|
||||||
pkg = packagize(pkg)
|
pkg = packagize(pkg)
|
||||||
|
|
||||||
|
@ -215,6 +255,9 @@ def pkg_rules(self, pkg):
|
||||||
fn.node(pkg.name))
|
fn.node(pkg.name))
|
||||||
self.out.write('\n')
|
self.out.write('\n')
|
||||||
|
|
||||||
|
# default compilers for this package
|
||||||
|
self.package_compiler_defaults(pkg)
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
for name, conditions in pkg.dependencies.items():
|
for name, conditions in pkg.dependencies.items():
|
||||||
for cond, dep in conditions.items():
|
for cond, dep in conditions.items():
|
||||||
|
@ -239,14 +282,28 @@ def spec_rules(self, spec):
|
||||||
for vname, variant in spec.variants.items():
|
for vname, variant in spec.variants.items():
|
||||||
self.fact(fn.variant_set(spec.name, vname, variant.value))
|
self.fact(fn.variant_set(spec.name, vname, variant.value))
|
||||||
|
|
||||||
|
# compiler and compiler version
|
||||||
|
if spec.compiler:
|
||||||
|
self.fact(fn.node_compiler_set(spec.name, spec.compiler.name))
|
||||||
|
if spec.compiler.concrete:
|
||||||
|
self.fact(fn.node_compiler_version_set(
|
||||||
|
spec.name, spec.compiler.name, spec.compiler.version))
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
# dependencies
|
# dependencies
|
||||||
# compiler
|
|
||||||
# external_path
|
# external_path
|
||||||
# external_module
|
# external_module
|
||||||
# compiler_flags
|
# compiler_flags
|
||||||
# namespace
|
# namespace
|
||||||
|
|
||||||
|
def arch_defaults(self):
|
||||||
|
"""Add facts about the default architecture for a package."""
|
||||||
|
self.h2('Default architecture')
|
||||||
|
default_arch = spack.spec.ArchSpec(spack.architecture.sys_type())
|
||||||
|
self.fact(fn.arch_platform_default(default_arch.platform))
|
||||||
|
self.fact(fn.arch_os_default(default_arch.os))
|
||||||
|
self.fact(fn.arch_target_default(default_arch.target))
|
||||||
|
|
||||||
def generate_asp_program(self, specs):
|
def generate_asp_program(self, specs):
|
||||||
"""Write an ASP program for specs.
|
"""Write an ASP program for specs.
|
||||||
|
|
||||||
|
@ -265,12 +322,8 @@ def generate_asp_program(self, specs):
|
||||||
self.out.write(concretize_lp.decode("utf-8"))
|
self.out.write(concretize_lp.decode("utf-8"))
|
||||||
|
|
||||||
self.h1('General Constraints')
|
self.h1('General Constraints')
|
||||||
|
self.compiler_defaults()
|
||||||
self.h2('Default architecture')
|
self.arch_defaults()
|
||||||
default_arch = spack.spec.ArchSpec(spack.architecture.sys_type())
|
|
||||||
self.fact(fn.arch_platform_default(default_arch.platform))
|
|
||||||
self.fact(fn.arch_os_default(default_arch.os))
|
|
||||||
self.fact(fn.arch_target_default(default_arch.target))
|
|
||||||
|
|
||||||
self.h1('Package Constraints')
|
self.h1('Package Constraints')
|
||||||
for pkg in pkgs:
|
for pkg in pkgs:
|
||||||
|
@ -321,6 +374,13 @@ def variant_value(self, pkg, name, value):
|
||||||
def version(self, pkg, version):
|
def version(self, pkg, version):
|
||||||
self._specs[pkg].versions = ver([version])
|
self._specs[pkg].versions = ver([version])
|
||||||
|
|
||||||
|
def node_compiler(self, pkg, compiler):
|
||||||
|
self._specs[pkg].compiler = spack.spec.CompilerSpec(compiler)
|
||||||
|
|
||||||
|
def node_compiler_version(self, pkg, compiler, version):
|
||||||
|
self._specs[pkg].compiler.versions = spack.version.VersionList(
|
||||||
|
[version])
|
||||||
|
|
||||||
def depends_on(self, pkg, dep):
|
def depends_on(self, pkg, dep):
|
||||||
self._specs[pkg]._add_dependency(
|
self._specs[pkg]._add_dependency(
|
||||||
self._specs[dep], ('link', 'run'))
|
self._specs[dep], ('link', 'run'))
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
{ arch_platform(P, A) : arch_platform(P, A) } = 1 :- node(P).
|
{ arch_platform(P, A) : arch_platform(P, A) } = 1 :- node(P).
|
||||||
{ arch_os(P, A) : arch_os(P, A) } = 1 :- node(P).
|
{ arch_os(P, A) : arch_os(P, A) } = 1 :- node(P).
|
||||||
{ arch_target(P, T) : arch_target(P, T) } = 1 :- node(P).
|
{ arch_target(P, T) : arch_target(P, T) } = 1 :- node(P).
|
||||||
|
{ node_compiler(P, C) : node_compiler(P, C) } = 1 :- node(P).
|
||||||
|
{ node_compiler_version(P, C, V) :
|
||||||
|
node_compiler_version(P, C, V) } = 1 :- node(P).
|
||||||
|
|
||||||
% one variant value for single-valued variants.
|
% one variant value for single-valued variants.
|
||||||
{ variant_value(P, V, X) : variant_value(P, V, X) } = 1
|
{ variant_value(P, V, X) : variant_value(P, V, X) } = 1
|
||||||
|
@ -65,3 +68,43 @@ arch_target(P, A) :- node(P), not arch_target_set(P), arch_target_default(A).
|
||||||
arch_platform_set(D, A) :- node(D), depends_on(P, D), arch_platform_set(P, A).
|
arch_platform_set(D, A) :- node(D), depends_on(P, D), arch_platform_set(P, A).
|
||||||
arch_os_set(D, A) :- node(D), depends_on(P, D), arch_os_set(P, A).
|
arch_os_set(D, A) :- node(D), depends_on(P, D), arch_os_set(P, A).
|
||||||
arch_target_set(D, A) :- node(D), depends_on(P, D), arch_target_set(P, A).
|
arch_target_set(D, A) :- node(D), depends_on(P, D), arch_target_set(P, A).
|
||||||
|
|
||||||
|
%-----------------------------------------------------------------------------
|
||||||
|
% Compiler semantics
|
||||||
|
%-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
% compiler fields are set if set to anything
|
||||||
|
node_compiler_set(P) :- node_compiler_set(P, _).
|
||||||
|
node_compiler_version_set(P, C) :- node_compiler_version_set(P, C, _).
|
||||||
|
|
||||||
|
% avoid warnings: these are set by generated code and it's ok if they're not
|
||||||
|
#defined node_compiler_set/2.
|
||||||
|
#defined node_compiler_version_set/3.
|
||||||
|
|
||||||
|
% if compiler value of node is set to anything, it's the value.
|
||||||
|
node_compiler(P, C)
|
||||||
|
:- node(P), compiler(C), node_compiler_set(P, C).
|
||||||
|
node_compiler_version(P, C, V)
|
||||||
|
:- node(P), compiler(C), compiler_version(C, V), node_compiler(P, C),
|
||||||
|
node_compiler_version_set(P, C, V).
|
||||||
|
|
||||||
|
% node compiler versions can only be from the available compiler versions
|
||||||
|
node_compiler_version(P, C, V)
|
||||||
|
:- node(P), compiler(C), node_compiler(P, C),
|
||||||
|
compiler_version(C, V).
|
||||||
|
|
||||||
|
% if no compiler is set, fall back to default.
|
||||||
|
node_compiler(P, C)
|
||||||
|
:- node(P), compiler(C), not node_compiler_set(P),
|
||||||
|
node_compiler_default(P, C).
|
||||||
|
node_compiler_version(P, C, V)
|
||||||
|
:- node(P), compiler(C), compiler_version(C, V),
|
||||||
|
not node_compiler_version_set(P, C, V),
|
||||||
|
node_compiler_default_version(P, C, V).
|
||||||
|
|
||||||
|
% propagate compiler, compiler version to dependencies
|
||||||
|
node_compiler_set(D, C)
|
||||||
|
:- node(D), compiler(C), depends_on(P, D), node_compiler_set(P, C).
|
||||||
|
node_compiler_version_set(D, C, V)
|
||||||
|
:- node(D), compiler(C), depends_on(P, D), node_compiler(D, C),
|
||||||
|
node_compiler_version_set(P, C, V).
|
||||||
|
|
|
@ -10,3 +10,5 @@
|
||||||
#show arch_platform/2.
|
#show arch_platform/2.
|
||||||
#show arch_os/2.
|
#show arch_os/2.
|
||||||
#show arch_target/2.
|
#show arch_target/2.
|
||||||
|
#show node_compiler/2.
|
||||||
|
#show node_compiler_version/3.
|
||||||
|
|
Loading…
Reference in a new issue