From c8b44142303471e8aa1bdcf9a6a30b9eff852322 Mon Sep 17 00:00:00 2001 From: Robert Cohn Date: Wed, 7 Apr 2021 12:31:08 -0400 Subject: [oneapi] fix mkl deps, externally installed, and docs (#22607) --- .../docs/build_systems/inteloneapipackage.rst | 48 +++++++++++++++------- lib/spack/spack/build_systems/oneapi.py | 21 ++++++---- .../packages/intel-oneapi-compilers/package.py | 32 +++++++-------- .../builtin/packages/intel-oneapi-mkl/package.py | 8 ++-- .../builtin/packages/intel-oneapi-mpi/package.py | 18 ++++---- 5 files changed, 72 insertions(+), 55 deletions(-) diff --git a/lib/spack/docs/build_systems/inteloneapipackage.rst b/lib/spack/docs/build_systems/inteloneapipackage.rst index 036fc738ad..1e535775e2 100644 --- a/lib/spack/docs/build_systems/inteloneapipackage.rst +++ b/lib/spack/docs/build_systems/inteloneapipackage.rst @@ -38,21 +38,25 @@ Intel no longer releases new versions of Parallel Studio, which can be used in Spack via the :ref:. All of its components can now be found in oneAPI. -Example -======= +Examples +======== -We start with a simple example that will be sufficient for most -users. Install the oneAPI compilers:: +Building a Package With icx +--------------------------- + +In this example, we build patchelf with ``icc`` and ``icx``. The +compilers are installed with spack. + +Install the oneAPI compilers:: spack install intel-oneapi-compilers -Add the oneAPI compilers to the set of compilers that Spack can use:: +Add the compilers to your ``compilers.yaml`` so spack can use them:: spack compiler add `spack location -i intel-oneapi-compilers`/compiler/latest/linux/bin/intel64 spack compiler add `spack location -i intel-oneapi-compilers`/compiler/latest/linux/bin -This adds the compilers to your ``compilers.yaml``. Verify that the -compilers are available:: +Verify that the compilers are available:: spack compiler list @@ -72,9 +76,11 @@ To build with with ``icx``, do :: spack install patchelf%oneapi -In addition to compilers, oneAPI contains many libraries. The ``hdf5`` -package works with any compatible MPI implementation. To build -``hdf5`` with Intel oneAPI MPI do:: +Using oneAPI MPI to Satisfy a Virtual Dependence +------------------------------------------------------ + +The ``hdf5`` package works with any compatible MPI implementation. To +build ``hdf5`` with Intel oneAPI MPI do:: spack install hdf5 +mpi ^intel-oneapi-mpi @@ -95,11 +101,23 @@ To use the compilers, add some information about the installation to spack compiler add /opt/intel/oneapi/compiler/latest/linux/bin Adapt the paths above if you did not install the tools in the default -location. After adding the compilers, using them in Spack will be -exactly the same as if you had installed the -``intel-oneapi-compilers`` package. Another option is to manually add -the configuration to ``compilers.yaml`` as described in :ref:`Compiler -configuration `. +location. After adding the compilers, using them is the same +as if you had installed the ``intel-oneapi-compilers`` package. +Another option is to manually add the configuration to +``compilers.yaml`` as described in :ref:`Compiler configuration +`. + +Libraries +--------- + +If you want Spack to use MKL that you have installed without Spack in +the default location, then add the following to +``~/.spack/packages.yaml``, adjusting the version as appropriate:: + + intel-oneapi-mkl: + externals: + - spec: intel-oneapi-mkl@2021.1.1 + prefix: /opt/intel/oneapi/ Using oneAPI Tools Installed by Spack diff --git a/lib/spack/spack/build_systems/oneapi.py b/lib/spack/spack/build_systems/oneapi.py index e1a0c66a7e..dfa1e1da78 100644 --- a/lib/spack/spack/build_systems/oneapi.py +++ b/lib/spack/spack/build_systems/oneapi.py @@ -8,13 +8,13 @@ """ from sys import platform -from os.path import basename, dirname, isdir, join +from os.path import basename, dirname, isdir from spack.package import Package from spack.util.environment import EnvironmentModifications from spack.util.executable import Executable -from llnl.util.filesystem import find_headers, find_libraries +from llnl.util.filesystem import find_headers, find_libraries, join_path class IntelOneApiPackage(Package): @@ -33,6 +33,11 @@ class IntelOneApiPackage(Package): """Subdirectory for this component in the install prefix.""" raise NotImplementedError + @property + def component_path(self): + """Path to component //.""" + return join_path(self.prefix, self.component_dir, str(self.spec.version)) + def install(self, spec, prefix, installer_path=None): """Shared install method for all oneapi packages.""" @@ -53,21 +58,20 @@ class IntelOneApiPackage(Package): '--install-dir', prefix) # Some installers have a bug and do not return an error code when failing - if not isdir(join(prefix, self.component_dir)): + if not isdir(join_path(prefix, self.component_dir)): raise RuntimeError('install failed') def setup_run_environment(self, env): - """Adds environment variables to the generated module file. These environment variables come from running: .. code-block:: console - $ source {prefix}/setvars.sh --force + $ source {prefix}/{component}/{version}/env/vars.sh """ env.extend(EnvironmentModifications.from_sourcing_file( - join(self.prefix, self.component_dir, 'latest/env/vars.sh'))) + join_path(self.component_path, 'env', 'vars.sh'))) class IntelOneApiLibraryPackage(IntelOneApiPackage): @@ -75,12 +79,11 @@ class IntelOneApiLibraryPackage(IntelOneApiPackage): @property def headers(self): - include_path = '%s/%s/latest/include' % ( - self.prefix, self.component_dir) + include_path = join_path(self.component_path, 'include') return find_headers('*', include_path, recursive=True) @property def libs(self): - lib_path = '%s/%s/latest/lib/intel64' % (self.prefix, self.component_dir) + lib_path = join_path(self.component_path, 'lib', 'intel64') lib_path = lib_path if isdir(lib_path) else dirname(lib_path) return find_libraries('*', root=lib_path, shared=True, recursive=True) diff --git a/var/spack/repos/builtin/packages/intel-oneapi-compilers/package.py b/var/spack/repos/builtin/packages/intel-oneapi-compilers/package.py index b8d3dedc78..7b12fa92f3 100644 --- a/var/spack/repos/builtin/packages/intel-oneapi-compilers/package.py +++ b/var/spack/repos/builtin/packages/intel-oneapi-compilers/package.py @@ -4,8 +4,8 @@ # SPDX-License-Identifier: (Apache-2.0 OR MIT) import glob -import subprocess from os import path +import subprocess from sys import platform from spack import * @@ -36,19 +36,16 @@ class IntelOneapiCompilers(IntelOneApiPackage): def component_dir(self): return 'compiler' - def _join_prefix(self, p): - return path.join(self.prefix, 'compiler', 'latest', 'linux', p) - def _ld_library_path(self): dirs = ['lib', - path.join('lib', 'x64'), - path.join('lib', 'emu'), - path.join('lib', 'oclfpga', 'host', 'linux64', 'lib'), - path.join('lib', 'oclfpga', 'linux64', 'lib'), - path.join('compiler', 'lib', 'intel64_lin'), - path.join('compiler', 'lib')] + join_path('lib', 'x64'), + join_path('lib', 'emu'), + join_path('lib', 'oclfpga', 'host', 'linux64', 'lib'), + join_path('lib', 'oclfpga', 'linux64', 'lib'), + join_path('compiler', 'lib', 'intel64_lin'), + join_path('compiler', 'lib')] for dir in dirs: - yield self._join_prefix(dir) + yield join_path(self.component_path, 'linux', dir) def install(self, spec, prefix): # install cpp @@ -60,22 +57,23 @@ class IntelOneapiCompilers(IntelOneApiPackage): super(IntelOneapiCompilers, self).install( spec, prefix, - installer_path=glob.glob(path.join('fortran-installer', '*'))[0]) + installer_path=glob.glob(join_path('fortran-installer', '*'))[0]) # Some installers have a bug and do not return an error code when failing - if not path.isfile(path.join(prefix, 'compiler', 'latest', 'linux', + if not path.isfile(join_path(self.component_path, 'linux', 'bin', 'intel64', 'ifort')): raise RuntimeError('install failed') # set rpath so 'spack compiler add' can check version strings # without setting LD_LIBRARY_PATH rpath = ':'.join(self._ld_library_path()) - patch_dirs = [path.join('compiler', 'lib', 'intel64_lin'), - path.join('compiler', 'lib', 'intel64'), + patch_dirs = [join_path('compiler', 'lib', 'intel64_lin'), + join_path('compiler', 'lib', 'intel64'), 'bin'] for pd in patch_dirs: - patchables = glob.glob(self._join_prefix(path.join(pd, '*'))) - patchables.append(self._join_prefix(path.join('lib', 'icx-lto.so'))) + patchables = glob.glob(join_path(self.component_path, 'linux', pd, '*')) + patchables.append(join_path(self.component_path, + 'linux', 'lib', 'icx-lto.so')) for file in patchables: # Try to patch all files, patchelf will do nothing if # file should not be patched diff --git a/var/spack/repos/builtin/packages/intel-oneapi-mkl/package.py b/var/spack/repos/builtin/packages/intel-oneapi-mkl/package.py index fff8432ccb..aee6a50677 100644 --- a/var/spack/repos/builtin/packages/intel-oneapi-mkl/package.py +++ b/var/spack/repos/builtin/packages/intel-oneapi-mkl/package.py @@ -36,6 +36,8 @@ class IntelOneapiMkl(IntelOneApiLibraryPackage): @property def libs(self): - lib_path = '{0}/{1}/latest/lib/intel64'.format(self.prefix, self.component_dir) - mkl_libs = ['libmkl_intel_ilp64', 'libmkl_sequential', 'libmkl_core'] - return find_libraries(mkl_libs, root=lib_path, shared=True, recursive=False) + lib_path = join_path(self.component_path, 'lib', 'intel64') + mkl_libs = ['libmkl_intel_lp64', 'libmkl_sequential', 'libmkl_core'] + libs = find_libraries(mkl_libs, root=lib_path, shared=True, recursive=False) + libs += find_system_libraries(['libpthread', 'libm', 'libdl'], shared=True) + return libs diff --git a/var/spack/repos/builtin/packages/intel-oneapi-mpi/package.py b/var/spack/repos/builtin/packages/intel-oneapi-mpi/package.py index ae6d1fccbf..86eef9054e 100644 --- a/var/spack/repos/builtin/packages/intel-oneapi-mpi/package.py +++ b/var/spack/repos/builtin/packages/intel-oneapi-mpi/package.py @@ -4,7 +4,6 @@ # SPDX-License-Identifier: (Apache-2.0 OR MIT) -from os import path import subprocess from sys import platform @@ -34,7 +33,7 @@ class IntelOneapiMpi(IntelOneApiLibraryPackage): return 'mpi' def setup_dependent_package(self, module, dep_spec): - dir = join_path(self.prefix, 'mpi', 'latest', 'bin') + dir = join_path(self.component_path, 'bin') self.spec.mpicc = join_path(dir, 'mpicc') self.spec.mpicxx = join_path(dir, 'mpicxx') self.spec.mpif77 = join_path(dir, 'mpif77') @@ -48,7 +47,7 @@ class IntelOneapiMpi(IntelOneApiLibraryPackage): env.set('MPICH_FC', spack_fc) # Set compiler wrappers for dependent build stage - dir = self._join_prefix('bin') + dir = join_path(self.component_path, 'bin') env.set('MPICC', join_path(dir, 'mpicc')) env.set('MPICXX', join_path(dir, 'mpicxx')) env.set('MPIF77', join_path(dir, 'mpif77')) @@ -58,22 +57,19 @@ class IntelOneapiMpi(IntelOneApiLibraryPackage): @property def libs(self): libs = [] - for dir in [path.join('lib', 'release_mt'), + for dir in [join_path('lib', 'release_mt'), 'lib', - path.join('libfabric', 'lib')]: - lib_path = path.join(self.prefix, 'mpi', 'latest', dir) + join_path('libfabric', 'lib')]: + lib_path = join_path(self.component_path, dir) ldir = find_libraries('*', root=lib_path, shared=True, recursive=False) libs += ldir return libs - def _join_prefix(self, path): - return join_path(self.prefix, 'mpi', 'latest', path) - def install(self, spec, prefix): super(IntelOneapiMpi, self).install(spec, prefix) # need to patch libmpi.so so it can always find libfabric - libfabric_rpath = self._join_prefix(path.join('libfabric', 'lib')) + libfabric_rpath = join_path(self.component_path, 'libfabric', 'lib') for lib_version in ['debug', 'release', 'release_mt', 'debug_mt']: - file = self._join_prefix(path.join('lib', lib_version, 'libmpi.so')) + file = join_path(self.component_path, 'lib', lib_version, 'libmpi.so') subprocess.call(['patchelf', '--set-rpath', libfabric_rpath, file]) -- cgit v1.2.3-70-g09d2