Ejemplo n.º 1
0
class CudaPackage(PackageBase):
    """Auxiliary class which contains CUDA variant, dependencies and conflicts
    and is meant to unify and facilitate its usage.
    """

    # FIXME: keep cuda and cuda_arch separate to make usage easier untill
    # Spack has depends_on(cuda, when='cuda_arch!=None') or alike
    variant('cuda', default=False,
            description='Build with CUDA')
    # see http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#gpu-feature-list
    # https://developer.nvidia.com/cuda-gpus
    variant('cuda_arch', default=None,
            description='CUDA architecture',
            values=('20', '30', '32', '35', '50', '52', '53', '60', '61',
                    '62', '70'),
            multi=True)

    # see http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#nvcc-examples
    # and http://llvm.org/docs/CompileCudaWithLLVM.html#compiling-cuda-code
    @staticmethod
    def cuda_flags(arch_list):
        return [('--generate-code arch=compute_{0},code=sm_{0} '
                 '--generate-code arch=compute_{0},code=compute_{0}').format(s)
                for s in arch_list]

    depends_on("cuda@7:", when='+cuda')

    # CUDA version vs Architecture
    depends_on("cuda@8:", when='cuda_arch=60')
    depends_on("cuda@8:", when='cuda_arch=61')
    depends_on("cuda@8:", when='cuda_arch=62')
    depends_on("cuda@9:", when='cuda_arch=70')

    depends_on('cuda@:8.99', when='cuda_arch=20')

    # Compiler conflicts:
    # https://gist.github.com/ax3l/9489132
    conflicts('%gcc@5:', when='+cuda ^cuda@:7.5')
    conflicts('%gcc@6:', when='+cuda ^cuda@:8.99')
    conflicts('%gcc@7:', when='+cuda ^cuda@:9.99')
    if (platform.system() != "Darwin"):
        conflicts('%clang@:3.4,3.7:', when='+cuda ^[email protected]')
        conflicts('%clang@:3.7,4:', when='+cuda ^cuda@8:9')
    conflicts('%intel@:14,16:', when='+cuda ^[email protected]')
    conflicts('%intel@:14,17:', when='+cuda ^[email protected]')
    conflicts('%intel@:14,18:', when='+cuda ^[email protected]:9')

    # Make sure cuda_arch can not be used without +cuda
    conflicts('~cuda', when='cuda_arch=20')
    conflicts('~cuda', when='cuda_arch=30')
    conflicts('~cuda', when='cuda_arch=32')
    conflicts('~cuda', when='cuda_arch=35')
    conflicts('~cuda', when='cuda_arch=50')
    conflicts('~cuda', when='cuda_arch=52')
    conflicts('~cuda', when='cuda_arch=53')
    conflicts('~cuda', when='cuda_arch=60')
    conflicts('~cuda', when='cuda_arch=61')
    conflicts('~cuda', when='cuda_arch=62')
    conflicts('~cuda', when='cuda_arch=70')
Ejemplo n.º 2
0
class HipPackage(PackageBase):
    """Auxiliary class which contains HIP variant, dependencies and conflicts
    and is meant to unify and facilitate its usage. Closely mimics CudaPackage.

    Maintainers: dtaller
    """

    # https://llvm.org/docs/AMDGPUUsage.html
    # Possible architectures
    amdgpu_targets = (
        'gfx701', 'gfx801', 'gfx802', 'gfx803',
        'gfx900', 'gfx906', 'gfx908', 'gfx1010',
        'gfx1011', 'gfx1012', 'none'
    )

    variant('hip', default=False, description='Enable HIP support')

    # possible amd gpu targets for hip builds
    variant('amdgpu_target', default='none', values=amdgpu_targets)

    depends_on('llvm-amdgpu', when='+hip')
    depends_on('hsa-rocr-dev', when='+hip')
    depends_on('hip', when='+hip')

    # need amd gpu type for hip builds
    conflicts('amdgpu_target=none', when='+hip')

    # Make sure non-'none' amdgpu_targets cannot be used without +hip
    for value in amdgpu_targets[:-1]:
        conflicts('~hip', when='amdgpu_target=' + value)

    # https://github.com/ROCm-Developer-Tools/HIP/blob/master/bin/hipcc
    # It seems that hip-clang does not (yet?) accept this flag, in which case
    # we will still need to set the HCC_AMDGPU_TARGET environment flag in the
    # hip package file. But I will leave this here for future development.
    @staticmethod
    def hip_flags(amdgpu_target):
        return '--amdgpu-target={0}'.format(amdgpu_target)

    # https://llvm.org/docs/AMDGPUUsage.html
    # Possible architectures (not including 'none' option)
    @staticmethod
    def amd_gputargets_list():
        return (
            'gfx701', 'gfx801', 'gfx802', 'gfx803',
            'gfx900', 'gfx906', 'gfx908', 'gfx1010',
            'gfx1011', 'gfx1012'
        )
Ejemplo n.º 3
0
class ROCmPackage(PackageBase):
    """Auxiliary class which contains ROCm variant, dependencies and conflicts
    and is meant to unify and facilitate its usage. Closely mimics CudaPackage.

    Maintainers: dtaller
    """

    # https://llvm.org/docs/AMDGPUUsage.html
    # Possible architectures
    amdgpu_targets = (
        'gfx701', 'gfx801', 'gfx802', 'gfx803',
        'gfx900', 'gfx906', 'gfx908', 'gfx1010',
        'gfx1011', 'gfx1012'
    )

    variant('rocm', default=False, description='Enable ROCm support')

    # possible amd gpu targets for rocm builds
    variant('amdgpu_target',
            description='AMD GPU architecture',
            values=spack.variant.any_combination_of(*amdgpu_targets))

    depends_on('llvm-amdgpu', when='+rocm')
    depends_on('hsa-rocr-dev', when='+rocm')
    depends_on('hip', when='+rocm')

    conflicts('^blt@:0.3.6', when='+rocm')

    # need amd gpu type for rocm builds
    conflicts('amdgpu_target=none', when='+rocm')

    # Make sure amdgpu_targets cannot be used without +rocm
    for value in amdgpu_targets:
        conflicts('~rocm', when='amdgpu_target=' + value)

    # https://github.com/ROCm-Developer-Tools/HIP/blob/master/bin/hipcc
    # It seems that hip-clang does not (yet?) accept this flag, in which case
    # we will still need to set the HCC_AMDGPU_TARGET environment flag in the
    # hip package file. But I will leave this here for future development.
    @staticmethod
    def hip_flags(amdgpu_target):
        archs = ",".join(amdgpu_target)
        return '--amdgpu-target={0}'.format(archs)
Ejemplo n.º 4
0
class PyAtlinter(PythonPackage):
    """Interpolation of section images."""

    homepage = "https://atlas-interpolation.rtfd.io"
    git = "[email protected]:project/proj101/atlas_interpolation.git"

    maintainers = ["EmilieDel", "Stannislav"]

    version(
        "0.2.3",
        url=
        "https://files.pythonhosted.org/packages/57/d3/4cdfaacccff677b32687cbcfd689727bc7b3a8f4485401aa3eca157e5aaf/atlinter-0.2.3.tar.gz",
        sha256=
        "67f102b70bc7eeb450da8af3c19df38610dd081a025f9c04e8f5266d2d0cc6e3",
    )
    version("0.2.2", tag="v0.2.2")
    version("0.2.1", tag="v0.2.1")
    version("0.2.0", tag="v0.2.0")
    version("0.1.1", tag="v0.1.1")
    version("0.1.0", tag="v0.1.0")

    variant("cuda", default=False, description="Enable CUDA support")

    depends_on("[email protected]:", type=("build", "run"))
    depends_on("py-setuptools", type="build")
    depends_on("py-setuptools-scm", type="build")

    # opencv leads to problems:
    # fatal error: opencv2/opencv.hpp: No such file or directory
    depends_on("mxnet+cuda~opencv", when="@0.1.1:+cuda", type=("build", "run"))
    depends_on("mxnet~cuda~opencv", when="@0.1.1:~cuda", type=("build", "run"))
    depends_on("py-atlannot", when="@0.2.2:", type=("build", "run"))
    depends_on("[email protected]", type=("build", "run"))
    depends_on("py-numpy", type=("build", "run"))
    depends_on("py-pillow", type=("build", "run"))
    depends_on("py-pytorch-fid", type=("build", "run"))
    depends_on("py-pynrrd", when="@0.2.2:", type=("build", "run"))
    depends_on("py-pyyaml", when="@0.1.1:", type=("build", "run"))
    depends_on("py-requests", type=("build", "run"))
    depends_on("py-scikit-image", when="@0.2.2:", type=("build", "run"))
    depends_on("py-scipy", when="@0.1.1:", type=("build", "run"))
    depends_on("py-torch+cuda", when="+cuda", type=("build", "run"))
    depends_on("py-torch~cuda~cudnn~nccl", when="~cuda", type=("build", "run"))
    depends_on("py-torchvision", type=("build", "run"))
