diff --git a/lib/spack/env/cc b/lib/spack/env/cc index b5913c5f10..6de7df3576 100755 --- a/lib/spack/env/cc +++ b/lib/spack/env/cc @@ -107,19 +107,19 @@ case "$command" in cpp) mode=cpp ;; - cc|c89|c99|gcc|clang|armclang|icc|pgcc|xlc|xlc_r|fcc) + cc|c89|c99|gcc|clang|armclang|icc|pgcc|nvc|xlc|xlc_r|fcc) command="$SPACK_CC" language="C" comp="CC" lang_flags=C ;; - c++|CC|g++|clang++|armclang++|icpc|pgc++|xlc++|xlc++_r|FCC) + c++|CC|g++|clang++|armclang++|icpc|pgc++|nvc++|xlc++|xlc++_r|FCC) command="$SPACK_CXX" language="C++" comp="CXX" lang_flags=CXX ;; - ftn|f90|fc|f95|gfortran|flang|armflang|ifort|pgfortran|xlf90|xlf90_r|nagfor|frt) + ftn|f90|fc|f95|gfortran|flang|armflang|ifort|pgfortran|nvfortran|xlf90|xlf90_r|nagfor|frt) command="$SPACK_FC" language="Fortran 90" comp="FC" diff --git a/lib/spack/env/nvhpc/nvc b/lib/spack/env/nvhpc/nvc new file mode 120000 index 0000000000..82c2b8e90a --- /dev/null +++ b/lib/spack/env/nvhpc/nvc @@ -0,0 +1 @@ +../cc \ No newline at end of file diff --git a/lib/spack/env/nvhpc/nvc++ b/lib/spack/env/nvhpc/nvc++ new file mode 120000 index 0000000000..82c2b8e90a --- /dev/null +++ b/lib/spack/env/nvhpc/nvc++ @@ -0,0 +1 @@ +../cc \ No newline at end of file diff --git a/lib/spack/env/nvhpc/nvfortran b/lib/spack/env/nvhpc/nvfortran new file mode 120000 index 0000000000..82c2b8e90a --- /dev/null +++ b/lib/spack/env/nvhpc/nvfortran @@ -0,0 +1 @@ +../cc \ No newline at end of file diff --git a/lib/spack/spack/compilers/nvhpc.py b/lib/spack/spack/compilers/nvhpc.py new file mode 100644 index 0000000000..c102320132 --- /dev/null +++ b/lib/spack/spack/compilers/nvhpc.py @@ -0,0 +1,90 @@ +# Copyright 2013-2020 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) + +from spack.compiler import Compiler + + +class Nvhpc(Compiler): + # Subclasses use possible names of C compiler + cc_names = ['nvc'] + + # Subclasses use possible names of C++ compiler + cxx_names = ['nvc++'] + + # Subclasses use possible names of Fortran 77 compiler + f77_names = ['nvfortran'] + + # Subclasses use possible names of Fortran 90 compiler + fc_names = ['nvfortran'] + + # Named wrapper links within build_env_path + link_paths = {'cc': 'nvhpc/nvc', + 'cxx': 'nvhpc/nvc++', + 'f77': 'nvhpc/nvfortran', + 'fc': 'nvhpc/nvfortran'} + + PrgEnv = 'PrgEnv-nvhpc' + PrgEnv_compiler = 'nvhpc' + + version_argument = '--version' + version_regex = r'nv[^ ]* (?:[^ ]+ Dev-r)?([0-9.]+)(?:-[0-9]+)?' + + @property + def verbose_flag(self): + return "-v" + + @property + def debug_flags(self): + return ['-g', '-gopt'] + + @property + def opt_flags(self): + return ['-O', '-O0', '-O1', '-O2', '-O3', '-O4'] + + @property + def openmp_flag(self): + return "-mp" + + @property + def cc_pic_flag(self): + return "-fpic" + + @property + def cxx_pic_flag(self): + return "-fpic" + + @property + def f77_pic_flag(self): + return "-fpic" + + @property + def fc_pic_flag(self): + return "-fpic" + + @property + def c99_flag(self): + return '-c99' + + @property + def c11_flag(self): + return '-c11' + + @property + def cxx11_flag(self): + return '--c++11' + + @property + def cxx14_flag(self): + return '--c++14' + + @property + def cxx17_flag(self): + return '--c++17' + + @property + def stdcxx_libs(self): + return ('-c++libs', ) + + required_libs = ['libnvc', 'libnvf'] diff --git a/lib/spack/spack/test/compilers/basics.py b/lib/spack/spack/test/compilers/basics.py index 762a2e67aa..9af416dd7b 100644 --- a/lib/spack/spack/test/compilers/basics.py +++ b/lib/spack/spack/test/compilers/basics.py @@ -533,6 +533,23 @@ def test_nag_flags(): 'nag@1.0') +def test_nvhpc_flags(): + supported_flag_test("openmp_flag", "-mp", "nvhpc@20.9") + supported_flag_test("cxx11_flag", "--c++11", "nvhpc@20.9") + supported_flag_test("cxx14_flag", "--c++14", "nvhpc@20.9") + supported_flag_test("cxx17_flag", "--c++17", "nvhpc@20.9") + supported_flag_test("c99_flag", "-c99", "nvhpc@20.9") + supported_flag_test("c11_flag", "-c11", "nvhpc@20.9") + supported_flag_test("cc_pic_flag", "-fpic", "nvhpc@20.9") + supported_flag_test("cxx_pic_flag", "-fpic", "nvhpc@20.9") + supported_flag_test("f77_pic_flag", "-fpic", "nvhpc@20.9") + supported_flag_test("fc_pic_flag", "-fpic", "nvhpc@20.9") + supported_flag_test("debug_flags", ['-g', '-gopt'], 'nvhpc@20.9') + supported_flag_test("opt_flags", ['-O', '-O0', '-O1', '-O2', '-O3', '-O4'], + 'nvhpc@20.9') + supported_flag_test("stdcxx_libs", ('-c++libs',), 'nvhpc@20.9') + + def test_pgi_flags(): supported_flag_test("openmp_flag", "-mp", "pgi@1.0") supported_flag_test("cxx11_flag", "-std=c++11", "pgi@1.0") diff --git a/lib/spack/spack/test/compilers/detection.py b/lib/spack/spack/test/compilers/detection.py index 634189d02a..4cb80090b5 100644 --- a/lib/spack/spack/test/compilers/detection.py +++ b/lib/spack/spack/test/compilers/detection.py @@ -15,6 +15,7 @@ import spack.compilers.gcc import spack.compilers.intel import spack.compilers.nag +import spack.compilers.nvhpc import spack.compilers.pgi import spack.compilers.xl import spack.compilers.xl_r @@ -157,6 +158,60 @@ def test_nag_version_detection(version_str, expected_version): assert version == expected_version +@pytest.mark.parametrize('version_str,expected_version', [ + # C compiler on x86-64 + ('nvc 20.9-0 LLVM 64-bit target on x86-64 Linux -tp haswell\n' + 'NVIDIA Compilers and Tools\n' + 'Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.', + '20.9'), + # C++ compiler on x86-64 + ('nvc++ 20.9-0 LLVM 64-bit target on x86-64 Linux -tp haswell\n' + 'NVIDIA Compilers and Tools\n' + 'Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.', + '20.9'), + # Fortran compiler on x86-64 + ('nvfortran 20.9-0 LLVM 64-bit target on x86-64 Linux -tp haswell\n' + 'NVIDIA Compilers and Tools\n' + 'Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.', + '20.9'), + # C compiler on Power + ('nvc 20.9-0 linuxpower target on Linuxpower\n' + 'NVIDIA Compilers and Tools\n' + 'Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.', + '20.9'), + # C++ compiler on Power + ('nvc++ 20.9-0 linuxpower target on Linuxpower\n' + 'NVIDIA Compilers and Tools\n' + 'Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.', + '20.9'), + # Fortran compiler on Power + ('nvfortran 20.9-0 linuxpower target on Linuxpower\n' + 'NVIDIA Compilers and Tools\n' + 'Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.', + '20.9'), + # C compiler on Arm + ('nvc 20.9-0 linuxarm64 target on aarch64 Linux\n' + 'NVIDIA Compilers and Tools\n' + 'Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.', + '20.9'), + # C++ compiler on Arm + ('nvc++ 20.9-0 linuxarm64 target on aarch64 Linux\n' + 'NVIDIA Compilers and Tools\n' + 'Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.', + '20.9'), + # Fortran compiler on Arm + ('nvfortran 20.9-0 linuxarm64 target on aarch64 Linux\n' + 'NVIDIA Compilers and Tools\n' + 'Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.', + '20.9') +]) +def test_nvhpc_version_detection(version_str, expected_version): + version = spack.compilers.nvhpc.Nvhpc.extract_version_from_output( + version_str + ) + assert version == expected_version + + @pytest.mark.parametrize('version_str,expected_version', [ # Output on x86-64 ('pgcc 15.10-0 64-bit target on x86-64 Linux -tp sandybridge\n' diff --git a/var/spack/repos/builtin/packages/nvhpc/package.py b/var/spack/repos/builtin/packages/nvhpc/package.py new file mode 100644 index 0000000000..7a8ce0f36a --- /dev/null +++ b/var/spack/repos/builtin/packages/nvhpc/package.py @@ -0,0 +1,139 @@ +# Copyright 2013-2019 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) +# +# Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. + +from spack import * +from spack.util.prefix import Prefix +import os +import platform + +# FIXME Remove hack for polymorphic versions +# This package uses a ugly hack to be able to dispatch, given the same +# version, to different binary packages based on the platform that is +# running spack. See #13827 for context. +# If you need to add a new version, please be aware that: +# - versions in the following dict are automatically added to the package +# - version tuple must be in the form (checksum, url) +# - checksum must be sha256 +# - package key must be in the form '{os}-{arch}' where 'os' is in the +# format returned by platform.system() and 'arch' by platform.machine() +_versions = { + '20.9': { + 'Linux-aarch64': ('3bfb3d17f5ee99998bcc30d738e818d3b94b828e2d8da7db48bf152a01e22023', 'https://developer.download.nvidia.com/hpc-sdk/20.9/nvhpc_2020_209_Linux_aarch64_cuda_11.0.tar.gz'), + 'Linux-ppc64le': ('b2966d4047e1dfd981ce63b333ab9c0acbdc2a6a505fa217456ac9fa3b8e7474', 'https://developer.download.nvidia.com/hpc-sdk/20.9/nvhpc_2020_209_Linux_ppc64le_cuda_multi.tar.gz'), + 'Linux-x86_64': ('fe665ab611b03846a90bd70ca4e08c1e59ab527364b971ed0304e0ae73c778d8', 'https://developer.download.nvidia.com/hpc-sdk/20.9/nvhpc_2020_209_Linux_x86_64_cuda_multi.tar.gz')}, + '20.7': { + 'Linux-aarch64': ('5b83ca1919199ac0aa609309b31c345c5a6453dd3131fddeef9e3ee9059a0e9b', 'https://developer.download.nvidia.com/hpc-sdk/20.7/nvhpc_2020_207_Linux_aarch64_cuda_11.0.tar.gz'), + 'Linux-ppc64le': ('800ead240bdf61611910b2f6df24ee1d7359377ff3767c923738dd81fcea9312', 'https://developer.download.nvidia.com/hpc-sdk/20.7/nvhpc_2020_207_Linux_ppc64le_cuda_multi.tar.gz'), + 'Linux-x86_64': ('a5c5c8726d2210f2310a852c6d6e03c9ef8c75e3643e9c94e24909f5e9c2ea7a', 'https://developer.download.nvidia.com/hpc-sdk/20.7/nvhpc_2020_207_Linux_x86_64_cuda_multi.tar.gz')} +} + + +class Nvhpc(Package): + """The NVIDIA HPC SDK is a comprehensive suite of compilers, libraries + and tools essential to maximizing developer productivity and the + performance and portability of HPC applications. The NVIDIA HPC + SDK C, C++, and Fortran compilers support GPU acceleration of HPC + modeling and simulation applications with standard C++ and + Fortran, OpenACC directives, and CUDA. GPU-accelerated math + libraries maximize performance on common HPC algorithms, and + optimized communications libraries enable standards-based + multi-GPU and scalable systems programming. Performance profiling + and debugging tools simplify porting and optimization of HPC + applications.""" + + homepage = "http://developer.nvidia.com/hpc-sdk" + + maintainers = ['samcmill'] + + for ver, packages in _versions.items(): + key = "{0}-{1}".format(platform.system(), platform.machine()) + pkg = packages.get(key) + if pkg: + version(ver, sha256=pkg[0], url=pkg[1]) + + variant('blas', default=True, + description="Enable BLAS") + variant('install_type', default='single', + values=('single', 'network'), multi=False, + description='Network installs are for installations shared ' + 'by different operating systems') + variant('lapack', default=True, + description="Enable LAPACK") + variant('mpi', default=False, + description="Enable MPI") + + provides('blas', when='+blas') + provides('lapack', when='+lapack') + provides('mpi', when='+mpi') + + def install(self, spec, prefix): + # Enable the silent installation feature + os.environ['NVHPC_SILENT'] = "true" + os.environ['NVHPC_ACCEPT_EULA'] = "accept" + os.environ['NVHPC_INSTALL_DIR'] = prefix + + if spec.variants['install_type'].value == 'network': + os.environ['NVHPC_INSTALL_TYPE'] = "network" + os.environ['NVHPC_INSTALL_LOCAL_DIR'] = \ + "%s/%s/%s/share_objects" % \ + (prefix, 'Linux_%s' % spec.target.family, self.version) + else: + os.environ['NVHPC_INSTALL_TYPE'] = "single" + + # Run install script + os.system("./install") + + def setup_run_environment(self, env): + prefix = Prefix(join_path(self.prefix, + 'Linux_%s' % self.spec.target.family, + self.version, 'compilers')) + + env.set('CC', join_path(prefix.bin, 'nvc')) + env.set('CXX', join_path(prefix.bin, 'nvc++')) + env.set('F77', join_path(prefix.bin, 'nvfortran')) + env.set('FC', join_path(prefix.bin, 'nvfortran')) + + env.prepend_path('PATH', prefix.bin) + env.prepend_path('CPATH', prefix.include) + env.prepend_path('LIBRARY_PATH', prefix.lib) + env.prepend_path('LD_LIBRARY_PATH', prefix.lib) + env.prepend_path('MANPATH', prefix.man) + + if '+mpi' in self.spec: + mpi_prefix = Prefix(join_path(self.prefix, + 'Linux_%s' % self.spec.target.family, + self.version, 'comm_libs', 'mpi')) + env.prepend_path('PATH', mpi_prefix.bin) + env.prepend_path('CPATH', mpi_prefix.include) + env.prepend_path('LD_LIBRARY_PATH', mpi_prefix.lib) + + def setup_dependent_package(self, module, dependent_spec): + if '+mpi' in self.spec or self.provides('mpi'): + mpi_prefix = Prefix(join_path(self.prefix, + 'Linux_%s' % self.spec.target.family, + self.version, 'comm_libs', 'mpi')) + + self.spec.mpicc = join_path(mpi_prefix.bin, 'mpicc') + self.spec.mpicxx = join_path(mpi_prefix.bin, 'mpicxx') + self.spec.mpif77 = join_path(mpi_prefix.bin, 'mpif77') + self.spec.mpifc = join_path(mpi_prefix.bin, 'mpif90') + + @property + def libs(self): + prefix = Prefix(join_path(self.prefix, + 'Linux_%s' % self.spec.target.family, + self.version, 'compilers')) + libs = [] + + if '+blas' in self.spec: + libs.append('libblas') + + if '+lapack' in self.spec: + libs.append('liblapack') + libs.append('libnvf') + + return find_libraries(libs, root=prefix, recursive=True)