refactor openfoam packages (#3669)

* Several improvements for the openfoam packages

--

Refactor openfoam packages by adding an OpenfoamArch class

Use separate configure, build, install phases.

Provide FOAM_PROJECT_DIR dependent env for openfoam packages
- easier way to locate

Eliminate intermediate installation directories
- unneeded clutter.
- makes it less than easy to find the etc/bashrc file

Add versioning for all openfoam patches
- no certainty which parts (if any) will be needed in future versions,
  especially if we strive to ensure that the upstream version builds
  well with spack to begin with.

Support build of develop branches
- helps track build regressions for future openfoam releases

STYLE: use common/ and assets/ to provide additional (build) resources ...

* - adjust OpenFOAM provider

Move openfoam-com up front since this is the one being used as a base
for the others
This commit is contained in:
Mark Olesen
2017-06-21 17:35:31 +01:00
committed by Adam J. Stewart
parent b1fceb75d0
commit 1f2e56e1f3
15 changed files with 1313 additions and 754 deletions

View File

@@ -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
#------------------------------------------------------------------------------

View File

@@ -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

View File

@@ -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')
patch('openfoam-etc-41.patch', when='@4.1')
patch('openfoam-site-41.patch', when='@4.1')
# 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
# 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)
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")
@property
def _canonical(self):
"""Canonical name for this package and version"""
return 'OpenFOAM-{0}'.format(self.version)
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')
return join_path('platforms', self.foam_arch, '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
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.
"""
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!
# 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 @@ def configure(self, spec, prefix):
'scotch': {},
'metis': {},
'paraview': [],
'gperftools': [], # Currently unused
}
if True:
@@ -392,45 +260,30 @@ def configure(self, spec, prefix):
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 @@ def install(self, spec, prefix):
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 @@ def install(self, spec, prefix):
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))