.. Copyright 2013-2018 Lawrence Livermore National Security, LLC and other Spack Project Developers. See the top-level COPYRIGHT file for details. SPDX-License-Identifier: (Apache-2.0 OR MIT) .. _autotoolspackage: ---------------- AutotoolsPackage ---------------- Autotools is a GNU build system that provides a build-script generator. By running the platform-independent ``./configure`` script that comes with the package, you can generate a platform-dependent Makefile. ^^^^^^ Phases ^^^^^^ The ``AutotoolsPackage`` base class comes with the following phases: #. ``autoreconf`` - generate the configure script #. ``configure`` - generate the Makefiles #. ``build`` - build the package #. ``install`` - install the package Most of the time, the ``autoreconf`` phase will do nothing, but if the package is missing a ``configure`` script, ``autoreconf`` will generate one for you. The other phases run: .. code-block:: console $ ./configure --prefix=/path/to/installation/prefix $ make $ make check # optional $ make install $ make installcheck # optional Of course, you may need to add a few arguments to the ``./configure`` line. ^^^^^^^^^^^^^^^ Important files ^^^^^^^^^^^^^^^ The most important file for an Autotools-based package is the ``configure`` script. This script is automatically generated by Autotools and generates the appropriate Makefile when run. .. warning:: Watch out for fake Autotools packages! Autotools is a very popular build system, and many people are used to the classic steps to install a package: .. code-block:: console $ ./configure $ make $ make install For this reason, some developers will write their own ``configure`` scripts that have nothing to do with Autotools. These packages may not accept the same flags as other Autotools packages, so it is better to use the ``Package`` base class and create a :ref:`custom build system `. You can tell if a package uses Autotools by running ``./configure --help`` and comparing the output to other known Autotools packages. You should also look for files like: * ``configure.ac`` * ``configure.in`` * ``Makefile.am`` Packages that don't use Autotools aren't likely to have these files. ^^^^^^^^^^^^^^^^^^^^^^^^^ Build system dependencies ^^^^^^^^^^^^^^^^^^^^^^^^^ Whether or not your package requires Autotools to install depends on how the source code is distributed. Most of the time, when developers distribute tarballs, they will already contain the ``configure`` script necessary for installation. If this is the case, your package does not require any Autotools dependencies. However, a basic rule of version control systems is to never commit code that can be generated. The source code repository itself likely does not have a ``configure`` script. Developers typically write (or auto-generate) a ``configure.ac`` script that contains configuration preferences and a ``Makefile.am`` script that contains build instructions. Then, ``autoconf`` is used to convert ``configure.ac`` into ``configure``, while ``automake`` is used to convert ``Makefile.am`` into ``Makefile.in``. ``Makefile.in`` is used by ``configure`` to generate a platform-dependent ``Makefile`` for you. The following diagram provides a high-level overview of the process: .. figure:: Autoconf-automake-process.* :target: https://commons.wikimedia.org/w/index.php?curid=15581407 `GNU autoconf and automake process for generating makefiles `_ by `Jdthood` under `CC BY-SA 3.0 `_ If a ``configure`` script is not present in your tarball, you will need to generate one yourself. Luckily, Spack already has an ``autoreconf`` phase to do most of the work for you. By default, the ``autoreconf`` phase runs: .. code-block:: console $ libtoolize $ aclocal $ autoreconf --install --verbose --force All you need to do is add a few Autotools dependencies to the package. Most stable releases will come with a ``configure`` script, but if you check out a commit from the ``develop`` branch, you would want to add: .. code-block:: python depends_on('autoconf', type='build', when='@develop') depends_on('automake', type='build', when='@develop') depends_on('libtool', type='build', when='@develop') depends_on('m4', type='build', when='@develop') In some cases, developers might need to distribute a patch that modifies one of the files used to generate ``configure`` or ``Makefile.in``. In this case, these scripts will need to be regenerated. It is preferable to regenerate these manually using the patch, and then create a new patch that directly modifies ``configure``. That way, Spack can use the secondary patch and additional build system dependencies aren't necessary. """""""""""""""" force_autoreconf """""""""""""""" If for whatever reason you really want to add the original patch and tell Spack to regenerate ``configure``, you can do so using the following setting: .. code-block:: python force_autoreconf = True This line tells Spack to wipe away the existing ``configure`` script and generate a new one. If you only need to do this for a single version, this can be done like so: .. code-block:: python @property def force_autoreconf(self): return self.version == Version('1.2.3'): ^^^^^^^^^^^^^^^^^^^^^^^ Finding configure flags ^^^^^^^^^^^^^^^^^^^^^^^ Once you have a ``configure`` script present, the next step is to determine what option flags are available. These flags can be found by running: .. code-block:: console $ ./configure --help ``configure`` will display a list of valid flags separated into some or all of the following sections: * Configuration * Installation directories * Fine tuning of the installation directories * Program names * X features * System types * **Optional Features** * **Optional Packages** * **Some influential environment variables** For the most part, you can ignore all but the last 3 sections. The "Optional Features" sections lists flags that enable/disable features you may be interested in. The "Optional Packages" section often lists dependencies and the flags needed to locate them. The "environment variables" section lists environment variables that the build system uses to pass flags to the compiler and linker. ^^^^^^^^^^^^^^^^^^^^^^^^^^ Addings flags to configure ^^^^^^^^^^^^^^^^^^^^^^^^^^ For most of the flags you encounter, you will want a variant to optionally enable/disable them. You can then optionally pass these flags to the ``configure`` call by overriding the ``configure_args`` function like so: .. code-block:: python def configure_args(self): args = [] if '+mpi' in self.spec: args.append('--enable-mpi') else: args.append('--disable-mpi') return args Note that we are explicitly disabling MPI support if it is not requested. This is important, as many Autotools packages will enable options by default if the dependencies are found, and disable them otherwise. We want Spack installations to be as deterministic as possible. If two users install a package with the same variants, the goal is that both installations work the same way. See `here `__ and `here `__ for a rationale as to why these so-called "automagic" dependencies are a problem. By default, Autotools installs packages to ``/usr``. We don't want this, so Spack automatically adds ``--prefix=/path/to/installation/prefix`` to your list of ``configure_args``. You don't need to add this yourself. ^^^^^^^^^^^^^^^^ Helper functions ^^^^^^^^^^^^^^^^ You may have noticed that most of the Autotools flags are of the form ``--enable-foo``, ``--disable-bar``, ``--with-baz=``, or ``--without-baz``. Since these flags are so common, Spack provides a couple of helper functions to make your life easier. TODO: document ``with_or_without`` and ``enable_or_disable``. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Configure script in a sub-directory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Occasionally, developers will hide their source code and ``configure`` script in a subdirectory like ``src``. If this happens, Spack won't be able to automatically detect the build system properly when running ``spack create``. You will have to manually change the package base class and tell Spack where the ``configure`` script resides. You can do this like so: .. code-block:: python configure_directory = 'src' ^^^^^^^^^^^^^^^^^^^^^^ Building out of source ^^^^^^^^^^^^^^^^^^^^^^ Some packages like ``gcc`` recommend building their software in a different directory than the source code to prevent build pollution. This can be done using the ``build_directory`` variable: .. code-block:: python build_directory = 'spack-build' By default, Spack will build the package in the same directory that contains the ``configure`` script ^^^^^^^^^^^^^^^^^^^^^^^^^ Build and install targets ^^^^^^^^^^^^^^^^^^^^^^^^^ For most Autotools packages, the usual: .. code-block:: console $ configure $ make $ make install is sufficient to install the package. However, if you need to run make with any other targets, for example, to build an optional library or build the documentation, you can add these like so: .. code-block:: python build_targets = ['all', 'docs'] install_targets = ['install', 'docs'] ^^^^^^^ Testing ^^^^^^^ Autotools-based packages typically provide unit testing via the ``check`` and ``installcheck`` targets. If you build your software with ``spack install --test=root``, Spack will check for the presence of a ``check`` or ``test`` target in the Makefile and run ``make check`` for you. After installation, it will check for an ``installcheck`` target and run ``make installcheck`` if it finds one. ^^^^^^^^^^^^^^^^^^^^^^ External documentation ^^^^^^^^^^^^^^^^^^^^^^ For more information on the Autotools build system, see: https://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html