Ejemplo n.º 5
0
class CMakePackage(PackageBase):
    """Specialized class for packages built using CMake

    For more information on the CMake build system, see:
    https://cmake.org/cmake/help/latest/

    This class provides three phases that can be overridden:

        1. :py:meth:`~.CMakePackage.cmake`
        2. :py:meth:`~.CMakePackage.build`
        3. :py:meth:`~.CMakePackage.install`

    They all have sensible defaults and for many packages the only thing
    necessary will be to override :py:meth:`~.CMakePackage.cmake_args`.
    For a finer tuning you may also override:

        +-----------------------------------------------+--------------------+
        | **Method**                                    | **Purpose**        |
        +===============================================+====================+
        | :py:meth:`~.CMakePackage.root_cmakelists_dir` | Location of the    |
        |                                               | root CMakeLists.txt|
        +-----------------------------------------------+--------------------+
        | :py:meth:`~.CMakePackage.build_directory`     | Directory where to |
        |                                               | build the package  |
        +-----------------------------------------------+--------------------+


    The generator used by CMake can be specified by providing the
    generator attribute. Per
    https://cmake.org/cmake/help/git-master/manual/cmake-generators.7.html,
    the format is: [<secondary-generator> - ]<primary_generator>. The
    full list of primary and secondary generators supported by CMake may
    be found in the documentation for the version of CMake used;
    however, at this time Spack supports only the primary generators
    "Unix Makefiles" and "Ninja." Spack's CMake support is agnostic with
    respect to primary generators. Spack will generate a runtime error
    if the generator string does not follow the prescribed format, or if
    the primary generator is not supported.
    """
    #: Phases of a CMake package
    phases = ['cmake', 'build', 'install']
    #: This attribute is used in UI queries that need to know the build
    #: system base class
    build_system_class = 'CMakePackage'

    build_targets = []  # type: List[str]
    install_targets = ['install']

    build_time_test_callbacks = ['check']

    #: The build system generator to use.
    #:
    #: See ``cmake --help`` for a list of valid generators.
    #: Currently, "Unix Makefiles" and "Ninja" are the only generators
    #: that Spack supports. Defaults to "Unix Makefiles".
    #:
    #: See https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html
    #: for more information.
    generator = 'Unix Makefiles'

    # https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html
    variant('build_type', default='RelWithDebInfo',
            description='CMake build type',
            values=('Debug', 'Release', 'RelWithDebInfo', 'MinSizeRel'))

    # https://cmake.org/cmake/help/latest/variable/CMAKE_INTERPROCEDURAL_OPTIMIZATION.html
    variant('ipo', default=False,
            description='CMake interprocedural optimization')
    # CMAKE_INTERPROCEDURAL_OPTIMIZATION only exists for CMake >= 3.9
    conflicts('+ipo', when='^cmake@:3.8',
              msg='+ipo is not supported by CMake < 3.9')

    depends_on('cmake', type='build')

    @property
    def archive_files(self):
        """Files to archive for packages based on CMake"""
        return [os.path.join(self.build_directory, 'CMakeCache.txt')]

    @property
    def root_cmakelists_dir(self):
        """The relative path to the directory containing CMakeLists.txt

        This path is relative to the root of the extracted tarball,
        not to the ``build_directory``. Defaults to the current directory.

        :return: directory containing CMakeLists.txt
        """
        return self.stage.source_path

    @property
    def std_cmake_args(self):
        """Standard cmake arguments provided as a property for
        convenience of package writers

        :return: standard cmake arguments
        """
        # standard CMake arguments
        std_cmake_args = CMakePackage._std_args(self)
        std_cmake_args += getattr(self, 'cmake_flag_args', [])
        return std_cmake_args

    @staticmethod
    def _std_args(pkg):
        """Computes the standard cmake arguments for a generic package"""
        try:
            generator = pkg.generator
        except AttributeError:
            generator = 'Unix Makefiles'

        # Make sure a valid generator was chosen
        valid_primary_generators = ['Unix Makefiles', 'Ninja']
        primary_generator = _extract_primary_generator(generator)
        if primary_generator not in valid_primary_generators:
            msg  = "Invalid CMake generator: '{0}'\n".format(generator)
            msg += "CMakePackage currently supports the following "
            msg += "primary generators: '{0}'".\
                   format("', '".join(valid_primary_generators))
            raise InstallError(msg)

        try:
            build_type = pkg.spec.variants['build_type'].value
        except KeyError:
            build_type = 'RelWithDebInfo'

        try:
            ipo = pkg.spec.variants['ipo'].value
        except KeyError:
            ipo = False

        define = CMakePackage.define
        args = [
            '-G', generator,
            define('CMAKE_INSTALL_PREFIX', pkg.prefix),
            define('CMAKE_BUILD_TYPE', build_type),
        ]

        # CMAKE_INTERPROCEDURAL_OPTIMIZATION only exists for CMake >= 3.9
        if pkg.spec.satisfies('^[email protected]:'):
            args.append(define('CMAKE_INTERPROCEDURAL_OPTIMIZATION', ipo))

        if primary_generator == 'Unix Makefiles':
            args.append(define('CMAKE_VERBOSE_MAKEFILE', True))

        if platform.mac_ver()[0]:
            args.extend([
                define('CMAKE_FIND_FRAMEWORK', "LAST"),
                define('CMAKE_FIND_APPBUNDLE', "LAST"),
            ])

        # Set up CMake rpath
        args.extend([
            define('CMAKE_INSTALL_RPATH_USE_LINK_PATH', False),
            define('CMAKE_INSTALL_RPATH',
                   spack.build_environment.get_rpaths(pkg)),
        ])
        # CMake's find_package() looks in CMAKE_PREFIX_PATH first, help CMake
        # to find immediate link dependencies in right places:
        deps = [d.prefix for d in
                pkg.spec.dependencies(deptype=('build', 'link'))]
        deps = filter_system_paths(deps)
        args.append(define('CMAKE_PREFIX_PATH', deps))
        return args

    @staticmethod
    def define(cmake_var, value):
        """Return a CMake command line argument that defines a variable.

        The resulting argument will convert boolean values to OFF/ON
        and lists/tuples to CMake semicolon-separated string lists. All other
        values will be interpreted as strings.

        Examples:

            .. code-block:: python

                [define('BUILD_SHARED_LIBS', True),
                 define('CMAKE_CXX_STANDARD', 14),
                 define('swr', ['avx', 'avx2'])]

            will generate the following configuration options:

            .. code-block:: console

                ["-DBUILD_SHARED_LIBS:BOOL=ON",
                 "-DCMAKE_CXX_STANDARD:STRING=14",
                 "-DSWR:STRING=avx;avx2]

        """
        # Create a list of pairs. Each pair includes a configuration
        # option and whether or not that option is activated
        if isinstance(value, bool):
            kind = 'BOOL'
            value = "ON" if value else "OFF"
        else:
            kind = 'STRING'
            if isinstance(value, (list, tuple)):
                value = ";".join(str(v) for v in value)
            else:
                value = str(value)

        return "".join(["-D", cmake_var, ":", kind, "=", value])

    def define_from_variant(self, cmake_var, variant=None):
        """Return a CMake command line argument from the given variant's value.

        The optional ``variant`` argument defaults to the lower-case transform
        of ``cmake_var``.

        This utility function is similar to
        :py:meth:`~.AutotoolsPackage.with_or_without`.

        Examples:

            Given a package with:

            .. code-block:: python

                variant('cxxstd', default='11', values=('11', '14'),
                        multi=False, description='')
                variant('shared', default=True, description='')
                variant('swr', values=any_combination_of('avx', 'avx2'),
                        description='')

            calling this function like:

            .. code-block:: python

                [define_from_variant('BUILD_SHARED_LIBS', 'shared'),
                 define_from_variant('CMAKE_CXX_STANDARD', 'cxxstd'),
                 define_from_variant('SWR')]

            will generate the following configuration options:

            .. code-block:: console

                ["-DBUILD_SHARED_LIBS:BOOL=ON",
                 "-DCMAKE_CXX_STANDARD:STRING=14",
                 "-DSWR:STRING=avx;avx2]

            for ``<spec-name> cxxstd=14 +shared swr=avx,avx2``
        """

        if variant is None:
            variant = cmake_var.lower()

        if variant not in self.variants:
            raise KeyError(
                '"{0}" is not a variant of "{1}"'.format(variant, self.name))

        value = self.spec.variants[variant].value
        if isinstance(value, (tuple, list)):
            # Sort multi-valued variants for reproducibility
            value = sorted(value)

        return self.define(cmake_var, value)

    def flags_to_build_system_args(self, flags):
        """Produces a list of all command line arguments to pass the specified
        compiler flags to cmake. Note CMAKE does not have a cppflags option,
        so cppflags will be added to cflags, cxxflags, and fflags to mimic the
        behavior in other tools."""
        # Has to be dynamic attribute due to caching
        setattr(self, 'cmake_flag_args', [])

        flag_string = '-DCMAKE_{0}_FLAGS={1}'
        langs = {'C': 'c', 'CXX': 'cxx', 'Fortran': 'f'}

        # Handle language compiler flags
        for lang, pre in langs.items():
            flag = pre + 'flags'
            # cmake has no explicit cppflags support -> add it to all langs
            lang_flags = ' '.join(flags.get(flag, []) + flags.get('cppflags',
                                                                  []))
            if lang_flags:
                self.cmake_flag_args.append(flag_string.format(lang,
                                                               lang_flags))

        # Cmake has different linker arguments for different build types.
        # We specify for each of them.
        if flags['ldflags']:
            ldflags = ' '.join(flags['ldflags'])
            ld_string = '-DCMAKE_{0}_LINKER_FLAGS={1}'
            # cmake has separate linker arguments for types of builds.
            for type in ['EXE', 'MODULE', 'SHARED', 'STATIC']:
                self.cmake_flag_args.append(ld_string.format(type, ldflags))

        # CMake has libs options separated by language. Apply ours to each.
        if flags['ldlibs']:
            libs_flags = ' '.join(flags['ldlibs'])
            libs_string = '-DCMAKE_{0}_STANDARD_LIBRARIES={1}'
            for lang in langs:
                self.cmake_flag_args.append(libs_string.format(lang,
                                                               libs_flags))

    @property
    def build_dirname(self):
        """Returns the directory name to use when building the package

        :return: name of the subdirectory for building the package
        """
        return 'spack-build-%s' % self.spec.dag_hash(7)

    @property
    def build_directory(self):
        """Returns the directory to use when building the package

        :return: directory where to build the package
        """
        return os.path.join(self.stage.path, self.build_dirname)

    def cmake_args(self):
        """Produces a list containing all the arguments that must be passed to
        cmake, except:

            * CMAKE_INSTALL_PREFIX
            * CMAKE_BUILD_TYPE

        which will be set automatically.

        :return: list of arguments for cmake
        """
        return []

    def cmake(self, spec, prefix):
        """Runs ``cmake`` in the build directory"""
        options = self.std_cmake_args
        options += self.cmake_args()
        options.append(os.path.abspath(self.root_cmakelists_dir))
        with working_dir(self.build_directory, create=True):
            inspect.getmodule(self).cmake(*options)

    def build(self, spec, prefix):
        """Make the build targets"""
        with working_dir(self.build_directory):
            if self.generator == 'Unix Makefiles':
                inspect.getmodule(self).make(*self.build_targets)
            elif self.generator == 'Ninja':
                self.build_targets.append("-v")
                inspect.getmodule(self).ninja(*self.build_targets)

    def install(self, spec, prefix):
        """Make the install targets"""
        with working_dir(self.build_directory):
            if self.generator == 'Unix Makefiles':
                inspect.getmodule(self).make(*self.install_targets)
            elif self.generator == 'Ninja':
                inspect.getmodule(self).ninja(*self.install_targets)

    run_after('build')(PackageBase._run_default_build_time_test_callbacks)

    def check(self):
        """Searches the CMake-generated Makefile for the target ``test``
        and runs it if found.
        """
        with working_dir(self.build_directory):
            if self.generator == 'Unix Makefiles':
                self._if_make_target_execute('test',
                                             jobs_env='CTEST_PARALLEL_LEVEL')
                self._if_make_target_execute('check')
            elif self.generator == 'Ninja':
                self._if_ninja_target_execute('test',
                                              jobs_env='CTEST_PARALLEL_LEVEL')
                self._if_ninja_target_execute('check')

    # Check that self.prefix is there after installation
    run_after('install')(PackageBase.sanity_check_prefix)
