From 60cf3fdb34da13684778bb1d4787f68d8a79387c Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Sun, 11 Aug 2019 18:01:16 -0700 Subject: 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. --- lib/spack/spack/solver/asp.py | 74 ++++++++++++++++++++++++++++++++---- lib/spack/spack/solver/concretize.lp | 43 +++++++++++++++++++++ lib/spack/spack/solver/display.lp | 2 + 3 files changed, 112 insertions(+), 7 deletions(-) (limited to 'lib') diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index 6d80b20b74..0a1bdc3057 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -20,6 +20,7 @@ import spack import spack.cmd import spack.spec import spack.package +import spack.package_prefs import spack.repo from spack.util.executable import which from spack.version import ver @@ -187,6 +188,45 @@ class AspGenerator(object): self._or(fn.version(spec.name, v) for v in possible), 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): pkg = packagize(pkg) @@ -215,6 +255,9 @@ class AspGenerator(object): fn.node(pkg.name)) self.out.write('\n') + # default compilers for this package + self.package_compiler_defaults(pkg) + # dependencies for name, conditions in pkg.dependencies.items(): for cond, dep in conditions.items(): @@ -239,14 +282,28 @@ class AspGenerator(object): for vname, variant in spec.variants.items(): 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 # dependencies - # compiler # external_path # external_module # compiler_flags # 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): """Write an ASP program for specs. @@ -265,12 +322,8 @@ class AspGenerator(object): self.out.write(concretize_lp.decode("utf-8")) self.h1('General Constraints') - - 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)) + self.compiler_defaults() + self.arch_defaults() self.h1('Package Constraints') for pkg in pkgs: @@ -321,6 +374,13 @@ class ResultParser(object): def version(self, pkg, 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): self._specs[pkg]._add_dependency( self._specs[dep], ('link', 'run')) diff --git a/lib/spack/spack/solver/concretize.lp b/lib/spack/spack/solver/concretize.lp index b416b35e2b..bb4b22897f 100644 --- a/lib/spack/spack/solver/concretize.lp +++ b/lib/spack/spack/solver/concretize.lp @@ -6,6 +6,9 @@ { arch_platform(P, A) : arch_platform(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). +{ 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. { 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_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). + +%----------------------------------------------------------------------------- +% 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). diff --git a/lib/spack/spack/solver/display.lp b/lib/spack/spack/solver/display.lp index 61f12cd6fd..4c94720fc7 100644 --- a/lib/spack/spack/solver/display.lp +++ b/lib/spack/spack/solver/display.lp @@ -10,3 +10,5 @@ #show arch_platform/2. #show arch_os/2. #show arch_target/2. +#show node_compiler/2. +#show node_compiler_version/3. -- cgit v1.2.3-60-g2f50