xref: /petsc/config/BuildSystem/config/packages/MPICH.py (revision bd00f7f07346bd94eecebd6cb318bef8fbb8f4e9)
1import config.package
2import os
3
4class Configure(config.package.GNUPackage):
5  def __init__(self, framework):
6    config.package.GNUPackage.__init__(self, framework)
7    self.version          = '5.0.0'
8    self.download         = ['https://github.com/pmodels/mpich/releases/download/v'+self.version+'/mpich-'+self.version+'.tar.gz',
9                             'https://www.mpich.org/static/downloads/'+self.version+'/mpich-'+self.version+'.tar.gz', # does not always work from Python? So add in web.cels URL below
10                             'https://web.cels.anl.gov/projects/petsc/download/externalpackages'+'/mpich-'+self.version+'.tar.gz']
11    self.download_git     = ['git://https://github.com/pmodels/mpich.git']
12    self.versionname      = 'MPICH_NUMVERSION'
13    self.includes         = ['mpi.h']
14    self.gitsubmodules    = ['.']
15    self.downloaddirnames = ['mpich']
16    self.skippackagewithoptions = 1
17    self.skipMPIDependency      = 1
18    return
19
20  def setupDependencies(self, framework):
21    config.package.GNUPackage.setupDependencies(self, framework)
22    self.compilerFlags   = framework.require('config.compilerFlags',self)
23    self.cuda            = framework.require('config.packages.CUDA',self)
24    self.hip             = framework.require('config.packages.HIP',self)
25    self.hwloc           = framework.require('config.packages.hwloc',self)
26    self.python          = framework.require('config.packages.Python',self)
27    self.odeps           = [self.cuda, self.hip, self.hwloc]
28    return
29
30  def versionToStandardForm(self,ver):
31    '''Converts from MPICH 10007201 notation to standard notation 1.0.7'''
32    # See the format at https://github.com/pmodels/mpich/blob/main/src/include/mpi.h.in#L78
33    # 1 digit for MAJ, 2 digits for MIN, 2 digits for REV, 1 digit for EXT and 2 digits for EXT_NUMBER
34    return ".".join(map(str,[int(ver)//10000000, int(ver)//100000%100, int(ver)//1000%100]))
35
36  def setupHelp(self, help):
37    config.package.GNUPackage.setupHelp(self,help)
38    import nargs
39    help.addArgument('MPICH', '-download-mpich-pm=<hydra, gforker or mpd>',              nargs.Arg(None, 'hydra', 'Launcher for MPI processes'))
40    help.addArgument('MPICH', '-download-mpich-device=<ch3:nemesis or see MPICH docs>', nargs.Arg(None, None, 'Communicator for MPI processes'))
41    return
42
43  def checkDownload(self):
44    if config.setCompilers.Configure.isCygwin(self.log):
45      if config.setCompilers.Configure.isGNU(self.setCompilers.CC, self.log):
46        raise RuntimeError('Cannot download-install MPICH on Windows with cygwin compilers. Suggest installing Open MPI via cygwin installer')
47      else:
48        raise RuntimeError('Cannot download-install MPICH on Windows with Microsoft or Intel Compilers. Suggest using MS-MPI or Intel-MPI (do not use MPICH2')
49    if self.argDB['download-'+self.downloadname.lower()] and  'package-prefix-hash' in self.argDB and self.argDB['package-prefix-hash'] == 'reuse':
50      self.logWrite('Reusing package prefix install of '+self.defaultInstallDir+' for MPICH')
51      self.installDir = self.defaultInstallDir
52      self.updateCompilers(self.installDir,'mpicc','mpicxx','mpif77','mpif90')
53      return self.installDir
54    if self.argDB['download-'+self.downloadname.lower()]:
55      return self.getInstallDir()
56    return ''
57
58  def formGNUConfigureArgs(self):
59    '''MPICH has many specific extra configure arguments'''
60    args = config.package.GNUPackage.formGNUConfigureArgs(self)
61    args.append('--with-pm='+self.argDB['download-mpich-pm'])
62    args.append('--disable-java')
63    if self.hwloc.found:
64      args.append('--with-hwloc="'+self.hwloc.directory+'"')
65      args.append('--with-hwloc-prefix="'+self.hwloc.directory+'"')
66    elif 'with-hwloc' in self.framework.clArgDB and not self.argDB['with-hwloc'] :
67      args.append('--without-hwloc')
68    else:
69      args.append('--with-hwloc=embedded')
70    # make sure MPICH does not build with optimization for debug version of PETSc, so we can debug through MPICH
71    if self.compilerFlags.debugging:
72      args.append("--enable-fast=no")
73      args.append("--enable-error-messages=all")
74      mpich_device = 'ch3:sock'
75    else:
76      mpich_device = 'ch3:nemesis'
77    if self.cuda.found:
78      if not hasattr(self.cuda, 'cudaDir'):
79        raise RuntimeError('CUDA directory not detected! Mail configure.log to petsc-maint@mcs.anl.gov.')
80      args.append('--with-cuda='+self.cuda.cudaDir)
81      if hasattr(self.cuda,'cudaArch'): # MPICH's default to --with-cuda-sm=XX is 'auto', to auto-detect the arch of the visible GPUs (similar to our `native`).
82        if self.cuda.cudaArch == 'all':
83          args.append('--with-cuda-sm=all-major') # MPICH stopped supporting 'all' thus we do it with 'all-major'
84        else:
85          args.append('--with-cuda-sm='+self.cuda.cudaArch)
86      mpich_device = 'ch4:ucx'
87    elif self.hip.found:
88      args.append('--with-hip='+self.hip.hipDir)
89      mpich_device = 'ch4:ofi' # per https://github.com/pmodels/mpich/wiki/Using-MPICH-on-Crusher@OLCF
90
91    if 'download-mpich-device' in self.argDB:
92      mpich_device = self.argDB['download-mpich-device']
93    args.append('--with-device='+mpich_device)
94    # meminit: preinitialize memory associated structures and unions to eliminate access warnings from programs like valgrind
95    # dbg: add compiler flag, -g, to all internal compiler flag i.e. MPICHLIB_CFLAGS, MPICHLIB_CXXFLAGS, MPICHLIB_FFLAGS, and MPICHLIB_FCFLAGS, to make debugging easier
96    args.append('--enable-g=meminit,dbg')
97    if not self.setCompilers.isDarwin(self.log) and config.setCompilers.Configure.isClang(self.setCompilers.CC, self.log):
98      args.append('pac_cv_have_float16=no')
99    if config.setCompilers.Configure.isDarwin(self.log):
100      args.append('--disable-opencl')
101
102    # MPICH configure errors out on certain standard configure arguments
103    args = self.rmArgs(args,['--disable-f90','--enable-f90'])
104    args = self.rmArgsStartsWith(args,['F90=','F90FLAGS='])
105    args.append('PYTHON='+self.python.pyexe)
106    args.append('--disable-maintainer-mode')
107    args.append('--disable-dependency-tracking')
108    return args
109
110  def gitPreReqCheck(self):
111    return self.programs.autoreconf and self.programs.libtoolize
112
113  def preInstall(self):
114    if self.retriever.isDirectoryGitRepo(self.packageDir):
115      # no need to bootstrap tarballs
116      self.Bootstrap('./autogen.sh')
117
118  def Install(self):
119    '''After downloading and installing MPICH we need to reset the compilers to use those defined by the MPICH install'''
120    if 'package-prefix-hash' in self.argDB and self.argDB['package-prefix-hash'] == 'reuse':
121      return self.defaultInstallDir
122    installDir = config.package.GNUPackage.Install(self)
123    self.updateCompilers(installDir,'mpicc','mpicxx','mpif77','mpif90')
124    return installDir
125
126  def configure(self):
127    return config.package.Package.configure(self)
128