diff options
Diffstat (limited to 'var/spack/repos/builtin/packages/openfoam-org/package.py')
-rw-r--r-- | var/spack/repos/builtin/packages/openfoam-org/package.py | 344 |
1 files changed, 104 insertions, 240 deletions
diff --git a/var/spack/repos/builtin/packages/openfoam-org/package.py b/var/spack/repos/builtin/packages/openfoam-org/package.py index 53be5f6337..02c27a0db5 100644 --- a/var/spack/repos/builtin/packages/openfoam-org/package.py +++ b/var/spack/repos/builtin/packages/openfoam-org/package.py @@ -44,22 +44,23 @@ # entirely clear and thus untested. # - Resolution of flex, zlib needs more attention (within OpenFOAM) # -# - mpi handling: WM_MPLIB=SYSTEMMPI and use spack to populate the prefs.sh -# for it. -# Also provide wmake rules for special purpose 'USER' and 'USERMPI' +# - mpi handling: WM_MPLIB=SYSTEMMPI and use spack to populate prefs.sh for it. +# Provide wmake rules for special purpose 'USER' and 'USERMPI' # mpi implementations, in case these are required. # +# Known issues +# - Combining +zoltan with +int64 has not been tested, but probably won't work. +# - Combining +mgridgen with +int64 or +float32 probably won't work. +# ############################################################################## from spack import * from spack.environment import * import llnl.util.tty as tty -import multiprocessing import glob import re import shutil import os -from os.path import isdir, isfile from spack.pkg.builtin.openfoam_com import * @@ -78,19 +79,15 @@ class OpenfoamOrg(Package): version('4.1', '318a446c4ae6366c7296b61184acd37c', url=baseurl + '/OpenFOAM-4.x/archive/version-4.1.tar.gz') + version('dev', git='https://github.com/OpenFOAM/OpenFOAM-dev.git') variant('int64', default=False, - description='Compile with 64-bit labels') + description='Compile with 64-bit label') variant('float32', default=False, description='Compile with 32-bit scalar (single-precision)') - variant('source', default=True, description='Install library/application sources and tutorials') - #: Map spack compiler names to OpenFOAM compiler names - # By default, simply capitalize the first letter - compiler_mapping = {'intel': 'icc'} - provides('openfoam') depends_on('mpi') depends_on('zlib') @@ -98,31 +95,26 @@ class OpenfoamOrg(Package): depends_on('cmake', type='build') # Require scotch with ptscotch - corresponds to standard OpenFOAM setup - depends_on('scotch~int64+mpi', when='~int64') - depends_on('scotch+int64+mpi', when='+int64') + depends_on('scotch~metis+mpi~int64', when='~int64') + depends_on('scotch~metis+mpi+int64', when='+int64') - # General patches - patch('openfoam-site.patch') + # General patches - foamEtcFile as per openfoam.com (robuster) + common = ['spack-Allwmake', 'README-spack'] + assets = ['bin/foamEtcFile'] # Version-specific patches - patch('openfoam-etc-41.patch') - - # Some user settings, to be adjusted manually or via variants - foam_cfg = { - 'WM_COMPILER': 'Gcc', # <- %compiler - 'WM_ARCH_OPTION': '64', # (32/64-bit on x86_64) - 'WM_LABEL_SIZE': '32', # <- +int64 - 'WM_PRECISION_OPTION': 'DP', # <- +float32 - 'WM_COMPILE_OPTION': 'SPACKOpt', # Do not change - 'WM_MPLIB': 'SYSTEMMPI', # Use system mpi for spack + patch('openfoam-etc-41.patch', when='@4.1') + patch('openfoam-site-41.patch', when='@4.1') + + # Some user config settings + config = { + 'mplib': 'SYSTEMMPI', # Use system mpi for spack + # Add links into bin/, lib/ (eg, for other applications) + 'link': False } - # The system description is frequently needed - foam_sys = { - 'WM_ARCH': None, - 'WM_COMPILER': None, - 'WM_OPTIONS': None, - } + # The openfoam architecture, compiler information etc + _foam_arch = None # Content for etc/prefs.{csh,sh} etc_prefs = {} @@ -130,236 +122,111 @@ class OpenfoamOrg(Package): # Content for etc/config.{csh,sh}/ files etc_config = {} - build_script = './spack-Allwmake' # <- Generated by patch() method. - # phases = ['configure', 'build', 'install'] - # build_system_class = 'OpenfoamCom' + phases = ['configure', 'build', 'install'] + build_script = './spack-Allwmake' # <- Added by patch() method. - # Add symlinks into bin/, lib/ (eg, for other applications) - extra_symlinks = False + # + # - End of definitions / setup - + # def setup_environment(self, spack_env, run_env): + run_env.set('FOAM_PROJECT_DIR', self.projectdir) run_env.set('WM_PROJECT_DIR', self.projectdir) - - @property - def _canonical(self): - """Canonical name for this package and version""" - return 'OpenFOAM-{0}'.format(self.version) + for d in ['wmake', self.archbin]: # bin already added automatically + run_env.prepend_path('PATH', join_path(self.projectdir, d)) + run_env.set('MPI_BUFFER_SIZE', "20000000") + + def setup_dependent_environment(self, spack_env, run_env, dependent_spec): + """Provide location of the OpenFOAM project. + This is identical to the WM_PROJECT_DIR value, but we avoid that + variable since it would mask the normal OpenFOAM cleanup of + previous versions. + """ + spack_env.set('FOAM_PROJECT_DIR', self.projectdir) @property def projectdir(self): """Absolute location of project directory: WM_PROJECT_DIR/""" - return join_path(self.prefix, self._canonical) # <- prefix/canonical + return self.prefix # <- install directly under prefix @property - def etc(self): - """Absolute location of the OpenFOAM etc/ directory""" - return join_path(self.projectdir, 'etc') + def foam_arch(self): + if not self._foam_arch: + self._foam_arch = OpenfoamArch(self.spec, **self.config) + return self._foam_arch @property def archbin(self): """Relative location of architecture-specific executables""" - return join_path('platforms', self.wm_options, 'bin') + return join_path('platforms', self.foam_arch, 'bin') @property def archlib(self): """Relative location of architecture-specific libraries""" - return join_path('platforms', self.wm_options, 'lib') - - @property - def wm_options(self): - """The architecture+compiler+options for OpenFOAM""" - opts = self.set_openfoam() - return opts - - @property - def rpath_info(self): - """Define 'SPACKOpt' compiler optimization file to have wmake - use spack information with minimum modifications to OpenFOAM - """ - build_libpath = join_path(self.stage.source_path, self.archlib) - install_libpath = join_path(self.projectdir, self.archlib) - - # 'DBUG': rpaths - return '{0}{1} {2}{3}'.format( - self.compiler.cxx_rpath_arg, install_libpath, - self.compiler.cxx_rpath_arg, build_libpath) - - def openfoam_arch(self): - """Return an architecture value similar to what OpenFOAM does in - etc/config.sh/settings, but slightly more generous. - Uses and may adjust foam_cfg[WM_ARCH_OPTION] as a side-effect - """ - # spec.architecture.platform is like `uname -s`, but lower-case - platform = self.spec.architecture.platform - - # spec.architecture.target is like `uname -m` - target = self.spec.architecture.target - - if platform == 'linux': - if target == 'i686': - self.foam_cfg['WM_ARCH_OPTION'] = '32' # Force consistency - elif target == 'x86_64': - if self.foam_cfg['WM_ARCH_OPTION'] == '64': - platform += '64' - elif target == 'ia64': - platform += 'ia64' - elif target == 'armv7l': - platform += 'ARM7' - elif target == ppc64: - platform += 'PPC64' - elif target == ppc64le: - platform += 'PPC64le' - elif platform == 'darwin': - if target == 'x86_64': - platform += 'Intel' - if self.foam_cfg['WM_ARCH_OPTION'] == '64': - platform += '64' - # ... and others? - return platform - - def openfoam_compiler(self): - """Capitalized version of the compiler name, which usually corresponds - to how OpenFOAM will camel-case things. - Use compiler_mapping to handing special cases. - Also handle special compiler options (eg, KNL) - """ - comp = self.compiler.name - if comp in self.compiler_mapping: - comp = self.compiler_mapping[comp] - comp = comp.capitalize() - - if '+knl' in self.spec: - comp += 'KNL' - return comp - - def set_openfoam(self): - """Populate foam_cfg, foam_sys according to - variants, architecture, compiler. - Returns WM_OPTIONS. - """ - # Run once - opts = self.foam_sys['WM_OPTIONS'] - if opts: - return opts - - wm_arch = self.openfoam_arch() - wm_compiler = self.openfoam_compiler() - compileOpt = self.foam_cfg['WM_COMPILE_OPTION'] - - # Insist on a wmake rule for this architecture/compiler combination - archCompiler = wm_arch + wm_compiler - compiler_rule = join_path( - self.stage.source_path, 'wmake', 'rules', archCompiler) - - if not isdir(compiler_rule): - raise RuntimeError( - 'No wmake rule for {0}'.format(archCompiler)) - if not re.match(r'.+Opt$', compileOpt): - raise RuntimeError( - "WM_COMPILE_OPTION={0} is not type '*Opt'".format(compileOpt)) - - # Adjust for variants - self.foam_cfg['WM_LABEL_SIZE'] = ( - '64' if '+int64' in self.spec else '32' - ) - self.foam_cfg['WM_PRECISION_OPTION'] = ( - 'SP' if '+float32' in self.spec else 'DP' - ) - - # ---- - # WM_LABEL_OPTION=Int$WM_LABEL_SIZE - # WM_OPTIONS=$WM_ARCH$WM_COMPILER$WM_PRECISION_OPTION$WM_LABEL_OPTION$WM_COMPILE_OPTION - # ---- - self.foam_sys['WM_ARCH'] = wm_arch - self.foam_sys['WM_COMPILER'] = wm_compiler - self.foam_cfg['WM_COMPILER'] = wm_compiler # For bashrc,cshrc too - self.foam_sys['WM_OPTIONS'] = ''.join([ - wm_arch, - wm_compiler, - self.foam_cfg['WM_PRECISION_OPTION'], - 'Int', self.foam_cfg['WM_LABEL_SIZE'], # Int32/Int64 - compileOpt - ]) - return self.foam_sys['WM_OPTIONS'] + return join_path('platforms', self.foam_arch, 'lib') - def patch(self): - """Adjust OpenFOAM build for spack. Where needed, apply filter as an - alternative to normal patching. + def rename_source(self): + """This is fairly horrible. + The github tarfiles have weird names that do not correspond to the + canonical name. We need to rename these, but leave a symlink for + spack to work with. """ - self.set_openfoam() # May need foam_cfg/foam_sys information - - # This is fairly horrible. - # The github tarfiles have weird names that do not correspond to the - # canonical name. We need to rename these, but leave a symlink for - # spack to work with. - # - # Note that this particular OpenFOAM release requires absolute - # directories to build correctly! + # Note that this particular OpenFOAM requires absolute directories + # to build correctly! parent = os.path.dirname(self.stage.source_path) original = os.path.basename(self.stage.source_path) - target = self._canonical + target = 'OpenFOAM-{0}'.format(self.version) + # Could also grep through etc/bashrc for WM_PROJECT_VERSION with working_dir(parent): if original != target and not os.path.lexists(target): os.rename(original, target) os.symlink(target, original) tty.info('renamed {0} -> {1}'.format(original, target)) + def patch(self): + """Adjust OpenFOAM build for spack. + Where needed, apply filter as an alternative to normal patching.""" + self.rename_source() + add_extra_files(self, self.common, self.assets) + # Avoid WM_PROJECT_INST_DIR for ThirdParty, site or jobControl. # Use openfoam-site.patch to handle jobControl, site. # - # Filter (not patch) bashrc,cshrc for additional flexibility - wm_setting = { + # Filtering: bashrc,cshrc (using a patch is less flexible) + edits = { 'WM_THIRD_PARTY_DIR': r'$WM_PROJECT_DIR/ThirdParty #SPACK: No separate third-party', 'WM_VERSION': self.version, # consistency 'FOAMY_HEX_MESH': '', # This is horrible (unset variable?) } - rewrite_environ_files( # Adjust etc/bashrc and etc/cshrc - wm_setting, + edits, posix=join_path('etc', 'bashrc'), cshell=join_path('etc', 'cshrc')) - # Build wrapper script - with open(self.build_script, 'w') as out: - out.write( - """#!/bin/bash -. $PWD/etc/bashrc '' # No arguments -mkdir -p $FOAM_APPBIN $FOAM_LIBBIN 2>/dev/null # Allow interrupt -echo Build openfoam with SPACK -echo WM_PROJECT_DIR = $WM_PROJECT_DIR -./Allwmake $@ -# -""") - set_executable(self.build_script) - self.configure(self.spec, self.prefix) # Should be a separate phase - def configure(self, spec, prefix): """Make adjustments to the OpenFOAM configuration files in their various locations: etc/bashrc, etc/config.sh/FEATURE and customizations that don't properly fit get placed in the etc/prefs.sh file (similiarly for csh). """ - self.set_openfoam() # Need foam_cfg/foam_sys information - - # Some settings for filtering bashrc, cshrc - wm_setting = {} - wm_setting.update(self.foam_cfg) - + # Filtering bashrc, cshrc + edits = {} + edits.update(self.foam_arch.foam_dict()) rewrite_environ_files( # Adjust etc/bashrc and etc/cshrc - wm_setting, + edits, posix=join_path('etc', 'bashrc'), cshell=join_path('etc', 'cshrc')) # MPI content, with absolute paths - content = mplib_content(spec) + user_mpi = mplib_content(spec) # Content for etc/prefs.{csh,sh} self.etc_prefs = { r'MPI_ROOT': spec['mpi'].prefix, # Absolute - r'MPI_ARCH_FLAGS': '"%s"' % content['FLAGS'], - r'MPI_ARCH_INC': '"%s"' % content['PINC'], - r'MPI_ARCH_LIBS': '"%s"' % content['PLIBS'], + r'MPI_ARCH_FLAGS': '"%s"' % user_mpi['FLAGS'], + r'MPI_ARCH_INC': '"%s"' % user_mpi['PINC'], + r'MPI_ARCH_LIBS': '"%s"' % user_mpi['PLIBS'], } # Content for etc/config.{csh,sh}/ files @@ -368,6 +235,7 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR 'scotch': {}, 'metis': {}, 'paraview': [], + 'gperftools': [], # Currently unused } if True: @@ -392,45 +260,30 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR posix=join_path('etc', 'config.sh', component), cshell=join_path('etc', 'config.csh', component)) - archCompiler = self.foam_sys['WM_ARCH'] + self.foam_sys['WM_COMPILER'] - compileOpt = self.foam_cfg['WM_COMPILE_OPTION'] - general_rule = join_path('wmake', 'rules', 'General') - compiler_rule = join_path('wmake', 'rules', archCompiler) - generate_mplib_rules(general_rule, self.spec) - generate_compiler_rules(compiler_rule, compileOpt, self.rpath_info) - # Record the spack spec information - with open("log.spack-spec", 'w') as outfile: - outfile.write(spec.tree()) - def build(self, spec, prefix): """Build using the OpenFOAM Allwmake script, with a wrapper to source its environment first. + Only build if the compiler is known to be supported. """ - self.set_openfoam() # Force proper population of foam_cfg/foam_sys + self.foam_arch.has_rule(self.stage.source_path) + self.foam_arch.create_rules(self.stage.source_path, self) + args = [] if self.parallel: # Build in parallel? - pass via the environment - os.environ['WM_NCOMPPROCS'] = str(self.make_jobs) \ - if self.make_jobs else str(multiprocessing.cpu_count()) + os.environ['WM_NCOMPPROCS'] = str(make_jobs) builder = Executable(self.build_script) builder(*args) def install(self, spec, prefix): - """Install under the projectdir (== prefix/name-version)""" - self.build(spec, prefix) # Should be a separate phase - opts = self.wm_options - + """Install under the projectdir""" mkdirp(self.projectdir) projdir = os.path.basename(self.projectdir) - wm_setting = { + # Filtering: bashrc, cshrc + edits = { 'WM_PROJECT_INST_DIR': os.path.dirname(self.projectdir), 'WM_PROJECT_DIR': join_path('$WM_PROJECT_INST_DIR', projdir), } - # Retain build log file - out = "spack-build.out" - if isfile(out): - install(out, join_path(self.projectdir, "log." + opts)) - # All top-level files, except spack build info and possibly Allwmake if '+source' in spec: ignored = re.compile(r'^spack-.*') @@ -438,20 +291,23 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR ignored = re.compile(r'^(Allwmake|spack-).*') files = [ - f for f in glob.glob("*") if isfile(f) and not ignored.search(f) + f for f in glob.glob("*") + if os.path.isfile(f) and not ignored.search(f) ] for f in files: install(f, self.projectdir) - # Having wmake without sources is actually somewhat pointless... - dirs = ['bin', 'etc', 'wmake'] + # Having wmake and ~source is actually somewhat pointless... + # Install 'etc' before 'bin' (for symlinks) + dirs = ['etc', 'bin', 'wmake'] if '+source' in spec: dirs.extend(['applications', 'src', 'tutorials']) for d in dirs: install_tree( d, - join_path(self.projectdir, d)) + join_path(self.projectdir, d), + symlinks=True) dirs = ['platforms'] if '+source' in spec: @@ -463,29 +319,37 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR install_tree( d, join_path(self.projectdir, d), - ignore=shutil.ignore_patterns(*ignored)) + ignore=shutil.ignore_patterns(*ignored), + symlinks=True) + etc_dir = join_path(self.projectdir, 'etc') rewrite_environ_files( # Adjust etc/bashrc and etc/cshrc - wm_setting, - posix=join_path(self.etc, 'bashrc'), - cshell=join_path(self.etc, 'cshrc')) + edits, + posix=join_path(etc_dir, 'bashrc'), + cshell=join_path(etc_dir, 'cshrc')) self.install_links() def install_links(self): """Add symlinks into bin/, lib/ (eg, for other applications)""" - if not self.extra_symlinks: + # Make build log visible - it contains OpenFOAM-specific information + with working_dir(self.projectdir): + os.symlink( + join_path('.spack', 'build.out'), + join_path('log.' + str(self.foam_arch))) + + if not self.config['link']: return # ln -s platforms/linux64GccXXX/lib lib with working_dir(self.projectdir): - if isdir(self.archlib): + if os.path.isdir(self.archlib): os.symlink(self.archlib, 'lib') # (cd bin && ln -s ../platforms/linux64GccXXX/bin/* .) with working_dir(join_path(self.projectdir, 'bin')): for f in [ f for f in glob.glob(join_path('..', self.archbin, "*")) - if isfile(f) + if os.path.isfile(f) ]: os.symlink(f, os.path.basename(f)) |