Ejemplo n.º 6
0
class CudaPackage(PackageBase):
    """Auxiliary class which contains CUDA variant, dependencies and conflicts
    and is meant to unify and facilitate its usage.

    Maintainers: ax3l, Rombur
    """

    # https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#gpu-feature-list
    # https://developer.nvidia.com/cuda-gpus
    # https://en.wikipedia.org/wiki/CUDA#GPUs_supported
    cuda_arch_values = ('10', '11', '12', '13', '20', '21', '30', '32', '35',
                        '37', '50', '52', '53', '60', '61', '62', '70', '72',
                        '75', '80', '86')

    # FIXME: keep cuda and cuda_arch separate to make usage easier until
    # Spack has depends_on(cuda, when='cuda_arch!=None') or alike
    variant('cuda', default=False, description='Build with CUDA')

    variant('cuda_arch',
            description='CUDA architecture',
            values=spack.variant.any_combination_of(*cuda_arch_values))

    # https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#nvcc-examples
    # https://llvm.org/docs/CompileCudaWithLLVM.html#compiling-cuda-code
    @staticmethod
    def cuda_flags(arch_list):
        return [('--generate-code arch=compute_{0},code=sm_{0} '
                 '--generate-code arch=compute_{0},code=compute_{0}').format(s)
                for s in arch_list]

    depends_on('cuda', when='+cuda')

    # CUDA version vs Architecture
    # https://en.wikipedia.org/wiki/CUDA#GPUs_supported
    # https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html#deprecated-features
    depends_on('cuda@:6.0', when='cuda_arch=10')
    depends_on('cuda@:6.5', when='cuda_arch=11')
    depends_on('[email protected]:6.5', when='cuda_arch=12')
    depends_on('[email protected]:6.5', when='cuda_arch=13')

    depends_on('[email protected]:8.0', when='cuda_arch=20')
    depends_on('[email protected]:8.0', when='cuda_arch=21')

    depends_on('[email protected]:10.2', when='cuda_arch=30')
    depends_on('[email protected]:10.2', when='cuda_arch=32')
    depends_on('[email protected]:', when='cuda_arch=35')
    depends_on('[email protected]:', when='cuda_arch=37')

    depends_on('[email protected]:', when='cuda_arch=50')
    depends_on('[email protected]:', when='cuda_arch=52')
    depends_on('[email protected]:', when='cuda_arch=53')

    depends_on('[email protected]:', when='cuda_arch=60')
    depends_on('[email protected]:', when='cuda_arch=61')
    depends_on('[email protected]:', when='cuda_arch=62')

    depends_on('[email protected]:', when='cuda_arch=70')
    depends_on('[email protected]:', when='cuda_arch=72')
    depends_on('[email protected]:', when='cuda_arch=75')

    depends_on('[email protected]:', when='cuda_arch=80')
    depends_on('[email protected]:', when='cuda_arch=86')

    # There are at least three cases to be aware of for compiler conflicts
    # 1. Linux x86_64
    # 2. Linux ppc64le
    # 3. Mac OS X
    # CUDA-compiler conflicts are version-to-version specific and are
    # difficult to express with the current Spack conflict syntax

    # Linux x86_64 compiler conflicts from here:
    # https://gist.github.com/ax3l/9489132
    arch_platform = ' target=x86_64: platform=linux'
    conflicts('%gcc@5:', when='+cuda ^cuda@:7.5' + arch_platform)
    conflicts('%gcc@6:', when='+cuda ^cuda@:8' + arch_platform)
    conflicts('%gcc@7:', when='+cuda ^cuda@:9.1' + arch_platform)
    conflicts('%gcc@8:', when='+cuda ^cuda@:10.0.130' + arch_platform)
    conflicts('%gcc@9:', when='+cuda ^cuda@:10.2.89' + arch_platform)
    conflicts('%gcc@:4', when='+cuda ^[email protected]:' + arch_platform)
    conflicts('%gcc@10:', when='+cuda ^cuda@:11.0.2' + arch_platform)
    conflicts('%gcc@11:', when='+cuda ^cuda@:11.1.0' + arch_platform)
    conflicts('%pgi@:14.8', when='+cuda ^cuda@:7.0.27' + arch_platform)
    conflicts('%pgi@:15.3,15.5:', when='+cuda ^[email protected]' + arch_platform)
    conflicts('%pgi@:16.2,16.0:16.3', when='+cuda ^cuda@8' + arch_platform)
    conflicts('%pgi@:15,18:', when='+cuda ^[email protected]:9.1' + arch_platform)
    conflicts('%pgi@:16,19:', when='+cuda ^[email protected]:10' + arch_platform)
    conflicts('%pgi@:17,20:',
              when='+cuda ^[email protected]:10.2.89' + arch_platform)
    conflicts('%pgi@:17,21:', when='+cuda ^[email protected]:11.1.0' + arch_platform)
    conflicts('%clang@:3.4', when='+cuda ^cuda@:7.5' + arch_platform)
    conflicts('%clang@:3.7,4:', when='+cuda ^[email protected]:9.0' + arch_platform)
    conflicts('%clang@:3.7,4.1:', when='+cuda ^[email protected]' + arch_platform)
    conflicts('%clang@:3.7,5.1:', when='+cuda ^[email protected]' + arch_platform)
    conflicts('%clang@:3.7,6.1:', when='+cuda ^[email protected]' + arch_platform)
    conflicts('%clang@:3.7,7.1:', when='+cuda ^[email protected]' + arch_platform)
    conflicts('%clang@:3.7,8.1:',
              when='+cuda ^[email protected]:10.1.243' + arch_platform)
    conflicts('%clang@:3.2,9:', when='+cuda ^[email protected]' + arch_platform)
    conflicts('%clang@:5', when='+cuda ^[email protected]:' + arch_platform)
    conflicts('%clang@10:', when='+cuda ^cuda@:11.0.2' + arch_platform)
    conflicts('%clang@11:', when='+cuda ^cuda@:11.1.0' + arch_platform)

    # x86_64 vs. ppc64le differ according to NVidia docs
    # Linux ppc64le compiler conflicts from Table from the docs below:
    # https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html
    # https://docs.nvidia.com/cuda/archive/9.2/cuda-installation-guide-linux/index.html
    # https://docs.nvidia.com/cuda/archive/9.1/cuda-installation-guide-linux/index.html
    # https://docs.nvidia.com/cuda/archive/9.0/cuda-installation-guide-linux/index.html
    # https://docs.nvidia.com/cuda/archive/8.0/cuda-installation-guide-linux/index.html

    arch_platform = ' target=ppc64le: platform=linux'
    # information prior to CUDA 9 difficult to find
    conflicts('%gcc@6:', when='+cuda ^cuda@:9' + arch_platform)
    conflicts('%gcc@8:', when='+cuda ^cuda@:10.0.130' + arch_platform)
    conflicts('%gcc@9:', when='+cuda ^cuda@:10.1.243' + arch_platform)
    # officially, CUDA 11.0.2 only supports the system GCC 8.3 on ppc64le
    conflicts('%gcc@:4', when='+cuda ^[email protected]:' + arch_platform)
    conflicts('%gcc@10:', when='+cuda ^cuda@:11.0.2' + arch_platform)
    conflicts('%gcc@11:', when='+cuda ^cuda@:11.1.0' + arch_platform)
    conflicts('%pgi', when='+cuda ^cuda@:8' + arch_platform)
    conflicts('%pgi@:16', when='+cuda ^cuda@:9.1.185' + arch_platform)
    conflicts('%pgi@:17', when='+cuda ^cuda@:10' + arch_platform)
    conflicts('%clang@4:', when='+cuda ^cuda@:9.0.176' + arch_platform)
    conflicts('%clang@5:', when='+cuda ^cuda@:9.1' + arch_platform)
    conflicts('%clang@6:', when='+cuda ^cuda@:9.2' + arch_platform)
    conflicts('%clang@7:', when='+cuda ^[email protected]' + arch_platform)
    conflicts('%[email protected]:', when='+cuda ^cuda@:10.1.105' + arch_platform)
    conflicts('%[email protected]:', when='+cuda ^cuda@:10.2.89' + arch_platform)
    conflicts('%clang@:5', when='+cuda ^[email protected]:' + arch_platform)
    conflicts('%clang@10:', when='+cuda ^cuda@:11.0.2' + arch_platform)
    conflicts('%clang@11:', when='+cuda ^cuda@:11.1.0' + arch_platform)

    # Intel is mostly relevant for x86_64 Linux, even though it also
    # exists for Mac OS X. No information prior to CUDA 3.2 or Intel 11.1
    conflicts('%intel@:11.0', when='+cuda ^cuda@:3.1')
    conflicts('%intel@:12.0', when='+cuda ^[email protected]:')
    conflicts('%intel@:13.0', when='+cuda ^[email protected]:')
    conflicts('%intel@:13.2', when='+cuda ^[email protected]:')
    conflicts('%intel@:14.9', when='+cuda ^cuda@7:')
    # Intel 15.x is compatible with CUDA 7 thru current CUDA
    conflicts('%[email protected]:', when='+cuda ^cuda@:8.0.43')
    conflicts('%[email protected]:', when='+cuda ^cuda@:8.0.60')
    conflicts('%[email protected]:', when='+cuda ^cuda@:9.9')
    conflicts('%[email protected]:', when='+cuda ^cuda@:10.0')
    conflicts('%[email protected]:', when='+cuda ^cuda@:10.1')
    conflicts('%[email protected]:', when='+cuda ^cuda@:11.1.0')

    # XL is mostly relevant for ppc64le Linux
    conflicts('%xl@:12,14:', when='+cuda ^cuda@:9.1')
    conflicts('%xl@:12,14:15,17:', when='+cuda ^[email protected]')
    conflicts('%xl@:12,17:', when='+cuda ^cuda@:11.1.0')

    # Mac OS X
    # platform = ' platform=darwin'
    # Apple XCode clang vs. LLVM clang are difficult to specify
    # with spack syntax. Xcode clang name is `[email protected]`
    # which precludes ranges being specified. We have proposed
    # rename XCode clang to `[email protected]` or even
    # `[email protected] as a possible fix.
    # Compiler conflicts will be eventual taken from here:
    # https://docs.nvidia.com/cuda/cuda-installation-guide-mac-os-x/index.html#abstract
    conflicts('platform=darwin', when='+cuda ^[email protected]:')

    # Make sure cuda_arch can not be used without +cuda
    for value in cuda_arch_values:
        conflicts('~cuda', when='cuda_arch=' + value)
