support OpenFOAM package(s) (#3528)
* ENH: add package for building OpenFOAM (1612) from www.openfoam.com - provide 'openfoam' as virtual package. - package as openfoam-com to reflect the distribution point. This initial spack packaging for OpenFOAM supports a number of possible variants and should handle 64-bit labels properly now that the scotch package has been updated accordingly. * ENH: update package for foam-extend (extend-project.de) - provide 'openfoam' as virtual package. - much of the build is now aligned with how the openfoam-com package looks, with the aim of future refactoring. - avoid installing intermediate targets. - contains its own environment sourcing script for the build, for more flexibility and robustness (doesn't touch the python build environ) * ENH: added package for building from openfoam.org - provide 'openfoam' as a virtual package. - this is largely a direct copy of the openfoam-com package. It has been supplied as a courtesy for users and to ensure maximum consistency in quality and naming between the foam-extend, openfoam-com and openfoam-org packages. * CONFIG: add openfoam into bash completion providers list * ENH: have openfoam-com use spack as USERMPI - also simplify the generation of mplib/compiler rules * ENH: have openfoam-org use spack as SYSTEMMPI - this setup requires more environment settings than USERMPI (openfoam-com), but is currently the only means of integration for openfoam-org - simplify generation of mplib/compiler rules * ENH: simplify generation of mplib/compiler rules (foam-extend) - rename mpi rules from SPACK,SPACKMPI to USER,USERMPI for consistency with openfoam-com and to generalize for any build system. * STYLE: record spack tree as a log file (openfoam) - can be useful for future diagnostics and general record keeping
This commit is contained in:

committed by
Todd Gamblin

parent
2bd216a6a1
commit
9e1abb13dc
@@ -9,6 +9,8 @@
|
||||
# For details, see https://github.com/llnl/spack
|
||||
# Please also see the LICENSE file for our notice and the LGPL.
|
||||
#
|
||||
# License
|
||||
# -------
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License (as
|
||||
# published by the Free Software Foundation) version 2.1, February 1999.
|
||||
@@ -21,17 +23,51 @@
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# Legal Notice
|
||||
# ------------
|
||||
# OPENFOAM is a trademark owned by OpenCFD Ltd
|
||||
# (producer and distributor of the OpenFOAM software via www.openfoam.com).
|
||||
# The trademark information must remain visible and unadulterated in this
|
||||
# file and via the "spack info" and comply with the term set by
|
||||
# http://openfoam.com/legal/trademark-policy.php
|
||||
#
|
||||
# This file is not part of OpenFOAM, nor does it constitute a component of an
|
||||
# OpenFOAM distribution.
|
||||
#
|
||||
##############################################################################
|
||||
#
|
||||
# Notes
|
||||
# - mpi handling: WM_MPLIB=USER and provide wmake rules for special purpose
|
||||
# 'USER and 'USERMPI' mpi implementations.
|
||||
# The choice of 'USER' vs 'USERMPI' may change in the future.
|
||||
#
|
||||
# Changes
|
||||
# 2017-03-28 Mark Olesen <mark.olesen@esi-group.com>
|
||||
# - avoid installing intermediate targets.
|
||||
# - reworked to mirror the openfoam-com package.
|
||||
# If changes are needed here, consider if they need applying there too.
|
||||
#
|
||||
##############################################################################
|
||||
from spack import *
|
||||
from spack.environment import *
|
||||
|
||||
import multiprocessing
|
||||
import glob
|
||||
import re
|
||||
import shutil
|
||||
import os
|
||||
from os.path import isdir, isfile
|
||||
from spack.pkg.builtin.openfoam_com import *
|
||||
|
||||
|
||||
class FoamExtend(Package):
|
||||
"""The foam-extend project is a fork of the OpenFOAM open source library
|
||||
for Computational Fluid Dynamics (CFD)."""
|
||||
"""The Extend Project is a fork of the OpenFOAM opensource library
|
||||
for Computational Fluid Dynamics (CFD).
|
||||
This offering is not approved or endorsed by OpenCFD Ltd,
|
||||
producer and distributor of the OpenFOAM software via www.openfoam.com,
|
||||
and owner of the OPENFOAM trademark.
|
||||
"""
|
||||
|
||||
homepage = "http://www.extend-project.de/"
|
||||
|
||||
@@ -40,207 +76,235 @@ class FoamExtend(Package):
|
||||
version('3.1', git='http://git.code.sf.net/p/foam-extend/foam-extend-3.1')
|
||||
version('3.0', git='http://git.code.sf.net/p/foam-extend/foam-extend-3.0')
|
||||
|
||||
variant('paraview', default=False, description='Enable ParaFOAM')
|
||||
variant(
|
||||
'scotch', default=True,
|
||||
description='Activate Scotch as a possible decomposition library')
|
||||
variant(
|
||||
'ptscotch', default=True,
|
||||
description='Activate PT-Scotch as a possible decomposition library')
|
||||
variant(
|
||||
'metis', default=True,
|
||||
description='Activate Metis as a possible decomposition library')
|
||||
variant(
|
||||
'parmetis', default=True,
|
||||
description='Activate Parmetis as a possible decomposition library')
|
||||
variant(
|
||||
'parmgridgen', default=True,
|
||||
description='Activate Parmgridgen support')
|
||||
variant(
|
||||
'source', default=True,
|
||||
description='Installs also the source folder')
|
||||
# variant('int64', default=False,
|
||||
# description='Compile with 64-bit labels')
|
||||
variant('float32', default=False,
|
||||
description='Compile with 32-bit scalar (single-precision)')
|
||||
|
||||
supported_compilers = {'clang': 'Clang', 'gcc': 'Gcc', 'intel': 'Icc'}
|
||||
variant('paraview', default=False,
|
||||
description='Build paraview plugins (eg, paraFoam)')
|
||||
variant('scotch', default=True,
|
||||
description='With scotch for decomposition')
|
||||
variant('ptscotch', default=True,
|
||||
description='With ptscotch for decomposition')
|
||||
variant('metis', default=True,
|
||||
description='With metis for decomposition')
|
||||
variant('parmetis', default=True,
|
||||
description='With parmetis for decomposition')
|
||||
variant('parmgridgen', default=True,
|
||||
description='With parmgridgen support')
|
||||
variant('source', default=True,
|
||||
description='Install library/application sources and tutorials')
|
||||
|
||||
#: Map spack compiler names to OpenFOAM compiler names
|
||||
# By default, simply capitalize the first letter
|
||||
compiler_mapping = {'intel': 'icc'}
|
||||
|
||||
provides('openfoam')
|
||||
depends_on('mpi')
|
||||
depends_on('python')
|
||||
depends_on('flex')
|
||||
depends_on('zlib')
|
||||
depends_on('flex@:2.6.1') # <- restriction due to scotch
|
||||
depends_on('cmake', type='build')
|
||||
|
||||
depends_on('scotch ~ metis', when='~ptscotch+scotch')
|
||||
depends_on('scotch ~ metis + mpi', when='+ptscotch')
|
||||
depends_on('metis@5:', when='+metis')
|
||||
depends_on('parmetis', when='+parmetis')
|
||||
depends_on('parmgridgen', when='+parmgridgen')
|
||||
depends_on('scotch~metis', when='~ptscotch+scotch')
|
||||
depends_on('scotch~metis+mpi', when='+ptscotch')
|
||||
depends_on('metis@5:', when='+metis')
|
||||
depends_on('parmetis', when='+parmetis')
|
||||
depends_on('parmgridgen', when='+parmgridgen')
|
||||
depends_on('paraview@:5.0.1', when='+paraview')
|
||||
|
||||
depends_on('paraview', 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
|
||||
}
|
||||
|
||||
def set_arch(self):
|
||||
(sysname, nodename, release, version, machine) = os.uname()
|
||||
# The system description is frequently needed
|
||||
foam_sys = {
|
||||
'WM_ARCH': None,
|
||||
'WM_COMPILER': None,
|
||||
'WM_OPTIONS': None,
|
||||
}
|
||||
|
||||
if self.compiler.name not in self.supported_compilers:
|
||||
raise RuntimeError('{0} is not a supported compiler \
|
||||
to compile OpenFOAM'.format(self.compiler.name))
|
||||
# Content for etc/prefs.{csh,sh}
|
||||
etc_prefs = {}
|
||||
|
||||
foam_compiler = self.supported_compilers[self.compiler.name]
|
||||
if sysname == 'Linux':
|
||||
arch = 'linux'
|
||||
if foam_compiler == 'Clang':
|
||||
raise RuntimeError('OS, compiler combination not\
|
||||
supported ({0} {1})'.format(sysname, foam_compiler))
|
||||
elif sysname == 'Darwin':
|
||||
if machine == 'x86_64':
|
||||
arch = 'darwinIntel'
|
||||
if foam_compiler == 'Icc':
|
||||
raise RuntimeError('OS, compiler combination not\
|
||||
supported ({0} {1})'.format(sysname, foam_compiler))
|
||||
else:
|
||||
raise RuntimeError('{0} {1} is not a \
|
||||
supported architecture'.format(sysname, machine))
|
||||
# Content for etc/config.{csh,sh}/ files
|
||||
etc_config = {}
|
||||
|
||||
return (arch, foam_compiler)
|
||||
build_script = './spack-Allwmake' # <- Generated by patch() method.
|
||||
# phases = ['configure', 'build', 'install']
|
||||
# build_system_class = 'OpenfoamCom'
|
||||
|
||||
def get_openfoam_environment(self):
|
||||
return EnvironmentModifications.from_sourcing_files(
|
||||
join_path(self.stage.source_path,
|
||||
'etc/bashrc'))
|
||||
def setup_environment(self, spack_env, run_env):
|
||||
run_env.set('FOAM_INST_DIR', self.prefix)
|
||||
run_env.set('WM_PROJECT_DIR', self.projectdir)
|
||||
|
||||
@property
|
||||
def _canonical(self):
|
||||
"""Canonical name for this package and version"""
|
||||
return 'foam-extend-{0}'.format(self.version.up_to(2))
|
||||
|
||||
@property
|
||||
def projectdir(self):
|
||||
"""Absolute location of project directory: WM_PROJECT_DIR/"""
|
||||
return join_path(self.prefix, self._canonical) # <- prefix/canonical
|
||||
|
||||
@property
|
||||
def etc(self):
|
||||
"""Absolute location of the OpenFOAM etc/ directory"""
|
||||
return join_path(self.projectdir, 'etc')
|
||||
|
||||
@property
|
||||
def archbin(self):
|
||||
"""Relative location of architecture-specific executables"""
|
||||
wm_options = self.set_openfoam()
|
||||
return join_path('applications', 'bin', wm_options)
|
||||
|
||||
@property
|
||||
def archlib(self):
|
||||
"""Relative location of architecture-specific libraries"""
|
||||
wm_options = self.set_openfoam()
|
||||
return join_path('lib', wm_options)
|
||||
|
||||
@property
|
||||
def wm_options(self):
|
||||
"""The architecture+compiler+options for OpenFOAM"""
|
||||
opts = self.set_openfoam()
|
||||
return opts
|
||||
|
||||
@property
|
||||
def rpath_info(self):
|
||||
"""Define 'SPACKOpt' compiler optimization file to have wmake
|
||||
use spack information with minimum modifications to OpenFOAM
|
||||
"""
|
||||
build_libpath = join_path(self.stage.source_path, self.archlib)
|
||||
install_libpath = join_path(self.projectdir, self.archlib)
|
||||
|
||||
# 'DBUG': rpaths
|
||||
return '{0}{1} {2}{3}'.format(
|
||||
self.compiler.cxx_rpath_arg, install_libpath,
|
||||
self.compiler.cxx_rpath_arg, build_libpath)
|
||||
|
||||
def openfoam_arch(self):
|
||||
"""Return an architecture value similar to what OpenFOAM does in
|
||||
etc/config.sh/settings, but slightly more generous.
|
||||
Uses and may adjust foam_cfg[WM_ARCH_OPTION] as a side-effect
|
||||
"""
|
||||
# spec.architecture.platform is like `uname -s`, but lower-case
|
||||
platform = self.spec.architecture.platform
|
||||
|
||||
# spec.architecture.target is like `uname -m`
|
||||
target = self.spec.architecture.target
|
||||
|
||||
if platform == 'linux':
|
||||
if target == 'i686':
|
||||
self.foam_cfg['WM_ARCH_OPTION'] = '32' # Force consistency
|
||||
elif target == 'x86_64':
|
||||
if self.foam_cfg['WM_ARCH_OPTION'] == '64':
|
||||
platform += '64'
|
||||
elif target == 'ia64':
|
||||
platform += 'ia64'
|
||||
elif target == 'armv7l':
|
||||
platform += 'ARM7'
|
||||
elif target == ppc64:
|
||||
platform += 'PPC64'
|
||||
elif target == ppc64le:
|
||||
platform += 'PPC64le'
|
||||
elif platform == 'darwin':
|
||||
if target == 'x86_64':
|
||||
platform += 'Intel'
|
||||
if self.foam_cfg['WM_ARCH_OPTION'] == '64':
|
||||
platform += '64'
|
||||
# ... and others?
|
||||
return platform
|
||||
|
||||
def openfoam_compiler(self):
|
||||
"""Capitalized version of the compiler name, which usually corresponds
|
||||
to how OpenFOAM will camel-case things.
|
||||
Use compiler_mapping to handing special cases.
|
||||
Also handle special compiler options (eg, KNL)
|
||||
"""
|
||||
comp = self.compiler.name
|
||||
if comp in self.compiler_mapping:
|
||||
comp = self.compiler_mapping[comp]
|
||||
comp = comp.capitalize()
|
||||
|
||||
if '+knl' in self.spec:
|
||||
comp += 'KNL'
|
||||
return comp
|
||||
|
||||
# For foam-extend: does not yet support +int64
|
||||
def set_openfoam(self):
|
||||
"""Populate foam_cfg, foam_sys according to
|
||||
variants, architecture, compiler.
|
||||
Returns WM_OPTIONS.
|
||||
"""
|
||||
# Run once
|
||||
opts = self.foam_sys['WM_OPTIONS']
|
||||
if opts:
|
||||
return opts
|
||||
|
||||
wm_arch = self.openfoam_arch()
|
||||
wm_compiler = self.openfoam_compiler()
|
||||
compileOpt = self.foam_cfg['WM_COMPILE_OPTION']
|
||||
|
||||
# Insist on a wmake rule for this architecture/compiler combination
|
||||
archCompiler = wm_arch + wm_compiler
|
||||
compiler_rule = join_path(
|
||||
self.stage.source_path, 'wmake', 'rules', archCompiler)
|
||||
|
||||
if not isdir(compiler_rule):
|
||||
raise RuntimeError(
|
||||
'No wmake rule for {0}'.format(archCompiler))
|
||||
if not re.match(r'.+Opt$', compileOpt):
|
||||
raise RuntimeError(
|
||||
"WM_COMPILE_OPTION={0} is not type '*Opt'".format(compileOpt))
|
||||
|
||||
# Adjust for variants
|
||||
# FUTURE? self.foam_cfg['WM_LABEL_SIZE'] = (
|
||||
# FUTURE? '64' if '+int64' in self.spec else '32'
|
||||
# FUTURE? )
|
||||
self.foam_cfg['WM_PRECISION_OPTION'] = (
|
||||
'SP' if '+float32' in self.spec else 'DP'
|
||||
)
|
||||
|
||||
# ----
|
||||
# WM_OPTIONS=$WM_ARCH$WM_COMPILER$WM_PRECISION_OPTION$WM_COMPILE_OPTION
|
||||
# ----
|
||||
self.foam_sys['WM_ARCH'] = wm_arch
|
||||
self.foam_sys['WM_COMPILER'] = wm_compiler
|
||||
self.foam_cfg['WM_COMPILER'] = wm_compiler # For bashrc,cshrc too
|
||||
self.foam_sys['WM_OPTIONS'] = ''.join([
|
||||
wm_arch,
|
||||
wm_compiler,
|
||||
self.foam_cfg['WM_PRECISION_OPTION'],
|
||||
# FUTURE? 'Int', self.foam_cfg['WM_LABEL_SIZE'], # Int32/Int64
|
||||
compileOpt
|
||||
])
|
||||
return self.foam_sys['WM_OPTIONS']
|
||||
|
||||
def patch(self):
|
||||
# change names to match the package and not the one patch in
|
||||
# the Third-Party of foam-extend
|
||||
if '+parmgridgen' in self.spec:
|
||||
filter_file(r'-lMGridGen',
|
||||
r'-lmgrid',
|
||||
'src/dbns/Make/options')
|
||||
"""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
|
||||
|
||||
filter_file(
|
||||
r'-lMGridGen',
|
||||
r'-lmgrid',
|
||||
'src/fvAgglomerationMethods/MGridGenGamgAgglomeration/Make/options') # noqa: E501
|
||||
|
||||
# Get the wmake arch and compiler
|
||||
(arch, foam_compiler) = self.set_arch()
|
||||
|
||||
prefs_dict = {
|
||||
'compilerInstall': 'System',
|
||||
'WM_COMPILER': foam_compiler,
|
||||
'WM_ARCH_OPTION': '64',
|
||||
'WM_PRECISION_OPTION': 'DP',
|
||||
'WM_COMPILE_OPTION': 'SPACKOpt',
|
||||
'WM_MPLIB': 'SPACK',
|
||||
|
||||
'CMAKE_DIR': self.spec['cmake'].prefix,
|
||||
'CMAKE_BIN_DIR': self.spec['cmake'].prefix.bin,
|
||||
'PYTHON_DIR': self.spec['python'].prefix,
|
||||
'PYTHON_BIN_DIR': self.spec['python'].prefix.bin,
|
||||
|
||||
'FLEX_SYSTEM': 1,
|
||||
'FLEX_DIR': self.spec['flex'].prefix,
|
||||
|
||||
'BISON_SYSTEM': 1,
|
||||
'BISON_DIR': self.spec['flex'].prefix,
|
||||
|
||||
'ZLIB_SYSTEM': 1,
|
||||
'ZLIB_DIR': self.spec['zlib'].prefix,
|
||||
}
|
||||
|
||||
if '+scotch' in self.spec or '+ptscotch' in self.spec:
|
||||
prefs_dict['SCOTCH_SYSTEM'] = 1
|
||||
prefs_dict['SCOTCH_DIR'] = self.spec['scotch'].prefix
|
||||
prefs_dict['SCOTCH_BIN_DIR'] = self.spec['scotch'].prefix.bin
|
||||
prefs_dict['SCOTCH_LIB_DIR'] = self.spec['scotch'].prefix.lib
|
||||
prefs_dict['SCOTCH_INCLUDE_DIR'] = \
|
||||
self.spec['scotch'].prefix.include
|
||||
|
||||
if '+metis' in self.spec:
|
||||
prefs_dict['METIS_SYSTEM'] = 1
|
||||
prefs_dict['METIS_DIR'] = self.spec['metis'].prefix
|
||||
prefs_dict['METIS_BIN_DIR'] = self.spec['metis'].prefix.bin
|
||||
prefs_dict['METIS_LIB_DIR'] = self.spec['metis'].prefix.lib
|
||||
prefs_dict['METIS_INCLUDE_DIR'] = self.spec['metis'].prefix.include
|
||||
|
||||
if '+parmetis' in self.spec:
|
||||
prefs_dict['PARMETIS_SYSTEM'] = 1
|
||||
prefs_dict['PARMETIS_DIR'] = self.spec['parmetis'].prefix
|
||||
prefs_dict['PARMETIS_BIN_DIR'] = self.spec['parmetis'].prefix.bin
|
||||
prefs_dict['PARMETIS_LIB_DIR'] = self.spec['parmetis'].prefix.lib
|
||||
prefs_dict['PARMETIS_INCLUDE_DIR'] = \
|
||||
self.spec['parmetis'].prefix.include
|
||||
|
||||
if '+parmgridgen' in self.spec:
|
||||
prefs_dict['PARMGRIDGEN_SYSTEM'] = 1
|
||||
prefs_dict['PARMGRIDGEN_DIR'] = self.spec['parmgridgen'].prefix
|
||||
prefs_dict['PARMGRIDGEN_BIN_DIR'] = \
|
||||
self.spec['parmgridgen'].prefix.bin
|
||||
prefs_dict['PARMGRIDGEN_LIB_DIR'] = \
|
||||
self.spec['parmgridgen'].prefix.lib
|
||||
prefs_dict['PARMGRIDGEN_INCLUDE_DIR'] = \
|
||||
self.spec['parmgridgen'].prefix.include
|
||||
|
||||
if '+paraview' in self.spec:
|
||||
prefs_dict['PARAVIEW_SYSTEM'] = 1
|
||||
prefs_dict['PARAVIEW_DIR'] = self.spec['paraview'].prefix
|
||||
prefs_dict['PARAVIEW_BIN_DIR'] = self.spec['paraview'].prefix.bin
|
||||
prefs_dict['QT_SYSTEM'] = 1
|
||||
prefs_dict['QT_DIR'] = self.spec['qt'].prefix
|
||||
prefs_dict['QT_BIN_DIR'] = self.spec['qt'].prefix.bin
|
||||
|
||||
# write the prefs files to define the configuration needed,
|
||||
# only the prefs.sh is used by this script but both are
|
||||
# installed for end users
|
||||
with working_dir('.'):
|
||||
with open("etc/prefs.sh", "w") as fh:
|
||||
for key in sorted(prefs_dict):
|
||||
fh.write('export {0}={1}\n'.format(key, prefs_dict[key]))
|
||||
|
||||
with open("etc/prefs.csh", "w") as fh:
|
||||
for key in sorted(prefs_dict):
|
||||
fh.write('setenv {0}={1}\n'.format(key, prefs_dict[key]))
|
||||
|
||||
# Defining a different mpi and optimisation file to be able to
|
||||
# make wmake get spack info with minimum modifications on
|
||||
# configurations scripts
|
||||
mpi_info = [
|
||||
'PFLAGS = -DOMPI_SKIP_MPICXX -DMPICH_IGNORE_CXX_SEEK',
|
||||
'PINC = -I{0}'.format(self.spec['mpi'].prefix.include),
|
||||
'PLIBS = -L{0} -lmpi'.format(self.spec['mpi'].prefix.lib)
|
||||
# Adjust ParMGridGen - this is still a mess
|
||||
files = [
|
||||
'src/dbns/Make/options',
|
||||
'src/fvAgglomerationMethods/MGridGenGamgAgglomeration/Make/options' # noqa: E501
|
||||
]
|
||||
for f in files:
|
||||
filter_file(r'-lMGridGen', r'-lmgrid', f, backup=False)
|
||||
|
||||
arch_path = ''.join([arch, prefs_dict['WM_ARCH_OPTION'],
|
||||
foam_compiler])
|
||||
option_path = ''.join([arch_path,
|
||||
prefs_dict['WM_PRECISION_OPTION'],
|
||||
prefs_dict['WM_COMPILE_OPTION']])
|
||||
rule_path = join_path("wmake", "rules", arch_path)
|
||||
build_path = join_path(self.stage.source_path, 'lib', option_path)
|
||||
install_path = \
|
||||
join_path(self.prefix,
|
||||
'foam-extend-{0}'.format(self.version.up_to(2)),
|
||||
option_path)
|
||||
|
||||
rpaths_foam = ' '.join([
|
||||
'{0}{1}'.format(self.compiler.cxx_rpath_arg,
|
||||
install_path),
|
||||
'{0}{1}'.format(self.compiler.cxx_rpath_arg,
|
||||
build_path)
|
||||
])
|
||||
|
||||
compiler_flags = {
|
||||
'DBUG': rpaths_foam,
|
||||
'OPT': '-O3',
|
||||
}
|
||||
|
||||
with working_dir(rule_path):
|
||||
with open('mplibSPACK', "w") as fh:
|
||||
fh.write('\n'.join(mpi_info))
|
||||
|
||||
for comp in ['c', 'c++']:
|
||||
with open('{0}SPACKOpt'.format(comp), "w") as fh:
|
||||
for key, val in compiler_flags.iteritems():
|
||||
fh.write('{0}{1} = {2}\n'.format(comp, key, val))
|
||||
|
||||
_files_to_patch = [
|
||||
# Adjust for flex version check
|
||||
files = [
|
||||
'src/thermophysicalModels/reactionThermo/chemistryReaders/chemkinReader/chemkinLexer.L', # noqa: E501
|
||||
'src/surfMesh/surfaceFormats/stl/STLsurfaceFormatASCII.L', # noqa: E501
|
||||
'src/meshTools/triSurface/triSurface/interfaces/STL/readSTLASCII.L', # noqa: E501
|
||||
@@ -251,40 +315,198 @@ def patch(self):
|
||||
'applications/utilities/mesh/conversion/fluentMeshToFoam/fluentMeshToFoam.L', # noqa: E501
|
||||
'applications/utilities/mesh/conversion/fluent3DMeshToElmer/fluent3DMeshToElmer.L' # noqa: E501
|
||||
]
|
||||
for _file in _files_to_patch:
|
||||
filter_file(r'#if YY_FLEX_SUBMINOR_VERSION < 34',
|
||||
r'#if YY_FLEX_MAJOR_VERSION <= 2 && YY_FLEX_MINOR_VERSION <= 5 && YY_FLEX_SUBMINOR_VERSION < 34', # noqa: E501
|
||||
_file)
|
||||
for f in files:
|
||||
filter_file(
|
||||
r'#if YY_FLEX_SUBMINOR_VERSION < 34',
|
||||
r'#if YY_FLEX_MAJOR_VERSION <= 2 && YY_FLEX_MINOR_VERSION <= 5 && YY_FLEX_SUBMINOR_VERSION < 34', # noqa: E501
|
||||
f, backup=False
|
||||
)
|
||||
|
||||
def setup_environment(self, spack_env, run_env):
|
||||
with working_dir(self.stage.path):
|
||||
spack_env.set('FOAM_INST_DIR', os.path.abspath('.'))
|
||||
# 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
|
||||
|
||||
(arch, foam_compiler) = self.set_arch()
|
||||
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
|
||||
|
||||
run_env.set('FOAM_INST_DIR', self.prefix)
|
||||
# Content for etc/prefs.{csh,sh}
|
||||
self.etc_prefs = {
|
||||
'000': { # Sort first
|
||||
'compilerInstall': 'System',
|
||||
},
|
||||
'001': {},
|
||||
'cmake': {
|
||||
'CMAKE_DIR': spec['cmake'].prefix,
|
||||
'CMAKE_BIN_DIR': spec['cmake'].prefix.bin,
|
||||
},
|
||||
'python': {
|
||||
'PYTHON_DIR': spec['python'].prefix,
|
||||
'PYTHON_BIN_DIR': spec['python'].prefix.bin,
|
||||
},
|
||||
'flex': {
|
||||
'FLEX_SYSTEM': 1,
|
||||
'FLEX_DIR': spec['flex'].prefix,
|
||||
},
|
||||
'bison': {
|
||||
'BISON_SYSTEM': 1,
|
||||
'BISON_DIR': spec['flex'].prefix,
|
||||
},
|
||||
'zlib': {
|
||||
'ZLIB_SYSTEM': 1,
|
||||
'ZLIB_DIR': spec['zlib'].prefix,
|
||||
},
|
||||
}
|
||||
# Adjust configuration via prefs - sort second
|
||||
self.etc_prefs['001'].update(self.foam_cfg)
|
||||
|
||||
def install(self, spec, prefix):
|
||||
env_openfoam = self.get_openfoam_environment()
|
||||
env_openfoam.apply_modifications()
|
||||
if '+scotch' in spec or '+ptscotch' in spec:
|
||||
pkg = spec['scotch'].prefix
|
||||
self.etc_prefs['scotch'] = {
|
||||
'SCOTCH_SYSTEM': 1,
|
||||
'SCOTCH_DIR': pkg,
|
||||
'SCOTCH_BIN_DIR': pkg.bin,
|
||||
'SCOTCH_LIB_DIR': pkg.lib,
|
||||
'SCOTCH_INCLUDE_DIR': pkg.include,
|
||||
}
|
||||
|
||||
if self.parallel:
|
||||
if '+metis' in spec:
|
||||
pkg = spec['metis'].prefix
|
||||
self.etc_prefs['metis'] = {
|
||||
'METIS_SYSTEM': 1,
|
||||
'METIS_DIR': pkg,
|
||||
'METIS_BIN_DIR': pkg.bin,
|
||||
'METIS_LIB_DIR': pkg.lib,
|
||||
'METIS_INCLUDE_DIR': pkg.include,
|
||||
}
|
||||
|
||||
if '+parmetis' in spec:
|
||||
pkg = spec['parmetis'].prefix
|
||||
self.etc_prefs['parametis'] = {
|
||||
'PARMETIS_SYSTEM': 1,
|
||||
'PARMETIS_DIR': pkg,
|
||||
'PARMETIS_BIN_DIR': pkg.bin,
|
||||
'PARMETIS_LIB_DIR': pkg.lib,
|
||||
'PARMETIS_INCLUDE_DIR': pkg.include,
|
||||
}
|
||||
|
||||
if '+parmgridgen' in spec:
|
||||
pkg = spec['parmgridgen'].prefix
|
||||
self.etc_prefs['parmgridgen'] = {
|
||||
'PARMGRIDGEN_SYSTEM': 1,
|
||||
'PARMGRIDGEN_DIR': pkg,
|
||||
'PARMGRIDGEN_BIN_DIR': pkg.bin,
|
||||
'PARMGRIDGEN_LIB_DIR': pkg.lib,
|
||||
'PARMGRIDGEN_INCLUDE_DIR': pkg.include,
|
||||
}
|
||||
|
||||
if '+paraview' in self.spec:
|
||||
self.etc_prefs['paraview'] = {
|
||||
'PARAVIEW_SYSTEM': 1,
|
||||
'PARAVIEW_DIR': spec['paraview'].prefix,
|
||||
'PARAVIEW_BIN_DIR': spec['paraview'].prefix.bin,
|
||||
}
|
||||
self.etc_prefs['qt'] = {
|
||||
'QT_SYSTEM': 1,
|
||||
'QT_DIR': spec['qt'].prefix,
|
||||
'QT_BIN_DIR': spec['qt'].prefix.bin,
|
||||
}
|
||||
|
||||
# Write prefs files according to the configuration.
|
||||
# Only need prefs.sh for building, but install both for end-users
|
||||
write_environ(
|
||||
self.etc_prefs,
|
||||
posix=join_path('etc', 'prefs.sh'),
|
||||
cshell=join_path('etc', 'prefs.csh'))
|
||||
|
||||
archCompiler = self.foam_sys['WM_ARCH'] + self.foam_sys['WM_COMPILER']
|
||||
compileOpt = self.foam_cfg['WM_COMPILE_OPTION']
|
||||
# general_rule = join_path('wmake', 'rules', 'General')
|
||||
compiler_rule = join_path('wmake', 'rules', archCompiler)
|
||||
generate_mplib_rules(compiler_rule, self.spec)
|
||||
generate_compiler_rules(compiler_rule, compileOpt, self.rpath_info)
|
||||
# Record the spack spec information
|
||||
with open("log.spack-spec", 'w') as outfile:
|
||||
outfile.write(spec.tree())
|
||||
|
||||
def build(self, spec, prefix):
|
||||
"""Build using the OpenFOAM Allwmake script, with a wrapper to source
|
||||
its environment first.
|
||||
"""
|
||||
self.set_openfoam() # Force proper population of foam_cfg/foam_sys
|
||||
args = []
|
||||
if self.parallel: # Build in parallel? - pass via the environment
|
||||
os.environ['WM_NCOMPPROCS'] = str(self.make_jobs) \
|
||||
if self.make_jobs else str(multiprocessing.cpu_count())
|
||||
builder = Executable(self.build_script)
|
||||
builder(*args)
|
||||
|
||||
allwmake = Executable('./Allwmake')
|
||||
allwmake()
|
||||
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_path = \
|
||||
join_path(self.prefix,
|
||||
'foam-extend-{0}'.format(self.version.up_to(2)))
|
||||
# Fairly ugly since intermediate targets are scattered inside sources
|
||||
appdir = 'applications'
|
||||
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))
|
||||
|
||||
# All top-level files, except spack build info and possibly Allwmake
|
||||
if '+source' in spec:
|
||||
ignored = re.compile(r'^spack-.*')
|
||||
else:
|
||||
ignored = re.compile(r'^(Allclean|Allwmake|spack-).*')
|
||||
|
||||
files = [
|
||||
f for f in glob.glob("*") if 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_tree(
|
||||
d,
|
||||
join_path(self.projectdir, d))
|
||||
|
||||
if '+source' in spec:
|
||||
install_tree('src', join_path(install_path, 'src'))
|
||||
install_tree('tutorials', join_path(install_path, 'tutorials'))
|
||||
subitem = join_path(appdir, 'Allwmake')
|
||||
install(subitem, join_path(self.projectdir, subitem))
|
||||
|
||||
install_tree('lib', join_path(install_path, 'lib'))
|
||||
install_tree('bin', join_path(install_path, 'bin'))
|
||||
install_tree('applications', join_path(install_path, 'applications'))
|
||||
install_tree('etc', join_path(install_path, 'etc'))
|
||||
install_tree('wmake', join_path(install_path, 'wmake'))
|
||||
ignored = [opts] # Intermediate targets
|
||||
for d in ['src', 'tutorials']:
|
||||
install_tree(
|
||||
d,
|
||||
join_path(self.projectdir, d),
|
||||
ignore=shutil.ignore_patterns(*ignored))
|
||||
|
||||
for d in ['solvers', 'utilities']:
|
||||
install_tree(
|
||||
join_path(appdir, d),
|
||||
join_path(self.projectdir, appdir, d),
|
||||
ignore=shutil.ignore_patterns(*ignored))
|
||||
|
||||
def install_links(self):
|
||||
"""Add symlinks into bin/, lib/ (eg, for other applications)"""
|
||||
return
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user