From 7fc68240fe098ed3be682916cf44ab3b3dfdad12 Mon Sep 17 00:00:00 2001 From: Sergey Kosukhin Date: Tue, 28 Jun 2022 01:34:15 +0200 Subject: oneapi-* packages: improve use with modules (#30981) This commit adds some changes which improve use of Spack-installed oneAPI packages with Spack-generated modules, but not within Spack (e.g. if you install some of these packages with Spack, then load their associated modules to build other packages outside of Spack). The majority of the PR diff is refactoring. The functional changes are: * intel-oneapi-mkl: * setup_run_environment: update Intel compiler flags to RPATH the mkl libs * intel-oneapi-compilers: update the compiler configuration to RPATH libraries installed by this package (note that Spack already handled this when installing dependent packages with Spack, but this is specifically to use the intel-oneapi-compilers package outside of Spack). Specifically: * inject_rpaths: this modifies the binaries installed as part of the intel-oneapi-compilers package to RPATH libraries provided by this package * extend_config_flags: this instructs the compiler executables provided by this package to RPATH those same libraries Refactoring includes: * intel-oneapi-compilers: in addition to the functional changes, a large portion of this diff is reorganizing the creation of resources/archives downloaded for the install * The base oneAPI package renamed component_path, so several packages changed as a result: * intel-oneapi-dpl * intel-oneapi-dnn * extrae * intel-oneapi-mpi: * Perform file filtering in one pass rather than two --- lib/spack/spack/build_systems/oneapi.py | 26 +- var/spack/repos/builtin/packages/extrae/package.py | 2 +- .../packages/intel-oneapi-compilers/package.py | 278 ++++++++++++--------- .../builtin/packages/intel-oneapi-dnn/package.py | 5 +- .../builtin/packages/intel-oneapi-dpl/package.py | 2 +- .../builtin/packages/intel-oneapi-mkl/package.py | 63 +++-- .../builtin/packages/intel-oneapi-mpi/package.py | 76 +++--- 7 files changed, 245 insertions(+), 207 deletions(-) diff --git a/lib/spack/spack/build_systems/oneapi.py b/lib/spack/spack/build_systems/oneapi.py index 76c69acd5e..c0da2fdb53 100644 --- a/lib/spack/spack/build_systems/oneapi.py +++ b/lib/spack/spack/build_systems/oneapi.py @@ -45,17 +45,15 @@ class IntelOneApiPackage(Package): raise NotImplementedError @property - def component_path(self): + def component_prefix(self): """Path to component //.""" - return join_path(self.prefix, self.component_dir, str(self.spec.version)) + return self.prefix.join(join_path(self.component_dir, self.spec.version)) - def install(self, spec, prefix, installer_path=None): - """Shared install method for all oneapi packages.""" + def install(self, spec, prefix): + self.install_component(basename(self.url_for_version(spec.version))) - # intel-oneapi-compilers overrides the installer_path when - # installing fortran, which comes from a spack resource - if installer_path is None: - installer_path = basename(self.url_for_version(spec.version)) + def install_component(self, installer_path): + """Shared install method for all oneapi packages.""" if platform.system() == 'Linux': # Intel installer assumes and enforces that all components @@ -77,7 +75,7 @@ class IntelOneApiPackage(Package): bash = Executable('bash') # Installer writes files in ~/intel set HOME so it goes to prefix - bash.add_default_env('HOME', prefix) + bash.add_default_env('HOME', self.prefix) # Installer checks $XDG_RUNTIME_DIR/.bootstrapper_lock_file as well bash.add_default_env('XDG_RUNTIME_DIR', join_path(self.stage.path, 'runtime')) @@ -85,13 +83,13 @@ class IntelOneApiPackage(Package): bash(installer_path, '-s', '-a', '-s', '--action', 'install', '--eula', 'accept', - '--install-dir', prefix) + '--install-dir', self.prefix) if getpass.getuser() == 'root': shutil.rmtree('/var/intel/installercache', ignore_errors=True) # Some installers have a bug and do not return an error code when failing - if not isdir(join_path(prefix, self.component_dir)): + if not isdir(join_path(self.prefix, self.component_dir)): raise RuntimeError('install failed') def setup_run_environment(self, env): @@ -104,7 +102,7 @@ class IntelOneApiPackage(Package): $ source {prefix}/{component}/{version}/env/vars.sh """ env.extend(EnvironmentModifications.from_sourcing_file( - join_path(self.component_path, 'env', 'vars.sh'))) + join_path(self.component_prefix, 'env', 'vars.sh'))) class IntelOneApiLibraryPackage(IntelOneApiPackage): @@ -118,12 +116,12 @@ class IntelOneApiLibraryPackage(IntelOneApiPackage): @property def headers(self): - include_path = join_path(self.component_path, 'include') + include_path = join_path(self.component_prefix, 'include') return find_headers('*', include_path, recursive=True) @property def libs(self): - lib_path = join_path(self.component_path, 'lib', 'intel64') + lib_path = join_path(self.component_prefix, '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/extrae/package.py b/var/spack/repos/builtin/packages/extrae/package.py index e49cc6a329..79a1e11bce 100644 --- a/var/spack/repos/builtin/packages/extrae/package.py +++ b/var/spack/repos/builtin/packages/extrae/package.py @@ -84,7 +84,7 @@ class Extrae(AutotoolsPackage): def configure_args(self): spec = self.spec if '^intel-oneapi-mpi' in spec: - mpiroot = spec['mpi'].component_path + mpiroot = spec['mpi'].component_prefix else: mpiroot = spec['mpi'].prefix 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 2d0807fd60..5579e3146f 100644 --- a/var/spack/repos/builtin/packages/intel-oneapi-compilers/package.py +++ b/var/spack/repos/builtin/packages/intel-oneapi-compilers/package.py @@ -3,13 +3,93 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) -import glob import platform -import subprocess -from os import path +from spack.build_environment import dso_suffix from spack.package import * +linux_versions = [ + { + 'version': '2022.1.0', + 'cpp': { + 'url': 'https://registrationcenter-download.intel.com/akdlm/irc_nas/18717/l_dpcpp-cpp-compiler_p_2022.1.0.137_offline.sh', + 'sha256': '1027819581ba820470f351abfc2b2658ff2684ed8da9ed0e722a45774a2541d6' + }, + 'ftn': { + 'url': 'https://registrationcenter-download.intel.com/akdlm/irc_nas/18703/l_fortran-compiler_p_2022.1.0.134_offline.sh', + 'sha256': '583082abe54a657eb933ea4ba3e988eef892985316be13f3e23e18a3c9515020' + } + }, + + { + 'version': '2022.0.2', + 'cpp': { + 'url': 'https://registrationcenter-download.intel.com/akdlm/irc_nas/18478/l_dpcpp-cpp-compiler_p_2022.0.2.84_offline.sh', + 'sha256': 'ade5bbd203e7226ca096d7bf758dce07857252ec54e83908cac3849e6897b8f3' + }, + 'ftn': { + 'url': 'https://registrationcenter-download.intel.com/akdlm/irc_nas/18481/l_fortran-compiler_p_2022.0.2.83_offline.sh', + 'sha256': '78532b4118fc3d7afd44e679fc8e7aed1e84efec0d892908d9368e0c7c6b190c' + } + }, + + { + 'version': '2022.0.1', + 'cpp': { + 'url': 'https://registrationcenter-download.intel.com/akdlm/irc_nas/18435/l_dpcpp-cpp-compiler_p_2022.0.1.71_offline.sh', + 'sha256': 'c7cddc64c3040eece2dcaf48926ba197bb27e5a46588b1d7b3beddcdc379926a' + }, + 'ftn': { + 'url': 'https://registrationcenter-download.intel.com/akdlm/irc_nas/18436/l_fortran-compiler_p_2022.0.1.70_offline.sh', + 'sha256': '2cb28a04f93554bfeffd6cad8bd0e7082735f33d73430655dea86df8933f50d1' + } + }, + { + 'version': '2021.4.0', + 'cpp': { + 'url': 'https://registrationcenter-download.intel.com/akdlm/irc_nas/18209/l_dpcpp-cpp-compiler_p_2021.4.0.3201_offline.sh', + 'sha256': '9206bff1c2fdeb1ca0d5f79def90dcf3e6c7d5711b9b5adecd96a2ba06503828' + }, + 'ftn': { + 'url': 'https://registrationcenter-download.intel.com/akdlm/irc_nas/18210/l_fortran-compiler_p_2021.4.0.3224_offline.sh', + 'sha256': 'de2fcf40e296c2e882e1ddf2c45bb8d25aecfbeff2f75fcd7494068d621eb7e0' + } + }, + { + 'version': '2021.3.0', + 'cpp': { + 'url': 'https://registrationcenter-download.intel.com/akdlm/irc_nas/17928/l_dpcpp-cpp-compiler_p_2021.3.0.3168_offline.sh', + 'sha256': 'f848d81b7cabc76c2841c9757abb2290921efd7b82491d830605f5785600e7a1' + }, + 'ftn': { + 'url': 'https://registrationcenter-download.intel.com/akdlm/irc_nas/17959/l_fortran-compiler_p_2021.3.0.3168_offline.sh', + 'sha256': 'c4553f7e707be8e8e196f625e4e7fbc8eff5474f64ab85fc7146b5ed53ebc87c' + } + }, + { + 'version': '2021.2.0', + 'cpp': { + 'url': 'https://registrationcenter-download.intel.com/akdlm/irc_nas/17749/l_dpcpp-cpp-compiler_p_2021.2.0.118_offline.sh', + 'sha256': '5d01cbff1a574c3775510cd97ffddd27fdf56d06a6b0c89a826fb23da4336d59' + }, + 'ftn': { + 'url': 'https://registrationcenter-download.intel.com/akdlm/irc_nas/17756/l_fortran-compiler_p_2021.2.0.136_offline.sh', + 'sha256': 'a62e04a80f6d2f05e67cd5acb03fa58857ee22c6bd581ec0651c0ccd5bdec5a1' + } + }, + { + 'version': '2021.1.2', + 'cpp': { + 'url': 'https://registrationcenter-download.intel.com/akdlm/irc_nas/17513/l_dpcpp-cpp-compiler_p_2021.1.2.63_offline.sh', + 'sha256': '68d6cb638091990e578e358131c859f3bbbbfbf975c581fd0b4b4d36476d6f0a' + }, + 'ftn': { + 'url': 'https://registrationcenter-download.intel.com/akdlm/irc_nas/17508/l_fortran-compiler_p_2021.1.2.62_offline.sh', + 'sha256': '29345145268d08a59fa7eb6e58c7522768466dd98f6d9754540d1a0803596829' + } + } +] + @IntelOneApiPackage.update_description class IntelOneapiCompilers(IntelOneApiPackage): @@ -25,125 +105,15 @@ class IntelOneapiCompilers(IntelOneApiPackage): depends_on('patchelf', type='build') if platform.system() == 'Linux': - version('2022.1.0', - url='https://registrationcenter-download.intel.com/akdlm/irc_nas/18717/l_dpcpp-cpp-compiler_p_2022.1.0.137_offline.sh', - sha256='1027819581ba820470f351abfc2b2658ff2684ed8da9ed0e722a45774a2541d6', - expand=False) - resource(name='fortran-installer', - url='https://registrationcenter-download.intel.com/akdlm/irc_nas/18703/l_fortran-compiler_p_2022.1.0.134_offline.sh', - sha256='583082abe54a657eb933ea4ba3e988eef892985316be13f3e23e18a3c9515020', - expand=False, - placement='fortran-installer', - when='@2022.1.0') - version('2022.0.2', - url='https://registrationcenter-download.intel.com/akdlm/irc_nas/18478/l_dpcpp-cpp-compiler_p_2022.0.2.84_offline.sh', - sha256='ade5bbd203e7226ca096d7bf758dce07857252ec54e83908cac3849e6897b8f3', - expand=False) - resource(name='fortran-installer', - url='https://registrationcenter-download.intel.com/akdlm/irc_nas/18481/l_fortran-compiler_p_2022.0.2.83_offline.sh', - sha256='78532b4118fc3d7afd44e679fc8e7aed1e84efec0d892908d9368e0c7c6b190c', - expand=False, - placement='fortran-installer', - when='@2022.0.2') - version('2022.0.1', - url='https://registrationcenter-download.intel.com/akdlm/irc_nas/18435/l_dpcpp-cpp-compiler_p_2022.0.1.71_offline.sh', - sha256='c7cddc64c3040eece2dcaf48926ba197bb27e5a46588b1d7b3beddcdc379926a', - expand=False) - resource(name='fortran-installer', - url='https://registrationcenter-download.intel.com/akdlm/irc_nas/18436/l_fortran-compiler_p_2022.0.1.70_offline.sh', - sha256='2cb28a04f93554bfeffd6cad8bd0e7082735f33d73430655dea86df8933f50d1', - expand=False, - placement='fortran-installer', - when='@2022.0.1') - version('2021.4.0', - url='https://registrationcenter-download.intel.com/akdlm/irc_nas/18209/l_dpcpp-cpp-compiler_p_2021.4.0.3201_offline.sh', - sha256='9206bff1c2fdeb1ca0d5f79def90dcf3e6c7d5711b9b5adecd96a2ba06503828', - expand=False) - resource(name='fortran-installer', - url='https://registrationcenter-download.intel.com/akdlm/irc_nas/18210/l_fortran-compiler_p_2021.4.0.3224_offline.sh', - sha256='de2fcf40e296c2e882e1ddf2c45bb8d25aecfbeff2f75fcd7494068d621eb7e0', - expand=False, - placement='fortran-installer', - when='@2021.4.0') - version('2021.3.0', - url='https://registrationcenter-download.intel.com/akdlm/irc_nas/17928/l_dpcpp-cpp-compiler_p_2021.3.0.3168_offline.sh', - sha256='f848d81b7cabc76c2841c9757abb2290921efd7b82491d830605f5785600e7a1', - expand=False) - resource(name='fortran-installer', - url='https://registrationcenter-download.intel.com/akdlm/irc_nas/17959/l_fortran-compiler_p_2021.3.0.3168_offline.sh', - sha256='c4553f7e707be8e8e196f625e4e7fbc8eff5474f64ab85fc7146b5ed53ebc87c', - expand=False, - placement='fortran-installer', - when='@2021.3.0') - version('2021.2.0', - url='https://registrationcenter-download.intel.com/akdlm/irc_nas/17749/l_dpcpp-cpp-compiler_p_2021.2.0.118_offline.sh', - sha256='5d01cbff1a574c3775510cd97ffddd27fdf56d06a6b0c89a826fb23da4336d59', - expand=False) - resource(name='fortran-installer', - url='https://registrationcenter-download.intel.com/akdlm/irc_nas/17756/l_fortran-compiler_p_2021.2.0.136_offline.sh', - sha256='a62e04a80f6d2f05e67cd5acb03fa58857ee22c6bd581ec0651c0ccd5bdec5a1', - expand=False, - placement='fortran-installer', - when='@2021.2.0') - version('2021.1.2', - url='https://registrationcenter-download.intel.com/akdlm/irc_nas/17513/l_dpcpp-cpp-compiler_p_2021.1.2.63_offline.sh', - sha256='68d6cb638091990e578e358131c859f3bbbbfbf975c581fd0b4b4d36476d6f0a', - expand=False) - resource(name='fortran-installer', - url='https://registrationcenter-download.intel.com/akdlm/irc_nas/17508/l_fortran-compiler_p_2021.1.2.62_offline.sh', - sha256='29345145268d08a59fa7eb6e58c7522768466dd98f6d9754540d1a0803596829', - expand=False, - placement='fortran-installer', - when='@2021.1.2') + for v in linux_versions: + version(v['version'], expand=False, **v['cpp']) + resource(name='fortran-installer', placement='fortran-installer', + when='@{0}'.format(v['version']), expand=False, **v['ftn']) @property def component_dir(self): return 'compiler' - def _ld_library_path(self): - dirs = ['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 join_path(self.component_path, 'linux', dir) - - def install(self, spec, prefix): - # install cpp - # Copy instead of install to speed up debugging - # subprocess.run(f'cp -r /opt/intel/oneapi/compiler {prefix}', shell=True) - super(IntelOneapiCompilers, self).install(spec, prefix) - - # install fortran - super(IntelOneapiCompilers, self).install( - spec, - prefix, - 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(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 = [join_path('lib'), - join_path('compiler', 'lib', 'intel64_lin'), - join_path('compiler', 'lib', 'intel64'), - 'bin'] - for pd in patch_dirs: - 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 - subprocess.call(['patchelf', '--set-rpath', rpath, file]) - def setup_run_environment(self, env): """Adds environment variables to the generated module file. @@ -157,8 +127,72 @@ class IntelOneapiCompilers(IntelOneApiPackage): """ super(IntelOneapiCompilers, self).setup_run_environment(env) - bin = join_path(self.component_path, 'linux', 'bin') - env.set('CC', join_path(bin, 'icx')) - env.set('CXX', join_path(bin, 'icpx')) - env.set('F77', join_path(bin, 'ifx')) - env.set('FC', join_path(bin, 'ifx')) + env.set('CC', self.component_prefix.bin.icx) + env.set('CXX', self.component_prefix.bin.icpx) + env.set('F77', self.component_prefix.bin.ifx) + env.set('FC', self.component_prefix.bin.ifx) + + def install(self, spec, prefix): + # Copy instead of install to speed up debugging + # install_tree('/opt/intel/oneapi/compiler', self.prefix) + + # install cpp + super(IntelOneapiCompilers, self).install(spec, prefix) + + # install fortran + self.install_component(find('fortran-installer', '*')[0]) + + # Some installers have a bug and do not return an error code when failing + if not is_exe(self.component_prefix.linux.bin.intel64.ifort): + raise RuntimeError('install failed') + + @run_after('install') + def inject_rpaths(self): + # Sets rpath so the compilers can work without setting LD_LIBRARY_PATH. + patchelf = which('patchelf') + patchelf.add_default_arg('--set-rpath') + patchelf.add_default_arg(':'.join(self._ld_library_path())) + for pd in ['bin', 'lib', join_path('compiler', 'lib', 'intel64_lin')]: + for file in find(self.component_prefix.linux.join(pd), '*', + recursive=False): + # Try to patch all files, patchelf will do nothing and fail if file + # should not be patched + patchelf(file, fail_on_error=False) + + @run_after('install') + def extend_config_flags(self): + # Extends compiler config files to inject additional compiler flags. + + # Inject rpath flags to the runtime libraries. + # TODO: this uses a static string for the rpath argument, but should actually + # make sure that it matches the cc_rpath_arg etc. arguments defined in + # spack.compilers.oneapi and spack.compilers.intel (for now, these are + # inherited from spack.compilers.compiler.Compiler): these can theoretically be + # different for different compiler versions and for different languages (C, + # C++, and Fortran), but in practice are not. + # TODO: it is unclear whether we should really use all elements of + # _ld_library_path because it looks like the only rpath that needs to be + # injected is self.component_prefix.linux.compiler.lib.intel64_lin. + flags = ' '.join(['-Wl,-rpath,{0}'.format(d) for d in self._ld_library_path()]) + for cmp in ['icx', 'icpx', 'ifx', + join_path('intel64', 'icc'), + join_path('intel64', 'icpc'), + join_path('intel64', 'ifort')]: + cfg_file = self.component_prefix.linux.bin.join(cmp + '.cfg') + with open(cfg_file, 'w') as f: + f.write(flags) + set_install_permissions(cfg_file) + + def _ld_library_path(self): + # Returns an iterable of directories that might contain shared runtime libraries + # of the compilers themselves and the executables they produce. + for d in ['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')]: + p = join_path(self.component_prefix.linux, d) + if find(p, '*.' + dso_suffix, recursive=False): + yield p diff --git a/var/spack/repos/builtin/packages/intel-oneapi-dnn/package.py b/var/spack/repos/builtin/packages/intel-oneapi-dnn/package.py index f4f720d87a..204fc0d8d2 100644 --- a/var/spack/repos/builtin/packages/intel-oneapi-dnn/package.py +++ b/var/spack/repos/builtin/packages/intel-oneapi-dnn/package.py @@ -64,10 +64,11 @@ class IntelOneapiDnn(IntelOneApiLibraryPackage): @property def headers(self): - include_path = join_path(self.component_path, 'cpu_dpcpp_gpu_dpcpp', 'include') + include_path = join_path(self.component_prefix, + 'cpu_dpcpp_gpu_dpcpp', 'include') return find_headers('dnnl', include_path) @property def libs(self): - lib_path = join_path(self.component_path, 'cpu_dpcpp_gpu_dpcpp', 'lib') + lib_path = join_path(self.component_prefix, 'cpu_dpcpp_gpu_dpcpp', 'lib') return find_libraries(['libdnnl', 'libmkldnn'], root=lib_path, shared=True) diff --git a/var/spack/repos/builtin/packages/intel-oneapi-dpl/package.py b/var/spack/repos/builtin/packages/intel-oneapi-dpl/package.py index d41ce1c3ed..cdfb36e699 100644 --- a/var/spack/repos/builtin/packages/intel-oneapi-dpl/package.py +++ b/var/spack/repos/builtin/packages/intel-oneapi-dpl/package.py @@ -48,7 +48,7 @@ class IntelOneapiDpl(IntelOneApiLibraryPackage): @property def headers(self): - include_path = join_path(self.component_path, 'linux', 'include') + include_path = join_path(self.component_prefix, 'linux', 'include') headers = find_headers('*', include_path, recursive=True) # Force this directory to be added to include path, even # though no files are here because all includes are relative 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 2f47cf3fb7..bbd0e2b350 100644 --- a/var/spack/repos/builtin/packages/intel-oneapi-mkl/package.py +++ b/var/spack/repos/builtin/packages/intel-oneapi-mkl/package.py @@ -74,41 +74,54 @@ class IntelOneapiMkl(IntelOneApiLibraryPackage): def component_dir(self): return 'mkl' - def xlp64_lib(self, lib): - return lib + ('_ilp64' - if '+ilp64' in self.spec - else '_lp64') - @property def headers(self): - include_path = join_path(self.component_path, 'include') - return find_headers('*', include_path) - - # provide cluster libraries if +cluster variant is used or - # the scalapack virtual package was requested - def cluster(self): - return '+cluster' in self.spec + return find_headers('*', self.component_prefix.include) @property def libs(self): shared = '+shared' in self.spec - mkl_libs = [] - if self.cluster(): - mkl_libs += [self.xlp64_lib('libmkl_scalapack'), - 'libmkl_cdft_core'] - mkl_libs += [self.xlp64_lib('libmkl_intel'), - 'libmkl_sequential', - 'libmkl_core'] - if self.cluster(): - mkl_libs += [self.xlp64_lib('libmkl_blacs_intelmpi')] - libs = find_libraries(mkl_libs, - join_path(self.component_path, 'lib', 'intel64'), - shared=shared) + + libs = self._find_mkl_libs(shared) + system_libs = find_system_libraries(['libpthread', 'libm', 'libdl']) if shared: return libs + system_libs else: return IntelOneApiStaticLibraryList(libs, system_libs) + def setup_run_environment(self, env): + super(IntelOneapiMkl, self).setup_run_environment(env) + + # Support RPATH injection to the library directories when the '-mkl' or '-qmkl' + # flag of the Intel compilers are used outside the Spack build environment. We + # should not try to take care of other compilers because the users have to + # provide the linker flags anyway and are expected to take care of the RPATHs + # flags too. We prefer the __INTEL_POST_CFLAGS/__INTEL_POST_FFLAGS flags over + # the PRE ones so that any other RPATHs provided by the users on the command + # line come before and take precedence over the ones we inject here. + for d in self._find_mkl_libs('+shared' in self.spec).directories: + flag = '-Wl,-rpath,{0}'.format(d) + env.append_path('__INTEL_POST_CFLAGS', flag, separator=' ') + env.append_path('__INTEL_POST_FFLAGS', flag, separator=' ') + def setup_dependent_build_environment(self, env, dependent_spec): - env.set('MKLROOT', self.component_path) + env.set('MKLROOT', self.component_prefix) + + def _find_mkl_libs(self, shared): + libs = [] + + if '+cluster' in self.spec: + libs.extend([self._xlp64_lib('libmkl_scalapack'), 'libmkl_cdft_core']) + + libs.extend([self._xlp64_lib('libmkl_intel'), + 'libmkl_sequential', 'libmkl_core']) + + if '+cluster' in self.spec: + libs.append(self._xlp64_lib('libmkl_blacs_intelmpi')) + + return find_libraries( + libs, self.component_prefix.lib.intel64, shared=shared) + + def _xlp64_lib(self, lib): + return lib + ('_ilp64' if '+ilp64' in self.spec else '_lp64') 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 0582e1b2d2..e8e8e3e268 100644 --- a/var/spack/repos/builtin/packages/intel-oneapi-mpi/package.py +++ b/var/spack/repos/builtin/packages/intel-oneapi-mpi/package.py @@ -68,17 +68,16 @@ class IntelOneapiMpi(IntelOneApiLibraryPackage): return 'mpi' def setup_dependent_package(self, module, dep_spec): - dir = join_path(self.component_path, 'bin') if '+generic-names' in self.spec: - self.spec.mpicc = join_path(dir, 'mpicc') - self.spec.mpicxx = join_path(dir, 'mpicxx') - self.spec.mpif77 = join_path(dir, 'mpif77') - self.spec.mpifc = join_path(dir, 'mpifc') + self.spec.mpicc = join_path(self.component_prefix.bin, 'mpicc') + self.spec.mpicxx = join_path(self.component_prefix.bin, 'mpicxx') + self.spec.mpif77 = join_path(self.component_prefix.bin, 'mpif77') + self.spec.mpifc = join_path(self.component_prefix.bin, 'mpifc') else: - self.spec.mpicc = join_path(dir, 'mpiicc') - self.spec.mpicxx = join_path(dir, 'mpiicpc') - self.spec.mpif77 = join_path(dir, 'mpiifort') - self.spec.mpifc = join_path(dir, 'mpiifort') + self.spec.mpicc = join_path(self.component_prefix.bin, 'mpiicc') + self.spec.mpicxx = join_path(self.component_prefix.bin, 'mpiicpc') + self.spec.mpif77 = join_path(self.component_prefix.bin, 'mpiifort') + self.spec.mpifc = join_path(self.component_prefix.bin, 'mpiifort') def setup_dependent_build_environment(self, env, dependent_spec): env.set('MPICH_CC', spack_cc) @@ -88,61 +87,54 @@ class IntelOneapiMpi(IntelOneApiLibraryPackage): env.set('MPICH_FC', spack_fc) # Set compiler wrappers for dependent build stage - dir = join_path(self.component_path, 'bin') if '+generic-names' in self.spec: - env.set('MPICC', join_path(dir, 'mpicc')) - env.set('MPICXX', join_path(dir, 'mpicxx')) - env.set('MPIF77', join_path(dir, 'mpif77')) - env.set('MPIF90', join_path(dir, 'mpif90')) - env.set('MPIFC', join_path(dir, 'mpifc')) + env.set('MPICC', join_path(self.component_prefix.bin, 'mpicc')) + env.set('MPICXX', join_path(self.component_prefix.bin, 'mpicxx')) + env.set('MPIF77', join_path(self.component_prefix.bin, 'mpif77')) + env.set('MPIF90', join_path(self.component_prefix.bin, 'mpif90')) + env.set('MPIFC', join_path(self.component_prefix.bin, 'mpifc')) else: - env.set('MPICC', join_path(dir, 'mpiicc')) - env.set('MPICXX', join_path(dir, 'mpiicpc')) - env.set('MPIF77', join_path(dir, 'mpiifort')) - env.set('MPIF90', join_path(dir, 'mpiifort')) - env.set('MPIFC', join_path(dir, 'mpiifort')) + env.set('MPICC', join_path(self.component_prefix.bin, 'mpiicc')) + env.set('MPICXX', join_path(self.component_prefix.bin, 'mpiicpc')) + env.set('MPIF77', join_path(self.component_prefix.bin, 'mpiifort')) + env.set('MPIF90', join_path(self.component_prefix.bin, 'mpiifort')) + env.set('MPIFC', join_path(self.component_prefix.bin, 'mpiifort')) - env.set('I_MPI_ROOT', self.component_path) + env.set('I_MPI_ROOT', self.component_prefix) @property def headers(self): - include_path = join_path(self.component_path, 'include') - headers = find_headers('*', include_path) + headers = find_headers('*', self.component_prefix.include) if '+ilp64' in self.spec: - headers += find_headers('*', join_path(include_path, 'ilp64')) + headers += find_headers('*', self.component_prefix.include.ilp64) return headers @property def libs(self): - lib_dir = join_path(self.component_path, 'lib') - release_lib_dir = join_path(lib_dir, 'release') libs = [] if '+ilp64' in self.spec: - libs += find_libraries('libmpi_ilp64', release_lib_dir) - libs += find_libraries(['libmpicxx', 'libmpifort'], lib_dir) - libs += find_libraries('libmpi', release_lib_dir) + libs += find_libraries('libmpi_ilp64', self.component_prefix.lib.release) + libs += find_libraries(['libmpicxx', 'libmpifort'], self.component_prefix.lib) + libs += find_libraries('libmpi', self.component_prefix.lib.release) libs += find_system_libraries(['libdl', 'librt', 'libpthread']) # Find libfabric for libmpi.so if '+external-libfabric' in self.spec: libs += self.spec['libfabric'].libs else: - libs += find_libraries(['libfabric'], - join_path(self.component_path, 'libfabric', 'lib')) + libs += find_libraries(['libfabric'], self.component_prefix.libfabric.lib) return libs - def install(self, spec, prefix): - super(IntelOneapiMpi, self).install(spec, prefix) - + @run_after('install') + def fix_wrappers(self): # When spack builds from source # fix I_MPI_SUBSTITUTE_INSTALLDIR and # __EXEC_PREFIX_TO_BE_FILLED_AT_INSTALL_TIME__ - scripts = ["mpif77", "mpif90", "mpigcc", "mpigxx", "mpiicc", "mpiicpc", - "mpiifort"] - for script in scripts: - file = join_path(self.component_path, 'bin', script) - filter_file('I_MPI_SUBSTITUTE_INSTALLDIR', - self.component_path, file, backup=False) - filter_file('__EXEC_PREFIX_TO_BE_FILLED_AT_INSTALL_TIME__', - self.component_path, file, backup=False) + for wrapper in ['mpif77', 'mpif90', 'mpigcc', 'mpigxx', 'mpiicc', + 'mpiicpc', 'mpiifort']: + filter_file(r'I_MPI_SUBSTITUTE_INSTALLDIR|' + r'__EXEC_PREFIX_TO_BE_FILLED_AT_INSTALL_TIME__', + self.component_prefix, + self.component_prefix.bin.join(wrapper), + backup=False) -- cgit v1.2.3-70-g09d2