Ejemplo n.º 7
0
class CMakePackage(PackageBase):
    """Specialized class for packages built using CMake

    For more information on the CMake build system, see:
    https://cmake.org/cmake/help/latest/

    This class provides three phases that can be overridden:

        1. :py:meth:`~.CMakePackage.cmake`
        2. :py:meth:`~.CMakePackage.build`
        3. :py:meth:`~.CMakePackage.install`

    They all have sensible defaults and for many packages the only thing
    necessary will be to override :py:meth:`~.CMakePackage.cmake_args`.
    For a finer tuning you may also override:

        +-----------------------------------------------+--------------------+
        | **Method**                                    | **Purpose**        |
        +===============================================+====================+
        | :py:meth:`~.CMakePackage.root_cmakelists_dir` | Location of the    |
        |                                               | root CMakeLists.txt|
        +-----------------------------------------------+--------------------+
        | :py:meth:`~.CMakePackage.build_directory`     | Directory where to |
        |                                               | build the package  |
        +-----------------------------------------------+--------------------+


    """
    #: Phases of a CMake package
    phases = ['cmake', 'build', 'install']
    #: This attribute is used in UI queries that need to know the build
    #: system base class
    build_system_class = 'CMakePackage'

    build_targets = []
    install_targets = ['install']

    build_time_test_callbacks = ['check']

    #: The build system generator to use.
    #:
    #: See ``cmake --help`` for a list of valid generators.
    #: Currently, "Unix Makefiles" and "Ninja" are the only generators
    #: that Spack supports. Defaults to "Unix Makefiles".
    #:
    #: See https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html
    #: for more information.
    generator = 'Unix Makefiles'

    # https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html
    variant('build_type',
            default='RelWithDebInfo',
            description='CMake build type',
            values=('Debug', 'Release', 'RelWithDebInfo', 'MinSizeRel'))

    depends_on('cmake', type='build')

    @property
    def archive_files(self):
        """Files to archive for packages based on CMake"""
        return [os.path.join(self.build_directory, 'CMakeCache.txt')]

    @property
    def root_cmakelists_dir(self):
        """The relative path to the directory containing CMakeLists.txt

        This path is relative to the root of the extracted tarball,
        not to the ``build_directory``. Defaults to the current directory.

        :return: directory containing CMakeLists.txt
        """
        return self.stage.source_path

    @property
    def std_cmake_args(self):
        """Standard cmake arguments provided as a property for
        convenience of package writers

        :return: standard cmake arguments
        """
        # standard CMake arguments
        std_cmake_args = CMakePackage._std_args(self)
        std_cmake_args += getattr(self, 'cmake_flag_args', [])
        return std_cmake_args

    @staticmethod
    def _std_args(pkg):
        """Computes the standard cmake arguments for a generic package"""
        try:
            generator = pkg.generator
        except AttributeError:
            generator = 'Unix Makefiles'

        # Make sure a valid generator was chosen
        valid_generators = ['Unix Makefiles', 'Ninja']
        if generator not in valid_generators:
            msg = "Invalid CMake generator: '{0}'\n".format(generator)
            msg += "CMakePackage currently supports the following "
            msg += "generators: '{0}'".format("', '".join(valid_generators))
            raise InstallError(msg)

        try:
            build_type = pkg.spec.variants['build_type'].value
        except KeyError:
            build_type = 'RelWithDebInfo'

        args = [
            '-G', generator,
            '-DCMAKE_INSTALL_PREFIX:PATH={0}'.format(pkg.prefix),
            '-DCMAKE_BUILD_TYPE:STRING={0}'.format(build_type),
            '-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON'
        ]

        if platform.mac_ver()[0]:
            args.extend([
                '-DCMAKE_FIND_FRAMEWORK:STRING=LAST',
                '-DCMAKE_FIND_APPBUNDLE:STRING=LAST'
            ])

        # Set up CMake rpath
        args.append('-DCMAKE_INSTALL_RPATH_USE_LINK_PATH:BOOL=FALSE')
        rpaths = ';'.join(spack.build_environment.get_rpaths(pkg))
        args.append('-DCMAKE_INSTALL_RPATH:STRING={0}'.format(rpaths))
        # CMake's find_package() looks in CMAKE_PREFIX_PATH first, help CMake
        # to find immediate link dependencies in right places:
        deps = [
            d.prefix for d in pkg.spec.dependencies(deptype=('build', 'link'))
        ]
        deps = filter_system_paths(deps)
        args.append('-DCMAKE_PREFIX_PATH:STRING={0}'.format(';'.join(deps)))
        return args

    def flags_to_build_system_args(self, flags):
        """Produces a list of all command line arguments to pass the specified
        compiler flags to cmake. Note CMAKE does not have a cppflags option,
        so cppflags will be added to cflags, cxxflags, and fflags to mimic the
        behavior in other tools."""
        # Has to be dynamic attribute due to caching
        setattr(self, 'cmake_flag_args', [])

        flag_string = '-DCMAKE_{0}_FLAGS={1}'
        langs = {'C': 'c', 'CXX': 'cxx', 'Fortran': 'f'}

        # Handle language compiler flags
        for lang, pre in langs.items():
            flag = pre + 'flags'
            # cmake has no explicit cppflags support -> add it to all langs
            lang_flags = ' '.join(
                flags.get(flag, []) + flags.get('cppflags', []))
            if lang_flags:
                self.cmake_flag_args.append(
                    flag_string.format(lang, lang_flags))

        # Cmake has different linker arguments for different build types.
        # We specify for each of them.
        if flags['ldflags']:
            ldflags = ' '.join(flags['ldflags'])
            ld_string = '-DCMAKE_{0}_LINKER_FLAGS={1}'
            # cmake has separate linker arguments for types of builds.
            for type in ['EXE', 'MODULE', 'SHARED', 'STATIC']:
                self.cmake_flag_args.append(ld_string.format(type, ldflags))

        # CMake has libs options separated by language. Apply ours to each.
        if flags['ldlibs']:
            libs_flags = ' '.join(flags['ldlibs'])
            libs_string = '-DCMAKE_{0}_STANDARD_LIBRARIES={1}'
            for lang in langs:
                self.cmake_flag_args.append(
                    libs_string.format(lang, libs_flags))

    @property
    def build_directory(self):
        """Returns the directory to use when building the package

        :return: directory where to build the package
        """
        return os.path.join(self.stage.source_path, 'spack-build')

    def cmake_args(self):
        """Produces a list containing all the arguments that must be passed to
        cmake, except:

            * CMAKE_INSTALL_PREFIX
            * CMAKE_BUILD_TYPE

        which will be set automatically.

        :return: list of arguments for cmake
        """
        return []

    def cmake(self, spec, prefix):
        """Runs ``cmake`` in the build directory"""
        options = [os.path.abspath(self.root_cmakelists_dir)]
        options += self.std_cmake_args
        options += self.cmake_args()
        with working_dir(self.build_directory, create=True):
            inspect.getmodule(self).cmake(*options)

    def build(self, spec, prefix):
        """Make the build targets"""
        with working_dir(self.build_directory):
            if self.generator == 'Unix Makefiles':
                inspect.getmodule(self).make(*self.build_targets)
            elif self.generator == 'Ninja':
                inspect.getmodule(self).ninja(*self.build_targets)

    def install(self, spec, prefix):
        """Make the install targets"""
        with working_dir(self.build_directory):
            if self.generator == 'Unix Makefiles':
                inspect.getmodule(self).make(*self.install_targets)
            elif self.generator == 'Ninja':
                inspect.getmodule(self).ninja(*self.install_targets)

    run_after('build')(PackageBase._run_default_build_time_test_callbacks)

    def check(self):
        """Searches the CMake-generated Makefile for the target ``test``
        and runs it if found.
        """
        with working_dir(self.build_directory):
            if self.generator == 'Unix Makefiles':
                self._if_make_target_execute('test')
                self._if_make_target_execute('check')
            elif self.generator == 'Ninja':
                self._if_ninja_target_execute('test')
                self._if_ninja_target_execute('check')

    # Check that self.prefix is there after installation
    run_after('install')(PackageBase.sanity_check_prefix)
