From 9e1abb13dcc4fb21042c6ca3b2e5c445811d6c15 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Fri, 31 Mar 2017 01:35:57 +0200 Subject: support OpenFOAM package(s) (#3528) * ENH: add package for building OpenFOAM (1612) from www.openfoam.com - provide 'openfoam' as virtual package. - package as openfoam-com to reflect the distribution point. This initial spack packaging for OpenFOAM supports a number of possible variants and should handle 64-bit labels properly now that the scotch package has been updated accordingly. * ENH: update package for foam-extend (extend-project.de) - provide 'openfoam' as virtual package. - much of the build is now aligned with how the openfoam-com package looks, with the aim of future refactoring. - avoid installing intermediate targets. - contains its own environment sourcing script for the build, for more flexibility and robustness (doesn't touch the python build environ) * ENH: added package for building from openfoam.org - provide 'openfoam' as a virtual package. - this is largely a direct copy of the openfoam-com package. It has been supplied as a courtesy for users and to ensure maximum consistency in quality and naming between the foam-extend, openfoam-com and openfoam-org packages. * CONFIG: add openfoam into bash completion providers list * ENH: have openfoam-com use spack as USERMPI - also simplify the generation of mplib/compiler rules * ENH: have openfoam-org use spack as SYSTEMMPI - this setup requires more environment settings than USERMPI (openfoam-com), but is currently the only means of integration for openfoam-org - simplify generation of mplib/compiler rules * ENH: simplify generation of mplib/compiler rules (foam-extend) - rename mpi rules from SPACK,SPACKMPI to USER,USERMPI for consistency with openfoam-com and to generalize for any build system. * STYLE: record spack tree as a log file (openfoam) - can be useful for future diagnostics and general record keeping --- .../repos/builtin/packages/foam-extend/package.py | 664 ++++++++++++------- .../packages/openfoam-com/openfoam-bin-1612.patch | 503 ++++++++++++++ .../openfoam-com/openfoam-build-1612.patch | 17 + .../packages/openfoam-com/openfoam-etc-1612.patch | 41 ++ .../packages/openfoam-com/openfoam-mpi-1612.patch | 36 + .../packages/openfoam-com/openfoam-site.patch | 42 ++ .../repos/builtin/packages/openfoam-com/package.py | 722 +++++++++++++++++++++ .../openfoam-com/scotch-metis-lib-1612.patch | 48 ++ .../packages/openfoam-com/zoltan-lib-1612.patch | 84 +++ .../packages/openfoam-org/openfoam-etc-41.patch | 25 + .../packages/openfoam-org/openfoam-site.patch | 42 ++ .../repos/builtin/packages/openfoam-org/package.py | 492 ++++++++++++++ 12 files changed, 2495 insertions(+), 221 deletions(-) create mode 100644 var/spack/repos/builtin/packages/openfoam-com/openfoam-bin-1612.patch create mode 100644 var/spack/repos/builtin/packages/openfoam-com/openfoam-build-1612.patch create mode 100644 var/spack/repos/builtin/packages/openfoam-com/openfoam-etc-1612.patch create mode 100644 var/spack/repos/builtin/packages/openfoam-com/openfoam-mpi-1612.patch create mode 100644 var/spack/repos/builtin/packages/openfoam-com/openfoam-site.patch create mode 100644 var/spack/repos/builtin/packages/openfoam-com/package.py create mode 100644 var/spack/repos/builtin/packages/openfoam-com/scotch-metis-lib-1612.patch create mode 100644 var/spack/repos/builtin/packages/openfoam-com/zoltan-lib-1612.patch create mode 100644 var/spack/repos/builtin/packages/openfoam-org/openfoam-etc-41.patch create mode 100644 var/spack/repos/builtin/packages/openfoam-org/openfoam-site.patch create mode 100644 var/spack/repos/builtin/packages/openfoam-org/package.py (limited to 'var') diff --git a/var/spack/repos/builtin/packages/foam-extend/package.py b/var/spack/repos/builtin/packages/foam-extend/package.py index e009d64f51..559cc45d7a 100644 --- a/var/spack/repos/builtin/packages/foam-extend/package.py +++ b/var/spack/repos/builtin/packages/foam-extend/package.py @@ -9,6 +9,8 @@ # For details, see https://github.com/llnl/spack # Please also see the LICENSE file for our notice and the LGPL. # +# License +# ------- # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License (as # published by the Free Software Foundation) version 2.1, February 1999. @@ -21,17 +23,51 @@ # You should have received a copy of the GNU Lesser General Public # License along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Legal Notice +# ------------ +# OPENFOAM is a trademark owned by OpenCFD Ltd +# (producer and distributor of the OpenFOAM software via www.openfoam.com). +# The trademark information must remain visible and unadulterated in this +# file and via the "spack info" and comply with the term set by +# http://openfoam.com/legal/trademark-policy.php +# +# This file is not part of OpenFOAM, nor does it constitute a component of an +# OpenFOAM distribution. +# +############################################################################## +# +# Notes +# - mpi handling: WM_MPLIB=USER and provide wmake rules for special purpose +# 'USER and 'USERMPI' mpi implementations. +# The choice of 'USER' vs 'USERMPI' may change in the future. +# +# Changes +# 2017-03-28 Mark Olesen +# - avoid installing intermediate targets. +# - reworked to mirror the openfoam-com package. +# If changes are needed here, consider if they need applying there too. +# ############################################################################## from spack import * from spack.environment import * import multiprocessing +import glob +import re +import shutil import os +from os.path import isdir, isfile +from spack.pkg.builtin.openfoam_com import * class FoamExtend(Package): - """The foam-extend project is a fork of the OpenFOAM open source library - for Computational Fluid Dynamics (CFD).""" + """The Extend Project is a fork of the OpenFOAM opensource library + for Computational Fluid Dynamics (CFD). + This offering is not approved or endorsed by OpenCFD Ltd, + producer and distributor of the OpenFOAM software via www.openfoam.com, + and owner of the OPENFOAM trademark. + """ homepage = "http://www.extend-project.de/" @@ -40,207 +76,235 @@ class FoamExtend(Package): version('3.1', git='http://git.code.sf.net/p/foam-extend/foam-extend-3.1') version('3.0', git='http://git.code.sf.net/p/foam-extend/foam-extend-3.0') - variant('paraview', default=False, description='Enable ParaFOAM') - variant( - 'scotch', default=True, - description='Activate Scotch as a possible decomposition library') - variant( - 'ptscotch', default=True, - description='Activate PT-Scotch as a possible decomposition library') - variant( - 'metis', default=True, - description='Activate Metis as a possible decomposition library') - variant( - 'parmetis', default=True, - description='Activate Parmetis as a possible decomposition library') - variant( - 'parmgridgen', default=True, - description='Activate Parmgridgen support') - variant( - 'source', default=True, - description='Installs also the source folder') - - supported_compilers = {'clang': 'Clang', 'gcc': 'Gcc', 'intel': 'Icc'} - + # variant('int64', default=False, + # description='Compile with 64-bit labels') + variant('float32', default=False, + description='Compile with 32-bit scalar (single-precision)') + + variant('paraview', default=False, + description='Build paraview plugins (eg, paraFoam)') + variant('scotch', default=True, + description='With scotch for decomposition') + variant('ptscotch', default=True, + description='With ptscotch for decomposition') + variant('metis', default=True, + description='With metis for decomposition') + variant('parmetis', default=True, + description='With parmetis for decomposition') + variant('parmgridgen', default=True, + description='With parmgridgen support') + 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('python') - depends_on('flex') depends_on('zlib') + depends_on('flex@:2.6.1') # <- restriction due to scotch depends_on('cmake', type='build') - depends_on('scotch ~ metis', when='~ptscotch+scotch') - depends_on('scotch ~ metis + mpi', when='+ptscotch') - depends_on('metis@5:', when='+metis') - depends_on('parmetis', when='+parmetis') - depends_on('parmgridgen', when='+parmgridgen') - - depends_on('paraview', when='+paraview') - - def set_arch(self): - (sysname, nodename, release, version, machine) = os.uname() - - if self.compiler.name not in self.supported_compilers: - raise RuntimeError('{0} is not a supported compiler \ - to compile OpenFOAM'.format(self.compiler.name)) - - foam_compiler = self.supported_compilers[self.compiler.name] - if sysname == 'Linux': - arch = 'linux' - if foam_compiler == 'Clang': - raise RuntimeError('OS, compiler combination not\ - supported ({0} {1})'.format(sysname, foam_compiler)) - elif sysname == 'Darwin': - if machine == 'x86_64': - arch = 'darwinIntel' - if foam_compiler == 'Icc': - raise RuntimeError('OS, compiler combination not\ - supported ({0} {1})'.format(sysname, foam_compiler)) - else: - raise RuntimeError('{0} {1} is not a \ - supported architecture'.format(sysname, machine)) - - return (arch, foam_compiler) + depends_on('scotch~metis', when='~ptscotch+scotch') + depends_on('scotch~metis+mpi', when='+ptscotch') + depends_on('metis@5:', when='+metis') + depends_on('parmetis', when='+parmetis') + depends_on('parmgridgen', when='+parmgridgen') + depends_on('paraview@:5.0.1', when='+paraview') + + # 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) + # FUTURE? 'WM_LABEL_SIZE': '32', # <- +int64 + 'WM_PRECISION_OPTION': 'DP', # <- +float32 + 'WM_COMPILE_OPTION': 'SPACKOpt', # Do not change + 'WM_MPLIB': 'USER', # USER | USERMPI + } + + # The system description is frequently needed + foam_sys = { + 'WM_ARCH': None, + 'WM_COMPILER': None, + 'WM_OPTIONS': None, + } + + # Content for etc/prefs.{csh,sh} + etc_prefs = {} + + # 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' - def get_openfoam_environment(self): - return EnvironmentModifications.from_sourcing_files( - join_path(self.stage.source_path, - 'etc/bashrc')) + def setup_environment(self, spack_env, run_env): + run_env.set('FOAM_INST_DIR', self.prefix) + run_env.set('WM_PROJECT_DIR', self.projectdir) + + @property + def _canonical(self): + """Canonical name for this package and version""" + return 'foam-extend-{0}'.format(self.version.up_to(2)) + + @property + def projectdir(self): + """Absolute location of project directory: WM_PROJECT_DIR/""" + return join_path(self.prefix, self._canonical) # <- prefix/canonical + + @property + def etc(self): + """Absolute location of the OpenFOAM etc/ directory""" + return join_path(self.projectdir, 'etc') + + @property + def archbin(self): + """Relative location of architecture-specific executables""" + wm_options = self.set_openfoam() + return join_path('applications', 'bin', wm_options) + + @property + def archlib(self): + """Relative location of architecture-specific libraries""" + wm_options = self.set_openfoam() + return join_path('lib', wm_options) + + @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 + + # For foam-extend: does not yet support +int64 + 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 + # FUTURE? self.foam_cfg['WM_LABEL_SIZE'] = ( + # FUTURE? '64' if '+int64' in self.spec else '32' + # FUTURE? ) + self.foam_cfg['WM_PRECISION_OPTION'] = ( + 'SP' if '+float32' in self.spec else 'DP' + ) + + # ---- + # WM_OPTIONS=$WM_ARCH$WM_COMPILER$WM_PRECISION_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'], + # FUTURE? 'Int', self.foam_cfg['WM_LABEL_SIZE'], # Int32/Int64 + compileOpt + ]) + return self.foam_sys['WM_OPTIONS'] def patch(self): - # change names to match the package and not the one patch in - # the Third-Party of foam-extend - if '+parmgridgen' in self.spec: - filter_file(r'-lMGridGen', - r'-lmgrid', - 'src/dbns/Make/options') - - filter_file( - r'-lMGridGen', - r'-lmgrid', - 'src/fvAgglomerationMethods/MGridGenGamgAgglomeration/Make/options') # noqa: E501 - - # Get the wmake arch and compiler - (arch, foam_compiler) = self.set_arch() - - prefs_dict = { - 'compilerInstall': 'System', - 'WM_COMPILER': foam_compiler, - 'WM_ARCH_OPTION': '64', - 'WM_PRECISION_OPTION': 'DP', - 'WM_COMPILE_OPTION': 'SPACKOpt', - 'WM_MPLIB': 'SPACK', - - 'CMAKE_DIR': self.spec['cmake'].prefix, - 'CMAKE_BIN_DIR': self.spec['cmake'].prefix.bin, - 'PYTHON_DIR': self.spec['python'].prefix, - 'PYTHON_BIN_DIR': self.spec['python'].prefix.bin, - - 'FLEX_SYSTEM': 1, - 'FLEX_DIR': self.spec['flex'].prefix, - - 'BISON_SYSTEM': 1, - 'BISON_DIR': self.spec['flex'].prefix, - - 'ZLIB_SYSTEM': 1, - 'ZLIB_DIR': self.spec['zlib'].prefix, - } - - if '+scotch' in self.spec or '+ptscotch' in self.spec: - prefs_dict['SCOTCH_SYSTEM'] = 1 - prefs_dict['SCOTCH_DIR'] = self.spec['scotch'].prefix - prefs_dict['SCOTCH_BIN_DIR'] = self.spec['scotch'].prefix.bin - prefs_dict['SCOTCH_LIB_DIR'] = self.spec['scotch'].prefix.lib - prefs_dict['SCOTCH_INCLUDE_DIR'] = \ - self.spec['scotch'].prefix.include - - if '+metis' in self.spec: - prefs_dict['METIS_SYSTEM'] = 1 - prefs_dict['METIS_DIR'] = self.spec['metis'].prefix - prefs_dict['METIS_BIN_DIR'] = self.spec['metis'].prefix.bin - prefs_dict['METIS_LIB_DIR'] = self.spec['metis'].prefix.lib - prefs_dict['METIS_INCLUDE_DIR'] = self.spec['metis'].prefix.include - - if '+parmetis' in self.spec: - prefs_dict['PARMETIS_SYSTEM'] = 1 - prefs_dict['PARMETIS_DIR'] = self.spec['parmetis'].prefix - prefs_dict['PARMETIS_BIN_DIR'] = self.spec['parmetis'].prefix.bin - prefs_dict['PARMETIS_LIB_DIR'] = self.spec['parmetis'].prefix.lib - prefs_dict['PARMETIS_INCLUDE_DIR'] = \ - self.spec['parmetis'].prefix.include - - if '+parmgridgen' in self.spec: - prefs_dict['PARMGRIDGEN_SYSTEM'] = 1 - prefs_dict['PARMGRIDGEN_DIR'] = self.spec['parmgridgen'].prefix - prefs_dict['PARMGRIDGEN_BIN_DIR'] = \ - self.spec['parmgridgen'].prefix.bin - prefs_dict['PARMGRIDGEN_LIB_DIR'] = \ - self.spec['parmgridgen'].prefix.lib - prefs_dict['PARMGRIDGEN_INCLUDE_DIR'] = \ - self.spec['parmgridgen'].prefix.include - - if '+paraview' in self.spec: - prefs_dict['PARAVIEW_SYSTEM'] = 1 - prefs_dict['PARAVIEW_DIR'] = self.spec['paraview'].prefix - prefs_dict['PARAVIEW_BIN_DIR'] = self.spec['paraview'].prefix.bin - prefs_dict['QT_SYSTEM'] = 1 - prefs_dict['QT_DIR'] = self.spec['qt'].prefix - prefs_dict['QT_BIN_DIR'] = self.spec['qt'].prefix.bin - - # write the prefs files to define the configuration needed, - # only the prefs.sh is used by this script but both are - # installed for end users - with working_dir('.'): - with open("etc/prefs.sh", "w") as fh: - for key in sorted(prefs_dict): - fh.write('export {0}={1}\n'.format(key, prefs_dict[key])) - - with open("etc/prefs.csh", "w") as fh: - for key in sorted(prefs_dict): - fh.write('setenv {0}={1}\n'.format(key, prefs_dict[key])) - - # Defining a different mpi and optimisation file to be able to - # make wmake get spack info with minimum modifications on - # configurations scripts - mpi_info = [ - 'PFLAGS = -DOMPI_SKIP_MPICXX -DMPICH_IGNORE_CXX_SEEK', - 'PINC = -I{0}'.format(self.spec['mpi'].prefix.include), - 'PLIBS = -L{0} -lmpi'.format(self.spec['mpi'].prefix.lib) + """Adjust OpenFOAM build for spack. Where needed, apply filter as an + alternative to normal patching. + """ + self.set_openfoam() # May need foam_cfg/foam_sys information + + # Adjust ParMGridGen - this is still a mess + files = [ + 'src/dbns/Make/options', + 'src/fvAgglomerationMethods/MGridGenGamgAgglomeration/Make/options' # noqa: E501 ] + for f in files: + filter_file(r'-lMGridGen', r'-lmgrid', f, backup=False) - arch_path = ''.join([arch, prefs_dict['WM_ARCH_OPTION'], - foam_compiler]) - option_path = ''.join([arch_path, - prefs_dict['WM_PRECISION_OPTION'], - prefs_dict['WM_COMPILE_OPTION']]) - rule_path = join_path("wmake", "rules", arch_path) - build_path = join_path(self.stage.source_path, 'lib', option_path) - install_path = \ - join_path(self.prefix, - 'foam-extend-{0}'.format(self.version.up_to(2)), - option_path) - - rpaths_foam = ' '.join([ - '{0}{1}'.format(self.compiler.cxx_rpath_arg, - install_path), - '{0}{1}'.format(self.compiler.cxx_rpath_arg, - build_path) - ]) - - compiler_flags = { - 'DBUG': rpaths_foam, - 'OPT': '-O3', - } - - with working_dir(rule_path): - with open('mplibSPACK', "w") as fh: - fh.write('\n'.join(mpi_info)) - - for comp in ['c', 'c++']: - with open('{0}SPACKOpt'.format(comp), "w") as fh: - for key, val in compiler_flags.iteritems(): - fh.write('{0}{1} = {2}\n'.format(comp, key, val)) - - _files_to_patch = [ + # Adjust for flex version check + files = [ 'src/thermophysicalModels/reactionThermo/chemistryReaders/chemkinReader/chemkinLexer.L', # noqa: E501 'src/surfMesh/surfaceFormats/stl/STLsurfaceFormatASCII.L', # noqa: E501 'src/meshTools/triSurface/triSurface/interfaces/STL/readSTLASCII.L', # noqa: E501 @@ -251,40 +315,198 @@ class FoamExtend(Package): 'applications/utilities/mesh/conversion/fluentMeshToFoam/fluentMeshToFoam.L', # noqa: E501 'applications/utilities/mesh/conversion/fluent3DMeshToElmer/fluent3DMeshToElmer.L' # noqa: E501 ] - for _file in _files_to_patch: - filter_file(r'#if YY_FLEX_SUBMINOR_VERSION < 34', - r'#if YY_FLEX_MAJOR_VERSION <= 2 && YY_FLEX_MINOR_VERSION <= 5 && YY_FLEX_SUBMINOR_VERSION < 34', # noqa: E501 - _file) + for f in files: + filter_file( + r'#if YY_FLEX_SUBMINOR_VERSION < 34', + r'#if YY_FLEX_MAJOR_VERSION <= 2 && YY_FLEX_MINOR_VERSION <= 5 && YY_FLEX_SUBMINOR_VERSION < 34', # noqa: E501 + f, backup=False + ) + + # Build wrapper script + with open(self.build_script, 'w') as out: + out.write( + """#!/bin/bash +export FOAM_INST_DIR=$(cd .. && pwd -L) +. $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 # No arguments +# +""") + 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 + + # Content for etc/prefs.{csh,sh} + self.etc_prefs = { + '000': { # Sort first + 'compilerInstall': 'System', + }, + '001': {}, + 'cmake': { + 'CMAKE_DIR': spec['cmake'].prefix, + 'CMAKE_BIN_DIR': spec['cmake'].prefix.bin, + }, + 'python': { + 'PYTHON_DIR': spec['python'].prefix, + 'PYTHON_BIN_DIR': spec['python'].prefix.bin, + }, + 'flex': { + 'FLEX_SYSTEM': 1, + 'FLEX_DIR': spec['flex'].prefix, + }, + 'bison': { + 'BISON_SYSTEM': 1, + 'BISON_DIR': spec['flex'].prefix, + }, + 'zlib': { + 'ZLIB_SYSTEM': 1, + 'ZLIB_DIR': spec['zlib'].prefix, + }, + } + # Adjust configuration via prefs - sort second + self.etc_prefs['001'].update(self.foam_cfg) + + if '+scotch' in spec or '+ptscotch' in spec: + pkg = spec['scotch'].prefix + self.etc_prefs['scotch'] = { + 'SCOTCH_SYSTEM': 1, + 'SCOTCH_DIR': pkg, + 'SCOTCH_BIN_DIR': pkg.bin, + 'SCOTCH_LIB_DIR': pkg.lib, + 'SCOTCH_INCLUDE_DIR': pkg.include, + } + + if '+metis' in spec: + pkg = spec['metis'].prefix + self.etc_prefs['metis'] = { + 'METIS_SYSTEM': 1, + 'METIS_DIR': pkg, + 'METIS_BIN_DIR': pkg.bin, + 'METIS_LIB_DIR': pkg.lib, + 'METIS_INCLUDE_DIR': pkg.include, + } + + if '+parmetis' in spec: + pkg = spec['parmetis'].prefix + self.etc_prefs['parametis'] = { + 'PARMETIS_SYSTEM': 1, + 'PARMETIS_DIR': pkg, + 'PARMETIS_BIN_DIR': pkg.bin, + 'PARMETIS_LIB_DIR': pkg.lib, + 'PARMETIS_INCLUDE_DIR': pkg.include, + } + + if '+parmgridgen' in spec: + pkg = spec['parmgridgen'].prefix + self.etc_prefs['parmgridgen'] = { + 'PARMGRIDGEN_SYSTEM': 1, + 'PARMGRIDGEN_DIR': pkg, + 'PARMGRIDGEN_BIN_DIR': pkg.bin, + 'PARMGRIDGEN_LIB_DIR': pkg.lib, + 'PARMGRIDGEN_INCLUDE_DIR': pkg.include, + } - def setup_environment(self, spack_env, run_env): - with working_dir(self.stage.path): - spack_env.set('FOAM_INST_DIR', os.path.abspath('.')) + if '+paraview' in self.spec: + self.etc_prefs['paraview'] = { + 'PARAVIEW_SYSTEM': 1, + 'PARAVIEW_DIR': spec['paraview'].prefix, + 'PARAVIEW_BIN_DIR': spec['paraview'].prefix.bin, + } + self.etc_prefs['qt'] = { + 'QT_SYSTEM': 1, + 'QT_DIR': spec['qt'].prefix, + 'QT_BIN_DIR': spec['qt'].prefix.bin, + } + + # Write prefs files according to the configuration. + # Only need prefs.sh for building, but install both for end-users + write_environ( + self.etc_prefs, + posix=join_path('etc', 'prefs.sh'), + cshell=join_path('etc', 'prefs.csh')) + + 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(compiler_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. + """ + self.set_openfoam() # Force proper population of foam_cfg/foam_sys + 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()) + builder = Executable(self.build_script) + builder(*args) - (arch, foam_compiler) = self.set_arch() + 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 - run_env.set('FOAM_INST_DIR', self.prefix) + # Fairly ugly since intermediate targets are scattered inside sources + appdir = 'applications' + mkdirp(self.projectdir, join_path(self.projectdir, appdir)) - def install(self, spec, prefix): - env_openfoam = self.get_openfoam_environment() - env_openfoam.apply_modifications() + # Retain build log file + out = "spack-build.out" + if isfile(out): + install(out, join_path(self.projectdir, "log." + opts)) - if self.parallel: - os.environ['WM_NCOMPPROCS'] = str(self.make_jobs) \ - if self.make_jobs else str(multiprocessing.cpu_count()) + # All top-level files, except spack build info and possibly Allwmake + if '+source' in spec: + ignored = re.compile(r'^spack-.*') + else: + ignored = re.compile(r'^(Allclean|Allwmake|spack-).*') - allwmake = Executable('./Allwmake') - allwmake() + files = [ + f for f in glob.glob("*") if isfile(f) and not ignored.search(f) + ] + for f in files: + install(f, self.projectdir) - install_path = \ - join_path(self.prefix, - 'foam-extend-{0}'.format(self.version.up_to(2))) + # Install directories. install applications/bin directly + for d in ['bin', 'etc', 'wmake', 'lib', join_path(appdir, 'bin')]: + install_tree( + d, + join_path(self.projectdir, d)) if '+source' in spec: - install_tree('src', join_path(install_path, 'src')) - install_tree('tutorials', join_path(install_path, 'tutorials')) - - install_tree('lib', join_path(install_path, 'lib')) - install_tree('bin', join_path(install_path, 'bin')) - install_tree('applications', join_path(install_path, 'applications')) - install_tree('etc', join_path(install_path, 'etc')) - install_tree('wmake', join_path(install_path, 'wmake')) + subitem = join_path(appdir, 'Allwmake') + install(subitem, join_path(self.projectdir, subitem)) + + ignored = [opts] # Intermediate targets + for d in ['src', 'tutorials']: + install_tree( + d, + join_path(self.projectdir, d), + ignore=shutil.ignore_patterns(*ignored)) + + for d in ['solvers', 'utilities']: + install_tree( + join_path(appdir, d), + join_path(self.projectdir, appdir, d), + ignore=shutil.ignore_patterns(*ignored)) + + def install_links(self): + """Add symlinks into bin/, lib/ (eg, for other applications)""" + return + +# ----------------------------------------------------------------------------- diff --git a/var/spack/repos/builtin/packages/openfoam-com/openfoam-bin-1612.patch b/var/spack/repos/builtin/packages/openfoam-com/openfoam-bin-1612.patch new file mode 100644 index 0000000000..b9e87a7ec8 --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-com/openfoam-bin-1612.patch @@ -0,0 +1,503 @@ +--- OpenFOAM-v1612+.orig/bin/foamEtcFile 2016-12-23 15:22:59.000000000 +0100 ++++ OpenFOAM-v1612+/bin/foamEtcFile 2017-03-23 10:08:37.296887070 +0100 +@@ -4,7 +4,7 @@ + # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + # \\ / O peration | + # \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation +-# \\/ M anipulation | ++# \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. + #------------------------------------------------------------------------------- + # License + # This file is part of OpenFOAM. +@@ -26,7 +26,7 @@ + # foamEtcFile + # + # Description +-# Locate user/group/shipped file with semantics similar to the ++# Locate user/group/other files with semantics similar to the + # ~OpenFOAM/fileName expansion. + # + # The -mode option can be used to allow chaining from +@@ -34,40 +34,53 @@ + # + # For example, within the user ~/.OpenFOAM//prefs.sh: + # \code +-# foamPrefs=`$WM_PROJECT_DIR/bin/foamEtcFile -m go prefs.sh` \ +-# && _foamSource $foamPrefs ++# eval $(foamEtcFile -sh -mode=go prefs.sh) + # \endcode + # ++# Environment ++# - WM_PROJECT: (unset defaults to OpenFOAM) ++# - WM_PROJECT_SITE: (unset defaults to PREFIX/site) ++# - WM_PROJECT_VERSION: (unset defaults to detect from path) ++# + # Note +-# This script must exist in $FOAM_INST_DIR/OpenFOAM-/bin/ +-# or $FOAM_INST_DIR/openfoam/bin/ (for the debian version) ++# This script must exist in one of these locations: ++# - $WM_PROJECT_INST_DIR/OpenFOAM-/bin ++# - $WM_PROJECT_INST_DIR/openfoam-/bin ++# - $WM_PROJECT_INST_DIR/OpenFOAM+/bin ++# - $WM_PROJECT_INST_DIR/openfoam+/bin ++# - $WM_PROJECT_INST_DIR/openfoam/bin (debian version) + # + #------------------------------------------------------------------------------- ++unset optQuiet optSilent + usage() { + [ "${optQuiet:-$optSilent}" = true ] && exit 1 +- + exec 1>&2 + while [ "$#" -ge 1 ]; do echo "$1"; shift; done + cat< any combination of u(user), g(group), o(other) +- -prefix specify an alternative installation prefix +- -quiet suppress all normal output +- -silent suppress all stderr output +- -version specify an alternative OpenFOAM version +- in the form Maj.Min.Rev (eg, 1.7.0) +- -help print the usage ++ -a, -all Return all files (otherwise stop after the first match) ++ -l, -list List directories or files to be checked ++ -list-test List (existing) directories or files to be checked ++ -mode=MODE Any combination of u(user), g(group), o(other) ++ -prefix=DIR Specify an alternative installation prefix ++ -version=VER Specify alternative OpenFOAM version (eg, 3.0, 1612, ...) ++ -csh | -sh Produce output suitable for a csh or sh 'eval' ++ -csh-verbose | -sh-verbose ++ As per -csh | -sh, with additional verbosity ++ -q, -quiet Suppress all normal output ++ -s, -silent Suppress stderr, except -csh-verbose, -sh-verbose output ++ -help Print the usage + +- Locate user/group/shipped file with semantics similar to the ++ Locate user/group/other file with semantics similar to the + ~OpenFOAM/fileName expansion. + +- The options can also be specified as a single character +- (eg, '-q' instead of '-quiet'), but must not be grouped. ++ Single character options must not be grouped. Equivalent options: ++ -mode=MODE, -mode MODE, -m MODE ++ -prefix=DIR, -prefix DIR, -p DIR ++ -version=VER, -version VER, -v VER + + Exit status + 0 when the file is found. Print resolved path to stdout. +@@ -78,61 +91,117 @@ + exit 1 + } + +-#------------------------------------------------------------------------------- ++# Report error and exit ++die() ++{ ++ [ "${optQuiet:-$optSilent}" = true ] && exit 1 ++ exec 1>&2 ++ echo ++ echo "Error encountered:" ++ while [ "$#" -ge 1 ]; do echo " $1"; shift; done ++ echo ++ echo "See 'foamEtcFile -help' for usage" ++ echo ++ exit 1 ++} + +-# the bin dir: +-binDir="${0%/*}" ++#------------------------------------------------------------------------------- ++binDir="${0%/*}" # The bin dir ++projectDir="${binDir%/bin}" # The project dir ++prefixDir="${projectDir%/*}" # The prefix dir (same as $WM_PROJECT_INST_DIR) + +-# the project dir: ++# Could not resolve projectDir, prefixDir? (eg, called as ./bin/foamEtcFile) ++if [ "$prefixDir" = "$projectDir" ] ++then ++ binDir="$(cd $binDir && pwd -L)" + projectDir="${binDir%/bin}" +- +-# the prefix dir (same as $FOAM_INST_DIR): + prefixDir="${projectDir%/*}" ++fi ++projectDirName="${projectDir##*/}" # The project directory name + +-# the name used for the project directory +-projectDirName="${projectDir##*/}" ++projectName="${WM_PROJECT:-OpenFOAM}" # The project name ++projectVersion="$WM_PROJECT_VERSION" # Empty? - will be treated later + +-# version number used for debian packaging +-unset versionNum + ++#------------------------------------------------------------------------------- ++ ++# Guess project version or simply get the stem part of the projectDirName. ++# Handle standard and debian naming conventions. + # +-# handle standard and debian naming convention ++# - projectVersion: update unless already set + # +-case "$projectDirName" in +-OpenFOAM-*) # standard naming convention OpenFOAM- +- version="${projectDirName##OpenFOAM-}" +- ;; ++# Helper variables: ++# - dirBase (for reassembling name) == projectDirName without the version ++# - versionNum (debian packaging) ++unset dirBase versionNum ++guessVersion() ++{ ++ local version + +-openfoam[0-9]* | openfoam-dev) # debian naming convention 'openfoam' +- versionNum="${projectDirName##openfoam}" +- case "$versionNum" in +- ??) # convert 2 digit version number to decimal delineated +- version=$(echo "$versionNum" | sed -e 's@\(.\)\(.\)@\1.\2@') +- ;; +- ???) # convert 3 digit version number to decimal delineated +- version=$(echo "$versionNum" | sed -e 's@\(.\)\(.\)\(.\)@\1.\2.\3@') +- ;; +- ????) # convert 4 digit version number to decimal delineated +- version=$(echo "$versionNum" | sed -e 's@\(.\)\(.\)\(.\)\(.\)@\1.\2.\3.\4@') +- ;; +- *) # failback - use current environment setting +- version="$WM_PROJECT_VERSION" ++ case "$projectDirName" in ++ (OpenFOAM-* | openfoam-*) ++ # Standard naming: OpenFOAM- or openfoam- ++ dirBase="${projectDirName%%-*}-" ++ version="${projectDirName#*-}" ++ version="${version%%*-}" # Extra safety, eg openfoam-version-packager ++ ;; ++ ++ (OpenFOAM+* | openfoam+*) ++ # Alternative naming: OpenFOAM+ or openfoam+ ++ dirBase="${projectDirName%%+*}+" ++ version="${projectDirName#*+}" ++ version="${version%%*-}" # Extra safety, eg openfoam-version-packager ++ ;; ++ ++ (openfoam[0-9]*) ++ # Debian naming: openfoam ++ dirBase="openfoam" ++ version="${projectDirName#openfoam}" ++ versionNum="$version" ++ ++ # Convert digits version number to decimal delineated ++ case "${#versionNum}" in (2|3|4) ++ version=$(echo "$versionNum" | sed -e 's@\([0-9]\)@\1.@g') ++ version="${version%.}" + ;; + esac ++ ++ # Ignore special treatment if no decimals were inserted. ++ [ "${#version}" -gt "${#versionNum}" ] || unset versionNum + ;; + +-*) +- echo "Error : unknown/unsupported naming convention" +- exit 1 ++ (*) ++ die "unknown/unsupported naming convention for '$projectDirName'" + ;; + esac + ++ # Set projectVersion if required ++ : ${projectVersion:=$version} ++} ++ ++ ++# Set projectVersion and update versionNum, projectDirName accordingly ++setVersion() ++{ ++ projectVersion="$1" ++ ++ # Need dirBase when reassembling projectDirName ++ [ -n "$dirBase" ] || guessVersion ++ ++ # Debian: update x.y.z -> xyz version ++ if [ -n "$versionNum" ] ++ then ++ versionNum=$(echo "$projectVersion" | sed -e 's@\.@@g') ++ fi ++ ++ projectDirName="$dirBase${versionNum:-$projectVersion}" ++} ++ + +-# default mode is 'ugo' +-mode=ugo +-unset optAll optList optQuiet optSilent ++optMode=ugo # Default mode is always 'ugo' ++unset optAll optList optShell optVersion + +-# parse options ++# Parse options + while [ "$#" -gt 0 ] + do + case "$1" in +@@ -141,27 +210,45 @@ + ;; + -a | -all) + optAll=true ++ unset optShell + ;; + -l | -list) + optList=true ++ unset optShell ++ ;; ++ -list-test) ++ optList='test' ++ unset optShell ++ ;; ++ -csh | -sh | -csh-verbose | -sh-verbose) ++ optShell="${1#-}" ++ unset optAll ++ ;; ++ -mode=[ugo]*) ++ optMode="${1#*=}" ++ ;; ++ -prefix=/*) ++ prefixDir="${1#*=}" ++ prefixDir="${prefixDir%/}" ++ ;; ++ -version=*) ++ optVersion="${1#*=}" + ;; + -m | -mode) +- [ "$#" -ge 2 ] || usage "'$1' option requires an argument" +- mode="$2" +- +- # sanity check: +- case "$mode" in +- *u* | *g* | *o* ) ++ optMode="$2" ++ shift ++ # Sanity check. Handles missing argument too. ++ case "$optMode" in ++ ([ugo]*) + ;; +- *) +- usage "'$1' option with invalid mode '$mode'" ++ (*) ++ die "invalid mode '$optMode'" + ;; + esac +- shift + ;; + -p | -prefix) +- [ "$#" -ge 2 ] || usage "'$1' option requires an argument" +- prefixDir="$2" ++ [ "$#" -ge 2 ] || die "'$1' option requires an argument" ++ prefixDir="${2%/}" + shift + ;; + -q | -quiet) +@@ -171,13 +258,8 @@ + optSilent=true + ;; + -v | -version) +- [ "$#" -ge 2 ] || usage "'$1' option requires an argument" +- version="$2" +- # convert x.y.z -> xyz version (if installation looked like debian) +- if [ -n "$versionNum" ] +- then +- versionNum=$(echo "$version" | sed -e 's@\.@@g') +- fi ++ [ "$#" -ge 2 ] || die "'$1' option requires an argument" ++ optVersion="$2" + shift + ;; + --) +@@ -185,7 +267,7 @@ + break + ;; + -*) +- usage "unknown option: '$*'" ++ die "unknown option: '$1'" + ;; + *) + break +@@ -195,11 +277,28 @@ + done + + +-# debugging: +-# echo "Installed locations:" +-# for i in projectDir prefixDir projectDirName version versionNum ++#------------------------------------------------------------------------------- ++ ++if [ -n "$optVersion" ] ++then ++ setVersion $optVersion ++elif [ -z "$projectVersion" ] ++then ++ guessVersion ++fi ++ ++# Updates: ++# - projectDir for changes via -prefix or -version ++# - projectSite for changes via -prefix ++projectDir="$prefixDir/$projectDirName" ++projectSite="${WM_PROJECT_SITE:-$prefixDir/site}" ++ ++ ++# Debugging: ++# echo "Installed locations:" 1>&2 ++# for i in projectDir prefixDir projectDirName projectVersion + # do +-# eval echo "$i=\$$i" ++# eval echo "$i=\$$i" 1>&2 + # done + + +@@ -210,30 +309,18 @@ + + # Define the various places to be searched: + unset dirList +-case "$mode" in +-*u*) # user +- userDir="$HOME/.${WM_PROJECT:-OpenFOAM}" +- dirList="$dirList $userDir/$version $userDir" ++case "$optMode" in (*u*) # (U)ser ++ dirList="$dirList $HOME/.$projectName/$projectVersion $HOME/.$projectName" + ;; + esac + +-case "$mode" in +-*g*) # group (site) +- siteDir="${WM_PROJECT_SITE:-$prefixDir/site}" +- dirList="$dirList $siteDir/$version $siteDir" ++case "$optMode" in (*g*) # (G)roup == site ++ dirList="$dirList $projectSite/$projectVersion $projectSite" + ;; + esac + +-case "$mode" in +-*o*) # other (shipped) +- if [ -n "$versionNum" ] +- then +- # debian packaging +- dirList="$dirList $prefixDir/openfoam$versionNum/etc" +- else +- # standard packaging +- dirList="$dirList $prefixDir/${WM_PROJECT:-OpenFOAM}-$version/etc" +- fi ++case "$optMode" in (*o*) # (O)ther == shipped ++ dirList="$dirList $projectDir/etc" + ;; + esac + set -- $dirList +@@ -244,50 +331,87 @@ + # + + exitCode=0 +-if [ "$optList" = true ] ++if [ -n "$optList" ] + then + +- # list directories, or potential file locations +- [ "$nArgs" -le 1 ] || usage ++ # List directories, or potential file locations ++ [ "$nArgs" -le 1 ] || \ ++ die "-list expects 0 or 1 filename, but $nArgs provided" ++ ++ # A silly combination, but -quiet does have precedence ++ [ -n "$optQuiet" ] && exit 0 + +- # a silly combination, but -quiet does have precedence +- [ "$optQuiet" = true ] && exit 0 ++ # Test for directory or file too? ++ if [ "$optList" = "test" ] ++ then ++ exitCode=2 # Fallback to a general error (file not found) + ++ if [ "$nArgs" -eq 1 ] ++ then + for dir + do +- if [ "$nArgs" -eq 1 ] ++ resolved="$dir/$fileName" ++ if [ -f "$resolved" ] + then +- echo "$dir/$fileName" ++ echo "$resolved" ++ exitCode=0 # OK ++ fi ++ done + else ++ for dir ++ do ++ if [ -d "$dir" ] ++ then + echo "$dir" ++ exitCode=0 # OK + fi + done ++ fi ++ else ++ for dir ++ do ++ echo "$dir${fileName:+/}$fileName" ++ done ++ fi + + else + +- [ "$nArgs" -eq 1 ] || usage ++ [ "$nArgs" -eq 1 ] || die "One filename expected - $nArgs provided" + +- # general error, eg file not found +- exitCode=2 ++ exitCode=2 # Fallback to a general error (file not found) + + for dir + do + if [ -f "$dir/$fileName" ] + then + exitCode=0 +- if [ "$optQuiet" = true ] +- then ++ [ -n "$optQuiet" ] && break ++ ++ case "$optShell" in ++ (*verbose) ++ echo "Using: $dir/$fileName" 1>&2 ++ ;; ++ esac ++ ++ case "$optShell" in ++ csh*) ++ echo "source $dir/$fileName" + break +- else ++ ;; ++ sh*) ++ echo ". $dir/$fileName" ++ break ++ ;; ++ *) + echo "$dir/$fileName" +- [ "$optAll" = true ] || break +- fi ++ [ -n "$optAll" ] || break ++ ;; ++ esac + fi + done + + fi + +- + exit $exitCode + + #------------------------------------------------------------------------------ diff --git a/var/spack/repos/builtin/packages/openfoam-com/openfoam-build-1612.patch b/var/spack/repos/builtin/packages/openfoam-com/openfoam-build-1612.patch new file mode 100644 index 0000000000..26e2d8f085 --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-com/openfoam-build-1612.patch @@ -0,0 +1,17 @@ +--- OpenFOAM-v1612+.orig/Allwmake 2016-12-23 15:22:59.000000000 +0100 ++++ OpenFOAM-v1612+/Allwmake 2017-03-29 09:08:15.503865203 +0200 +@@ -17,6 +17,14 @@ + exit 1 + } + ++#------------------------------------------------------------------------------ ++echo "========================================" ++date "+%Y-%m-%d %H:%M:%S %z" 2>/dev/null || echo "date is unknown" ++echo "Starting ${WM_PROJECT_DIR##*/} ${0##*}" ++echo " $WM_COMPILER $WM_COMPILER_TYPE compiler" ++echo " ${WM_OPTIONS}, with ${WM_MPLIB} ${FOAM_MPI}" ++echo ++ + # Compile wmake support applications + (cd wmake/src && make) + diff --git a/var/spack/repos/builtin/packages/openfoam-com/openfoam-etc-1612.patch b/var/spack/repos/builtin/packages/openfoam-com/openfoam-etc-1612.patch new file mode 100644 index 0000000000..dd8146e953 --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-com/openfoam-etc-1612.patch @@ -0,0 +1,41 @@ +--- OpenFOAM-v1612+.orig/etc/bashrc 2016-12-23 15:22:59.000000000 +0100 ++++ OpenFOAM-v1612+/etc/bashrc 2017-03-22 16:05:05.751237072 +0100 +@@ -42,7 +42,8 @@ + # + # Please set to the appropriate path if the default is not correct. + # +-[ $BASH_SOURCE ] && FOAM_INST_DIR=$(\cd ${BASH_SOURCE%/*/*/*} && \pwd -P) || \ ++rc="${BASH_SOURCE:-${ZSH_NAME:+$0}}" ++[ -n "$rc" ] && FOAM_INST_DIR=$(\cd $(dirname $rc)/../.. && \pwd -L) || \ + FOAM_INST_DIR=$HOME/$WM_PROJECT + # FOAM_INST_DIR=~$WM_PROJECT + # FOAM_INST_DIR=/opt/$WM_PROJECT +@@ -135,8 +136,10 @@ + # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + . $WM_PROJECT_DIR/etc/config.sh/functions + +-# Add in preset user or site preferences: +-_foamSource `$WM_PROJECT_DIR/bin/foamEtcFile prefs.sh` ++# Override definitions via prefs, with 'other' first so the sys-admin ++# can provide base values independent of WM_PROJECT_SITE ++_foamSource `$WM_PROJECT_DIR/bin/foamEtcFile -mode o prefs.sh` ++_foamSource `$WM_PROJECT_DIR/bin/foamEtcFile -mode ug prefs.sh` + + # Evaluate command-line parameters and record settings for later + # these can be used to set/unset values, or specify alternative pref files +diff -uw OpenFOAM-v1612+.orig/etc/cshrc OpenFOAM-v1612+/etc/cshrc +--- OpenFOAM-v1612+.orig/etc/cshrc 2016-12-23 15:22:59.000000000 +0100 ++++ OpenFOAM-v1612+/etc/cshrc 2017-03-22 16:04:51.839291067 +0100 +@@ -148,8 +148,10 @@ + # Source files, possibly with some verbosity + alias _foamSource 'if ($?FOAM_VERBOSE && $?prompt) echo "Sourcing: \!*"; if (\!* != "") source \!*' + +-# Add in preset user or site preferences: +-_foamSource `$WM_PROJECT_DIR/bin/foamEtcFile prefs.csh` ++# Override definitions via prefs, with 'other' first so the sys-admin ++# can provide base values independent of WM_PROJECT_SITE ++_foamSource `$WM_PROJECT_DIR/bin/foamEtcFile -mode o prefs.csh` ++_foamSource `$WM_PROJECT_DIR/bin/foamEtcFile -mode ug prefs.csh` + + # Evaluate command-line parameters and record settings for later + # these can be used to set/unset values, or specify alternative pref files diff --git a/var/spack/repos/builtin/packages/openfoam-com/openfoam-mpi-1612.patch b/var/spack/repos/builtin/packages/openfoam-com/openfoam-mpi-1612.patch new file mode 100644 index 0000000000..b3663b0a49 --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-com/openfoam-mpi-1612.patch @@ -0,0 +1,36 @@ +--- OpenFOAM-v1612+.orig/etc/config.sh/mpi 2016-12-23 15:22:59.000000000 +0100 ++++ OpenFOAM-v1612+/etc/config.sh/mpi 2017-03-29 13:55:57.507980699 +0200 +@@ -75,8 +75,15 @@ + _foamAddMan $MPI_ARCH_PATH/share/man + ;; + ++USERMPI) ++ # Use an arbitrary, user-specified mpi implementation ++ export FOAM_MPI=mpi-user ++ _foamSource `$WM_PROJECT_DIR/bin/foamEtcFile config.sh/mpi-user` ++ ;; ++ + SYSTEMMPI) + export FOAM_MPI=mpi-system ++ _foamSource `$WM_PROJECT_DIR/bin/foamEtcFile config.sh/mpi-system` + + if [ -z "$MPI_ROOT" ] + then +--- OpenFOAM-v1612+.orig/etc/config.csh/mpi 2016-12-23 15:22:59.000000000 +0100 ++++ OpenFOAM-v1612+/etc/config.csh/mpi 2017-03-29 13:56:36.347835938 +0200 +@@ -71,8 +71,15 @@ + _foamAddMan $MPI_ARCH_PATH/share/man + breaksw + ++case USERMPI: ++ # Use an arbitrary, user-specified mpi implementation ++ setenv FOAM_MPI mpi-user ++ _foamSource `$WM_PROJECT_DIR/bin/foamEtcFile config.csh/mpi-user` ++ breaksw ++ + case SYSTEMMPI: + setenv FOAM_MPI mpi-system ++ _foamSource `$WM_PROJECT_DIR/bin/foamEtcFile config.csh/mpi-system` + + if ( ! ($?MPI_ROOT) ) then + echo diff --git a/var/spack/repos/builtin/packages/openfoam-com/openfoam-site.patch b/var/spack/repos/builtin/packages/openfoam-com/openfoam-site.patch new file mode 100644 index 0000000000..6631025788 --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-com/openfoam-site.patch @@ -0,0 +1,42 @@ +diff -uw OpenFOAM-v1612+.orig/etc/config.sh/settings OpenFOAM-v1612+/etc/config.sh/settings +--- OpenFOAM-v1612+.orig/etc/config.sh/settings 2016-12-23 15:22:59.000000000 +0100 ++++ OpenFOAM-v1612+/etc/config.sh/settings 2017-03-23 12:22:52.002101020 +0100 +@@ -141,7 +141,7 @@ + #------------------------------------------------------------------------------ + + # Location of the jobControl directory +-export FOAM_JOB_DIR=$WM_PROJECT_INST_DIR/jobControl ++export FOAM_JOB_DIR=$HOME/$WM_PROJECT/jobControl #SPACK: non-central location + + # wmake configuration + export WM_DIR=$WM_PROJECT_DIR/wmake +@@ -157,7 +157,7 @@ + export FOAM_EXT_LIBBIN=$WM_THIRD_PARTY_DIR/platforms/$WM_ARCH$WM_COMPILER$WM_PRECISION_OPTION$WM_LABEL_OPTION/lib + + # Site-specific directory +-siteDir="${WM_PROJECT_SITE:-$WM_PROJECT_INST_DIR/site}" ++siteDir="${WM_PROJECT_SITE:-$WM_PROJECT/site}" #SPACK: not in parent directory + + # Shared site executables/libraries + # Similar naming convention as ~OpenFOAM expansion +diff -uw OpenFOAM-v1612+.orig/etc/config.csh/settings OpenFOAM-v1612+/etc/config.csh/settings +--- OpenFOAM-v1612+.orig/etc/config.csh/settings 2016-12-23 15:22:59.000000000 +0100 ++++ OpenFOAM-v1612+/etc/config.csh/settings 2017-03-23 12:23:52.737891912 +0100 +@@ -137,7 +137,7 @@ + #------------------------------------------------------------------------------ + + # Location of the jobControl directory +-setenv FOAM_JOB_DIR $WM_PROJECT_INST_DIR/jobControl ++setenv FOAM_JOB_DIR=$HOME/$WM_PROJECT/jobControl #SPACK: non-central location + + # wmake configuration + setenv WM_DIR $WM_PROJECT_DIR/wmake +@@ -156,7 +156,7 @@ + if ( $?WM_PROJECT_SITE ) then + set siteDir=$WM_PROJECT_SITE + else +- set siteDir=$WM_PROJECT_INST_DIR/site ++ set siteDir=$WM_PROJECT_DIR/site #SPACK: not in parent directory + endif + + # Shared site executables/libraries diff --git a/var/spack/repos/builtin/packages/openfoam-com/package.py b/var/spack/repos/builtin/packages/openfoam-com/package.py new file mode 100644 index 0000000000..fcd33eadcb --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-com/package.py @@ -0,0 +1,722 @@ +############################################################################## +# Copyright (c) 2017 Mark Olesen, OpenCFD Ltd. +# +# This file was authored by Mark Olesen +# and is released as part of spack under the LGPL license. +# LLNL-CODE-647188 +# +# For details, see https://github.com/llnl/spack +# Please also see the LICENSE file for the LLNL notice and the LGPL. +# +# License +# ------- +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License (as +# published by the Free Software Foundation) version 2.1, February 1999. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +# conditions of the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Legal Notice +# ------------ +# OPENFOAM is a trademark owned by OpenCFD Ltd +# (producer and distributor of the OpenFOAM software via www.openfoam.com). +# The trademark information must remain visible and unadulterated in this +# file and via the "spack info" and comply with the term set by +# http://openfoam.com/legal/trademark-policy.php +# +# This file is not part of OpenFOAM, nor does it constitute a component of an +# OpenFOAM distribution. +# +############################################################################## +# +# Notes +# - mpi handling: WM_MPLIB=USERMPI and use spack to populate an appropriate +# configuration and generate wmake rules for 'USER' and 'USERMPI' +# mpi implementations. +# +# - Resolution of flex, zlib needs more attention (within OpenFOAM) +# - +paraview: +# depends_on should just be 'paraview+plugins' but that resolves poorly. +# Workaround: use preferred variants "+plugins +qt" +# packages: +# paraview: +# variants: +plugins +qt +# in ~/.spack/packages.yaml +# +# - Combining +zoltan with +int64 has not been tested, but probably won't work. +# +############################################################################## +from spack import * +from spack.environment import * + +import glob +import re +import shutil +import os +from os.path import isdir, isfile + +# Not the nice way of doing things, but is a start for refactoring +__all__ = [ + 'format_export', + 'format_setenv', + 'write_environ', + 'rewrite_environ_files', + 'mplib_content', + 'generate_mplib_rules', + 'generate_compiler_rules', +] + + +def format_export(key, value): + """Format key,value pair as 'export' with newline for POSIX shell.""" + return 'export {0}={1}\n'.format(key, value) + + +def format_setenv(key, value): + """Format key,value pair as 'setenv' with newline for C-shell.""" + return 'setenv {0} {1}\n'.format(key, value) + + +def _write_environ_entries(outfile, environ, formatter): + """Write environment settings as 'export' or 'setenv'. + If environ is a dict, write in sorted order. + If environ is a list, write pair-wise. + Also descends into sub-dict and sub-list, but drops the key. + """ + if isinstance(environ, dict): + for key in sorted(environ): + entry = environ[key] + if isinstance(entry, dict): + _write_environ_entries(outfile, entry, formatter) + elif isinstance(entry, list): + _write_environ_entries(outfile, entry, formatter) + else: + outfile.write(formatter(key, entry)) + elif isinstance(environ, list): + for item in environ: + outfile.write(formatter(item[0], item[1])) + + +def _write_environ_file(output, environ, formatter): + """Write environment settings as 'export' or 'setenv'. + If environ is a dict, write in sorted order. + If environ is a list, write pair-wise. + Also descends into sub-dict and sub-list, but drops the key. + """ + with open(output, 'w') as outfile: + outfile.write('# SPACK settings\n\n') + _write_environ_entries(outfile, environ, formatter) + + +def write_environ(environ, **kwargs): + """Write environment settings as 'export' or 'setenv'. + If environ is a dict, write in sorted order. + If environ is a list, write pair-wise. + + Keyword Options: + posix[=None] If set, the name of the POSIX file to rewrite. + cshell[=None] If set, the name of the C-shell file to rewrite. + """ + posix = kwargs.get('posix', None) + if posix: + _write_environ_file(posix, environ, format_export) + cshell = kwargs.get('cshell', None) + if cshell: + _write_environ_file(cshell, environ, format_setenv) + + +def rewrite_environ_files(environ, **kwargs): + """Use filter_file to rewrite (existing) POSIX shell or C-shell files. + Keyword Options: + posix[=None] If set, the name of the POSIX file to rewrite. + cshell[=None] If set, the name of the C-shell file to rewrite. + """ + posix = kwargs.get('posix', None) + if posix and isfile(posix): + for k, v in environ.iteritems(): + filter_file( + r'^(\s*export\s+%s)=.*$' % k, + r'\1=%s' % v, + posix, + backup=False) + cshell = kwargs.get('cshell', None) + if cshell and isfile(cshell): + for k, v in environ.iteritems(): + filter_file( + r'^(\s*setenv\s+%s)\s+.*$' % k, + r'\1 %s' % v, + cshell, + backup=False) + + +def pkglib(package): + """Get lib64 or lib from package prefix""" + libdir = package.prefix.lib64 + if isdir(libdir): + return libdir + return package.prefix.lib + + +def mplib_content(spec, pre=None): + """The mpi settings to have wmake + use spack information with minimum modifications to OpenFOAM. + + Optional parameter 'pre' to provid alternative prefix + """ + mpi_spec = spec['mpi'] + bin = mpi_spec.prefix.bin + inc = mpi_spec.prefix.include + lib = pkglib(mpi_spec) + if pre: + bin = join_path(pre, os.path.basename(bin)) + inc = join_path(pre, os.path.basename(inc)) + lib = join_path(pre, os.path.basename(lib)) + else: + pre = mpi_spec.prefix + + info = { + 'name': '{0}-{1}'.format(mpi_spec.name, mpi_spec.version), + 'prefix': pre, + 'include': inc, + 'bindir': bin, + 'libdir': lib, + 'FLAGS': '-DOMPI_SKIP_MPICXX -DMPICH_IGNORE_CXX_SEEK', + 'PINC': '-I{0}'.format(inc), + 'PLIBS': '-L{0} -lmpi'.format(lib), + } + return info + + +def generate_mplib_rules(directory, spec): + """ Create mplibUSER,mplibUSERMPI rules in the specified directory""" + content = mplib_content(spec) + with working_dir(directory): + for mplib in ['mplibUSER', 'mplibUSERMPI']: + with open(mplib, 'w') as out: + out.write("""# Use mpi from spack ({name})\n +PFLAGS = {FLAGS} +PINC = {PINC} +PLIBS = {PLIBS} +""".format(**content)) + + +def generate_compiler_rules(directory, compOpt, value): + """ Create cSPACKOpt,c++SPACKOpt rules in the specified directory. + The file content is copied and filtered from the corresponding + cOpt,c++Opt rules""" + # Compiler options for SPACK - eg, wmake/rules/linux64Gcc/ + # Copy from existing cOpt, c++Opt and modify DBUG value + with working_dir(directory): + for lang in ['c', 'c++']: + src = '{0}Opt'.format(lang) + dst = '{0}{1}'.format(lang, compOpt) + shutil.copyfile(src, dst) # src -> dst + filter_file( + r'^(\S+DBUG\s*)=.*$', + r'\1= %s' % value, + dst, + backup=False) + + +class OpenfoamCom(Package): + """OpenFOAM is a GPL-opensource C++ CFD-toolbox. + This offering is supported by OpenCFD Ltd, + producer and distributor of the OpenFOAM software via www.openfoam.com, + and owner of the OPENFOAM trademark. + OpenCFD Ltd has been developing and releasing OpenFOAM since its debut + in 2004. + """ + + homepage = "http://www.openfoam.com/" + baseurl = "https://sourceforge.net/projects/openfoamplus/files" + + version('1612', 'ca02c491369150ab127cbb88ec60fbdf', + url=baseurl + '/v1612+/OpenFOAM-v1612+.tgz') + + variant('int64', default=False, + description='Compile with 64-bit labels') + variant('float32', default=False, + description='Compile with 32-bit scalar (single-precision)') + variant('knl', default=False, + description='Use KNL compiler settings') + + variant('scotch', default=True, + description='With scotch/ptscotch for decomposition') + variant('metis', default=False, + description='With metis for decomposition') + variant('zoltan', default=False, + description='With zoltan renumbering') + # TODO?# variant('parmgridgen', default=True, + # TODO?# description='With parmgridgen support') + variant('source', default=True, + description='Install library/application sources and tutorials') + + variant('paraview', default=True, + description='Build paraview plugins and runtime post-processing') + + #: 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') + depends_on('fftw') + depends_on('boost') + depends_on('cgal') + depends_on('flex@:2.6.1') # <- restriction due to scotch + depends_on('cmake', type='build') + + # Require scotch with ptscotch - corresponds to standard OpenFOAM setup + depends_on('scotch~int64+mpi', when='+scotch~int64') + depends_on('scotch+int64+mpi', when='+scotch+int64') + depends_on('metis@5:', when='+metis') + depends_on('metis+int64', when='+metis+int64') + depends_on('parmgridgen', when='+parmgridgen') + depends_on('zoltan', when='+zoltan') + + # For OpenFOAM plugins and run-time post-processing this should just be + # 'paraview+plugins' but that resolves poorly. + # Workaround: use preferred variants "+plugins +qt" in + # ~/.spack/packages.yaml + + # 1612 plugins need older paraview + # The native reader in paraview 5.2 is broken, so start after that + depends_on('paraview@:5.0.1', when='@:1612+paraview') + depends_on('paraview@5.3:', when='@1706:+paraview') + + # General patches + patch('openfoam-site.patch') + + # Version-specific patches + patch('openfoam-bin-1612.patch', when='@1612') + patch('openfoam-etc-1612.patch', when='@1612') + patch('openfoam-mpi-1612.patch', when='@1612') + patch('openfoam-build-1612.patch', when='@1612') + patch('scotch-metis-lib-1612.patch', when='@1612') + patch('zoltan-lib-1612.patch', when='@1612') + + # 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': 'USERMPI', # Use user mpi for spack + } + + # The system description is frequently needed + foam_sys = { + 'WM_ARCH': None, + 'WM_COMPILER': None, + 'WM_OPTIONS': None, + } + + # Content for etc/prefs.{csh,sh} + etc_prefs = {} + + # 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' + + # Add symlinks into bin/, lib/ (eg, for other applications) + extra_symlinks = False + + # Quickly enable/disable testing with the current develop branch + if False: + version( + 'plus', + branch='develop', + git='file://{0}/{1}' + .format(os.path.expanduser("~"), 'openfoam/OpenFOAM-plus/.git')) + + def setup_environment(self, spack_env, run_env): + run_env.set('WM_PROJECT_DIR', self.projectdir) + + @property + def projectdir(self): + """Absolute location of project directory: WM_PROJECT_DIR/""" + return self.prefix # <- install directly under prefix + + @property + def etc(self): + """Absolute location of the OpenFOAM etc/ directory""" + return join_path(self.projectdir, 'etc') + + @property + def archbin(self): + """Relative location of architecture-specific executables""" + return join_path('platforms', self.wm_options, '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'] + + def patch(self): + """Adjust OpenFOAM build for spack. Where needed, apply filter as an + alternative to normal patching. + """ + self.set_openfoam() # May need foam_cfg/foam_sys information + + # 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 = { + 'WM_THIRD_PARTY_DIR': + r'$WM_PROJECT_DIR/ThirdParty #SPACK: No separate third-party', + } + + rewrite_environ_files( # Adjust etc/bashrc and etc/cshrc + wm_setting, + posix=join_path('etc', 'bashrc'), + cshell=join_path('etc', 'cshrc')) + + # Adjust ParMGridGen - this is still a mess. + # We also have no assurances about sizes (int/long, float/double) etc. + # + # Need to adjust src/fvAgglomerationMethods/Allwmake + # "export ParMGridGen=%s" % spec['parmgridgen'].prefix + # + # and src/fvAgglomerationMethods/MGridGenGamgAgglomeration/Make/options + # "-I=%s" % spec['parmgridgen'].include + # "-L=%s -lmgrid" % spec['parmgridgen'].lib + + # 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) + + rewrite_environ_files( # Adjust etc/bashrc and etc/cshrc + wm_setting, + posix=join_path('etc', 'bashrc'), + cshell=join_path('etc', 'cshrc')) + + # Content for etc/prefs.{csh,sh} + self.etc_prefs = { + # TODO + # 'CMAKE_ARCH_PATH': spec['cmake'].prefix, + # 'FLEX_ARCH_PATH': spec['flex'].prefix, + # 'ZLIB_ARCH_PATH': spec['zlib'].prefix, + } + + # MPI content, using MPI_ARCH_PATH + content = mplib_content(spec, '${MPI_ARCH_PATH}') + + # Content for etc/config.{csh,sh}/ files + self.etc_config = { + 'CGAL': { + 'BOOST_ARCH_PATH': spec['boost'].prefix, + 'CGAL_ARCH_PATH': spec['cgal'].prefix, + }, + 'FFTW': { + 'FFTW_ARCH_PATH': spec['fftw'].prefix, + }, + # User-defined MPI + 'mpi-user': [ + ('MPI_ARCH_PATH', spec['mpi'].prefix), # Absolute + ('LD_LIBRARY_PATH', + '"%s:${LD_LIBRARY_PATH}"' % content['libdir']), + ('PATH', '"%s:${PATH}"' % content['bindir']), + ], + 'scotch': {}, + 'metis': {}, + 'paraview': [], + } + + if '+scotch' in spec: + self.etc_config['scotch'] = { + 'SCOTCH_ARCH_PATH': spec['scotch'].prefix, + # For src/parallel/decompose/Allwmake + 'SCOTCH_VERSION': 'scotch-{0}'.format(spec['scotch'].version), + } + + if '+metis' in spec: + self.etc_config['metis'] = { + 'METIS_ARCH_PATH': spec['metis'].prefix, + } + + if '+paraview' in spec: + pvMajor = 'paraview-{0}'.format(spec['paraview'].version.up_to(2)) + self.etc_config['paraview'] = [ + ('ParaView_DIR', spec['paraview'].prefix), + ('ParaView_INCLUDE_DIR', '$ParaView_DIR/include/' + pvMajor), + ('PV_PLUGIN_PATH', '$FOAM_LIBBIN/' + pvMajor), + ('PATH', '"${ParaView_DIR}/bin:${PATH}"'), + ] + + # Not normally included as etc/config file + if '+parmgridgen' in spec: + self.etc_config['parmgridgen'] = { + 'PARMGRIDGEN_ARCH_PATH': spec['parmgridgen'].prefix + } + + # Optional + if '+zoltan' in spec: + self.etc_config['zoltan'] = { + 'ZOLTAN_ARCH_PATH': spec['zoltan'].prefix + } + + # Write prefs files according to the configuration. + # Only need prefs.sh for building, but install both for end-users + if self.etc_prefs: + write_environ( + self.etc_prefs, + posix=join_path('etc', 'prefs.sh'), + cshell=join_path('etc', 'prefs.csh')) + + # Adjust components to use SPACK variants + for component, subdict in self.etc_config.iteritems(): + write_environ( + subdict, + 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. + """ + self.set_openfoam() # Force proper population of foam_cfg/foam_sys + args = ['-silent'] + if self.parallel: # Build in parallel? - pass as an argument + args.append( + '-j{0}'.format(str(self.make_jobs) if self.make_jobs else '')) + builder = Executable(self.build_script) + builder(*args) + + def install(self, spec, prefix): + """Install under the projectdir (== prefix)""" + self.build(spec, prefix) # Should be a separate phase + opts = self.wm_options + + mkdirp(self.projectdir) + projdir = os.path.basename(self.projectdir) + wm_setting = { + '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-.*') + else: + ignored = re.compile(r'^(Allwmake|spack-).*') + + files = [ + f for f in glob.glob("*") if 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'] + if '+source' in spec: + dirs.extend(['applications', 'src', 'tutorials']) + + for d in dirs: + install_tree( + d, + join_path(self.projectdir, d)) + + dirs = ['platforms'] + if '+source' in spec: + dirs.extend(['doc']) + + # Install platforms (and doc) skipping intermediate targets + ignored = ['src', 'applications', 'html', 'Guides'] + for d in dirs: + install_tree( + d, + join_path(self.projectdir, d), + ignore=shutil.ignore_patterns(*ignored)) + + rewrite_environ_files( # Adjust etc/bashrc and etc/cshrc + wm_setting, + posix=join_path(self.etc, 'bashrc'), + cshell=join_path(self.etc, 'cshrc')) + self.install_links() + + def install_links(self): + """Add symlinks into bin/, lib/ (eg, for other applications)""" + if not self.extra_symlinks: + return + + # ln -s platforms/linux64GccXXX/lib lib + with working_dir(self.projectdir): + if 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) + ]: + os.symlink(f, os.path.basename(f)) + +# ----------------------------------------------------------------------------- diff --git a/var/spack/repos/builtin/packages/openfoam-com/scotch-metis-lib-1612.patch b/var/spack/repos/builtin/packages/openfoam-com/scotch-metis-lib-1612.patch new file mode 100644 index 0000000000..b7530e6320 --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-com/scotch-metis-lib-1612.patch @@ -0,0 +1,48 @@ +--- OpenFOAM-v1612+.orig/src/parallel/decompose/Allwmake 2017-03-21 16:34:44.599021283 +0100 ++++ OpenFOAM-v1612+/src/parallel/decompose/Allwmake 2017-03-21 16:28:57.243969660 +0100 +@@ -36,6 +36,7 @@ + + # Library + [ -r $FOAM_EXT_LIBBIN/libmetis.so ] || \ ++ [ -r $METIS_ARCH_PATH/lib/libmetis.so ] || \ + [ -r $METIS_ARCH_PATH/lib$WM_COMPILER_LIB_ARCH/libmetis.so ] || \ + [ "${METIS_ARCH_PATH##*-}" = system ] || { + echo "$warning (missing library)" +@@ -90,6 +91,7 @@ + + # Library + [ -r $FOAM_EXT_LIBBIN/libscotch.so ] || \ ++ [ -r $SCOTCH_ARCH_PATH/lib/libscotch.so ] || \ + [ -r $SCOTCH_ARCH_PATH/lib$WM_COMPILER_LIB_ARCH/libscotch.so ] || \ + [ "${SCOTCH_ARCH_PATH##*-}" = system ] || { + echo "$warning (missing library)" +--- OpenFOAM-v1612+.orig/src/parallel/decompose/metisDecomp/Make/options 2017-03-21 16:34:25.383075328 +0100 ++++ OpenFOAM-v1612+/src/parallel/decompose/metisDecomp/Make/options 2017-03-21 16:30:15.727758338 +0100 +@@ -8,6 +8,7 @@ + * to support central, non-thirdparty installations + */ + LIB_LIBS = \ ++ -L$(METIS_ARCH_PATH)/lib \ + -L$(METIS_ARCH_PATH)/lib$(WM_COMPILER_LIB_ARCH) \ + -L$(FOAM_EXT_LIBBIN) \ + -lmetis +--- OpenFOAM-v1612+.orig/src/parallel/decompose/ptscotchDecomp/Make/options 2017-03-21 16:34:34.607049385 +0100 ++++ OpenFOAM-v1612+/src/parallel/decompose/ptscotchDecomp/Make/options 2017-03-21 16:30:00.479799399 +0100 +@@ -16,6 +16,7 @@ + * to support central, non-thirdparty installations + */ + LIB_LIBS = \ ++ -L$(SCOTCH_ARCH_PATH)/lib \ + -L$(SCOTCH_ARCH_PATH)/lib$(WM_COMPILER_LIB_ARCH) \ + -L$(FOAM_EXT_LIBBIN) \ + -L$(FOAM_EXT_LIBBIN)/$(FOAM_MPI) \ +--- OpenFOAM-v1612+.orig/src/parallel/decompose/scotchDecomp/Make/options 2017-03-21 16:34:39.159036582 +0100 ++++ OpenFOAM-v1612+/src/parallel/decompose/scotchDecomp/Make/options 2017-03-21 16:29:46.719836452 +0100 +@@ -16,6 +16,7 @@ + * to support central, non-thirdparty installations + */ + LIB_LIBS = \ ++ -L$(SCOTCH_ARCH_PATH)/lib \ + -L$(SCOTCH_ARCH_PATH)/lib$(WM_COMPILER_LIB_ARCH) \ + -L$(FOAM_EXT_LIBBIN) \ + -lscotch \ diff --git a/var/spack/repos/builtin/packages/openfoam-com/zoltan-lib-1612.patch b/var/spack/repos/builtin/packages/openfoam-com/zoltan-lib-1612.patch new file mode 100644 index 0000000000..712e6a7dfd --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-com/zoltan-lib-1612.patch @@ -0,0 +1,84 @@ +--- OpenFOAM-v1612+.orig/applications/utilities/mesh/manipulation/renumberMesh/Allwmake 2016-12-23 15:22:59.000000000 +0100 ++++ OpenFOAM-v1612+/applications/utilities/mesh/manipulation/renumberMesh/Allwmake 2017-03-28 11:13:35.222727218 +0200 +@@ -4,20 +4,35 @@ + # Parse arguments for compilation (at least for error catching) + . $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments + +-export COMPILE_FLAGS='' +-export LINK_FLAGS='' ++unset COMP_FLAGS LINK_FLAGS + + if [ -f "${FOAM_LIBBIN}/libSloanRenumber.so" ] + then +- echo "Found libSloanRenumber.so -- enabling Sloan renumbering support." ++ echo " found libSloanRenumber -- enabling sloan renumbering support." + export LINK_FLAGS="${LINK_FLAGS} -lSloanRenumber" + fi + +-if [ -f "${ZOLTAN_ARCH_PATH}/lib/libzoltan.a" -a -f "${FOAM_LIBBIN}/libzoltanRenumber.so" ] ++if [ -f "${FOAM_LIBBIN}/libzoltanRenumber.so" ] + then +- echo "Found libzoltanRenumber.so -- enabling zoltan renumbering support." +- export COMPILE_FLAGS="-DFOAM_USE_ZOLTAN" +- export LINK_FLAGS="${LINK_FLAGS} -lzoltanRenumber -L${ZOLTAN_ARCH_PATH}/lib -lzoltan" ++ if [ -z "$ZOLTAN_ARCH_PATH" ] ++ then ++ # Optional: get ZOLTAN_ARCH_PATH ++ if settings=$($WM_PROJECT_DIR/bin/foamEtcFile config.sh/zoltan) ++ then ++ . $settings ++ fi ++ fi ++ ++ for libdir in lib "lib${WM_COMPILER_LIB_ARCH}" ++ do ++ if [ -f "$ZOLTAN_ARCH_PATH/$libdir/libzoltan.a" ] ++ then ++ echo " found libzoltanRenumber -- enabling zoltan renumbering support." ++ export COMP_FLAGS="-DFOAM_USE_ZOLTAN" ++ export LINK_FLAGS="${LINK_FLAGS} -lzoltanRenumber -L$ZOLTAN_ARCH_PATH/$libdir -lzoltan" ++ break ++ fi ++ done + fi + + wmake $targetType +--- OpenFOAM-v1612+.orig/src/renumber/Allwmake 2016-12-23 15:22:59.000000000 +0100 ++++ OpenFOAM-v1612+/src/renumber/Allwmake 2017-03-28 11:10:22.195543610 +0200 +@@ -5,14 +5,11 @@ + targetType=libso + . $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments + +-## Get ZOLTAN_ARCH_PATH +-#if settings=$($WM_PROJECT_DIR/bin/foamEtcFile config.sh/zoltan) +-#then +-# . $settings +-# echo "using ZOLTAN_ARCH_PATH=$ZOLTAN_ARCH_PATH" +-#else +-# echo "Error: no config.sh/zoltan settings" +-#fi ++# Optional: get ZOLTAN_ARCH_PATH ++if settings=$($WM_PROJECT_DIR/bin/foamEtcFile config.sh/zoltan) ++then ++ . $settings ++fi + + wmake $targetType renumberMethods + +--- OpenFOAM-v1612+.orig/src/renumber/zoltanRenumber/Make/options 2016-12-23 15:22:59.000000000 +0100 ++++ OpenFOAM-v1612+/src/renumber/zoltanRenumber/Make/options 2017-03-28 11:50:46.484343848 +0200 +@@ -4,10 +4,13 @@ + EXE_INC = \ + /* -DFULLDEBUG -g -O0 */ \ + $(PFLAGS) $(PINC) \ ++ ${c++LESSWARN} \ + -I$(FOAM_SRC)/renumber/renumberMethods/lnInclude \ + -I$(ZOLTAN_ARCH_PATH)/include/ \ + -I$(LIB_SRC)/meshTools/lnInclude + + LIB_LIBS = \ +- /* -L$(ZOLTAN_ARCH_PATH)/lib -lzoltan */ \ ++ -L$(ZOLTAN_ARCH_PATH)/lib \ ++ -L$(ZOLTAN_ARCH_PATH)/lib$(WM_COMPILER_LIB_ARCH) \ ++ -lzoltan \ + -lmeshTools diff --git a/var/spack/repos/builtin/packages/openfoam-org/openfoam-etc-41.patch b/var/spack/repos/builtin/packages/openfoam-org/openfoam-etc-41.patch new file mode 100644 index 0000000000..6fe3b7b4d3 --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-org/openfoam-etc-41.patch @@ -0,0 +1,25 @@ +--- OpenFOAM-4.x.orig/etc/bashrc 2016-10-16 16:11:45.000000000 +0200 ++++ OpenFOAM-4.x/etc/bashrc 2017-03-24 12:41:25.233267894 +0100 +@@ -43,17 +43,17 @@ + # Please set to the appropriate path if the default is not correct. + # + [ $BASH_SOURCE ] && \ +-export FOAM_INST_DIR=$(cd ${BASH_SOURCE%/*/*/*} && pwd -P) || \ +-export FOAM_INST_DIR=$HOME/$WM_PROJECT +-# export FOAM_INST_DIR=~$WM_PROJECT +-# export FOAM_INST_DIR=/opt/$WM_PROJECT +-# export FOAM_INST_DIR=/usr/local/$WM_PROJECT ++FOAM_INST_DIR=$(\cd $(dirname $BASH_SOURCE)/../.. && \pwd -P) || \ ++FOAM_INST_DIR=$HOME/$WM_PROJECT ++# FOAM_INST_DIR=/opt/$WM_PROJECT ++# FOAM_INST_DIR=/usr/local/$WM_PROJECT + # + # Build foamyHexMesh + export FOAMY_HEX_MESH=yes + # + # END OF (NORMAL) USER EDITABLE PART + ################################################################################ ++export FOAM_INST_DIR + + # The default environment variables below can be overridden in a prefs.sh file + # located in ~/.OpenFOAM/$WM_PROJECT_VERSION, ~/.OpenFOAM, diff --git a/var/spack/repos/builtin/packages/openfoam-org/openfoam-site.patch b/var/spack/repos/builtin/packages/openfoam-org/openfoam-site.patch new file mode 100644 index 0000000000..6631025788 --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-org/openfoam-site.patch @@ -0,0 +1,42 @@ +diff -uw OpenFOAM-v1612+.orig/etc/config.sh/settings OpenFOAM-v1612+/etc/config.sh/settings +--- OpenFOAM-v1612+.orig/etc/config.sh/settings 2016-12-23 15:22:59.000000000 +0100 ++++ OpenFOAM-v1612+/etc/config.sh/settings 2017-03-23 12:22:52.002101020 +0100 +@@ -141,7 +141,7 @@ + #------------------------------------------------------------------------------ + + # Location of the jobControl directory +-export FOAM_JOB_DIR=$WM_PROJECT_INST_DIR/jobControl ++export FOAM_JOB_DIR=$HOME/$WM_PROJECT/jobControl #SPACK: non-central location + + # wmake configuration + export WM_DIR=$WM_PROJECT_DIR/wmake +@@ -157,7 +157,7 @@ + export FOAM_EXT_LIBBIN=$WM_THIRD_PARTY_DIR/platforms/$WM_ARCH$WM_COMPILER$WM_PRECISION_OPTION$WM_LABEL_OPTION/lib + + # Site-specific directory +-siteDir="${WM_PROJECT_SITE:-$WM_PROJECT_INST_DIR/site}" ++siteDir="${WM_PROJECT_SITE:-$WM_PROJECT/site}" #SPACK: not in parent directory + + # Shared site executables/libraries + # Similar naming convention as ~OpenFOAM expansion +diff -uw OpenFOAM-v1612+.orig/etc/config.csh/settings OpenFOAM-v1612+/etc/config.csh/settings +--- OpenFOAM-v1612+.orig/etc/config.csh/settings 2016-12-23 15:22:59.000000000 +0100 ++++ OpenFOAM-v1612+/etc/config.csh/settings 2017-03-23 12:23:52.737891912 +0100 +@@ -137,7 +137,7 @@ + #------------------------------------------------------------------------------ + + # Location of the jobControl directory +-setenv FOAM_JOB_DIR $WM_PROJECT_INST_DIR/jobControl ++setenv FOAM_JOB_DIR=$HOME/$WM_PROJECT/jobControl #SPACK: non-central location + + # wmake configuration + setenv WM_DIR $WM_PROJECT_DIR/wmake +@@ -156,7 +156,7 @@ + if ( $?WM_PROJECT_SITE ) then + set siteDir=$WM_PROJECT_SITE + else +- set siteDir=$WM_PROJECT_INST_DIR/site ++ set siteDir=$WM_PROJECT_DIR/site #SPACK: not in parent directory + endif + + # Shared site executables/libraries diff --git a/var/spack/repos/builtin/packages/openfoam-org/package.py b/var/spack/repos/builtin/packages/openfoam-org/package.py new file mode 100644 index 0000000000..19ffd40507 --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-org/package.py @@ -0,0 +1,492 @@ +############################################################################## +# Copyright (c) 2017 Mark Olesen, OpenCFD Ltd. +# +# This file was authored by Mark Olesen +# and is released as part of spack under the LGPL license. +# LLNL-CODE-647188 +# +# For details, see https://github.com/llnl/spack +# Please also see the LICENSE file for the LLNL notice and the LGPL. +# +# License +# ------- +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License (as +# published by the Free Software Foundation) version 2.1, February 1999. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +# conditions of the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Legal Notice +# ------------ +# OPENFOAM is a trademark owned by OpenCFD Ltd +# (producer and distributor of the OpenFOAM software via www.openfoam.com). +# The trademark information must remain visible and unadulterated in this +# file and via the "spack info" and comply with the term set by +# http://openfoam.com/legal/trademark-policy.php +# +# This file is not part of OpenFOAM, nor does it constitute a component of an +# OpenFOAM distribution. +# +############################################################################## +# +# Notes +# - The openfoam-org package is a modified version of the openfoam-com package. +# If changes are needed here, consider if they should also be applied there. +# +# - Building with boost/cgal is not included, since some of the logic is not +# 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 implementations, in case these are required. +# +############################################################################## +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 * + + +class OpenfoamOrg(Package): + """OpenFOAM is a GPL-opensource C++ CFD-toolbox. + The openfoam.org release is managed by the OpenFOAM Foundation Ltd as + a licensee of the OPENFOAM trademark. + This offering is not approved or endorsed by OpenCFD Ltd, + producer and distributor of the OpenFOAM software via www.openfoam.com, + and owner of the OPENFOAM trademark. + """ + + homepage = "http://www.openfoam.org/" + baseurl = "https://github.com/OpenFOAM" + url = "https://github.com/OpenFOAM/OpenFOAM-4.x/archive/version-4.1.tar.gz" + + version('4.1', '318a446c4ae6366c7296b61184acd37c', + url=baseurl + '/OpenFOAM-4.x/archive/version-4.1.tar.gz') + + variant('int64', default=False, + description='Compile with 64-bit labels') + 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') + depends_on('flex@:2.6.1') # <- restriction due to scotch + 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') + + # General patches + patch('openfoam-site.patch') + + # 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 + } + + # The system description is frequently needed + foam_sys = { + 'WM_ARCH': None, + 'WM_COMPILER': None, + 'WM_OPTIONS': None, + } + + # Content for etc/prefs.{csh,sh} + etc_prefs = {} + + # 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' + + # Add symlinks into bin/, lib/ (eg, for other applications) + extra_symlinks = False + + def setup_environment(self, spack_env, run_env): + 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) + + @property + def projectdir(self): + """Absolute location of project directory: WM_PROJECT_DIR/""" + return join_path(self.prefix, self._canonical) # <- prefix/canonical + + @property + def etc(self): + """Absolute location of the OpenFOAM etc/ directory""" + return join_path(self.projectdir, 'etc') + + @property + def archbin(self): + """Relative location of architecture-specific executables""" + return join_path('platforms', self.wm_options, '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'] + + def patch(self): + """Adjust OpenFOAM build for spack. Where needed, apply filter as an + alternative to normal patching. + """ + 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! + parent = os.path.dirname(self.stage.source_path) + original = os.path.basename(self.stage.source_path) + target = self._canonical + 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)) + + # 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 = { + '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, + 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) + + rewrite_environ_files( # Adjust etc/bashrc and etc/cshrc + wm_setting, + posix=join_path('etc', 'bashrc'), + cshell=join_path('etc', 'cshrc')) + + # MPI content, with absolute paths + content = 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'], + } + + # Content for etc/config.{csh,sh}/ files + self.etc_config = { + 'CGAL': {}, + 'scotch': {}, + 'metis': {}, + 'paraview': [], + } + + if True: + self.etc_config['scotch'] = { + 'SCOTCH_ARCH_PATH': spec['scotch'].prefix, + # For src/parallel/decompose/Allwmake + 'SCOTCH_VERSION': 'scotch-{0}'.format(spec['scotch'].version), + } + + # Write prefs files according to the configuration. + # Only need prefs.sh for building, but install both for end-users + if self.etc_prefs: + write_environ( + self.etc_prefs, + posix=join_path('etc', 'prefs.sh'), + cshell=join_path('etc', 'prefs.csh')) + + # Adjust components to use SPACK variants + for component, subdict in self.etc_config.iteritems(): + write_environ( + subdict, + 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. + """ + self.set_openfoam() # Force proper population of foam_cfg/foam_sys + 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()) + 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 + + mkdirp(self.projectdir) + projdir = os.path.basename(self.projectdir) + wm_setting = { + '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-.*') + else: + ignored = re.compile(r'^(Allwmake|spack-).*') + + files = [ + f for f in glob.glob("*") if 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'] + if '+source' in spec: + dirs.extend(['applications', 'src', 'tutorials']) + + for d in dirs: + install_tree( + d, + join_path(self.projectdir, d)) + + dirs = ['platforms'] + if '+source' in spec: + dirs.extend(['doc']) + + # Install platforms (and doc) skipping intermediate targets + ignored = ['src', 'applications', 'html', 'Guides'] + for d in dirs: + install_tree( + d, + join_path(self.projectdir, d), + ignore=shutil.ignore_patterns(*ignored)) + + rewrite_environ_files( # Adjust etc/bashrc and etc/cshrc + wm_setting, + posix=join_path(self.etc, 'bashrc'), + cshell=join_path(self.etc, 'cshrc')) + self.install_links() + + def install_links(self): + """Add symlinks into bin/, lib/ (eg, for other applications)""" + if not self.extra_symlinks: + return + + # ln -s platforms/linux64GccXXX/lib lib + with working_dir(self.projectdir): + if 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) + ]: + os.symlink(f, os.path.basename(f)) + +# ----------------------------------------------------------------------------- -- cgit v1.2.3-60-g2f50