diff options
15 files changed, 1316 insertions, 757 deletions
diff --git a/etc/spack/defaults/packages.yaml b/etc/spack/defaults/packages.yaml index 0cafab28e9..d04ce76e6b 100644 --- a/etc/spack/defaults/packages.yaml +++ b/etc/spack/defaults/packages.yaml @@ -28,6 +28,6 @@ packages: mpe: [mpe2] mpi: [openmpi, mpich] opencl: [pocl] - openfoam: [foam-extend] + openfoam: [openfoam-com, openfoam-org, foam-extend] pil: [py-pillow] scalapack: [netlib-scalapack] diff --git a/var/spack/repos/builtin/packages/foam-extend/package.py b/var/spack/repos/builtin/packages/foam-extend/package.py index c68e570c0f..d417ef8cf3 100644 --- a/var/spack/repos/builtin/packages/foam-extend/package.py +++ b/var/spack/repos/builtin/packages/foam-extend/package.py @@ -48,16 +48,17 @@ # - reworked to mirror the openfoam-com package. # If changes are needed here, consider if they need applying there too. # +# Known issues +# - Combining +parmgridgen with +float32 probably won't work. +# ############################################################################## 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 * @@ -77,10 +78,9 @@ class FoamExtend(Package): version('3.0', git='http://git.code.sf.net/p/foam-extend/foam-extend-3.0') # variant('int64', default=False, - # description='Compile with 64-bit labels') + # description='Compile with 64-bit label') variant('float32', default=False, description='Compile with 32-bit scalar (single-precision)') - variant('paraview', default=False, description='Build paraview plugins (eg, paraFoam)') variant('scotch', default=True, @@ -96,10 +96,6 @@ class FoamExtend(Package): 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') @@ -111,189 +107,77 @@ class FoamExtend(Package): depends_on('scotch~metis+mpi', when='+ptscotch') depends_on('metis@5:', when='+metis') depends_on('parmetis', when='+parmetis') - depends_on('parmgridgen', when='+parmgridgen') + # mgridgen is statically linked + depends_on('parmgridgen', when='+parmgridgen', type='build') 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 - } + # General patches + common = ['spack-Allwmake', 'README-spack'] + assets = [] - # The system description is frequently needed - foam_sys = { - 'WM_ARCH': None, - 'WM_COMPILER': None, - 'WM_OPTIONS': None, + # Some user config settings + config = { + 'label-size': False, # <- No int32/int64 support + 'mplib': 'USERMPI', # USER | USERMPI } + # The openfoam architecture, compiler information etc + _foam_arch = 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' + phases = ['configure', 'build', 'install'] + build_script = './spack-Allwmake' # <- Added by patch() method. + + # + # - End of definitions / setup - + # def setup_environment(self, spack_env, run_env): - run_env.set('FOAM_INST_DIR', self.prefix) + run_env.set('FOAM_INST_DIR', os.path.dirname(self.projectdir)), + run_env.set('FOAM_PROJECT_DIR', self.projectdir) run_env.set('WM_PROJECT_DIR', self.projectdir) - - @property - def _canonical(self): - """Canonical name for this package and version""" - return 'foam-extend-{0}'.format(self.version.up_to(2)) + for d in ['wmake', self.archbin]: # bin already added automatically + run_env.prepend_path('PATH', join_path(self.projectdir, d)) + run_env.set('MPI_BUFFER_SIZE', "20000000") + + def setup_dependent_environment(self, spack_env, run_env, dependent_spec): + """Provide location of the OpenFOAM project. + This is identical to the WM_PROJECT_DIR value, but we avoid that + variable since it would mask the normal OpenFOAM cleanup of + previous versions. + """ + spack_env.set('FOAM_PROJECT_DIR', self.projectdir) @property def projectdir(self): """Absolute location of project directory: WM_PROJECT_DIR/""" - return join_path(self.prefix, self._canonical) # <- prefix/canonical + return self.prefix # <- install directly under prefix @property - def etc(self): - """Absolute location of the OpenFOAM etc/ directory""" - return join_path(self.projectdir, 'etc') + def foam_arch(self): + if not self._foam_arch: + self._foam_arch = OpenfoamArch(self.spec, **self.config) + return self._foam_arch @property def archbin(self): """Relative location of architecture-specific executables""" - wm_options = self.set_openfoam() - return join_path('applications', 'bin', wm_options) + return join_path('applications', 'bin', self.foam_arch) @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'] + return join_path('lib', self.foam_arch) 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 + """Adjust OpenFOAM build for spack. + Where needed, apply filter as an alternative to normal patching.""" + add_extra_files(self, self.common, self.assets) # Adjust ParMGridGen - this is still a mess files = [ @@ -319,23 +203,7 @@ class FoamExtend(Package): 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 + f, backup=False) def configure(self, spec, prefix): """Make adjustments to the OpenFOAM configuration files in their various @@ -343,8 +211,6 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR 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 @@ -373,7 +239,7 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR }, } # Adjust configuration via prefs - sort second - self.etc_prefs['001'].update(self.foam_cfg) + self.etc_prefs['001'].update(self.foam_arch.foam_dict()) if '+scotch' in spec or '+ptscotch' in spec: pkg = spec['scotch'].prefix @@ -434,41 +300,33 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR 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. + Only build if the compiler is known to be supported. """ - self.set_openfoam() # Force proper population of foam_cfg/foam_sys + self.foam_arch.has_rule(self.stage.source_path) + self.foam_arch.create_rules(self.stage.source_path, self) + args = [] if self.parallel: # Build in parallel? - pass via the environment - os.environ['WM_NCOMPPROCS'] = str(self.make_jobs) \ - if self.make_jobs else str(multiprocessing.cpu_count()) + os.environ['WM_NCOMPPROCS'] = str(make_jobs) builder = Executable(self.build_script) builder(*args) def install(self, spec, prefix): - """Install under the projectdir (== prefix/name-version)""" - self.build(spec, prefix) # Should be a separate phase - opts = self.wm_options + """Install under the projectdir""" + opts = str(self.foam_arch) # Fairly ugly since intermediate targets are scattered inside sources appdir = 'applications' + projdir = os.path.basename(self.projectdir) mkdirp(self.projectdir, join_path(self.projectdir, appdir)) - - # Retain build log file - out = "spack-build.out" - if isfile(out): - install(out, join_path(self.projectdir, "log." + opts)) + # Filtering: bashrc, cshrc + edits = { + 'WM_PROJECT_INST_DIR': os.path.dirname(self.projectdir), + 'WM_PROJECT_DIR': join_path('$WM_PROJECT_INST_DIR', projdir), + } # All top-level files, except spack build info and possibly Allwmake if '+source' in spec: @@ -477,36 +335,52 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR ignored = re.compile(r'^(Allclean|Allwmake|spack-).*') files = [ - f for f in glob.glob("*") if isfile(f) and not ignored.search(f) + f for f in glob.glob("*") + if os.path.isfile(f) and not ignored.search(f) ] for f in files: install(f, self.projectdir) # Install directories. install applications/bin directly - for d in ['bin', 'etc', 'wmake', 'lib', join_path(appdir, 'bin')]: + # Install 'etc' before 'bin' (for symlinks) + for d in ['etc', 'bin', 'wmake', 'lib', join_path(appdir, 'bin')]: install_tree( d, - join_path(self.projectdir, d)) + join_path(self.projectdir, d), + symlinks=True) if '+source' in spec: subitem = join_path(appdir, 'Allwmake') install(subitem, join_path(self.projectdir, subitem)) - ignored = [opts] # Intermediate targets + ignored = [opts] # Ignore intermediate targets for d in ['src', 'tutorials']: install_tree( d, join_path(self.projectdir, d), - ignore=shutil.ignore_patterns(*ignored)) + ignore=shutil.ignore_patterns(*ignored), + symlinks=True) for d in ['solvers', 'utilities']: install_tree( join_path(appdir, d), join_path(self.projectdir, appdir, d), - ignore=shutil.ignore_patterns(*ignored)) + ignore=shutil.ignore_patterns(*ignored), + symlinks=True) + + etc_dir = join_path(self.projectdir, 'etc') + rewrite_environ_files( # Adjust etc/bashrc and etc/cshrc + edits, + posix=join_path(etc_dir, 'bashrc'), + cshell=join_path(etc_dir, 'cshrc')) + self.install_links() def install_links(self): """Add symlinks into bin/, lib/ (eg, for other applications)""" - return + # Make build log visible - it contains OpenFOAM-specific information + with working_dir(self.projectdir): + os.symlink( + join_path('.spack', 'build.out'), + join_path('log.' + str(self.foam_arch))) # ----------------------------------------------------------------------------- diff --git a/var/spack/repos/builtin/packages/openfoam-com/common/README b/var/spack/repos/builtin/packages/openfoam-com/common/README new file mode 100644 index 0000000000..d116bbaa23 --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-com/common/README @@ -0,0 +1,2 @@ +Some helper tools for packaging applications/libraries dependent on an +openfoam provider. diff --git a/var/spack/repos/builtin/packages/openfoam-com/common/README-spack b/var/spack/repos/builtin/packages/openfoam-com/common/README-spack new file mode 100644 index 0000000000..83b606dda1 --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-com/common/README-spack @@ -0,0 +1,15 @@ +Additional notes for spack +-------------------------- + +OpenFOAM largely manages its own PATH and LD_LIBRARY_PATH settings. +The spack build currently also follows this and only provides +a minimum modules environment. + +The variable FOAM_PROJECT_DIR points to the location of the OpenFOAM project +and shall contain a $FOAM_PROJECT_DIR/etc/bashrc file for OpenFOAM. +The variable FOAM_INST_DIR may also be provided for older OpenFOAM versions. + +It is the aim for the future to use spack to provide the environment directly, +but this still needs more work. + +2017-04-18 diff --git a/var/spack/repos/builtin/packages/openfoam-com/common/change-sitedir.sh b/var/spack/repos/builtin/packages/openfoam-com/common/change-sitedir.sh new file mode 100644 index 0000000000..61d9c3ea8b --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-com/common/change-sitedir.sh @@ -0,0 +1,94 @@ +#----------------------------------*-sh-*-------------------------------------- +# ========= | +# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox +# \\ / O peration | +# \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. +# \\/ M anipulation | +#------------------------------------------------------------------------------ +# License +# This file is part of OpenFOAM. +# +# OpenFOAM is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OpenFOAM 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 GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License +# along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. +# +# Script +# . change-sitedir.sh PREFIX [SUFFIX] +# +# Shortcuts (prefix) +# -prefix "$WM_PROJECT_INST_DIR/site" +# -project "$WM_PROJECT_DIR/site" +# -none remove from environment +# +# Shortcuts (suffix) +# -platforms "platforms/$WM_OPTIONS" +# +# Description +# Change WM_PROJECT_SITE, FOAM_SITE_APPBIN, FOAM_SITE_LIBBIN +# and the respective entries in PATH, LD_LIBRARY_PATH. +# +# This can be useful when temporarily reassigning the site directory +# when packaging OpenFOAM. +# +# The suffix value should normally include "platforms/$WM_OPTIONS" +# +# Example +# . /path/change-sitedir.sh -prefix -platforms +# +# corresponds to the standard site location: +# +# $WM_PROJECT_INST_DIR/site{/$WM_PROJECT_VERSION/platforms/$WM_OPTIONS} +# +#------------------------------------------------------------------------------ + +if [ "$#" -ge 1 ] +then + prefix="$1" + suffix="$2" + + foamOldDirs="$FOAM_SITE_APPBIN $FOAM_SITE_LIBBIN \ + $WM_PROJECT_SITE $WM_PROJECT_INST_DIR/site $WM_PROJECT_DIR/site" + foamClean=$WM_PROJECT_DIR/bin/foamCleanPath + if [ -x "$foamClean" ] + then + cleaned=$($foamClean "$PATH" "$foamOldDirs") && PATH="$cleaned" + cleaned=$($foamClean "$LD_LIBRARY_PATH" "$foamOldDirs") \ + && LD_LIBRARY_PATH="$cleaned" + fi + + case "$suffix" in + -plat*) suffix="platforms/$WM_OPTIONS" ;; + esac + case "$prefix" in + -prefix) prefix="$WM_PROJECT_INST_DIR/site" ;; + -project) prefix="$WM_PROJECT_DIR/site" ;; + -none) unset prefix ;; + esac + + if [ -n "$prefix" ] + then + export WM_PROJECT_SITE="$prefix" + + prefix="$prefix/${WM_PROJECT_VERSION:-unknown}${suffix:+/}${suffix}" + + export FOAM_SITE_APPBIN="$prefix/bin" + export FOAM_SITE_LIBBIN="$prefix/lib" + PATH="$FOAM_SITE_APPBIN:$PATH" + LD_LIBRARY_PATH="$FOAM_SITE_LIBBIN:$LD_LIBRARY_PATH" + else + unset WM_PROJECT_SITE FOAM_SITE_APPBIN FOAM_SITE_LIBBIN + fi +fi + +unset foamClean foamOldDirs cleaned prefix suffix + +#------------------------------------------------------------------------------ diff --git a/var/spack/repos/builtin/packages/openfoam-com/common/change-userdir.sh b/var/spack/repos/builtin/packages/openfoam-com/common/change-userdir.sh new file mode 100644 index 0000000000..d126fcfe5d --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-com/common/change-userdir.sh @@ -0,0 +1,94 @@ +#----------------------------------*-sh-*-------------------------------------- +# ========= | +# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox +# \\ / O peration | +# \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. +# \\/ M anipulation | +#------------------------------------------------------------------------------ +# License +# This file is part of OpenFOAM. +# +# OpenFOAM is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OpenFOAM 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 GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License +# along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. +# +# Script +# . change-userdir.sh PREFIX [SUFFIX] +# +# Shortcuts (prefix) +# -home "$HOME/OpenFOAM/$USER-$WM_PROJECT_VERSION" +# -none remove from environment +# +# Shortcuts (suffix) +# -platforms "platforms/$WM_OPTIONS" +# +# Description +# Change WM_PROJECT_USER_DIR, FOAM_USER_APPBIN, FOAM_USER_LIBBIN +# and the respective entries in PATH, LD_LIBRARY_PATH. +# Also adjusts FOAM_RUN. +# +# This can be useful with compiling additional OpenFOAM programs +# (that use FOAM_USER_APPBIN, FOAM_USER_LIBBIN for their build), +# to avoid conflicts with the normal user bin/lib files. +# +# The suffix value should normally include "platforms/$WM_OPTIONS" +# +# Example +# . /path/change-userdir.sh -home -platforms +# +# corresponds to the standard user location: +# +# $HOME/OpenFOAM/$USER-$WM_PROJECT_VERSION/platforms/$WM_OPTIONS +# +#------------------------------------------------------------------------------ + +if [ "$#" -ge 1 ] +then + prefix="$1" + suffix="$2" + + foamOldDirs="$FOAM_USER_APPBIN $FOAM_USER_LIBBIN" + foamClean=$WM_PROJECT_DIR/bin/foamCleanPath + if [ -x "$foamClean" ] + then + cleaned=$($foamClean "$PATH" "$foamOldDirs") && PATH="$cleaned" + cleaned=$($foamClean "$LD_LIBRARY_PATH" "$foamOldDirs") \ + && LD_LIBRARY_PATH="$cleaned" + fi + + case "$suffix" in + -plat*) suffix="platforms/$WM_OPTIONS" ;; + esac + case "$prefix" in + -home) prefix="$HOME/OpenFOAM/$USER-${WM_PROJECT_VERSION:-unknown}" ;; + -none) unset prefix ;; + esac + + if [ -n "$prefix" ] + then + export WM_PROJECT_USER_DIR="$prefix" + export FOAM_RUN="$prefix/run" + + prefix="$prefix${suffix:+/}${suffix}" + export FOAM_USER_APPBIN="$prefix/bin" + export FOAM_USER_LIBBIN="$prefix/lib" + + PATH="$FOAM_USER_APPBIN:$PATH" + LD_LIBRARY_PATH="$FOAM_USER_LIBBIN:$LD_LIBRARY_PATH" + else + unset WM_PROJECT_USER_DIR FOAM_RUN FOAM_USER_APPBIN FOAM_USER_LIBBIN + fi +fi + +unset foamClean foamOldDirs cleaned prefix suffix + +#------------------------------------------------------------------------------ diff --git a/var/spack/repos/builtin/packages/openfoam-com/common/spack-Allwmake b/var/spack/repos/builtin/packages/openfoam-com/common/spack-Allwmake new file mode 100755 index 0000000000..cff22daf10 --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-com/common/spack-Allwmake @@ -0,0 +1,22 @@ +#!/bin/bash +# Build wrapper script - FOAM_INST_DIR is only required by foam-extend +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 $@ # Pass arguments + +# Link non-dummy MPI_FOAM type to parent-dir, where rpath can find it +if [ "${FOAM_MPI:=dummy}" != dummy -a -d "$FOAM_LIBBIN/$FOAM_MPI" ] +then +( + cd "$FOAM_LIBBIN" || exit 1 + for i in $FOAM_MPI/lib*.so + do + [ -f $i ] && ln -sf $i "${i##*/}" + done +) +fi + +# ----------------------------------------------------------------------------- diff --git a/var/spack/repos/builtin/packages/openfoam-com/common/spack-derived-Allwmake b/var/spack/repos/builtin/packages/openfoam-com/common/spack-derived-Allwmake new file mode 100755 index 0000000000..407ad734e8 --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-com/common/spack-derived-Allwmake @@ -0,0 +1,26 @@ +#!/bin/bash +# The openfoam providers must export 'FOAM_PROJECT_DIR' +# The package is expected to supply an appropriate Allwmake file. + +[ -d "$FOAM_PROJECT_DIR" -a -f "$FOAM_PROJECT_DIR/etc/bashrc" ] || { + echo "Error: no PROJECT=$FOAM_PROJECT_DIR" 1>&2 + echo " or no etc/bashrc found" 1>&2 + exit 1 +} + +export FOAM_INST_DIR=$(cd $FOAM_PROJECT_DIR/.. && pwd -L) # Needed by foam-extend +. $FOAM_PROJECT_DIR/etc/bashrc '' # No arguments + +# Package-specific adjustments +[ -f spack-config.sh ] && . ./spack-config.sh '' # No arguments + +echo "========================================" +date "+%Y-%m-%d %H:%M:%S %z" 2>/dev/null || echo "date is unknown" +echo "Build with ${WM_PROJECT}-${WM_PROJECT_VERSION}" +echo " WM_PROJECT_DIR = $WM_PROJECT_DIR" +echo " $WM_COMPILER $WM_COMPILER_TYPE compiler" +echo " $WM_OPTIONS - with $WM_MPLIB $FOAM_MPI" +echo + +./Allwmake $@ # Pass arguments +# ----------------------------------------------------------------------------- diff --git a/var/spack/repos/builtin/packages/openfoam-com/mgridgen-lib-1612.patch b/var/spack/repos/builtin/packages/openfoam-com/mgridgen-lib-1612.patch new file mode 100644 index 0000000000..8dc0b995ff --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-com/mgridgen-lib-1612.patch @@ -0,0 +1,41 @@ +--- OpenFOAM-v1612+.orig/src/fvAgglomerationMethods/Allwmake 2017-01-02 09:56:17.578558265 +0100 ++++ OpenFOAM-v1612+/src/fvAgglomerationMethods/Allwmake 2017-04-18 18:58:38.236795902 +0200 +@@ -4,9 +4,13 @@ + # Parse arguments for library compilation + . $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments + +-export ParMGridGen=$WM_THIRD_PARTY_DIR/ParMGridGen-1.0 ++unset MGRIDGEN_ARCH_PATH ++if settings=$($WM_PROJECT_DIR/bin/foamEtcFile config.sh/mgridgen) ++then ++ . $settings ++fi + +-if [ -e "$FOAM_LIBBIN/libMGridGen.so" ] ++if [ -e "$MGRIDGEN_ARCH_PATH/include/mgridgen.h" ] + then + wmake $targetType MGridGenGamgAgglomeration + fi +--- OpenFOAM-v1612+.orig/src/fvAgglomerationMethods/MGridGenGamgAgglomeration/Make/options 2017-01-02 09:56:17.578558265 +0100 ++++ OpenFOAM-v1612+/src/fvAgglomerationMethods/MGridGenGamgAgglomeration/Make/options 2017-04-18 18:59:16.860662811 +0200 +@@ -1,15 +1,9 @@ +-/* Needs ParMGridGen environment variable set. (see Allwmake script) */ +- +-TYPE_REAL= +-#if defined(WM_SP) +-TYPE_REAL=-DTYPE_REAL +-#endif +- + EXE_INC = \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ +- -I$(ParMGridGen)/MGridGen/Lib/lnInclude \ +- -I$(ParMGridGen)/MGridGen/IMlib/lnInclude \ +- $(TYPE_REAL) ++ -I$(MGRIDGEN_ARCH_PATH)/include + + LIB_LIBS = \ +- -L$(FOAM_EXT_LIBBIN) -lMGridGen ++ -L$(FOAM_EXT_LIBBIN) \ ++ -L$(MGRIDGEN_ARCH_PATH)/lib \ ++ -L$(MGRIDGEN_ARCH_PATH)/lib$(WM_COMPILER_LIB_ARCH) \ ++ -lmgrid diff --git a/var/spack/repos/builtin/packages/openfoam-com/openfoam-site.patch b/var/spack/repos/builtin/packages/openfoam-com/openfoam-site-1612.patch index 6631025788..d988c2f9b8 100644 --- a/var/spack/repos/builtin/packages/openfoam-com/openfoam-site.patch +++ b/var/spack/repos/builtin/packages/openfoam-com/openfoam-site-1612.patch @@ -6,7 +6,7 @@ diff -uw OpenFOAM-v1612+.orig/etc/config.sh/settings OpenFOAM-v1612+/etc/config. # 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 ++export FOAM_JOB_DIR=$HOME/.OpenFOAM/jobControl #SPACK: non-central location # wmake configuration export WM_DIR=$WM_PROJECT_DIR/wmake @@ -15,7 +15,7 @@ diff -uw OpenFOAM-v1612+.orig/etc/config.sh/settings OpenFOAM-v1612+/etc/config. # Site-specific directory -siteDir="${WM_PROJECT_SITE:-$WM_PROJECT_INST_DIR/site}" -+siteDir="${WM_PROJECT_SITE:-$WM_PROJECT/site}" #SPACK: not in parent directory ++siteDir="${WM_PROJECT_SITE:-$WM_PROJECT_DIR/site}" #SPACK: not in parent directory # Shared site executables/libraries # Similar naming convention as ~OpenFOAM expansion @@ -27,7 +27,7 @@ diff -uw OpenFOAM-v1612+.orig/etc/config.csh/settings OpenFOAM-v1612+/etc/config # 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 ++setenv FOAM_JOB_DIR=$HOME/.OpenFOAM/jobControl #SPACK: non-central location # wmake configuration setenv WM_DIR $WM_PROJECT_DIR/wmake diff --git a/var/spack/repos/builtin/packages/openfoam-com/openfoam-site-plus.patch b/var/spack/repos/builtin/packages/openfoam-com/openfoam-site-plus.patch new file mode 100644 index 0000000000..a1f5d8a08a --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-com/openfoam-site-plus.patch @@ -0,0 +1,35 @@ +diff -uw OpenFOAM-plus.orig/etc/config.sh/settings OpenFOAM-plus/etc/config.sh/settings +--- OpenFOAM-plus.orig/etc/config.sh/settings 2017-04-04 17:34:29.875873400 +0200 ++++ OpenFOAM-plus/etc/config.sh/settings 2017-04-04 17:38:40.174992466 +0200 +@@ -154,10 +154,10 @@ + export FOAM_LIBBIN=$WM_PROJECT_DIR/platforms/$WM_OPTIONS/lib + + # External (ThirdParty) libraries +-export FOAM_EXT_LIBBIN=$WM_THIRD_PARTY_DIR/platforms/$WM_ARCH$WM_COMPILER$WM_PRECISION_OPTION$WM_LABEL_OPTION/lib ++unset FOAM_EXT_LIBBIN #SPACK: none + + # Site-specific directory +-siteDir="${WM_PROJECT_SITE:-$WM_PROJECT_INST_DIR/site}" ++siteDir="${WM_PROJECT_SITE:-$WM_PROJECT_DIR/site}" #SPACK: not in parent directory + + # Shared site executables/libraries + # Similar naming convention as ~OpenFOAM expansion +diff -uw OpenFOAM-plus.orig/etc/config.csh/settings OpenFOAM-plus/etc/config.csh/settings +--- OpenFOAM-plus.orig/etc/config.csh/settings 2017-04-04 17:34:28.255879107 +0200 ++++ OpenFOAM-plus/etc/config.csh/settings 2017-04-04 17:39:22.214844670 +0200 +@@ -151,13 +151,13 @@ + setenv FOAM_LIBBIN $WM_PROJECT_DIR/platforms/$WM_OPTIONS/lib + + # External (ThirdParty) libraries +-setenv FOAM_EXT_LIBBIN $WM_THIRD_PARTY_DIR/platforms/$WM_ARCH$WM_COMPILER$WM_PRECISION_OPTION$WM_LABEL_OPTION/lib ++unsetenv FOAM_EXT_LIBBIN #SPACK: none + + # Site-specific directory + 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 index 15c4f8fdd4..c6dd6dbe9a 100644 --- a/var/spack/repos/builtin/packages/openfoam-com/package.py +++ b/var/spack/repos/builtin/packages/openfoam-com/package.py @@ -50,38 +50,74 @@ # variants: +plugins +qt # in ~/.spack/packages.yaml # +# Known issues # - Combining +zoltan with +int64 has not been tested, but probably won't work. +# - Combining +mgridgen with +int64 or +float32 probably won't work. # ############################################################################## from spack import * from spack.environment import * +import llnl.util.tty as tty import 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', + 'add_extra_files', 'write_environ', 'rewrite_environ_files', 'mplib_content', - 'generate_mplib_rules', - 'generate_compiler_rules', + 'foamAddPath', + 'foamAddLib', + 'OpenfoamArch', ] +def add_extra_files(foam_pkg, common, local, **kwargs): + """Copy additional common and local files into the stage.source_path + from the openfoam-com/common and the package/assets directories, + respectively + """ + outdir = foam_pkg.stage.source_path + + indir = join_path(os.path.dirname(__file__), 'common') + for f in common: + tty.info('Added file {0}'.format(f)) + install(join_path(indir, f), join_path(outdir, f)) + + indir = join_path(foam_pkg.package_dir, 'assets') + for f in local: + tty.info('Added file {0}'.format(f)) + install(join_path(indir, f), join_path(outdir, f)) + + def format_export(key, value): - """Format key,value pair as 'export' with newline for POSIX shell.""" - return 'export {0}={1}\n'.format(key, value) + """Format key,value pair as 'export' with newline for POSIX shell. + A leading '#' for key adds a comment character to the entire line. + A value of 'None' corresponds to 'unset'. + """ + if key.startswith('#'): + return '## export {0}={1}\n'.format(re.sub(r'^#+\s*', '', key), value) + elif value is None: + return 'unset {0}\n'.format(key) + else: + 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) + """Format key,value pair as 'setenv' with newline for C-shell. + A leading '#' for key adds a comment character to the entire line. + A value of 'None' corresponds to 'unsetenv'. + """ + if key.startswith('#'): + return '## setenv {0} {1}\n'.format(re.sub(r'^#+\s*', '', key), value) + elif value is None: + return 'unsetenv {0}\n'.format(key) + else: + return 'setenv {0} {1}\n'.format(key, value) def _write_environ_entries(outfile, environ, formatter): @@ -139,7 +175,7 @@ def rewrite_environ_files(environ, **kwargs): cshell[=None] If set, the name of the C-shell file to rewrite. """ posix = kwargs.get('posix', None) - if posix and isfile(posix): + if posix and os.path.isfile(posix): for k, v in environ.items(): filter_file( r'^(\s*export\s+%s)=.*$' % k, @@ -147,7 +183,7 @@ def rewrite_environ_files(environ, **kwargs): posix, backup=False) cshell = kwargs.get('cshell', None) - if cshell and isfile(cshell): + if cshell and os.path.isfile(cshell): for k, v in environ.items(): filter_file( r'^(\s*setenv\s+%s)\s+.*$' % k, @@ -156,19 +192,35 @@ def rewrite_environ_files(environ, **kwargs): backup=False) -def pkglib(package): - """Get lib64 or lib from package prefix""" +def foamAddPath(*args): + """A string with args prepended to 'PATH'""" + return '"' + ':'.join(args) + ':${PATH}"' + + +def foamAddLib(*args): + """A string with args prepended to 'LD_LIBRARY_PATH'""" + return '"' + ':'.join(args) + ':${LD_LIBRARY_PATH}"' + + +def pkglib(package, pre=None): + """Get lib64 or lib from package prefix. + + Optional parameter 'pre' to provide alternative prefix + """ libdir = package.prefix.lib64 - if isdir(libdir): + if not os.path.isdir(libdir): + libdir = package.prefix.lib + if pre: + return join_path(pre, os.path.basename(libdir)) + else: 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 + Optional parameter 'pre' to provide alternative prefix """ mpi_spec = spec['mpi'] bin = mpi_spec.prefix.bin @@ -194,36 +246,7 @@ def mplib_content(spec, pre=None): 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. @@ -239,31 +262,28 @@ class OpenfoamCom(Package): version('1612', 'ca02c491369150ab127cbb88ec60fbdf', url=baseurl + '/v1612+/OpenFOAM-v1612+.tgz') + version('plus', branch='develop', # Note: needs user credentials + git='https://develop.openfoam.com/Development/OpenFOAM-plus.git') variant('int64', default=False, - description='Compile with 64-bit labels') + description='Compile with 64-bit label') variant('float32', default=False, description='Compile with 32-bit scalar (single-precision)') variant('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') - + # TODO?# variant('scalasca', default=False, + # TODO?# description='With scalasca profiling') + variant('mgridgen', default=False, description='With mgridgen support') 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'} + variant('source', default=True, + description='Install library/application sources and tutorials') provides('openfoam') depends_on('mpi') @@ -275,12 +295,14 @@ class OpenfoamCom(Package): 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('scotch~metis+mpi~int64', when='+scotch~int64') + depends_on('scotch~metis+mpi+int64', when='+scotch+int64') depends_on('metis@5:', when='+metis') depends_on('metis+int64', when='+metis+int64') - depends_on('parmgridgen', when='+parmgridgen') + # mgridgen is statically linked + depends_on('parmgridgen', when='+mgridgen', type='build') depends_on('zoltan', when='+zoltan') + # TODO?# depends_on('scalasca', when='+scalasca') # For OpenFOAM plugins and run-time post-processing this should just be # 'paraview+plugins' but that resolves poorly. @@ -289,60 +311,64 @@ class OpenfoamCom(Package): # 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.0.1', when='@1612+paraview') depends_on('paraview@5.3:', when='@1706:+paraview') + depends_on('paraview@5.3:', when='@plus+paraview') # General patches - patch('openfoam-site.patch') + common = ['spack-Allwmake', 'README-spack'] + assets = [] # Version-specific patches patch('openfoam-bin-1612.patch', when='@1612') patch('openfoam-etc-1612.patch', when='@1612') + patch('openfoam-site-1612.patch', when='@1612') patch('openfoam-mpi-1612.patch', when='@1612') patch('openfoam-build-1612.patch', when='@1612') + patch('mgridgen-lib-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 - } + patch('openfoam-site-plus.patch', when='@plus') - # The system description is frequently needed - foam_sys = { - 'WM_ARCH': None, - 'WM_COMPILER': None, - 'WM_OPTIONS': None, + # Some user config settings + # default: 'compile-option': 'RpathOpt', + # default: 'mplib': 'USERMPI', # Use user mpi for spack + config = { + # Add links into bin/, lib/ (eg, for other applications) + 'link': False } + # The openfoam architecture, compiler information etc + _foam_arch = 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' + phases = ['configure', 'build', 'install'] + build_script = './spack-Allwmake' # <- Added by patch() method. - # 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')) + # + # - End of definitions / setup - + # def setup_environment(self, spack_env, run_env): + run_env.set('FOAM_PROJECT_DIR', self.projectdir) run_env.set('WM_PROJECT_DIR', self.projectdir) + for d in ['wmake', self.archbin]: # bin already added automatically + run_env.prepend_path('PATH', join_path(self.projectdir, d)) + run_env.set('MPI_BUFFER_SIZE', "20000000") + + def setup_dependent_environment(self, spack_env, run_env, dependent_spec): + """Provide location of the OpenFOAM project. + This is identical to the WM_PROJECT_DIR value, but we avoid that + variable since it would mask the normal OpenFOAM cleanup of + previous versions. + """ + spack_env.set('FOAM_PROJECT_DIR', self.projectdir) @property def projectdir(self): @@ -350,195 +376,50 @@ class OpenfoamCom(Package): return self.prefix # <- install directly under prefix @property - def etc(self): - """Absolute location of the OpenFOAM etc/ directory""" - return join_path(self.projectdir, 'etc') + def foam_arch(self): + if not self._foam_arch: + self._foam_arch = OpenfoamArch(self.spec, **self.config) + return self._foam_arch @property def archbin(self): """Relative location of architecture-specific executables""" - return join_path('platforms', self.wm_options, 'bin') + return join_path('platforms', self.foam_arch, 'bin') @property def archlib(self): """Relative location of architecture-specific libraries""" - return join_path('platforms', self.wm_options, 'lib') - - @property - def wm_options(self): - """The architecture+compiler+options for OpenFOAM""" - opts = self.set_openfoam() - return opts - - @property - def rpath_info(self): - """Define 'SPACKOpt' compiler optimization file to have wmake - use spack information with minimum modifications to OpenFOAM - """ - build_libpath = join_path(self.stage.source_path, self.archlib) - install_libpath = join_path(self.projectdir, self.archlib) - - # 'DBUG': rpaths - return '{0}{1} {2}{3}'.format( - self.compiler.cxx_rpath_arg, install_libpath, - self.compiler.cxx_rpath_arg, build_libpath) - - def openfoam_arch(self): - """Return an architecture value similar to what OpenFOAM does in - etc/config.sh/settings, but slightly more generous. - Uses and may adjust foam_cfg[WM_ARCH_OPTION] as a side-effect - """ - # spec.architecture.platform is like `uname -s`, but lower-case - platform = self.spec.architecture.platform - - # spec.architecture.target is like `uname -m` - target = self.spec.architecture.target - - if platform == 'linux': - if target == 'i686': - self.foam_cfg['WM_ARCH_OPTION'] = '32' # Force consistency - elif target == 'x86_64': - if self.foam_cfg['WM_ARCH_OPTION'] == '64': - platform += '64' - elif target == 'ia64': - platform += 'ia64' - elif target == 'armv7l': - platform += 'ARM7' - elif target == ppc64: - platform += 'PPC64' - elif target == ppc64le: - platform += 'PPC64le' - elif platform == 'darwin': - if target == 'x86_64': - platform += 'Intel' - if self.foam_cfg['WM_ARCH_OPTION'] == '64': - platform += '64' - # ... and others? - return platform - - def openfoam_compiler(self): - """Capitalized version of the compiler name, which usually corresponds - to how OpenFOAM will camel-case things. - Use compiler_mapping to handing special cases. - Also handle special compiler options (eg, KNL) - """ - comp = self.compiler.name - if comp in self.compiler_mapping: - comp = self.compiler_mapping[comp] - comp = comp.capitalize() - - if '+knl' in self.spec: - comp += 'KNL' - return comp - - def set_openfoam(self): - """Populate foam_cfg, foam_sys according to - variants, architecture, compiler. - Returns WM_OPTIONS. - """ - # Run once - opts = self.foam_sys['WM_OPTIONS'] - if opts: - return opts - - wm_arch = self.openfoam_arch() - wm_compiler = self.openfoam_compiler() - compileOpt = self.foam_cfg['WM_COMPILE_OPTION'] - - # Insist on a wmake rule for this architecture/compiler combination - archCompiler = wm_arch + wm_compiler - compiler_rule = join_path( - self.stage.source_path, 'wmake', 'rules', archCompiler) - - if not isdir(compiler_rule): - raise RuntimeError( - 'No wmake rule for {0}'.format(archCompiler)) - if not re.match(r'.+Opt$', compileOpt): - raise RuntimeError( - "WM_COMPILE_OPTION={0} is not type '*Opt'".format(compileOpt)) - - # Adjust for variants - self.foam_cfg['WM_LABEL_SIZE'] = ( - '64' if '+int64' in self.spec else '32' - ) - self.foam_cfg['WM_PRECISION_OPTION'] = ( - 'SP' if '+float32' in self.spec else 'DP' - ) - - # ---- - # WM_LABEL_OPTION=Int$WM_LABEL_SIZE - # WM_OPTIONS=$WM_ARCH$WM_COMPILER$WM_PRECISION_OPTION$WM_LABEL_OPTION$WM_COMPILE_OPTION - # ---- - self.foam_sys['WM_ARCH'] = wm_arch - self.foam_sys['WM_COMPILER'] = wm_compiler - self.foam_cfg['WM_COMPILER'] = wm_compiler # For bashrc,cshrc too - self.foam_sys['WM_OPTIONS'] = ''.join([ - wm_arch, - wm_compiler, - self.foam_cfg['WM_PRECISION_OPTION'], - 'Int', self.foam_cfg['WM_LABEL_SIZE'], # Int32/Int64 - compileOpt - ]) - return self.foam_sys['WM_OPTIONS'] + return join_path('platforms', self.foam_arch, 'lib') def patch(self): - """Adjust OpenFOAM build for spack. Where needed, apply filter as an - alternative to normal patching. - """ - self.set_openfoam() # May need foam_cfg/foam_sys information + """Adjust OpenFOAM build for spack. + Where needed, apply filter as an alternative to normal patching.""" + add_extra_files(self, self.common, self.assets) # Avoid WM_PROJECT_INST_DIR for ThirdParty, site or jobControl. # Use openfoam-site.patch to handle jobControl, site. # - # Filter (not patch) bashrc,cshrc for additional flexibility - wm_setting = { + # Filtering: bashrc,cshrc (using a patch is less flexible) + edits = { 'WM_THIRD_PARTY_DIR': r'$WM_PROJECT_DIR/ThirdParty #SPACK: No separate third-party', } - rewrite_environ_files( # Adjust etc/bashrc and etc/cshrc - wm_setting, + edits, 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) - + # Filtering bashrc, cshrc + edits = {} + edits.update(self.foam_arch.foam_dict()) rewrite_environ_files( # Adjust etc/bashrc and etc/cshrc - wm_setting, + edits, posix=join_path('etc', 'bashrc'), cshell=join_path('etc', 'cshrc')) @@ -551,27 +432,34 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR } # MPI content, using MPI_ARCH_PATH - content = mplib_content(spec, '${MPI_ARCH_PATH}') + user_mpi = 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, - }, + 'CGAL': [ + ('BOOST_ARCH_PATH', spec['boost'].prefix), + ('CGAL_ARCH_PATH', spec['cgal'].prefix), + ('LD_LIBRARY_PATH', + foamAddLib( + pkglib(spec['boost'], '${BOOST_ARCH_PATH}'), + pkglib(spec['cgal'], '${CGAL_ARCH_PATH}'))), + ], + 'FFTW': [ + ('FFTW_ARCH_PATH', spec['fftw'].prefix), # Absolute + ('LD_LIBRARY_PATH', + foamAddLib( + pkglib(spec['fftw'], '${BOOST_ARCH_PATH}'))), + ], # 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']), + ('LD_LIBRARY_PATH', foamAddLib(user_mpi['libdir'])), + ('PATH', foamAddPath(user_mpi['bindir'])), ], 'scotch': {}, 'metis': {}, 'paraview': [], + 'gperftools': [], # Currently unused } if '+scotch' in spec: @@ -590,15 +478,15 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR 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), + ('ParaView_INCLUDE_DIR', '${ParaView_DIR}/include/' + pvMajor), ('PV_PLUGIN_PATH', '$FOAM_LIBBIN/' + pvMajor), - ('PATH', '"${ParaView_DIR}/bin:${PATH}"'), + ('PATH', foamAddPath('${ParaView_DIR}/bin')), ] - # Not normally included as etc/config file - if '+parmgridgen' in spec: - self.etc_config['parmgridgen'] = { - 'PARMGRIDGEN_ARCH_PATH': spec['parmgridgen'].prefix + # Optional + if '+mgridgen' in spec: + self.etc_config['mgridgen'] = { + 'MGRIDGEN_ARCH_PATH': spec['parmgridgen'].prefix } # Optional @@ -622,45 +510,30 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR posix=join_path('etc', 'config.sh', component), cshell=join_path('etc', 'config.csh', component)) - archCompiler = self.foam_sys['WM_ARCH'] + self.foam_sys['WM_COMPILER'] - compileOpt = self.foam_cfg['WM_COMPILE_OPTION'] - general_rule = join_path('wmake', 'rules', 'General') - compiler_rule = join_path('wmake', 'rules', archCompiler) - generate_mplib_rules(general_rule, self.spec) - generate_compiler_rules(compiler_rule, compileOpt, self.rpath_info) - # Record the spack spec information - with open("log.spack-spec", 'w') as outfile: - outfile.write(spec.tree()) - def build(self, spec, prefix): """Build using the OpenFOAM Allwmake script, with a wrapper to source its environment first. + Only build if the compiler is known to be supported. """ - self.set_openfoam() # Force proper population of foam_cfg/foam_sys + self.foam_arch.has_rule(self.stage.source_path) + self.foam_arch.create_rules(self.stage.source_path, self) + args = ['-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 '')) + args.append('-j{0}'.format(make_jobs)) 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 - + """Install under the projectdir""" mkdirp(self.projectdir) projdir = os.path.basename(self.projectdir) - wm_setting = { + # Filtering: bashrc, cshrc + edits = { 'WM_PROJECT_INST_DIR': os.path.dirname(self.projectdir), 'WM_PROJECT_DIR': join_path('$WM_PROJECT_INST_DIR', projdir), } - # Retain build log file - out = "spack-build.out" - if isfile(out): - install(out, join_path(self.projectdir, "log." + opts)) - # All top-level files, except spack build info and possibly Allwmake if '+source' in spec: ignored = re.compile(r'^spack-.*') @@ -668,20 +541,23 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR ignored = re.compile(r'^(Allwmake|spack-).*') files = [ - f for f in glob.glob("*") if isfile(f) and not ignored.search(f) + f for f in glob.glob("*") + if os.path.isfile(f) and not ignored.search(f) ] for f in files: install(f, self.projectdir) - # Having wmake without sources is actually somewhat pointless... - dirs = ['bin', 'etc', 'wmake'] + # Having wmake and ~source is actually somewhat pointless... + # Install 'etc' before 'bin' (for symlinks) + dirs = ['etc', 'bin', 'wmake'] if '+source' in spec: dirs.extend(['applications', 'src', 'tutorials']) for d in dirs: install_tree( d, - join_path(self.projectdir, d)) + join_path(self.projectdir, d), + symlinks=True) dirs = ['platforms'] if '+source' in spec: @@ -693,30 +569,229 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR install_tree( d, join_path(self.projectdir, d), - ignore=shutil.ignore_patterns(*ignored)) + ignore=shutil.ignore_patterns(*ignored), + symlinks=True) + etc_dir = join_path(self.projectdir, 'etc') rewrite_environ_files( # Adjust etc/bashrc and etc/cshrc - wm_setting, - posix=join_path(self.etc, 'bashrc'), - cshell=join_path(self.etc, 'cshrc')) + edits, + posix=join_path(etc_dir, 'bashrc'), + cshell=join_path(etc_dir, 'cshrc')) self.install_links() def install_links(self): """Add symlinks into bin/, lib/ (eg, for other applications)""" - if not self.extra_symlinks: + # Make build log visible - it contains OpenFOAM-specific information + with working_dir(self.projectdir): + os.symlink( + join_path('.spack', 'build.out'), + join_path('log.' + str(self.foam_arch))) + + if not self.config['link']: return # ln -s platforms/linux64GccXXX/lib lib with working_dir(self.projectdir): - if isdir(self.archlib): + if os.path.isdir(self.archlib): os.symlink(self.archlib, 'lib') # (cd bin && ln -s ../platforms/linux64GccXXX/bin/* .) with working_dir(join_path(self.projectdir, 'bin')): for f in [ f for f in glob.glob(join_path('..', self.archbin, "*")) - if isfile(f) + if os.path.isfile(f) ]: os.symlink(f, os.path.basename(f)) + def openfoam_run_environment(self, projdir): + # This seems to bomb out with an ImportError 'site'! + # mods = EnvironmentModifications.from_sourcing_files( + # join_path(projdir, 'etc/bashrc')) + pass + + +# ----------------------------------------------------------------------------- + +class OpenfoamArch(object): + """OpenfoamArch represents architecture/compiler settings for OpenFOAM. + The string representation is WM_OPTIONS. + + Keywords + label-size=[True] supports int32/int64 + compile-option[=RpathOpt] + mplib[=USERMPI] + """ + + #: Map spack compiler names to OpenFOAM compiler names + # By default, simply capitalize the first letter + compiler_mapping = {'intel': 'icc'} + + def __init__(self, spec, **kwargs): + # Some user settings, to be adjusted manually or via variants + self.compiler = None # <- %compiler + self.arch_option = '64' # (32/64-bit on x86_64) + self.label_size = None # <- +int64 + self.precision_option = 'DP' # <- +float32 + self.compile_option = kwargs.get('compile-option', 'RpathOpt') + self.arch = None + self.options = None + self.rule = None + self.mplib = kwargs.get('mplib', 'USERMPI') + + # Normally support WM_LABEL_OPTION, but not yet for foam-extend + if '+int64' in spec: + self.label_size = '64' + elif kwargs.get('label-size', True): + self.label_size = '32' + + if '+float32' in spec: + self.precision_option = 'SP' + + # spec.architecture.platform is like `uname -s`, but lower-case + platform = spec.architecture.platform + + # spec.architecture.target is like `uname -m` + target = spec.architecture.target + + if platform == 'linux': + if target == 'i686': + self.arch_option = '32' # Force consistency + elif target == 'x86_64': + if self.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.arch_option == '64': + platform += '64' + # ... and others? + + self.arch = platform + + # 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 = spec.compiler.name + + if comp in self.compiler_mapping: + comp = self.compiler_mapping[comp] + comp = comp.capitalize() + + if '+knl' in spec: + comp += 'KNL' + self.compiler = comp + self.rule = self.arch + self.compiler + + # Build WM_OPTIONS + # ---- + # WM_LABEL_OPTION=Int$WM_LABEL_SIZE + # WM_OPTIONS=$WM_ARCH$WM_COMPILER$WM_PRECISION_OPTION$WM_LABEL_OPTION$WM_COMPILE_OPTION + # or + # WM_OPTIONS=$WM_ARCH$WM_COMPILER$WM_PRECISION_OPTION$WM_COMPILE_OPTION + # ---- + self.options = ''.join([ + self.rule, + self.precision_option, + ('Int' + self.label_size if self.label_size else ''), + self.compile_option]) + + def __str__(self): + return self.options + + def __repr__(self): + return str(self) + + def foam_dict(self): + """Returns a dictionary for OpenFOAM prefs, bashrc, cshrc.""" + return dict([ + ('WM_COMPILER', self.compiler), + ('WM_ARCH_OPTION', self.arch_option), + ('WM_LABEL_SIZE', self.label_size), + ('WM_PRECISION_OPTION', self.precision_option), + ('WM_COMPILE_OPTION', self.compile_option), + ('WM_MPLIB', self.mplib), + ]) + + def _rule_directory(self, projdir=None, general=False): + """The wmake/rules/ compiler directory""" + if general: + relative = os.path.join('wmake', 'rules', 'General') + else: + relative = os.path.join('wmake', 'rules', self.rule) + if projdir: + return os.path.join(projdir, relative) + else: + return relative + + def has_rule(self, projdir): + """Verify that a wmake/rules/ compiler rule exists in the project + directory. + """ + # Insist on a wmake rule for this architecture/compiler combination + rule_dir = self._rule_directory(projdir) + + if not os.path.isdir(rule_dir): + raise InstallError( + 'No wmake rule for {0}'.format(self.rule)) + if not re.match(r'.+Opt$', self.compile_option): + raise InstallError( + "WM_COMPILE_OPTION={0} is not type '*Opt'" + .format(self.compile_option)) + return True + + def create_rules(self, projdir, foam_pkg): + """ Create cRpathOpt,c++RpathOpt and mplibUSER,mplibUSERMPI + rules in the specified project directory. + The compiler rules are based on the respective cOpt,c++Opt rules + but with additional rpath information for the OpenFOAM libraries. + + The rpath rules allow wmake to use spack information with minimal + modification to OpenFOAM. + The rpath is used for the installed libpath (continue to use + LD_LIBRARY_PATH for values during the build). + """ + # Note: the 'c' rules normally don't need rpath, since they are just + # used for statically linked wmake utilities, but left in anyhow. + + # rpath for installed OpenFOAM libraries + rpath = '{0}{1}'.format( + foam_pkg.compiler.cxx_rpath_arg, + join_path(foam_pkg.projectdir, foam_pkg.archlib)) + + user_mpi = mplib_content(foam_pkg.spec) + rule_dir = self._rule_directory(projdir) + + with working_dir(rule_dir): + # Compiler: copy existing cOpt,c++Opt and modify '*DBUG' value + for lang in ['c', 'c++']: + src = '{0}Opt'.format(lang) + dst = '{0}{1}'.format(lang, self.compile_option) + with open(src, 'r') as infile: + with open(dst, 'w') as outfile: + for line in infile: + line = line.rstrip() + outfile.write(line) + if re.match(r'^\S+DBUG\s*=', line): + outfile.write(' ') + outfile.write(rpath) + outfile.write('\n') + + # MPI rules + 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(**user_mpi)) + # ----------------------------------------------------------------------------- diff --git a/var/spack/repos/builtin/packages/openfoam-org/assets/bin/foamEtcFile b/var/spack/repos/builtin/packages/openfoam-org/assets/bin/foamEtcFile new file mode 100755 index 0000000000..294cc26505 --- /dev/null +++ b/var/spack/repos/builtin/packages/openfoam-org/assets/bin/foamEtcFile @@ -0,0 +1,417 @@ +#!/bin/sh +#------------------------------------------------------------------------------ +# ========= | +# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox +# \\ / O peration | +# \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation +# \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. +#------------------------------------------------------------------------------- +# License +# This file is part of OpenFOAM. +# +# OpenFOAM is free software: you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# OpenFOAM 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 GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License +# along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. +# +# Script +# foamEtcFile +# +# Description +# Locate user/group/other files with semantics similar to the +# ~OpenFOAM/fileName expansion. +# +# The -mode option can be used to allow chaining from +# personal settings to site-wide settings. +# +# For example, within the user ~/.OpenFOAM/<VER>/prefs.sh: +# \code +# 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 one of these locations: +# - $WM_PROJECT_INST_DIR/OpenFOAM-<VERSION>/bin +# - $WM_PROJECT_INST_DIR/openfoam-<VERSION>/bin +# - $WM_PROJECT_INST_DIR/OpenFOAM+<VERSION>/bin +# - $WM_PROJECT_INST_DIR/openfoam+<VERSION>/bin +# - $WM_PROJECT_INST_DIR/openfoam<VERSION>/bin (debian version) +# +#------------------------------------------------------------------------------- +unset optQuiet optSilent +usage() { + [ "${optQuiet:-$optSilent}" = true ] && exit 1 + exec 1>&2 + while [ "$#" -ge 1 ]; do echo "$1"; shift; done + cat<<USAGE + +Usage: foamEtcFile [OPTION] fileName + foamEtcFile [OPTION] [-list|-list-test] [fileName] + +options: + -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/other file with semantics similar to the +~OpenFOAM/fileName expansion. + +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. + 1 for miscellaneous errors. + 2 when the file is not found. + +USAGE + 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 +} + +#------------------------------------------------------------------------------- +binDir="${0%/*}" # The bin dir +projectDir="${binDir%/bin}" # The project dir +prefixDir="${projectDir%/*}" # The prefix dir (same as $WM_PROJECT_INST_DIR) + +# Could not resolve projectDir, prefixDir? (eg, called as ./bin/foamEtcFile) +if [ "$prefixDir" = "$projectDir" ] +then + binDir="$(cd $binDir && pwd -L)" + projectDir="${binDir%/bin}" + prefixDir="${projectDir%/*}" +fi +projectDirName="${projectDir##*/}" # The project directory name + +projectVersion="$WM_PROJECT_VERSION" # Empty? - will be treated later +userDir="$HOME/.OpenFOAM" # Hard-coded as per foamVersion.H + +#------------------------------------------------------------------------------- + +# Guess project version or simply get the stem part of the projectDirName. +# Handle standard and debian naming conventions. +# +# - projectVersion: update unless already set +# +# Helper variables: +# - dirBase (for reassembling name) == projectDirName without the version +# - versionNum (debian packaging) +unset dirBase versionNum +guessVersion() +{ + local version + + case "$projectDirName" in + (OpenFOAM-* | openfoam-*) + # Standard naming: OpenFOAM-<VERSION> or openfoam-<VERSION> + dirBase="${projectDirName%%-*}-" + version="${projectDirName#*-}" + version="${version%%*-}" # Extra safety, eg openfoam-version-packager + ;; + + (OpenFOAM+* | openfoam+*) + # Alternative naming: OpenFOAM+<VERSION> or openfoam+<VERSION> + dirBase="${projectDirName%%+*}+" + version="${projectDirName#*+}" + version="${version%%*-}" # Extra safety, eg openfoam-version-packager + ;; + + (openfoam[0-9]*) + # Debian naming: openfoam<VERSION> + 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 + ;; + + (*) + 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}" +} + + +optMode=ugo # Default mode is always 'ugo' +unset optAll optList optShell optVersion + +# Parse options +while [ "$#" -gt 0 ] +do + case "$1" in + -h | -help) + usage + ;; + -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) + optMode="$2" + shift + # Sanity check. Handles missing argument too. + case "$optMode" in + ([ugo]*) + ;; + (*) + die "invalid mode '$optMode'" + ;; + esac + ;; + -p | -prefix) + [ "$#" -ge 2 ] || die "'$1' option requires an argument" + prefixDir="${2%/}" + shift + ;; + -q | -quiet) + optQuiet=true + ;; + -s | -silent) + optSilent=true + ;; + -v | -version) + [ "$#" -ge 2 ] || die "'$1' option requires an argument" + optVersion="$2" + shift + ;; + --) + shift + break + ;; + -*) + die "unknown option: '$1'" + ;; + *) + break + ;; + esac + shift +done + + +#------------------------------------------------------------------------------- + +if [ -n "$optVersion" ] +then + setVersion $optVersion +elif [ -z "$projectVersion" ] +then + guessVersion +fi + +# Updates: +# - projectDir for changes via -prefix or -version +# - groupDir for changes via -prefix +projectDir="$prefixDir/$projectDirName" +groupDir="${WM_PROJECT_SITE:-$prefixDir/site}" + + +# Debugging: +# echo "Installed locations:" 1>&2 +# for i in projectDir prefixDir projectDirName projectVersion +# do +# eval echo "$i=\$$i" 1>&2 +# done + + +# Save the essential bits of information +# silently remove leading ~OpenFOAM/ (used in Foam::findEtcFile) +nArgs=$# +fileName="${1#~OpenFOAM/}" + +# Define the various places to be searched: +unset dirList +case "$optMode" in (*u*) # (U)ser + dirList="$dirList $userDir/$projectVersion $userDir" + ;; +esac + +case "$optMode" in (*g*) # (G)roup == site + dirList="$dirList $groupDir/$projectVersion $groupDir" + ;; +esac + +case "$optMode" in (*o*) # (O)ther == shipped + dirList="$dirList $projectDir/etc" + ;; +esac +set -- $dirList + + +# +# The main routine +# + +exitCode=0 +if [ -n "$optList" ] +then + + # 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 + + # 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 + resolved="$dir/$fileName" + if [ -f "$resolved" ] + then + 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 ] || die "One filename expected - $nArgs provided" + + exitCode=2 # Fallback to a general error (file not found) + + for dir + do + if [ -f "$dir/$fileName" ] + then + exitCode=0 + [ -n "$optQuiet" ] && break + + case "$optShell" in + (*verbose) + echo "Using: $dir/$fileName" 1>&2 + ;; + esac + + case "$optShell" in + csh*) + echo "source $dir/$fileName" + break + ;; + sh*) + echo ". $dir/$fileName" + break + ;; + *) + echo "$dir/$fileName" + [ -n "$optAll" ] || break + ;; + esac + fi + done + +fi + +exit $exitCode + +#------------------------------------------------------------------------------ diff --git a/var/spack/repos/builtin/packages/openfoam-org/openfoam-site.patch b/var/spack/repos/builtin/packages/openfoam-org/openfoam-site-41.patch index 6631025788..d988c2f9b8 100644 --- a/var/spack/repos/builtin/packages/openfoam-org/openfoam-site.patch +++ b/var/spack/repos/builtin/packages/openfoam-org/openfoam-site-41.patch @@ -6,7 +6,7 @@ diff -uw OpenFOAM-v1612+.orig/etc/config.sh/settings OpenFOAM-v1612+/etc/config. # 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 ++export FOAM_JOB_DIR=$HOME/.OpenFOAM/jobControl #SPACK: non-central location # wmake configuration export WM_DIR=$WM_PROJECT_DIR/wmake @@ -15,7 +15,7 @@ diff -uw OpenFOAM-v1612+.orig/etc/config.sh/settings OpenFOAM-v1612+/etc/config. # Site-specific directory -siteDir="${WM_PROJECT_SITE:-$WM_PROJECT_INST_DIR/site}" -+siteDir="${WM_PROJECT_SITE:-$WM_PROJECT/site}" #SPACK: not in parent directory ++siteDir="${WM_PROJECT_SITE:-$WM_PROJECT_DIR/site}" #SPACK: not in parent directory # Shared site executables/libraries # Similar naming convention as ~OpenFOAM expansion @@ -27,7 +27,7 @@ diff -uw OpenFOAM-v1612+.orig/etc/config.csh/settings OpenFOAM-v1612+/etc/config # 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 ++setenv FOAM_JOB_DIR=$HOME/.OpenFOAM/jobControl #SPACK: non-central location # wmake configuration setenv WM_DIR $WM_PROJECT_DIR/wmake diff --git a/var/spack/repos/builtin/packages/openfoam-org/package.py b/var/spack/repos/builtin/packages/openfoam-org/package.py index 53be5f6337..02c27a0db5 100644 --- a/var/spack/repos/builtin/packages/openfoam-org/package.py +++ b/var/spack/repos/builtin/packages/openfoam-org/package.py @@ -44,22 +44,23 @@ # entirely clear and thus untested. # - Resolution of flex, zlib needs more attention (within OpenFOAM) # -# - mpi handling: WM_MPLIB=SYSTEMMPI and use spack to populate the prefs.sh -# for it. -# Also provide wmake rules for special purpose 'USER' and 'USERMPI' +# - mpi handling: WM_MPLIB=SYSTEMMPI and use spack to populate prefs.sh for it. +# Provide wmake rules for special purpose 'USER' and 'USERMPI' # mpi implementations, in case these are required. # +# Known issues +# - Combining +zoltan with +int64 has not been tested, but probably won't work. +# - Combining +mgridgen with +int64 or +float32 probably won't work. +# ############################################################################## from spack import * from spack.environment import * import llnl.util.tty as tty -import multiprocessing import glob import re import shutil import os -from os.path import isdir, isfile from spack.pkg.builtin.openfoam_com import * @@ -78,19 +79,15 @@ class OpenfoamOrg(Package): version('4.1', '318a446c4ae6366c7296b61184acd37c', url=baseurl + '/OpenFOAM-4.x/archive/version-4.1.tar.gz') + version('dev', git='https://github.com/OpenFOAM/OpenFOAM-dev.git') variant('int64', default=False, - description='Compile with 64-bit labels') + description='Compile with 64-bit label') variant('float32', default=False, description='Compile with 32-bit scalar (single-precision)') - variant('source', default=True, description='Install library/application sources and tutorials') - #: Map spack compiler names to OpenFOAM compiler names - # By default, simply capitalize the first letter - compiler_mapping = {'intel': 'icc'} - provides('openfoam') depends_on('mpi') depends_on('zlib') @@ -98,31 +95,26 @@ class OpenfoamOrg(Package): depends_on('cmake', type='build') # Require scotch with ptscotch - corresponds to standard OpenFOAM setup - depends_on('scotch~int64+mpi', when='~int64') - depends_on('scotch+int64+mpi', when='+int64') + depends_on('scotch~metis+mpi~int64', when='~int64') + depends_on('scotch~metis+mpi+int64', when='+int64') - # General patches - patch('openfoam-site.patch') + # General patches - foamEtcFile as per openfoam.com (robuster) + common = ['spack-Allwmake', 'README-spack'] + assets = ['bin/foamEtcFile'] # Version-specific patches - patch('openfoam-etc-41.patch') - - # Some user settings, to be adjusted manually or via variants - foam_cfg = { - 'WM_COMPILER': 'Gcc', # <- %compiler - 'WM_ARCH_OPTION': '64', # (32/64-bit on x86_64) - 'WM_LABEL_SIZE': '32', # <- +int64 - 'WM_PRECISION_OPTION': 'DP', # <- +float32 - 'WM_COMPILE_OPTION': 'SPACKOpt', # Do not change - 'WM_MPLIB': 'SYSTEMMPI', # Use system mpi for spack + patch('openfoam-etc-41.patch', when='@4.1') + patch('openfoam-site-41.patch', when='@4.1') + + # Some user config settings + config = { + 'mplib': 'SYSTEMMPI', # Use system mpi for spack + # Add links into bin/, lib/ (eg, for other applications) + 'link': False } - # The system description is frequently needed - foam_sys = { - 'WM_ARCH': None, - 'WM_COMPILER': None, - 'WM_OPTIONS': None, - } + # The openfoam architecture, compiler information etc + _foam_arch = None # Content for etc/prefs.{csh,sh} etc_prefs = {} @@ -130,236 +122,111 @@ class OpenfoamOrg(Package): # Content for etc/config.{csh,sh}/ files etc_config = {} - build_script = './spack-Allwmake' # <- Generated by patch() method. - # phases = ['configure', 'build', 'install'] - # build_system_class = 'OpenfoamCom' + phases = ['configure', 'build', 'install'] + build_script = './spack-Allwmake' # <- Added by patch() method. - # Add symlinks into bin/, lib/ (eg, for other applications) - extra_symlinks = False + # + # - End of definitions / setup - + # def setup_environment(self, spack_env, run_env): + run_env.set('FOAM_PROJECT_DIR', self.projectdir) run_env.set('WM_PROJECT_DIR', self.projectdir) - - @property - def _canonical(self): - """Canonical name for this package and version""" - return 'OpenFOAM-{0}'.format(self.version) + for d in ['wmake', self.archbin]: # bin already added automatically + run_env.prepend_path('PATH', join_path(self.projectdir, d)) + run_env.set('MPI_BUFFER_SIZE', "20000000") + + def setup_dependent_environment(self, spack_env, run_env, dependent_spec): + """Provide location of the OpenFOAM project. + This is identical to the WM_PROJECT_DIR value, but we avoid that + variable since it would mask the normal OpenFOAM cleanup of + previous versions. + """ + spack_env.set('FOAM_PROJECT_DIR', self.projectdir) @property def projectdir(self): """Absolute location of project directory: WM_PROJECT_DIR/""" - return join_path(self.prefix, self._canonical) # <- prefix/canonical + return self.prefix # <- install directly under prefix @property - def etc(self): - """Absolute location of the OpenFOAM etc/ directory""" - return join_path(self.projectdir, 'etc') + def foam_arch(self): + if not self._foam_arch: + self._foam_arch = OpenfoamArch(self.spec, **self.config) + return self._foam_arch @property def archbin(self): """Relative location of architecture-specific executables""" - return join_path('platforms', self.wm_options, 'bin') + return join_path('platforms', self.foam_arch, 'bin') @property def archlib(self): """Relative location of architecture-specific libraries""" - return join_path('platforms', self.wm_options, 'lib') - - @property - def wm_options(self): - """The architecture+compiler+options for OpenFOAM""" - opts = self.set_openfoam() - return opts - - @property - def rpath_info(self): - """Define 'SPACKOpt' compiler optimization file to have wmake - use spack information with minimum modifications to OpenFOAM - """ - build_libpath = join_path(self.stage.source_path, self.archlib) - install_libpath = join_path(self.projectdir, self.archlib) - - # 'DBUG': rpaths - return '{0}{1} {2}{3}'.format( - self.compiler.cxx_rpath_arg, install_libpath, - self.compiler.cxx_rpath_arg, build_libpath) - - def openfoam_arch(self): - """Return an architecture value similar to what OpenFOAM does in - etc/config.sh/settings, but slightly more generous. - Uses and may adjust foam_cfg[WM_ARCH_OPTION] as a side-effect - """ - # spec.architecture.platform is like `uname -s`, but lower-case - platform = self.spec.architecture.platform - - # spec.architecture.target is like `uname -m` - target = self.spec.architecture.target - - if platform == 'linux': - if target == 'i686': - self.foam_cfg['WM_ARCH_OPTION'] = '32' # Force consistency - elif target == 'x86_64': - if self.foam_cfg['WM_ARCH_OPTION'] == '64': - platform += '64' - elif target == 'ia64': - platform += 'ia64' - elif target == 'armv7l': - platform += 'ARM7' - elif target == ppc64: - platform += 'PPC64' - elif target == ppc64le: - platform += 'PPC64le' - elif platform == 'darwin': - if target == 'x86_64': - platform += 'Intel' - if self.foam_cfg['WM_ARCH_OPTION'] == '64': - platform += '64' - # ... and others? - return platform - - def openfoam_compiler(self): - """Capitalized version of the compiler name, which usually corresponds - to how OpenFOAM will camel-case things. - Use compiler_mapping to handing special cases. - Also handle special compiler options (eg, KNL) - """ - comp = self.compiler.name - if comp in self.compiler_mapping: - comp = self.compiler_mapping[comp] - comp = comp.capitalize() - - if '+knl' in self.spec: - comp += 'KNL' - return comp - - def set_openfoam(self): - """Populate foam_cfg, foam_sys according to - variants, architecture, compiler. - Returns WM_OPTIONS. - """ - # Run once - opts = self.foam_sys['WM_OPTIONS'] - if opts: - return opts - - wm_arch = self.openfoam_arch() - wm_compiler = self.openfoam_compiler() - compileOpt = self.foam_cfg['WM_COMPILE_OPTION'] - - # Insist on a wmake rule for this architecture/compiler combination - archCompiler = wm_arch + wm_compiler - compiler_rule = join_path( - self.stage.source_path, 'wmake', 'rules', archCompiler) - - if not isdir(compiler_rule): - raise RuntimeError( - 'No wmake rule for {0}'.format(archCompiler)) - if not re.match(r'.+Opt$', compileOpt): - raise RuntimeError( - "WM_COMPILE_OPTION={0} is not type '*Opt'".format(compileOpt)) - - # Adjust for variants - self.foam_cfg['WM_LABEL_SIZE'] = ( - '64' if '+int64' in self.spec else '32' - ) - self.foam_cfg['WM_PRECISION_OPTION'] = ( - 'SP' if '+float32' in self.spec else 'DP' - ) - - # ---- - # WM_LABEL_OPTION=Int$WM_LABEL_SIZE - # WM_OPTIONS=$WM_ARCH$WM_COMPILER$WM_PRECISION_OPTION$WM_LABEL_OPTION$WM_COMPILE_OPTION - # ---- - self.foam_sys['WM_ARCH'] = wm_arch - self.foam_sys['WM_COMPILER'] = wm_compiler - self.foam_cfg['WM_COMPILER'] = wm_compiler # For bashrc,cshrc too - self.foam_sys['WM_OPTIONS'] = ''.join([ - wm_arch, - wm_compiler, - self.foam_cfg['WM_PRECISION_OPTION'], - 'Int', self.foam_cfg['WM_LABEL_SIZE'], # Int32/Int64 - compileOpt - ]) - return self.foam_sys['WM_OPTIONS'] + return join_path('platforms', self.foam_arch, 'lib') - def patch(self): - """Adjust OpenFOAM build for spack. Where needed, apply filter as an - alternative to normal patching. + def rename_source(self): + """This is fairly horrible. + The github tarfiles have weird names that do not correspond to the + canonical name. We need to rename these, but leave a symlink for + spack to work with. """ - self.set_openfoam() # May need foam_cfg/foam_sys information - - # This is fairly horrible. - # The github tarfiles have weird names that do not correspond to the - # canonical name. We need to rename these, but leave a symlink for - # spack to work with. - # - # Note that this particular OpenFOAM release requires absolute - # directories to build correctly! + # Note that this particular OpenFOAM requires absolute directories + # to build correctly! parent = os.path.dirname(self.stage.source_path) original = os.path.basename(self.stage.source_path) - target = self._canonical + target = 'OpenFOAM-{0}'.format(self.version) + # Could also grep through etc/bashrc for WM_PROJECT_VERSION with working_dir(parent): if original != target and not os.path.lexists(target): os.rename(original, target) os.symlink(target, original) tty.info('renamed {0} -> {1}'.format(original, target)) + def patch(self): + """Adjust OpenFOAM build for spack. + Where needed, apply filter as an alternative to normal patching.""" + self.rename_source() + add_extra_files(self, self.common, self.assets) + # Avoid WM_PROJECT_INST_DIR for ThirdParty, site or jobControl. # Use openfoam-site.patch to handle jobControl, site. # - # Filter (not patch) bashrc,cshrc for additional flexibility - wm_setting = { + # Filtering: bashrc,cshrc (using a patch is less flexible) + edits = { 'WM_THIRD_PARTY_DIR': r'$WM_PROJECT_DIR/ThirdParty #SPACK: No separate third-party', 'WM_VERSION': self.version, # consistency 'FOAMY_HEX_MESH': '', # This is horrible (unset variable?) } - rewrite_environ_files( # Adjust etc/bashrc and etc/cshrc - wm_setting, + edits, posix=join_path('etc', 'bashrc'), cshell=join_path('etc', 'cshrc')) - # Build wrapper script - with open(self.build_script, 'w') as out: - out.write( - """#!/bin/bash -. $PWD/etc/bashrc '' # No arguments -mkdir -p $FOAM_APPBIN $FOAM_LIBBIN 2>/dev/null # Allow interrupt -echo Build openfoam with SPACK -echo WM_PROJECT_DIR = $WM_PROJECT_DIR -./Allwmake $@ -# -""") - set_executable(self.build_script) - self.configure(self.spec, self.prefix) # Should be a separate phase - def configure(self, spec, prefix): """Make adjustments to the OpenFOAM configuration files in their various locations: etc/bashrc, etc/config.sh/FEATURE and customizations that don't properly fit get placed in the etc/prefs.sh file (similiarly for csh). """ - self.set_openfoam() # Need foam_cfg/foam_sys information - - # Some settings for filtering bashrc, cshrc - wm_setting = {} - wm_setting.update(self.foam_cfg) - + # Filtering bashrc, cshrc + edits = {} + edits.update(self.foam_arch.foam_dict()) rewrite_environ_files( # Adjust etc/bashrc and etc/cshrc - wm_setting, + edits, posix=join_path('etc', 'bashrc'), cshell=join_path('etc', 'cshrc')) # MPI content, with absolute paths - content = mplib_content(spec) + user_mpi = mplib_content(spec) # Content for etc/prefs.{csh,sh} self.etc_prefs = { r'MPI_ROOT': spec['mpi'].prefix, # Absolute - r'MPI_ARCH_FLAGS': '"%s"' % content['FLAGS'], - r'MPI_ARCH_INC': '"%s"' % content['PINC'], - r'MPI_ARCH_LIBS': '"%s"' % content['PLIBS'], + r'MPI_ARCH_FLAGS': '"%s"' % user_mpi['FLAGS'], + r'MPI_ARCH_INC': '"%s"' % user_mpi['PINC'], + r'MPI_ARCH_LIBS': '"%s"' % user_mpi['PLIBS'], } # Content for etc/config.{csh,sh}/ files @@ -368,6 +235,7 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR 'scotch': {}, 'metis': {}, 'paraview': [], + 'gperftools': [], # Currently unused } if True: @@ -392,45 +260,30 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR posix=join_path('etc', 'config.sh', component), cshell=join_path('etc', 'config.csh', component)) - archCompiler = self.foam_sys['WM_ARCH'] + self.foam_sys['WM_COMPILER'] - compileOpt = self.foam_cfg['WM_COMPILE_OPTION'] - general_rule = join_path('wmake', 'rules', 'General') - compiler_rule = join_path('wmake', 'rules', archCompiler) - generate_mplib_rules(general_rule, self.spec) - generate_compiler_rules(compiler_rule, compileOpt, self.rpath_info) - # Record the spack spec information - with open("log.spack-spec", 'w') as outfile: - outfile.write(spec.tree()) - def build(self, spec, prefix): """Build using the OpenFOAM Allwmake script, with a wrapper to source its environment first. + Only build if the compiler is known to be supported. """ - self.set_openfoam() # Force proper population of foam_cfg/foam_sys + self.foam_arch.has_rule(self.stage.source_path) + self.foam_arch.create_rules(self.stage.source_path, self) + args = [] if self.parallel: # Build in parallel? - pass via the environment - os.environ['WM_NCOMPPROCS'] = str(self.make_jobs) \ - if self.make_jobs else str(multiprocessing.cpu_count()) + os.environ['WM_NCOMPPROCS'] = str(make_jobs) builder = Executable(self.build_script) builder(*args) def install(self, spec, prefix): - """Install under the projectdir (== prefix/name-version)""" - self.build(spec, prefix) # Should be a separate phase - opts = self.wm_options - + """Install under the projectdir""" mkdirp(self.projectdir) projdir = os.path.basename(self.projectdir) - wm_setting = { + # Filtering: bashrc, cshrc + edits = { 'WM_PROJECT_INST_DIR': os.path.dirname(self.projectdir), 'WM_PROJECT_DIR': join_path('$WM_PROJECT_INST_DIR', projdir), } - # Retain build log file - out = "spack-build.out" - if isfile(out): - install(out, join_path(self.projectdir, "log." + opts)) - # All top-level files, except spack build info and possibly Allwmake if '+source' in spec: ignored = re.compile(r'^spack-.*') @@ -438,20 +291,23 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR ignored = re.compile(r'^(Allwmake|spack-).*') files = [ - f for f in glob.glob("*") if isfile(f) and not ignored.search(f) + f for f in glob.glob("*") + if os.path.isfile(f) and not ignored.search(f) ] for f in files: install(f, self.projectdir) - # Having wmake without sources is actually somewhat pointless... - dirs = ['bin', 'etc', 'wmake'] + # Having wmake and ~source is actually somewhat pointless... + # Install 'etc' before 'bin' (for symlinks) + dirs = ['etc', 'bin', 'wmake'] if '+source' in spec: dirs.extend(['applications', 'src', 'tutorials']) for d in dirs: install_tree( d, - join_path(self.projectdir, d)) + join_path(self.projectdir, d), + symlinks=True) dirs = ['platforms'] if '+source' in spec: @@ -463,29 +319,37 @@ echo WM_PROJECT_DIR = $WM_PROJECT_DIR install_tree( d, join_path(self.projectdir, d), - ignore=shutil.ignore_patterns(*ignored)) + ignore=shutil.ignore_patterns(*ignored), + symlinks=True) + etc_dir = join_path(self.projectdir, 'etc') rewrite_environ_files( # Adjust etc/bashrc and etc/cshrc - wm_setting, - posix=join_path(self.etc, 'bashrc'), - cshell=join_path(self.etc, 'cshrc')) + edits, + posix=join_path(etc_dir, 'bashrc'), + cshell=join_path(etc_dir, 'cshrc')) self.install_links() def install_links(self): """Add symlinks into bin/, lib/ (eg, for other applications)""" - if not self.extra_symlinks: + # Make build log visible - it contains OpenFOAM-specific information + with working_dir(self.projectdir): + os.symlink( + join_path('.spack', 'build.out'), + join_path('log.' + str(self.foam_arch))) + + if not self.config['link']: return # ln -s platforms/linux64GccXXX/lib lib with working_dir(self.projectdir): - if isdir(self.archlib): + if os.path.isdir(self.archlib): os.symlink(self.archlib, 'lib') # (cd bin && ln -s ../platforms/linux64GccXXX/bin/* .) with working_dir(join_path(self.projectdir, 'bin')): for f in [ f for f in glob.glob(join_path('..', self.archbin, "*")) - if isfile(f) + if os.path.isfile(f) ]: os.symlink(f, os.path.basename(f)) |