Ejemplo n.º 8
0
class Cns(Package):
    """CNS The Crystallography & NMR System for structure calculation (1.2 for ARIA + aria patches)"""

    # FIXME: Add a proper url for your package's homepage here.
    homepage = "http://cns-online.org"
    url = "http://cns-online.org/download/v1.21/cns_solve_1.21_all-mp.tar.gz"

    read_releases('cns', version, resource)

    # patch to make SETFPEPS (set floating point epsilon work)
    # see https://ask.bioexcel.eu/t/cns-errors-before-after-recompilation/54
    # main patch courtesy of Brian Smith U of Glasgow
    variant('configuration',
            default='none',
            description='where to find the configuration file',
            validator=check_config_file)
    variant('fp_epsilon',
            default=True,
            description='SETFPEPS required for modern compilers')
    variant('aria', default=True, description='patches required to run aria')

    resource(
        name='aria2.3.2',
        aria_url='http://aria.pasteur.fr/archives/aria2.3.2.tar.gz',
        sha256=
        'a06e9c256bf876f8bbab244a80b9c52bbd891f14cb956d85bb3bd0312b5cd5c6',
        destination='.')

    patch('getarch_darwin_x86_64.patch',
          when='@1.21',
          sha256=
          '42a0d10d7684000d5c4cf1114e14d5549cc19c84b19df4d42419abd7187cf887')
    patch('machvar_fpeps.patch',
          when='@1.21+fp_epsilon',
          sha256=
          'a00db99086c63961abe4e19d253590421973a80a9e104ac85dbcc07d472b6485')

    def install(self, spec, prefix):

        # edit cns_solve_environment to allow a build
        shutil.copy('cns_solve_env', 'cns_solve_env.back')
        filter_file(r"setenv CNS_SOLVE '_CNSsolve_location_'",
                    f"setenv CNS_SOLVE '{self.stage.source_path}'",
                    'cns_solve_env')

        # copy over an almost right machine make file we could have got it from v1.3 but this is simpler
        src_file = 'instlib/machine/supported/intel-x86_64bit-linux/Makefile.header.2.gfortran'
        dest_file = 'instlib/machine/supported/mac-intel-darwin/Makefile.header.5.gfortran'
        shutil.move(src_file, dest_file)

        if not self.spec.satisfies('%fortran@:10.0.0'):
            # patch the machine make file, can't be done with a patch statement it doesn't exists till we copy it
            # tried just copying the file from the package directory but it caused a lockup
            patch = which('patch')
            patch_file = join_path(
                package_root, 'nmrpack/packages/cns',
                'gfortran_10_allow_argument_mismatch.patch')
            patch('-p1', '-i', patch_file)

        if '+aria' in self.spec:
            from_path = pathlib.Path('aria2.3/cns/src')
            to_path = 'source'

            for target_file in from_path.iterdir():
                if target_file.is_file() and target_file.suffix in ('.f',
                                                                    '.inc'):
                    print(f'copying {target_file} to {to_path}')
                    shutil.copy(target_file, to_path)
                if target_file.is_dir():
                    print(f'copying {target_file} to {to_path}')
                    shutil.copytree(target_file,
                                    join_path(to_path, target_file.name))

            shutil.copytree(from_path, 'aria2.3_patches_applied')
            shutil.rmtree('aria2.3')

        make('install')

        install_tree('.', prefix)

        with working_dir(prefix):
            shutil.move('cns_solve_env.back', 'cns_solve_env')

            replacement_env = f" setenv CNS_SOLVE  '{prefix}'"
            filter_file(r"setenv CNS_SOLVE '_CNSsolve_location_'",
                        replacement_env, 'cns_solve_env')

        # remove a leftover from our previous edits
        os.remove(pathlib.Path(prefix) / pathlib.Path('cns_solve_env' + '~'))

    @run_after('install')
    @on_package_attributes(run_tests=True)
    def test(self):
        try:
            import tempfile
            with tempfile.TemporaryDirectory() as tmp_dir_name:
                tmp_dir_name = '/tmp'

                test_inp = f'''
                stop
                '''

                with open(join_path(tmp_dir_name, 'test.inp'), 'w') as fp:
                    fp.write(test_inp)

                test_csh = f'''
                source  {self.prefix}/cns_solve_env
        
                cns_solve < {tmp_dir_name}/test.inp >& {tmp_dir_name}/test_output.txt 
                '''

                with open(join_path(tmp_dir_name, 'test.csh'), 'w') as fp:
                    fp.write(test_csh)

            csh(join(tmp_dir_name, 'test.csh'))

            expected = '''
            ============================================================
            |                                                          |
            |            Crystallography & NMR System (CNS)            |
            |                         CNSsolve                         |
            |                                                          |
            ============================================================
             Version: 1.2 at patch level 1
             Status: General release with ARIA enhancements
            ============================================================
            '''.split("\n")
            expected = [line.strip() for line in expected if len(line)]

            ok = True
            result = ''
            with open(f"{tmp_dir_name}/test_output.txt", 'r') as file_handle:
                result = file_handle.readlines()
                result = [line.strip() for line in result if len(line)]
                for line in expected:
                    if not line in result:
                        tty.error(f'line --{line}-- not in result')
                        ok = False
                        break
            if not ok:
                tty.error(f'''during testing strings 
                              {expected} 
                              not found in test output")
                           ''')
                tty.error("")
                tty.error(f" output was")
                tty.error("")
                for line in result:
                    tty.error(line.strip())
        except Exception as e:
            tty.error('there was an error', e)

    def setup_run_environment(self, env):

        environment_changes = get_environment_change(self.prefix,
                                                     CNS_SOLVE_ENV)

        # print('** environment_changes **', environment_changes)
        #
        for name, type, value in environment_changes:
            if type == PREPEND:
                env.prepend_path(name, value)
            elif type == NEW:
                env.set(name, value)
            else:
                raise Exception(f'unexpected change type {type}')
