summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2018-07-22 17:56:53 -0700
committerTodd Gamblin <tgamblin@llnl.gov>2018-07-23 11:57:52 -0700
commitd4c4effb5e73c2af60154a9690d9eb749f59b9a4 (patch)
tree78c04af44815c43a343cf457290012db96ca643c /lib
parentbd3ffc7b76f4eda034765d1eadf507614f0ec098 (diff)
downloadspack-d4c4effb5e73c2af60154a9690d9eb749f59b9a4.tar.gz
spack-d4c4effb5e73c2af60154a9690d9eb749f59b9a4.tar.bz2
spack-d4c4effb5e73c2af60154a9690d9eb749f59b9a4.tar.xz
spack-d4c4effb5e73c2af60154a9690d9eb749f59b9a4.zip
docs: update old docs for `spack.package.PackageBase`
- There was a lot of documentation in `PackageBase` dating back to the very first versions of Spack. - It was repetitive and out of date, and the docs at spack.readthedocs.io are better. - Remove the outdated specifics, and leave the minimal useful set of developer docs in `package.py`.
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/package.py242
1 files changed, 37 insertions, 205 deletions
diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py
index 75aed2e899..3b4c5fa394 100644
--- a/lib/spack/spack/package.py
+++ b/lib/spack/spack/package.py
@@ -22,16 +22,12 @@
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
-"""
-This is where most of the action happens in Spack.
-See the Package docs for detailed instructions on how the class works
-and on how to write your own packages.
-
-The spack package structure is based strongly on Homebrew
-(http://wiki.github.com/mxcl/homebrew/), mainly because
-Homebrew makes it very easy to create packages. For a complete
-rundown on spack and how it differs from homebrew, look at the
-README.
+"""This is where most of the action happens in Spack.
+
+The spack package class structure is based strongly on Homebrew
+(http://brew.sh/), mainly because Homebrew makes it very easy to create
+packages.
+
"""
import base64
import contextlib
@@ -313,209 +309,39 @@ class PackageBase(with_metaclass(PackageMeta, PackageViewMixin, object)):
***The Package class***
- Package is where the bulk of the work of installing packages is done.
-
- A package defines how to fetch, verfiy (via, e.g., md5), build, and
- install a piece of software. A Package also defines what other
+ A package defines how to fetch, verify (via, e.g., sha256), build,
+ and install a piece of software. A Package also defines what other
packages it depends on, so that dependencies can be installed along
- with the package itself. Packages are written in pure python.
-
- Packages live in repositories (see repo.py). If spack is installed
- in ``$prefix``, all of its built-in package files are in the builtin
- repo at ``$prefix/var/spack/repos/builtin/packages``.
-
- All you have to do to create a package is make a new subclass of Package
- in this directory. Spack automatically scans the python files there
- and figures out which one to import when you invoke it.
-
- **An example package**
-
- Let's look at the cmake package to start with. This package lives in
- ``$prefix/var/spack/repos/builtin/packages/cmake/package.py``:
-
- .. code-block:: python
-
- from spack import *
- class Cmake(Package):
- homepage = 'https://www.cmake.org'
- url = 'http://www.cmake.org/files/v2.8/cmake-2.8.10.2.tar.gz'
- md5 = '097278785da7182ec0aea8769d06860c'
-
- def install(self, spec, prefix):
- configure('--prefix=%s' % prefix,
- '--parallel=%s' % make_jobs)
- make()
- make('install')
-
- **Naming conventions**
-
- There are two names you should care about:
-
- 1. The module name, ``cmake``.
-
- * User will refers to this name, e.g. 'spack install cmake'.
- * It can include ``_``, ``-``, and numbers (it can even start with a
- number).
-
- 2. The class name, "Cmake". This is formed by converting `-` or
- ``_`` in the module name to camel case. If the name starts with
- a number, we prefix the class name with ``_``. Examples:
-
- =========== ==========
- Module Name Class Name
- =========== ==========
- foo_bar FooBar
- docbook-xml DocbookXml
- FooBar Foobar
- 3proxy _3proxy
- =========== ==========
-
- The class name is what spack looks for when it loads a package module.
-
- **Required Attributes**
-
- Aside from proper naming, here is the bare minimum set of things you
- need when you make a package:
-
- homepage:
- informational URL, so that users know what they're
- installing.
-
- url or url_for_version(self, version):
- If url, then the URL of the source archive that spack will fetch.
- If url_for_version(), then a method returning the URL required
- to fetch a particular version.
-
- install():
- This function tells spack how to build and install the
- software it downloaded.
-
- **Optional Attributes**
+ with the package itself. Packages are written in pure python by
+ users of Spack.
- You can also optionally add these attributes, if needed:
+ There are two main parts of a Spack package:
- list_url:
- Webpage to scrape for available version strings. Default is the
- directory containing the tarball; use this if the default isn't
- correct so that invoking 'spack versions' will work for this
- package.
+ 1. **The package class**. Classes contain ``directives``, which are
+ special functions, that add metadata (versions, patches,
+ dependencies, and other information) to packages (see
+ ``directives.py``). Directives provide the constraints that are
+ used as input to the concretizer.
- url_version(self, version):
- When spack downloads packages at particular versions, it just
- converts version to string with str(version). Override this if
- your package needs special version formatting in its URL. boost
- is an example of a package that needs this.
+ 2. **Package instances**. Once instantiated, a package is
+ essentially an installer for a particular piece of
+ software. Spack calls methods like ``do_install()`` on the
+ ``Package`` object, and it uses those to drive user-implemented
+ methods like ``patch()``, ``install()``, and other build steps.
+ To install software, An instantiated package needs a *concrete*
+ spec, which guides the behavior of the various install methods.
- ***Creating Packages***
+ Packages are imported from repos (see ``repo.py``).
- As a package creator, you can probably ignore most of the preceding
- information, because you can use the 'spack create' command to do it
- all automatically.
+ **Package DSL**
- You as the package creator generally only have to worry about writing
- your install function and specifying dependencies.
-
- **spack create**
-
- Most software comes in nicely packaged tarballs, like this one
-
- http://www.cmake.org/files/v2.8/cmake-2.8.10.2.tar.gz
-
- Taking a page from homebrew, spack deduces pretty much everything it
- needs to know from the URL above. If you simply type this::
-
- spack create http://www.cmake.org/files/v2.8/cmake-2.8.10.2.tar.gz
-
- Spack will download the tarball, generate an md5 hash, figure out the
- version and the name of the package from the URL, and create a new
- package file for you with all the names and attributes set correctly.
-
- Once this skeleton code is generated, spack pops up the new package in
- your $EDITOR so that you can modify the parts that need changes.
-
- **Dependencies**
-
- If your package requires another in order to build, you can specify that
- like this:
-
- .. code-block:: python
-
- class Stackwalker(Package):
- ...
- depends_on("libdwarf")
- ...
-
- This tells spack that before it builds stackwalker, it needs to build
- the libdwarf package as well. Note that this is the module name, not
- the class name (The class name is really only used by spack to find
- your package).
-
- Spack will download and install each dependency before it installs your
- package. In addtion, it will add -L, -I, and rpath arguments to your
- compiler and linker for each dependency. In most cases, this allows you
- to avoid specifying any dependencies in your configure or cmake line;
- you can just run configure or cmake without any additional arguments and
- it will find the dependencies automatically.
-
- **The Install Function**
-
- The install function is designed so that someone not too terribly familiar
- with Python could write a package installer. For example, we put a number
- of commands in install scope that you can use almost like shell commands.
- These include make, configure, cmake, rm, rmtree, mkdir, mkdirp, and
- others.
-
- You can see above in the cmake script that these commands are used to run
- configure and make almost like they're used on the command line. The
- only difference is that they are python function calls and not shell
- commands.
-
- It may be puzzling to you where the commands and functions in install live.
- They are NOT instance variables on the class; this would require us to
- type 'self.' all the time and it makes the install code unnecessarily long.
- Rather, spack puts these commands and variables in *module* scope for your
- Package subclass. Since each package has its own module, this doesn't
- pollute other namespaces, and it allows you to more easily implement an
- install function.
-
- For a full list of commands and variables available in module scope, see
- the add_commands_to_module() function in this class. This is where most
- of them are created and set on the module.
-
- **Parallel Builds**
-
- By default, Spack will run make in parallel when you run make() in your
- install function. Spack figures out how many cores are available on
- your system and runs make with -j<cores>. If you do not want this
- behavior, you can explicitly mark a package not to use parallel make:
-
- .. code-block:: python
-
- class SomePackage(Package):
- ...
- parallel = False
- ...
-
- This changes the default behavior so that make is sequential. If you still
- want to build some parts in parallel, you can do this in your install
- function:
-
- .. code-block:: python
-
- make(parallel=True)
-
- Likewise, if you do not supply parallel = True in your Package, you can
- keep the default parallel behavior and run make like this when you want a
- sequential build:
-
- .. code-block:: python
-
- make(parallel=False)
+ Look in ``lib/spack/docs`` or check https://spack.readthedocs.io for
+ the full documentation of the package domain-specific language. That
+ used to be partially documented here, but as it grew, the docs here
+ became increasingly out of date.
**Package Lifecycle**
- This section is really only for developers of new spack commands.
-
A package's lifecycle over a run of Spack looks something like this:
.. code-block:: python
@@ -541,8 +367,14 @@ class PackageBase(with_metaclass(PackageMeta, PackageViewMixin, object)):
package writers to override, and doing so may break the functionality
of the Package class.
- Package creators override functions like install() (all of them do this),
- clean() (some of them do this), and others to provide custom behavior.
+ Package creators have a lot of freedom, and they could technically
+ override anything in this class. That is not usually required.
+
+ For most use cases. Package creators typically just add attributes
+ like ``url`` and ``homepage``, or functions like ``install()``.
+ There are many custom ``Package`` subclasses in the
+ ``spack.build_systems`` package that make things even easier for
+ specific build systems.
"""
#