From e042bd9d89670a92e8c0ca44ef5adb6d98659dc7 Mon Sep 17 00:00:00 2001 From: Dan Bonachea Date: Wed, 25 Mar 2020 19:05:13 -0400 Subject: [PATCH] UPC++ 2020.3.0 update (#15623) ## Summary This PR updates and improves the Spack package for [UPC++](https://upcxx.lbl.gov). I'm an LBL employee and developer on the UPC++ team, as well as the maintainer of this Spack package. ### Key Improvements: * Adding new 2020.3.0 release and support for use of develop/master branches - Our build infrastructure underwent a major change in this release, switching from a hand-rolled Python2 script to a bash-based autoconf work-alike. - The new build system is NOT using autotools (nor does it support some of the more esoteric autoconf options), but the user interface for common builds is similar. * Add explicit support for an MPI optional dependency - New `mpi` variant enables use of the MPI-based spawner (most relevant on loosely coupled clusters), and the (unofficial) mpi-conduit backend - This variant is OFF by default, since UPC++ works fine without MPI on many systems, increasing the likelihood first-time Spack users get a working build without needing to correctly setup MPI * Add support for post-install testing using the test support deployed in the new build infrastructure * Fix or workaround a few bugs observed during testing ### Status The new package has been validated with a variety of specs across over seven different systems, including: NERSC cori, ALCF Theta, OLCF Summit, an in-house Linux cluster, and macOS laptops (Mojave and Catalina). --- .../repos/builtin/packages/upcxx/package.py | 109 ++++++++++++++++-- 1 file changed, 100 insertions(+), 9 deletions(-) diff --git a/var/spack/repos/builtin/packages/upcxx/package.py b/var/spack/repos/builtin/packages/upcxx/package.py index e4806c4c9c..d5c74bebb9 100644 --- a/var/spack/repos/builtin/packages/upcxx/package.py +++ b/var/spack/repos/builtin/packages/upcxx/package.py @@ -10,7 +10,7 @@ def cross_detect(): if spack.architecture.platform().name == 'cray': if which('srun'): return 'cray-aries-slurm' - if which('alps'): + if which('aprun'): return 'cray-aries-alps' return 'none' @@ -25,9 +25,17 @@ class Upcxx(Package): homepage = "https://upcxx.lbl.gov" maintainers = ['bonachea'] + git = 'https://bonachea@bitbucket.org/berkeleylab/upcxx.git' + version('develop', branch='develop') + version('master', branch='master') + + version('2020.3.0', sha256='01be35bef4c0cfd24e9b3d50c88866521b9cac3ad4cbb5b1fc97aea55078810f') version('2019.9.0', sha256='7d67ccbeeefb59de9f403acc719f52127a30801a2c2b9774a1df03f850f8f1d4') version('2019.3.2', sha256='dcb0b337c05a0feb2ed5386f5da6c60342412b49cab10f282f461e74411018ad') + variant('mpi', default=False, + description='Enables MPI-based spawners and mpi-conduit') + variant('cuda', default=False, description='Builds a CUDA-enabled version of UPC++') @@ -35,10 +43,19 @@ class Upcxx(Package): description="UPC++ cross-compile target (autodetect by default)") conflicts('cross=none', when='platform=cray', - msg='None is unacceptable on Cray.') + msg='cross=none is unacceptable on Cray.' + + 'Please specify an appropriate "cross" value') + depends_on('mpi', when='+mpi') depends_on('cuda', when='+cuda') - depends_on('python@2.7.5:2.999', type=("build", "run")) + # Require Python2 2.7.5+ up to v2019.9.0 + depends_on('python@2.7.5:2.999', + type=("build", "run"), when='@:2019.9.0') + # v2020.3.0 and later also permit Python3 + depends_on('python@2.7.5:', type=("build", "run"), when='@2020.3.0:') + + # All flags should be passed to the build-env in autoconf-like vars + flag_handler = env_flags def url_for_version(self, version): if version > Version('2019.3.2'): @@ -48,8 +65,14 @@ def url_for_version(self, version): return url.format(version) def setup_build_environment(self, env): - if 'platform=cray' in self.spec: - env.set('GASNET_CONFIGURE_ARGS', '--enable-mpi=probe') + # ensure we use the correct python + env.set('UPCXX_PYTHON', self.spec['python'].command.path) + + if '+mpi' in self.spec: + env.set('GASNET_CONFIGURE_ARGS', + '--enable-mpi --enable-mpi-compat') + else: + env.set('GASNET_CONFIGURE_ARGS', '--without-mpicc') if 'cross=none' not in self.spec: env.set('CROSS', self.spec.variants['cross'].value) @@ -59,6 +82,9 @@ def setup_build_environment(self, env): env.set('UPCXX_CUDA_NVCC', self.spec['cuda'].prefix.bin.nvcc) def setup_run_environment(self, env): + # ensure we use the correct python + env.set('UPCXX_PYTHON', self.spec['python'].command.path) + env.set('UPCXX_INSTALL', self.prefix) env.set('UPCXX', self.prefix.bin.upcxx) if 'platform=cray' in self.spec: @@ -76,7 +102,72 @@ def setup_dependent_build_environment(self, env, dependent_spec): env.set('UPCXX_NETWORK', 'aries') def install(self, spec, prefix): - env['CC'] = self.compiler.cc - env['CXX'] = self.compiler.cxx - installsh = Executable("./install") - installsh(prefix) + # UPC++ follows autoconf naming convention for LDLIBS, which is 'LIBS' + if (env.get('LDLIBS')): + env['LIBS'] = env['LDLIBS'] + + if spec.version <= Version('2019.9.0'): + env['CC'] = self.compiler.cc + if '+mpi' in self.spec: + if 'platform=cray' in self.spec: + env['GASNET_CONFIGURE_ARGS'] += \ + " --with-mpicc=" + self.compiler.cc + else: + env['CXX'] = spec['mpi'].mpicxx + else: + env['CXX'] = self.compiler.cxx + installsh = Executable("./install") + installsh(prefix) + else: + if 'platform=cray' in self.spec: + # Spack loads the cray-libsci module incorrectly on ALCF theta, + # breaking the Cray compiler wrappers + # cray-libsci is irrelevant to our build, so disable it + for var in ['PE_PKGCONFIG_PRODUCTS', 'PE_PKGCONFIG_LIBS']: + env[var] = ":".join( + filter(lambda x: "libsci" not in x.lower(), + env[var].split(":"))) + # Undo spack compiler wrappers: + # the C/C++ compilers must work post-install + # hack above no longer works after the fix to UPC++ issue #287 + real_cc = join_path(env['CRAYPE_DIR'], 'bin', 'cc') + real_cxx = join_path(env['CRAYPE_DIR'], 'bin', 'CC') + # workaround a bug in the UPC++ installer: (issue #346) + env['GASNET_CONFIGURE_ARGS'] += \ + " --with-cc=" + real_cc + " --with-cxx=" + real_cxx + if '+mpi' in self.spec: + env['GASNET_CONFIGURE_ARGS'] += " --with-mpicc=" + real_cc + else: + real_cc = self.compiler.cc + real_cxx = self.compiler.cxx + if '+mpi' in self.spec: + real_cxx = spec['mpi'].mpicxx + + env['CC'] = real_cc + env['CXX'] = real_cxx + + installsh = Executable("./configure") + installsh('--prefix=' + prefix) + + make() + + make('install') + + @run_after('install') + @on_package_attributes(run_tests=True) + def test_install(self): + if self.spec.version <= Version('2019.9.0'): + spack.main.send_warning_to_tty( + "run_tests not supported in UPC++ version " + + self.spec.version.string + " -- SKIPPED") + else: + # enable testing of unofficial conduits (mpi) + test_networks = 'NETWORKS=$(CONDUITS)' + # build hello world against installed tree in all configurations + make('test_install', test_networks) + make('tests-clean') # cleanup + # build all tests for all networks in debug mode + make('tests', test_networks) + if 'cross=none' in self.spec: + make('run-tests', 'NETWORKS=smp') # runs tests for smp backend + make('tests-clean') # cleanup