Ejemplo n.º 9
0
class MesonPackage(PackageBase):
    """Specialized class for packages built using Meson

    For more information on the Meson build system, see:
    https://mesonbuild.com/

    This class provides three phases that can be overridden:

        1. :py:meth:`~.MesonPackage.meson`
        2. :py:meth:`~.MesonPackage.build`
        3. :py:meth:`~.MesonPackage.install`

    They all have sensible defaults and for many packages the only thing
    necessary will be to override :py:meth:`~.MesonPackage.meson_args`.
    For a finer tuning you may also override:

        +-----------------------------------------------+--------------------+
        | **Method**                                    | **Purpose**        |
        +===============================================+====================+
        | :py:meth:`~.MesonPackage.root_mesonlists_dir` | Location of the    |
        |                                               | root MesonLists.txt|
        +-----------------------------------------------+--------------------+
        | :py:meth:`~.MesonPackage.build_directory`     | Directory where to |
        |                                               | build the package  |
        +-----------------------------------------------+--------------------+


    """
    #: Phases of a Meson package
    phases = ['meson', 'build', 'install']
    #: This attribute is used in UI queries that need to know the build
    #: system base class
    build_system_class = 'MesonPackage'

    build_targets = []  # type: List[str]
    install_targets = ['install']

    build_time_test_callbacks = ['check']

    variant('buildtype',
            default='debugoptimized',
            description='Meson build type',
            values=('plain', 'debug', 'debugoptimized', 'release', 'minsize'))
    variant('default_library',
            default='shared',
            description=' Default library type',
            values=('shared', 'static', 'both'))
    variant('strip', default=False, description='Strip targets on install')

    depends_on('meson', type='build')
    depends_on('ninja', type='build')

    @property
    def archive_files(self):
        """Files to archive for packages based on Meson"""
        return [os.path.join(self.build_directory, 'meson-logs/meson-log.txt')]

    @property
    def root_mesonlists_dir(self):
        """The relative path to the directory containing meson.build

        This path is relative to the root of the extracted tarball,
        not to the ``build_directory``. Defaults to the current directory.

        :return: directory containing meson.build
        """
        return self.stage.source_path

    @property
    def std_meson_args(self):
        """Standard meson arguments provided as a property for
        convenience of package writers

        :return: standard meson arguments
        """
        # standard Meson arguments
        std_meson_args = MesonPackage._std_args(self)
        std_meson_args += getattr(self, 'meson_flag_args', [])
        return std_meson_args

    @staticmethod
    def _std_args(pkg):
        """Computes the standard meson arguments for a generic package"""

        try:
            build_type = pkg.spec.variants['buildtype'].value
        except KeyError:
            build_type = 'release'

        strip = 'true' if '+strip' in pkg.spec else 'false'

        try:
            default_library = pkg.spec.variants['default_library'].value
        except KeyError:
            default_library = 'shared'

        args = [
            '--prefix={0}'.format(pkg.prefix),
            # If we do not specify libdir explicitly, Meson chooses something
            # like lib/x86_64-linux-gnu, which causes problems when trying to
            # find libraries and pkg-config files.
            # See https://github.com/mesonbuild/meson/issues/2197
            '--libdir={0}'.format(pkg.prefix.lib),
            '-Dbuildtype={0}'.format(build_type),
            '-Dstrip={0}'.format(strip),
            '-Ddefault_library={0}'.format(default_library)
        ]

        return args

    def flags_to_build_system_args(self, flags):
        """Produces a list of all command line arguments to pass the specified
        compiler flags to meson."""
        # Has to be dynamic attribute due to caching
        setattr(self, 'meson_flag_args', [])

    @property
    def build_directory(self):
        """Returns the directory to use when building the package

        :return: directory where to build the package
        """
        return os.path.join(self.stage.source_path, 'spack-build')

    def meson_args(self):
        """Produces a list containing all the arguments that must be passed to
        meson, except:

        * ``--prefix``
        * ``--libdir``
        * ``--buildtype``
        * ``--strip``
        * ``--default_library``

        which will be set automatically.

        :return: list of arguments for meson
        """
        return []

    def meson(self, spec, prefix):
        """Runs ``meson`` in the build directory"""
        options = [os.path.abspath(self.root_mesonlists_dir)]
        options += self.std_meson_args
        options += self.meson_args()
        with working_dir(self.build_directory, create=True):
            inspect.getmodule(self).meson(*options)

    def build(self, spec, prefix):
        """Make the build targets"""
        options = ['-v']
        options += self.build_targets
        with working_dir(self.build_directory):
            inspect.getmodule(self).ninja(*options)

    def install(self, spec, prefix):
        """Make the install targets"""
        with working_dir(self.build_directory):
            inspect.getmodule(self).ninja(*self.install_targets)

    run_after('build')(PackageBase._run_default_build_time_test_callbacks)

    def check(self):
        """Searches the Meson-generated file for the target ``test``
        and runs it if found.
        """
        with working_dir(self.build_directory):
            self._if_ninja_target_execute('test')
            self._if_ninja_target_execute('check')

    # Check that self.prefix is there after installation
    run_after('install')(PackageBase.sanity_check_prefix)
Ejemplo n.º 10
0
class Genie(Package):  # Genie doesn"t use Autotools
    """Genie is a neutrino Monte Carlo Generator."""

    homepage = "https://www.genie-mc.org"
    url = "https://github.com/GENIE-MC/Generator/archive/R-3_00_06.tar.gz"
    git = "https://github.com/GENIE-MC/Generator.git"

    tags = ["neutrino", "hep"]

    maintainers = [
        # maintainer of this recipe, not affliated with the GENIE collaboration
        "davehadley",
    ]

    version("master", branch="master")
    version("3.0.6",
            sha256=
            "ab56ea85d0c1d09029254365bfe75a1427effa717389753b9e0c1b6c2eaa5eaf")
    version("3.0.4",
            sha256=
            "53f034618fef9f7f0e17d1c4ed72743e4bba590e824b795177a1a8a8486c861e")
    version("3.0.2",
            sha256=
            "34d6c37017b2387c781aea7bc727a0aac0ef45d6b3f3982cc6f3fc82493f65c3")
    version("3.0.0",
            sha256=
            "3953c7d9f1f832dd32dfbc0b9260be59431206c204aec6ab0aa68c01176f2ae6")
    version("2.12.10",
            sha256=
            "c8762db3dcc490f80f8a61268f5b964d4d35b80134b622e89fe2307a836f2a0b")
    version("2.12.8",
            sha256=
            "7ca169a8d9eda7267d28b76b2f3110552852f8eeae263a03cd5139caacebb4ea")
    version("2.12.6",
            sha256=
            "3b450c609875459798ec98e12cf671cc971cbb13345af6d75bd6278d422f3309")
    version("2.12.4",
            sha256=
            "19a4a1633b0847a9f16a44e0c74b9c224ca3bb93975aecf108603c22e807517b")
    version("2.12.2",
            sha256=
            "cbdc45a739878940dadcaaed575b5cad6b5e7035f29605045b1ca557e6faa6d1")
    version("2.12.0",
            sha256=
            "d2b01c80f38d269cb0296b3f2932798ef3f1d51bd130e81274fbfeeb381fac6b")
    version("2.11.2",
            sha256=
            "0f4c25d8ceb7513553671643c9cdac5aa98c40fc8594a5ecb25c077c6b36166e")
    version("2.11.0",
            sha256=
            "1ebe0eb65d797595413632f1cec1cb2621cb8e8d0384a2843799724a79b1d80c")
    version("2.10.10",
            sha256=
            "1dfaadcf1bbaf6e164b612f410c4399301e63497ad6a4891706b1787ac11a7a1")
    version("2.10.8",
            sha256=
            "4f6f5af2062e7c505b76e70547ac2ae304a9790c3e9b9592818d8aebeebc8398")
    version("2.10.6",
            sha256=
            "d00b4288c886f81459fb2967e539f30315d4385f82d1d3f4330298d313f9a176")
    version("2.10.4",
            sha256=
            "df909bf7e1a789ca01794995687da2af803769f0823273a4a3a31678d6d5b0f1")
    version("2.10.2",
            sha256=
            "6abe4e0cdb5e8f5beddf0ccdbebc94c175a9f72592b1cbbffe01b88ee3972bf9")
    version("2.10.0",
            sha256=
            "17bda900c996b6f4f10a7f6a3be94e56c3b8dcdeb2ef8865ca7f20c5fe725291")
    version("2.9.0",
            sha256=
            "8229beb73f65f5af86a77bf141acfbe4a8b68cba9d797aae083a929906f6f2a2")
    version("2.8.6",
            sha256=
            "310dc8e0d17a65e6b9773e398250703a3a6f94ceafe94f599ae0f7b3fecf7e6c")

    depends_on("root+pythia6")
    depends_on("pythia6")
    depends_on("lhapdf", when="@3:")
    depends_on("lhapdf5", when="@:2")
    depends_on("log4cpp")
    depends_on("libxml2")
    depends_on("gsl")

    # GENIE does not actually require cmake, but root does.
    # Spack's concretizer fails with "unsatisfiable constraint" if we don't add this.
    depends_on("cmake@3:")

    # GENIE Makefile's think that the spack compiler is invalid.
    # Disables this check.
    patch("genie_disable_gopt_with_compiler_check.patch",
          level=0,
          when="@2.11:")

    # Flags for GENIE"s optional but disabled by default features
    variant(
        "atmo",
        default=False,
        description="Enable GENIE Atmospheric neutrino event generation app")
    variant(
        "fnal",
        default=False,
        description="Enables FNAL experiment-specific event generation app")
    variant("nucleondecay",
            default=False,
            description="Enable GENIE Nucleon decay event generation app")
    variant("masterclass",
            default=False,
            description="Enable GENIE neutrino masterclass app")
    variant("t2k",
            default=False,
            description="Enable T2K-specific generation app")
    variant(
        "vleextension",
        default=False,
        description="Enable GENIE very low energy (1 MeV - 100 MeV) extension")

    phases = ["configure", "build", "install"]

    def url_for_version(self, version):
        url = "https://github.com/GENIE-MC/Generator/archive/R-{0}.tar.gz"
        if version >= Version(3):
            return url.format("{0}_{1:02d}_{2:02d}".format(*version))
        else:
            return url.format(version.underscored)

    def setup_build_environment(self, env):
        env.set("GENIE", self.stage.source_path)
        return super(Genie, self).setup_build_environment(env)

    def setup_run_environment(self, env):
        env.set("GENIE", self.prefix)
        return super(Genie, self).setup_run_environment(env)

    def configure(self, spec, prefix):
        configure = Executable("./configure")
        args = self._configure_args(spec, prefix)
        configure(*args)

    def build(self, spec, prefix):
        # parallel build is not supported on GENIE 2
        self._make(parallel=spec.satisfies("@3:"))

    def install(self, spec, prefix):
        # GENIE make install does not support parallel jobs
        self._make("install", parallel=False)
        # GENIE requires these files to be present at runtime, but doesn"t install them
        # so we must install them ourselves
        # install_tree function is injected into scope by spack build_environment.py
        install_tree("config", os.sep.join((prefix, "config")))
        install_tree("data", os.sep.join((prefix, "data")))

    def _configure_args(self, spec, prefix):
        args = [
            "--prefix=" + prefix,
            "--with-compiler=" + os.environ["CC"],
            "--with-libxml2-inc={0}{1}libxml2".format(
                spec["libxml2"].prefix.include, os.sep),
            "--with-libxml2-lib=" + spec["libxml2"].prefix.lib,
            "--with-log4cpp-inc=" + spec["log4cpp"].prefix.include,
            "--with-log4cpp-lib=" + spec["log4cpp"].prefix.lib,
            "--with-pythia6-lib=" + spec["pythia6"].prefix.lib,
        ]
        if self.spec.satisfies("@:2"):
            args += [
                "--enable-lhapdf",
                "--with-lhapdf-inc=" + spec["lhapdf5"].prefix.include,
                "--with-lhapdf-lib=" + spec["lhapdf5"].prefix.lib,
                # must be enabled or some GENIE 2 versions fail to link
                # this option was removed in GENIE 3
                "--enable-rwght",
            ]
        else:
            args += [
                "--enable-lhapdf6",
                "--with-lhapdf6-inc=" + spec["lhapdf"].prefix.include,
                "--with-lhapdf6-lib=" + spec["lhapdf"].prefix.lib,
            ]
        if "+vleextension" in self.spec:
            args += ["--enable-vle-extension"]
        if "+t2k" in self.spec:
            args += ["--enable-t2k"]
        if "+fnal" in self.spec:
            args += ["--enable-fnal"]
        if "+atmo" in self.spec:
            args += ["--enable-atmo"]
        if "+nucleondecay" in self.spec:
            args += ["--enable-nucleon-decay"]
        if "+masterclass" in self.spec:
            args += ["--enable-masterclass"]
        return args

    def _make(self, *args, **kwargs):
        parallel = kwargs.get("parallel", False)
        args = list(self._make_args) + list(args)
        # make function is injected into scope by spack build_environment.py
        make(*args, parallel=parallel)

    @property
    def _make_args(self):
        return [
            "CC=c++",
            "CXX=c++",
            "LD=c++",
        ]
