diff options
author | Matthew LeGendre <legendre1@llnl.gov> | 2017-11-12 19:09:12 -0800 |
---|---|---|
committer | Todd Gamblin <tgamblin@llnl.gov> | 2017-11-12 20:09:12 -0700 |
commit | 265c30b943798b71d1a312ffa4f940d48f8f1ef7 (patch) | |
tree | 6df2c44a0aeb0a3024add85bdbf5693007c65e4c | |
parent | b09341d861f90c4d3745d25d44d76ff90b3c4967 (diff) | |
download | spack-265c30b943798b71d1a312ffa4f940d48f8f1ef7.tar.gz spack-265c30b943798b71d1a312ffa4f940d48f8f1ef7.tar.bz2 spack-265c30b943798b71d1a312ffa4f940d48f8f1ef7.tar.xz spack-265c30b943798b71d1a312ffa4f940d48f8f1ef7.zip |
Update packaging tutorial (#6270)
* Allow types and 'any' in variant definitions.
- Previously variant values had to be a tuple or a callable predicate.
- This allows 'any' as shorthand for `lambda x: True` and type objects
as shorthand for "any value of this type".
- Makes variant definitions more readable, keeps lambdas out of
packages for common cases.
* Update packaging tutorial
* Fix bad file reference in packaging tutorial
-rw-r--r-- | lib/spack/docs/tutorial/examples/0.package.py | 15 | ||||
-rw-r--r-- | lib/spack/docs/tutorial/examples/1.package.py | 15 | ||||
-rw-r--r-- | lib/spack/docs/tutorial/examples/2.package.py | 11 | ||||
-rw-r--r-- | lib/spack/docs/tutorial/examples/3.package.py | 11 | ||||
-rw-r--r-- | lib/spack/docs/tutorial/examples/4.package.py | 18 | ||||
-rw-r--r-- | lib/spack/docs/tutorial/examples/5.package.py | 53 | ||||
-rw-r--r-- | lib/spack/docs/tutorial_packaging.rst | 232 | ||||
-rw-r--r-- | lib/spack/spack/variant.py | 19 |
8 files changed, 232 insertions, 142 deletions
diff --git a/lib/spack/docs/tutorial/examples/0.package.py b/lib/spack/docs/tutorial/examples/0.package.py index d44e06dd6c..0a42cdc802 100644 --- a/lib/spack/docs/tutorial/examples/0.package.py +++ b/lib/spack/docs/tutorial/examples/0.package.py @@ -40,7 +40,7 @@ from spack import * -class Mpileaks(AutotoolsPackage): +class Mpileaks(Package): """FIXME: Put a proper description of your package here.""" # FIXME: Add a proper url for your package's homepage here. @@ -50,14 +50,9 @@ class Mpileaks(AutotoolsPackage): version('1.0', '8838c574b39202a57d7c2d68692718aa') # FIXME: Add dependencies if required. - # depends_on('m4', type='build') - # depends_on('autoconf', type='build') - # depends_on('automake', type='build') - # depends_on('libtool', type='build') # depends_on('foo') - def configure_args(self): - # FIXME: Add arguments other than --prefix - # FIXME: If not needed delete the function - args = [] - return args + def install(self, spec, prefix): + # FIXME: Unknown build system + make() + make('install') diff --git a/lib/spack/docs/tutorial/examples/1.package.py b/lib/spack/docs/tutorial/examples/1.package.py index 30f708be2f..359a457567 100644 --- a/lib/spack/docs/tutorial/examples/1.package.py +++ b/lib/spack/docs/tutorial/examples/1.package.py @@ -25,7 +25,7 @@ from spack import * -class Mpileaks(AutotoolsPackage): +class Mpileaks(Package): """Tool to detect and report MPI objects like MPI_Requests and MPI_Datatypes.""" @@ -35,14 +35,9 @@ class Mpileaks(AutotoolsPackage): version('1.0', '8838c574b39202a57d7c2d68692718aa') # FIXME: Add dependencies if required. - # depends_on('m4', type='build') - # depends_on('autoconf', type='build') - # depends_on('automake', type='build') - # depends_on('libtool', type='build') # depends_on('foo') - def configure_args(self): - # FIXME: Add arguments other than --prefix - # FIXME: If not needed delete the function - args = [] - return args + def install(self, spec, prefix): + # FIXME: Unknown build system + make() + make('install') diff --git a/lib/spack/docs/tutorial/examples/2.package.py b/lib/spack/docs/tutorial/examples/2.package.py index 5f706d1ff6..7980768e06 100644 --- a/lib/spack/docs/tutorial/examples/2.package.py +++ b/lib/spack/docs/tutorial/examples/2.package.py @@ -25,7 +25,7 @@ from spack import * -class Mpileaks(AutotoolsPackage): +class Mpileaks(Package): """Tool to detect and report MPI objects like MPI_Requests and MPI_Datatypes.""" @@ -38,8 +38,7 @@ class Mpileaks(AutotoolsPackage): depends_on('adept-utils') depends_on('callpath') - def configure_args(self): - # FIXME: Add arguments other than --prefix - # FIXME: If not needed delete the function - args = [] - return args + def install(self, spec, prefix): + # FIXME: Unknown build system + make() + make('install') diff --git a/lib/spack/docs/tutorial/examples/3.package.py b/lib/spack/docs/tutorial/examples/3.package.py index b34d1545b4..b30dd900ae 100644 --- a/lib/spack/docs/tutorial/examples/3.package.py +++ b/lib/spack/docs/tutorial/examples/3.package.py @@ -25,9 +25,10 @@ from spack import * -class Mpileaks(AutotoolsPackage): +class Mpileaks(Package): """Tool to detect and report MPI objects like MPI_Requests and MPI_Datatypes.""" + homepage = "https://github.com/hpc/mpileaks" url = "https://github.com/hpc/mpileaks/releases/download/v1.0/mpileaks-1.0.tar.gz" @@ -37,7 +38,7 @@ class Mpileaks(AutotoolsPackage): depends_on('adept-utils') depends_on('callpath') - def configure_args(self): - args = ['--with-adept-utils=%s' % self.spec['adept-utils'].prefix, - '--with-callpath=%s' % self.spec['callpath'].prefix] - return args + def install(self, spec, prefix): + configure() + make() + make('install') diff --git a/lib/spack/docs/tutorial/examples/4.package.py b/lib/spack/docs/tutorial/examples/4.package.py index 74f9d2e527..116a11a0fa 100644 --- a/lib/spack/docs/tutorial/examples/4.package.py +++ b/lib/spack/docs/tutorial/examples/4.package.py @@ -25,7 +25,7 @@ from spack import * -class Mpileaks(AutotoolsPackage): +class Mpileaks(Package): """Tool to detect and report MPI objects like MPI_Requests and MPI_Datatypes.""" @@ -34,17 +34,13 @@ class Mpileaks(AutotoolsPackage): version('1.0', '8838c574b39202a57d7c2d68692718aa') - variant('stackstart', default=0, description='Specify the number of stack frames to truncate.') - depends_on('mpi') depends_on('adept-utils') depends_on('callpath') - def configure_args(self): - args = ['--with-adept-utils=%s' % self.spec['adept-utils'].prefix, - '--with-callpath=%s' % self.spec['callpath'].prefix] - stackstart = int(self.spec.variants['stackstart'].value) - if stackstart: - args.extend(['--with-stack-start-c=%s' % stackstart, - '--with-stack-start-fortran=%s' % stackstart]) - return args + def install(self, spec, prefix): + configure('--with-adept-utils=%s' % self.spec['adept-utils'].prefix, + '--with-callpath=%s' % self.spec['callpath'].prefix, + '--prefix=%s' % self.spec.prefix) + make() + make('install') diff --git a/lib/spack/docs/tutorial/examples/5.package.py b/lib/spack/docs/tutorial/examples/5.package.py new file mode 100644 index 0000000000..3e7a1f83cb --- /dev/null +++ b/lib/spack/docs/tutorial/examples/5.package.py @@ -0,0 +1,53 @@ +############################################################################## +# Copyright (c) 2013-2017, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory. +# +# This file is part of Spack. +# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. +# LLNL-CODE-647188 +# +# For details, see https://github.com/spack/spack +# Please also see the NOTICE and LICENSE files for our notice and the LGPL. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License (as +# published by the Free Software Foundation) version 2.1, February 1999. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +# conditions of the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################## +from spack import * + + +class Mpileaks(Package): + """Tool to detect and report MPI objects like MPI_Requests and + MPI_Datatypes.""" + + homepage = "https://github.com/hpc/mpileaks" + url = "https://github.com/hpc/mpileaks/releases/download/v1.0/mpileaks-1.0.tar.gz" + + version('1.0', '8838c574b39202a57d7c2d68692718aa') + + variant('stackstart', values=int, default=0, description='Specify the number of stack frames to truncate.') + + depends_on('mpi') + depends_on('adept-utils') + depends_on('callpath') + + def install(self, spec, prefix): + stackstart = int(self.spec.variants['stackstart'].value) + confargs = ['--with-adept-utils=%s' % self.spec['adept-utils'].prefix, + '--with-callpath=%s' % self.spec['callpath'].prefix, + '--prefix=%s' % self.spec.prefix] + if stackstart: + confargs.extend(['--with-stack-start-c=%s' % stackstart, + '--with-stack-start-fortran=%s' % stackstart]) + configure(*confargs) + make() + make('install') diff --git a/lib/spack/docs/tutorial_packaging.rst b/lib/spack/docs/tutorial_packaging.rst index e250ab835e..e85be7c637 100644 --- a/lib/spack/docs/tutorial_packaging.rst +++ b/lib/spack/docs/tutorial_packaging.rst @@ -43,7 +43,7 @@ A few things before we get started: Creating the Package File ------------------------- -Spack comes with a handy command to create a new package: ``spack create`` +Spack comes with a handy command to create a new package: ``spack create``. This command is given the location of a package's source code, downloads the code, and sets up some basic packaging infrastructure for you. The @@ -52,12 +52,20 @@ we run ``spack create`` on it: .. code-block:: console - $ spack create -f https://github.com/hpc/mpileaks/releases/download/v1.0/mpileaks-1.0.tar.gz - ==> This looks like a URL for mpileaks version 1.0 - ==> Creating template for package mpileaks + $ spack create -t generic -f https://github.com/hpc/mpileaks/releases/download/v1.0/mpileaks-1.0.tar.gz + ==> This looks like a URL for mpileaks + ==> Found 1 version of mpileaks: + + 1.0 https://github.com/LLNL/mpileaks/releases/download/v1.0/mpileaks-1.0.tar.gz + + ==> How many would you like to checksum? (default is 1, q to abort) 1 ==> Downloading... - ==> Fetching https://github.com/hpc/mpileaks/releases/download/v1.0/mpileaks-1.0.tar.gz - ###################################################################################### 100.0% + ==> Fetching https://github.com/LLNL/mpileaks/releases/download/v1.0/mpileaks-1.0.tar.gz + ############################################################################# 100.0% + ==> Checksummed 1 version of mpileaks + ==> Using specified package template: 'generic' + ==> Created template for mpileaks package + ==> Created package file: $SPACK_ROOT/var/spack/repos/builtin/packages/mpileaks/package.py And Spack should spawn a text editor with this file: @@ -192,29 +200,27 @@ Now when we try to install this package a lot more happens: .. code-block:: console $ spack install mpileaks + ... + ==> libdwarf is already installed in SPACK_ROOT/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/libdwarf-20160507-er4jrjynul6uba7wiu5tasuj35roxw6m + ==> dyninst is already installed in SPACK_ROOT/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/dyninst-9.3.2-t7mau34jv3e76mpspdzhf2p2a6k7qubg + ==> callpath is already installed in SPACK_ROOT/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/callpath-1.0.4-ikbbkvfmsfmqzo624nvvrbooovf7egoc ==> Installing mpileaks - ==> openmpi is already installed in /usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/openmpi-2.0.1-5ee5j34c2y4kb5c3joygrgahidqnwhnz - ==> callpath is already installed in /usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/callpath-1.0.2-zm4pf3gasgxeibyu2y262suktvaazube - ==> adept-utils is already installed in /usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/adept-utils-1.0.1-7p7ezxwtajdglj6cmojy2vybjct4j4jz - ==> Using cached archive: /usr/workspace/wsa/legendre/spack/var/spack/cache/mpileaks/mpileaks-1.0.tar.gz - ==> Already staged mpileaks-1.0-eum4hmnlt6ovalwjnciaygfb3beja4gk in /usr/workspace/wsa/legendre/spack/var/spack/stage/mpileaks-1.0-eum4hmnlt6ovalwjnciaygfb3beja4gk - ==> Already patched mpileaks - ==> Building mpileaks [AutotoolsPackage] - ==> Executing phase : 'autoreconf' - ==> Executing phase : 'configure' - ==> Error: ProcessError: Command exited with status 1: - './configure' '--prefix=/usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/mpileaks-1.0-eum4hmnlt6ovalwjnciaygfb3beja4gk' - /usr/workspace/wsa/legendre/spack/lib/spack/spack/build_systems/autotools.py:150, in configure: - 145 def configure(self, spec, prefix): - 146 """Runs configure with the arguments specified in `configure_args` - 147 and an appropriately set prefix - 148 """ - 149 options = ['--prefix={0}'.format(prefix)] + self.configure_args() - >> 150 inspect.getmodule(self).configure(*options) - + ==> Using cached archive: SPACK_ROOT/var/spack/cache/mpileaks/mpileaks-1.0.tar.gz + ==> Already staged mpileaks-1.0-lfgf53rns5mswq25rxckzgvmjc6ywam7 in SPACK_ROOT/var/spack/stage/mpileaks-1.0-lfgf53rns5mswq25rxckzgvmjc6ywam7 + ==> No patches needed for mpileaks + ==> Building mpileaks [Package] + ==> Executing phase: 'install' + ==> Error: ProcessError: Command exited with status 2: + 'make' '-j36' + + 1 error found in build log: + 1 ==> Executing phase: 'install' + 2 ==> 'make' '-j36' + >> 3 make: *** No targets specified and no makefile found. Stop. + See build log for details: - /tmp/legendre/spack-stage/spack-stage-7V5yyk/mpileaks-1.0/spack-build.out - + SPACK_ROOT/var/spack/stage/mpileaks-1.0-lfgf53rns5mswq25rxckzgvmjc6ywam7/mpileaks-1.0/spack-build.out + Note that this command may take a while to run and produce more output if you don't have an MPI already installed or configured in Spack. @@ -228,44 +234,79 @@ Debugging Package Builds ------------------------ Our ``mpileaks`` package is still not building. It may be obvious to -many of you that we're still missing the configure options. But let's -pretend we're not all intelligent developers and use this opportunity -spend some time debugging. We a few options that can tell us about +many of you that we never ran the configure script. Let's add a +call to ``configure()`` to the top of the install routine. The resulting +package.py is in ``$SPACK_ROOT/lib/spack/docs/tutorial/examples/3.package.py``: + +.. literalinclude:: tutorial/examples/3.package.py + :lines: 25- + :language: python + +If we re-run we still get errors: + +.. code-block:: console + + ==> Installing mpileaks + ==> Using cached archive: SPACK_ROOT/var/spack/cache/mpileaks/mpileaks-1.0.tar.gz + ==> Already staged mpileaks-1.0-lfgf53rns5mswq25rxckzgvmjc6ywam7 in SPACK_ROOT/var/spack/stage/mpileaks-1.0-lfgf53rns5mswq25rxckzgvmjc6ywam7 + ==> No patches needed for mpileaks + ==> Building mpileaks [Package] + ==> Executing phase: 'install' + ==> Error: ProcessError: Command exited with status 1: + './configure' + + 1 error found in build log: + [ ... ] + 21 checking whether SPACK_ROOT/lib/spack/env/gcc/gcc and cc understand -c and -o together... yes + 22 checking whether we are using the GNU C++ compiler... yes + 23 checking whether SPACK_ROOT/lib/spack/env/gcc/g++ accepts -g... yes + 24 checking dependency style of SPACK_ROOT/lib/spack/env/gcc/g++... gcc3 + 25 checking for SPACK_ROOT/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/openmpi-3.0.0-yo5qkfvumpmgmvlbalqcadu46j5bd52f/bin/mpicc... SPACK_ROOT/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/openmpi-3.0.0-yo5qkfvumpmgmvlbalqcadu46j5bd52f/bin/mpicc + 26 Checking whether SPACK_ROOT/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/openmpi-3.0.0-yo5qkfvumpmgmvlbalqcadu46j5bd52f/bin/mpicc responds to '-showme:compile'... yes + >> 27 configure: error: unable to locate adept-utils installation + + See build log for details: + SPACK_ROOT/var/spack/stage/mpileaks-1.0-lfgf53rns5mswq25rxckzgvmjc6ywam7/mpileaks-1.0/spack-build.out + +Again, the problem may be obvious. But let's pretend we're not +all intelligent developers and use this opportunity spend some +time debugging. We have a few options that can tell us about what's going wrong: As per the error message, Spack has given us a ``spack-build.out`` debug log: .. code-block:: console - - ==> './configure' '--prefix=/usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/mpileaks-1.0-eum4hmnlt6ovalwjnciaygfb3beja4gk' + + ==> Executing phase: 'install' + ==> './configure' checking metadata... no checking installation directory variables... yes checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes - checking for a thread-safe mkdir -p... /usr/bin/mkdir -p + checking for a thread-safe mkdir -p... /bin/mkdir -p checking for gawk... gawk checking whether make sets $(MAKE)... yes - checking for gcc... /usr/workspace/wsa/legendre/spack/lib/spack/env/gcc/gcc + checking for gcc... SPACK_ROOT/lib/spack/env/gcc/gcc checking for C compiler default output file name... a.out checking whether the C compiler works... yes checking whether we are cross compiling... no - checking for suffix of executables... + checking for suffix of executables... checking for suffix of object files... o checking whether we are using the GNU C compiler... yes - checking whether /usr/workspace/wsa/legendre/spack/lib/spack/env/gcc/gcc accepts -g... yes - checking for /usr/workspace/wsa/legendre/spack/lib/spack/env/gcc/gcc option to accept ISO C89... none needed + checking whether SPACK_ROOT/lib/spack/env/gcc/gcc accepts -g... yes + checking for SPACK_ROOT/lib/spack/env/gcc/gcc option to accept ISO C89... none needed checking for style of include used by make... GNU - checking dependency style of /usr/workspace/wsa/legendre/spack/lib/spack/env/gcc/gcc... gcc3 - checking whether /usr/workspace/wsa/legendre/spack/lib/spack/env/gcc/gcc and cc understand -c and -o together... yes + checking dependency style of SPACK_ROOT/lib/spack/env/gcc/gcc... gcc3 + checking whether SPACK_ROOT/lib/spack/env/gcc/gcc and cc understand -c and -o together... yes checking whether we are using the GNU C++ compiler... yes - checking whether /usr/workspace/wsa/legendre/spack/lib/spack/env/gcc/g++ accepts -g... yes - checking dependency style of /usr/workspace/wsa/legendre/spack/lib/spack/env/gcc/g++... gcc3 - checking for /usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/openmpi-2.0.1-5ee5j34c2y4kb5c3joygrgahidqnwhnz/bin/mpicc... /usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/openmpi-2.0.1-5ee5j34c2y4kb5c3joygrgahidqnwhnz/bin/mpicc - Checking whether /usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/openmpi-2.0.1-5ee5j34c2y4kb5c3joygrgahidqnwhnz/bin/mpicc responds to '-showme:compile'... yes - configure: error: unable to locate ``adept-utils`` installation - -This gives us the output from the build, and it's fairly obvious that -mpileaks isn't finding its ``adept-utils`` package. Spack has + checking whether SPACK_ROOT/lib/spack/env/gcc/g++ accepts -g... yes + checking dependency style of SPACK_ROOT/lib/spack/env/gcc/g++... gcc3 + checking for SPACK_ROOT/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/openmpi-3.0.0-yo5qkfvumpmgmvlbalqcadu46j5bd52f/bin/mpicc... SPACK_ROOT/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/openmpi-3.0.0-yo5qkfvumpmgmvlbalqcadu46j5bd52f/bin/mpicc + Checking whether SPACK_ROOT/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/openmpi-3.0.0-yo5qkfvumpmgmvlbalqcadu46j5bd52f/bin/mpicc responds to '-showme:compile'... yes + configure: error: unable to locate adept-utils installation + +This gives us the output from the build, and mpileaks isn't +finding its ``adept-utils`` package. Spack has automatically added the include and library directories of ``adept-utils`` to the compiler's search path, but some packages like mpileaks can sometimes be picky and still want things spelled out on @@ -292,26 +333,26 @@ From here we can manually re-run the build: checking installation directory variables... yes checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes - checking for a thread-safe mkdir -p... /usr/bin/mkdir -p + checking for a thread-safe mkdir -p... /bin/mkdir -p checking for gawk... gawk checking whether make sets $(MAKE)... yes - checking for gcc... /usr/workspace/wsa/legendre/spack/lib/spack/env/gcc/gcc + checking for gcc... SPACK_ROOT/lib/spack/env/gcc/gcc checking for C compiler default output file name... a.out checking whether the C compiler works... yes checking whether we are cross compiling... no - checking for suffix of executables... + checking for suffix of executables... checking for suffix of object files... o checking whether we are using the GNU C compiler... yes - checking whether /usr/workspace/wsa/legendre/spack/lib/spack/env/gcc/gcc accepts -g... yes - checking for /usr/workspace/wsa/legendre/spack/lib/spack/env/gcc/gcc option to accept ISO C89... none needed + checking whether SPACK_ROOT/lib/spack/env/gcc/gcc accepts -g... yes + checking for SPACK_ROOT/lib/spack/env/gcc/gcc option to accept ISO C89... none needed checking for style of include used by make... GNU - checking dependency style of /usr/workspace/wsa/legendre/spack/lib/spack/env/gcc/gcc... gcc3 - checking whether /usr/workspace/wsa/legendre/spack/lib/spack/env/gcc/gcc and cc understand -c and -o together... yes + checking dependency style of SPACK_ROOT/lib/spack/env/gcc/gcc... gcc3 + checking whether SPACK_ROOT/lib/spack/env/gcc/gcc and cc understand -c and -o together... yes checking whether we are using the GNU C++ compiler... yes - checking whether /usr/workspace/wsa/legendre/spack/lib/spack/env/gcc/g++ accepts -g... yes - checking dependency style of /usr/workspace/wsa/legendre/spack/lib/spack/env/gcc/g++... gcc3 - checking for /usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/openmpi-2.0.1-5ee5j34c2y4kb5c3joygrgahidqnwhnz/bin/mpicc... /usr/workspace/wsa /legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/openmpi-2.0.1-5ee5j34c2y4kb5c3joygrgahidqnwhnz/bin/mpicc - Checking whether /usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/openmpi-2.0.1-5ee5j34c2y4kb5c3joygrgahidqnwhnz/bin/mpicc responds to '-showme:compile'... yes + checking whether SPACK_ROOT/lib/spack/env/gcc/g++ accepts -g... yes + checking dependency style of SPACK_ROOT/lib/spack/env/gcc/g++... gcc3 + checking for SPACK_ROOT/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/openmpi-3.0.0-yo5qkfvumpmgmvlbalqcadu46j5bd52f/bin/mpicc... SPACK_ROOT/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/openmpi-3.0.0-yo5qkfvumpmgmvlbalqcadu46j5bd52f/bin/mpicc + Checking whether SPACK_ROOT/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/openmpi-3.0.0-yo5qkfvumpmgmvlbalqcadu46j5bd52f/bin/mpicc responds to '-showme:compile'... yes configure: error: unable to locate adept-utils installation We're seeing the same error, but now we're in a shell where we can run @@ -328,9 +369,9 @@ Specifying Configure Arguments Let's add the configure arguments to the mpileaks' ``package.py``. This version can be found in -``$SPACK_ROOT/lib/spack/docs/tutorial/examples/3.package.py``: +``$SPACK_ROOT/lib/spack/docs/tutorial/examples/4.package.py``: -.. literalinclude:: tutorial/examples/3.package.py +.. literalinclude:: tutorial/examples/4.package.py :lines: 25- :language: python @@ -339,37 +380,35 @@ This is all we need for working mpileaks! If we install now we'll see: .. code-block:: console $ spack install mpileaks - spack install mpileaks + ... ==> Installing mpileaks - ==> openmpi is already installed in /usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/openmpi-2.0.1-5ee5j34c2y4kb5c3joygrgahidqnwhnz - ==> callpath is already installed in /usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/callpath-1.0.2-zm4pf3gasgxeibyu2y262suktvaazube - ==> adept-utils is already installed in /usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/adept-utils-1.0.1-7p7ezxwtajdglj6cmojy2vybjct4j4jz - ==> Using cached archive: /usr/workspace/wsa/legendre/spack/var/spack/cache/mpileaks/mpileaks-1.0.tar.gz - ==> Already staged mpileaks-1.0-eum4hmnlt6ovalwjnciaygfb3beja4gk in /usr/workspace/wsa/legendre/spack/var/spack/stage/mpileaks-1.0-eum4hmnlt6ovalwjnciaygfb3beja4gk - ==> Already patched mpileaks - ==> Building mpileaks [AutotoolsPackage] - ==> Executing phase : 'autoreconf' - ==> Executing phase : 'configure' - ==> Executing phase : 'build' - ==> Executing phase : 'install' + ==> Using cached archive: SPACK_ROOT/var/spack/cache/mpileaks/mpileaks-1.0.tar.gz + ==> Staging archive: SPACK_ROOT/var/spack/stage/mpileaks-1.0-lfgf53rns5mswq25rxckzgvmjc6ywam7/mpileaks-1.0.tar.gz + ==> Created stage in SPACK_ROOT/var/spack/stage/mpileaks-1.0-lfgf53rns5mswq25rxckzgvmjc6ywam7 + ==> No patches needed for mpileaks + ==> Building mpileaks [Package] + ==> Executing phase: 'install' ==> Successfully installed mpileaks - Fetch: 0.00s. Build: 14.08s. Total: 14.08s. - [+] /usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/mpileaks-1.0-eum4hmnlt6ovalwjnciaygfb3beja4gk + Fetch: 0.00s. Build: 9.01s. Total: 9.01s. + [+] SPACK_ROOT/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/mpileaks-1.0-lfgf53rns5mswq25rxckzgvmjc6ywam7 -We took a few shortcuts for this package that are worth highlighting. -Spack automatically detected that mpileaks was an Autotools-based package -when we ran ``spack create``. If this had been a CMake-based package we -would have been filling in a ``cmake_args`` function instead of -``configure_args``. If Spack hadn't been able to detect the build -system, we'd be filling in a generic install method that would manually -be calling build commands, such as is found in the ``zlib`` package: + +There are some special circumstances in package that are worth highlighting. +Normally spack would have automatically detected that mpileaks was an +Autotools-based package when we ran ``spack create`` and made it an ``AutoToolsPackage`` class (except we added the ``-t generic`` option to skip this). Instead of +a full install routine we would have just written: .. code-block:: python - def install(self, spec, prefix): - configure('--prefix={0}'.format(prefix)) - make() - make('install') + def configure_args(self): + args = ['--with-adept-utils=%s' % self.spec['adept-utils'].prefix, + '--with-callpath=%s' % self.spec['callpath'].prefix] + return args + +Similarly, if this had been a CMake-based package we +would have been filling in a ``cmake_args`` function instead of +``configure_args``. There are similar default package types for +many build environments. -------- Variants @@ -381,9 +420,9 @@ that it walks. Let's add a variant to allow users to set this when they build in Spack. To do this, we'll add a variant to our package, as per the following (see -``$SPACK_ROOT/lib/spack/docs/tutorial/examples/4.package.py``): +``$SPACK_ROOT/lib/spack/docs/tutorial/examples/5.package.py``): -.. literalinclude:: tutorial/examples/4.package.py +.. literalinclude:: tutorial/examples/5.package.py :lines: 25- :language: python @@ -394,18 +433,15 @@ configure line (output truncated for length): .. code-block:: console $ spack install --verbose mpileaks stackstart=4 + ... ==> Installing mpileaks - ==> openmpi is already installed in /usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/openmpi-2.0.1-5ee5j34c2y4kb5c3joygrgahidqnwhnz - ==> callpath is already installed in /usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/callpath-1.0.2-zm4pf3gasgxeibyu2y262suktvaazube - ==> adept-utils is already installed in /usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/adept-utils-1.0.1-7p7ezxwtajdglj6cmojy2vybjct4j4jz - ==> Using cached archive: /usr/workspace/wsa/legendre/spack/var/spack/cache/mpileaks/mpileaks-1.0.tar.gz - ==> Staging archive: /usr/workspace/wsa/legendre/spack/var/spack/stage/mpileaks-1.0-otqo2opkhan5ksujt6tpmdftydrieig7/mpileaks-1.0.tar.gz - ==> Created stage in /usr/workspace/wsa/legendre/spack/var/spack/stage/mpileaks-1.0-otqo2opkhan5ksujt6tpmdftydrieig7 - ==> Ran patch() for mpileaks - ==> Building mpileaks [AutotoolsPackage] - ==> Executing phase : 'autoreconf' - ==> Executing phase : 'configure' - ==> './configure' '--prefix=/usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/mpileaks-1.0-otqo2opkhan5ksujt6tpmdftydrieig7' '--with-adept-utils=/usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/adept-utils-1.0.1-7p7ezxwtajdglj6cmojy2vybjct4j4jz' '--with-callpath=/usr/workspace/wsa/legendre/spack/opt/spack/linux-rhel7-x86_64/gcc-4.9.3/callpath-1.0.2-zm4pf3gasgxeibyu2y262suktvaazube' '--with-stack-start-c=4' '--with-stack-start-fortran=4' + ==> Using cached archive: SPACK_ROOT/var/spack/cache/mpileaks/mpileaks-1.0.tar.gz + ==> Staging archive: SPACK_ROOT/var/spack/stage/mpileaks-1.0-gxxi4fp57b4j6xalra5t65hyx5rj25t7/mpileaks-1.0.tar.gz + ==> Created stage in SPACK_ROOT/var/spack/stage/mpileaks-1.0-gxxi4fp57b4j6xalra5t65hyx5rj25t7 + ==> No patches needed for mpileaks + ==> Building mpileaks [Package] + ==> Executing phase: 'install' + ==> './configure' '--with-adept-utils=SPACK_ROOT/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/adept-utils-1.0.1-pm3gffhrnwsdtqthtvsfvs2tny4r65wb' '--with-callpath=SPACK_ROOT/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/callpath-1.0.4-ikbbkvfmsfmqzo624nvvrbooovf7egoc' '--prefix=SPACK_ROOT/opt/spack/linux-ubuntu16.04-x86_64/gcc-5.4.0/mpileaks-1.0-gxxi4fp57b4j6xalra5t65hyx5rj25t7' '--with-stack-start-c=4' '--with-stack-start-fortran=4' --------------- The Spec Object diff --git a/lib/spack/spack/variant.py b/lib/spack/spack/variant.py index 54b0abbab5..43a1ab4ae6 100644 --- a/lib/spack/spack/variant.py +++ b/lib/spack/spack/variant.py @@ -67,11 +67,26 @@ class Variant(object): self.default = default self.description = str(description) + self.values = None + if values is any: + # 'any' is a special case to make it easy to say any value is ok + self.single_value_validator = lambda x: True + + elif isinstance(values, type): + # supplying a type means any value *of that type* + def isa_type(v): + try: + values(v) + return True + except ValueError: + return False + self.single_value_validator = isa_type + if callable(values): # If 'values' is a callable, assume it is a single value # validator and reset the values to be explicit during debug self.single_value_validator = values - self.values = None + else: # Otherwise assume values is the set of allowed explicit values self.values = tuple(values) @@ -114,7 +129,7 @@ class Variant(object): # Check and record the values that are not allowed not_allowed_values = [ - x for x in value if not self.single_value_validator(x) + x for x in value if self.single_value_validator(x) is False ] if not_allowed_values: raise InvalidVariantValueError(self, not_allowed_values, pkg) |