Ejemplo n.º 11
0
Archivo: cuda.py Proyecto: rexcsn/spack
class CudaPackage(PackageBase):
    """Auxiliary class which contains CUDA variant, dependencies and conflicts
    and is meant to unify and facilitate its usage.

    Maintainers: ax3l, Rombur
    """

    # https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#gpu-feature-list
    # https://developer.nvidia.com/cuda-gpus
    # https://en.wikipedia.org/wiki/CUDA#GPUs_supported
    cuda_arch_values = ('10', '11', '12', '13', '20', '21', '30', '32', '35',
                        '37', '50', '52', '53', '60', '61', '62', '70', '72',
                        '75', '80', '86')

    # FIXME: keep cuda and cuda_arch separate to make usage easier until
    # Spack has depends_on(cuda, when='cuda_arch!=None') or alike
    variant('cuda', default=False, description='Build with CUDA')

    variant('cuda_arch',
            description='CUDA architecture',
            values=spack.variant.any_combination_of(*cuda_arch_values))

    # https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#nvcc-examples
    # https://llvm.org/docs/CompileCudaWithLLVM.html#compiling-cuda-code
    @staticmethod
    def cuda_flags(arch_list):
        return [('--generate-code arch=compute_{0},code=sm_{0} '
                 '--generate-code arch=compute_{0},code=compute_{0}').format(s)
                for s in arch_list]

    depends_on('cuda', when='+cuda')

    # CUDA version vs Architecture
    # https://en.wikipedia.org/wiki/CUDA#GPUs_supported
    # https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html#deprecated-features
    depends_on('cuda@:6.0', when='cuda_arch=10')
    depends_on('cuda@:6.5', when='cuda_arch=11')
    depends_on('[email protected]:6.5', when='cuda_arch=12')
    depends_on('[email protected]:6.5', when='cuda_arch=13')

    depends_on('[email protected]:8.0', when='cuda_arch=20')
    depends_on('[email protected]:8.0', when='cuda_arch=21')

    depends_on('[email protected]:10.2', when='cuda_arch=30')
    depends_on('[email protected]:10.2', when='cuda_arch=32')
    depends_on('[email protected]:', when='cuda_arch=35')
    depends_on('[email protected]:', when='cuda_arch=37')

    depends_on('[email protected]:', when='cuda_arch=50')
    depends_on('[email protected]:', when='cuda_arch=52')
    depends_on('[email protected]:', when='cuda_arch=53')

    depends_on('[email protected]:', when='cuda_arch=60')
    depends_on('[email protected]:', when='cuda_arch=61')
    depends_on('[email protected]:', when='cuda_arch=62')

    depends_on('[email protected]:', when='cuda_arch=70')
    depends_on('[email protected]:', when='cuda_arch=72')
    depends_on('[email protected]:', when='cuda_arch=75')

    depends_on('[email protected]:', when='cuda_arch=80')
    depends_on('[email protected]:', when='cuda_arch=86')

    # From the NVIDIA install guide we know of conflicts for particular
    # platforms (linux, darwin), architectures (x86, powerpc) and compilers
    # (gcc, clang). We don't restrict %gcc and %clang conflicts to
    # platform=linux, since they should also apply to platform=cray, and may
    # apply to platform=darwin. We currently do not provide conflicts for
    # platform=darwin with %apple-clang.

    # Linux x86_64 compiler conflicts from here:
    # https://gist.github.com/ax3l/9489132
    conflicts('%gcc@5:', when='+cuda ^cuda@:7.5 target=x86_64:')
    conflicts('%gcc@6:', when='+cuda ^cuda@:8 target=x86_64:')
    conflicts('%gcc@7:', when='+cuda ^cuda@:9.1 target=x86_64:')
    conflicts('%gcc@8:', when='+cuda ^cuda@:10.0.130 target=x86_64:')
    conflicts('%gcc@9:', when='+cuda ^cuda@:10.2.89 target=x86_64:')
    conflicts('%gcc@:4', when='+cuda ^[email protected]: target=x86_64:')
    conflicts('%gcc@10:', when='+cuda ^cuda@:11.0.3 target=x86_64:')
    conflicts('%gcc@11:', when='+cuda ^cuda@:11.1.0 target=x86_64:')
    conflicts('%pgi@:14.8', when='+cuda ^cuda@:7.0.27 target=x86_64:')
    conflicts('%pgi@:15.3,15.5:', when='+cuda ^[email protected] target=x86_64:')
    conflicts('%pgi@:16.2,16.0:16.3', when='+cuda ^cuda@8 target=x86_64:')
    conflicts('%pgi@:15,18:', when='+cuda ^[email protected]:9.1 target=x86_64:')
    conflicts('%pgi@:16,19:', when='+cuda ^[email protected]:10 target=x86_64:')
    conflicts('%pgi@:17,20:',
              when='+cuda ^[email protected]:10.2.89 target=x86_64:')
    conflicts('%pgi@:17,21:', when='+cuda ^[email protected]:11.1.0 target=x86_64:')
    conflicts('%clang@:3.4', when='+cuda ^cuda@:7.5 target=x86_64:')
    conflicts('%clang@:3.7,4:', when='+cuda ^[email protected]:9.0 target=x86_64:')
    conflicts('%clang@:3.7,4.1:', when='+cuda ^[email protected] target=x86_64:')
    conflicts('%clang@:3.7,5.1:', when='+cuda ^[email protected] target=x86_64:')
    conflicts('%clang@:3.7,6.1:', when='+cuda ^[email protected] target=x86_64:')
    conflicts('%clang@:3.7,7.1:', when='+cuda ^[email protected] target=x86_64:')
    conflicts('%clang@:3.7,8.1:',
              when='+cuda ^[email protected]:10.1.243 target=x86_64:')
    conflicts('%clang@:3.2,9:', when='+cuda ^[email protected] target=x86_64:')
    conflicts('%clang@:5', when='+cuda ^[email protected]: target=x86_64:')
    conflicts('%clang@10:', when='+cuda ^cuda@:11.0.3 target=x86_64:')
    conflicts('%clang@11:', when='+cuda ^cuda@:11.1.0 target=x86_64:')

    # x86_64 vs. ppc64le differ according to NVidia docs
    # Linux ppc64le compiler conflicts from Table from the docs below:
    # https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html
    # https://docs.nvidia.com/cuda/archive/9.2/cuda-installation-guide-linux/index.html
    # https://docs.nvidia.com/cuda/archive/9.1/cuda-installation-guide-linux/index.html
    # https://docs.nvidia.com/cuda/archive/9.0/cuda-installation-guide-linux/index.html
    # https://docs.nvidia.com/cuda/archive/8.0/cuda-installation-guide-linux/index.html

    # information prior to CUDA 9 difficult to find
    conflicts('%gcc@6:', when='+cuda ^cuda@:9 target=ppc64le:')
    conflicts('%gcc@8:', when='+cuda ^cuda@:10.0.130 target=ppc64le:')
    conflicts('%gcc@9:', when='+cuda ^cuda@:10.1.243 target=ppc64le:')
    # officially, CUDA 11.0.2 only supports the system GCC 8.3 on ppc64le
    conflicts('%gcc@:4', when='+cuda ^[email protected]: target=ppc64le:')
    conflicts('%gcc@10:', when='+cuda ^cuda@:11.0.3 target=ppc64le:')
    conflicts('%gcc@11:', when='+cuda ^cuda@:11.1.0 target=ppc64le:')
    conflicts('%pgi', when='+cuda ^cuda@:8 target=ppc64le:')
    conflicts('%pgi@:16', when='+cuda ^cuda@:9.1.185 target=ppc64le:')
    conflicts('%pgi@:17', when='+cuda ^cuda@:10 target=ppc64le:')
    conflicts('%clang@4:', when='+cuda ^cuda@:9.0.176 target=ppc64le:')
    conflicts('%clang@5:', when='+cuda ^cuda@:9.1 target=ppc64le:')
    conflicts('%clang@6:', when='+cuda ^cuda@:9.2 target=ppc64le:')
    conflicts('%clang@7:', when='+cuda ^[email protected] target=ppc64le:')
    conflicts('%[email protected]:', when='+cuda ^cuda@:10.1.105 target=ppc64le:')
    conflicts('%[email protected]:', when='+cuda ^cuda@:10.2.89 target=ppc64le:')
    conflicts('%clang@:5', when='+cuda ^[email protected]: target=ppc64le:')
    conflicts('%clang@10:', when='+cuda ^cuda@:11.0.3 target=ppc64le:')
    conflicts('%clang@11:', when='+cuda ^cuda@:11.1.0 target=ppc64le:')

    # Intel is mostly relevant for x86_64 Linux, even though it also
    # exists for Mac OS X. No information prior to CUDA 3.2 or Intel 11.1
    conflicts('%intel@:11.0', when='+cuda ^cuda@:3.1')
    conflicts('%intel@:12.0', when='+cuda ^[email protected]:')
    conflicts('%intel@:13.0', when='+cuda ^[email protected]:')
    conflicts('%intel@:13.2', when='+cuda ^[email protected]:')
    conflicts('%intel@:14.9', when='+cuda ^cuda@7:')
    # Intel 15.x is compatible with CUDA 7 thru current CUDA
    conflicts('%[email protected]:', when='+cuda ^cuda@:8.0.43')
    conflicts('%[email protected]:', when='+cuda ^cuda@:8.0.60')
    conflicts('%[email protected]:', when='+cuda ^cuda@:9.9')
    conflicts('%[email protected]:', when='+cuda ^cuda@:10.0')
    conflicts('%[email protected]:', when='+cuda ^cuda@:10.1')
    conflicts('%[email protected]:', when='+cuda ^cuda@:11.1.0')

    # XL is mostly relevant for ppc64le Linux
    conflicts('%xl@:12,14:', when='+cuda ^cuda@:9.1')
    conflicts('%xl@:12,14:15,17:', when='+cuda ^[email protected]')
    conflicts('%xl@:12,17:', when='+cuda ^cuda@:11.1.0')

    # Darwin.
    # TODO: add missing conflicts for %apple-clang cuda@:10
    conflicts('platform=darwin', when='+cuda ^[email protected]:')

    # Make sure cuda_arch can not be used without +cuda
    for value in cuda_arch_values:
        conflicts('~cuda', when='cuda_arch=' + value)
Ejemplo n.º 12
0
class CudaPackage(PackageBase):
    """Auxiliary class which contains CUDA variant, dependencies and conflicts
    and is meant to unify and facilitate its usage.
    """

    # FIXME: keep cuda and cuda_arch separate to make usage easier untill
    # Spack has depends_on(cuda, when='cuda_arch!=None') or alike
    variant('cuda', default=False,
            description='Build with CUDA')
    # see http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#gpu-feature-list
    # https://developer.nvidia.com/cuda-gpus
    variant('cuda_arch',
            description='CUDA architecture',
            values=spack.variant.any_combination_of(
                '20', '30', '32', '35', '50', '52', '53', '60', '61',
                '62', '70', '72', '75'
            ))

    # see http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#nvcc-examples
    # and http://llvm.org/docs/CompileCudaWithLLVM.html#compiling-cuda-code
    @staticmethod
    def cuda_flags(arch_list):
        return [('--generate-code arch=compute_{0},code=sm_{0} '
                 '--generate-code arch=compute_{0},code=compute_{0}').format(s)
                for s in arch_list]

    depends_on("cuda@7:", when='+cuda')

    # CUDA version vs Architecture
    depends_on("cuda@8:", when='cuda_arch=60')
    depends_on("cuda@8:", when='cuda_arch=61')
    depends_on("cuda@8:", when='cuda_arch=62')
    depends_on("cuda@9:", when='cuda_arch=70')
    depends_on("cuda@9:", when='cuda_arch=72')
    depends_on("cuda@10:", when='cuda_arch=75')

    depends_on('cuda@:8', when='cuda_arch=20')

    # There are at least three cases to be aware of for compiler conflicts
    # 1. Linux x86_64
    # 2. Linux ppc64le
    # 3. Mac OS X

    # Linux x86_64 compiler conflicts from here:
    # https://gist.github.com/ax3l/9489132
    arch_platform = ' arch=x86_64 platform=linux'
    conflicts('%gcc@5:', when='+cuda ^cuda@:7.5' + arch_platform)
    conflicts('%gcc@6:', when='+cuda ^cuda@:8' + arch_platform)
    conflicts('%gcc@7:', when='+cuda ^cuda@:9.1' + arch_platform)
    conflicts('%gcc@8:', when='+cuda ^[email protected]' + arch_platform)
    conflicts('%pgi@:14.8', when='+cuda ^cuda@:7.0.27' + arch_platform)
    conflicts('%pgi@:15.3,15.5:', when='+cuda ^[email protected]' + arch_platform)
    conflicts('%pgi@:16.2,16.0:16.3', when='+cuda ^cuda@8' + arch_platform)
    conflicts('%pgi@:15,18:', when='+cuda ^[email protected]:9.1' + arch_platform)
    conflicts('%pgi@:16', when='+cuda ^[email protected]:10' + arch_platform)
    conflicts('%clang@:3.4', when='+cuda ^cuda@:7.5' + arch_platform)
    conflicts('%clang@:3.7,4:',
              when='+cuda ^[email protected]:9.0' + arch_platform)
    conflicts('%clang@:3.7,4.1:',
              when='+cuda ^[email protected]' + arch_platform)
    conflicts('%clang@:3.7,5.1:', when='+cuda ^[email protected]' + arch_platform)
    conflicts('%clang@:3.7,6.1:', when='+cuda ^[email protected]' + arch_platform)

    # x86_64 vs. ppc64le differ according to NVidia docs
    # Linux ppc64le compiler conflicts from Table from the docs below:
    # https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html
    # https://docs.nvidia.com/cuda/archive/9.2/cuda-installation-guide-linux/index.html
    # https://docs.nvidia.com/cuda/archive/9.1/cuda-installation-guide-linux/index.html
    # https://docs.nvidia.com/cuda/archive/9.0/cuda-installation-guide-linux/index.html
    # https://docs.nvidia.com/cuda/archive/8.0/cuda-installation-guide-linux/index.html

    arch_platform = ' arch=ppc64le platform=linux'
    # information prior to CUDA 9 difficult to find
    conflicts('%gcc@6:', when='+cuda ^cuda@:9' + arch_platform)
    conflicts('%gcc@8:', when='+cuda ^[email protected]' + arch_platform)
    conflicts('%pgi', when='+cuda ^cuda@:8' + arch_platform)
    conflicts('%pgi@:16', when='+cuda ^cuda@:9.1.185' + arch_platform)
    conflicts('%pgi@:17', when='+cuda ^cuda@:10' + arch_platform)
    conflicts('%clang@4:', when='+cuda ^cuda@:9.0.176' + arch_platform)
    conflicts('%clang@5:', when='+cuda ^cuda@:9.1' + arch_platform)
    conflicts('%clang@6:', when='+cuda ^cuda@:9.2' + arch_platform)
    conflicts('%clang@7:', when='+cuda ^[email protected]' + arch_platform)

    # Intel is mostly relevant for x86_64 Linux, even though it also
    # exists for Mac OS X.
    conflicts('%intel@:14,16:', when='+cuda ^[email protected]')
    conflicts('%intel@:14,17:', when='+cuda ^[email protected]')
    conflicts('%intel@:14,18:', when='+cuda ^[email protected]:9.1')
    conflicts('%intel@17:18', when='+cuda ^[email protected]:')
    conflicts('%intel@19:', when='+cuda')

    # XL is mostly relevant for ppc64le Linux
    conflicts('%xl@:12,14:', when='+cuda ^cuda@:9.1')
    conflicts('%xl@:12,14:15,17:', when='+cuda ^[email protected]')
    conflicts('%xl@17:', when='+cuda ^[email protected]')

    # Mac OS X
    # platform = ' platform=darwin'
    # Apple XCode clang vs. LLVM clang are difficult to specify
    # with spack syntax. Xcode clang name is `[email protected]`
    # which precludes ranges being specified. We have proposed
    # rename XCode clang to `[email protected]` or even
    # `[email protected] as a possible fix.
    # Compiler conflicts will be eventual taken from here:
    # https://docs.nvidia.com/cuda/cuda-installation-guide-mac-os-x/index.html#abstract

    # Make sure cuda_arch can not be used without +cuda
    conflicts('~cuda', when='cuda_arch=20')
    conflicts('~cuda', when='cuda_arch=30')
    conflicts('~cuda', when='cuda_arch=32')
    conflicts('~cuda', when='cuda_arch=35')
    conflicts('~cuda', when='cuda_arch=50')
    conflicts('~cuda', when='cuda_arch=52')
    conflicts('~cuda', when='cuda_arch=53')
    conflicts('~cuda', when='cuda_arch=60')
    conflicts('~cuda', when='cuda_arch=61')
    conflicts('~cuda', when='cuda_arch=62')
    conflicts('~cuda', when='cuda_arch=70')
    conflicts('~cuda', when='cuda_arch=72')
    conflicts('~cuda', when='cuda_arch=75')