Jean-Paul,
Thank you for sharing the code. After reviewing it, I am increasingly sure that ``spack spconfig`` will be useful for you.
First... I think a little "philosophy" is in order. In the old days, we had just Makefiles. To build your project, you just said "make." I'll call that a 1-stage build process. Then we got Autotools and now CMake. To build your project, you say "configure; make". The extra configure step, while a bit inconvenient, has proven its worth over the years and been generally accepted. Past approaches, which conflated the configure and build steps into a single build step, have fallen by the wayside.
The use of Spack actually extends that process further, to a three-stage process:
1. Run Spack to find your dependencies
2. Configure/CMake
3. make
This three-stage process corresponds to three things that need to happen:
1. Set up the build, making the appropriate dependencies available.
2. Once dependencies have been made available, determine how they will be used to create a build plan.
3. Build the software.
Before I had Spack, I would do step 1 manually. Generally, I would make a small site-specific script that would call CMake, giving it the right hints to find everything (eg by setting EIGEN3_ROOT_DIR). For example, here's how I built a particular piece of software in the pre-Spack era, when I used MacPorts to build my prerequisites. Note the variables FEXCEPTION_ROOT and NETCDF_INCLUDES, which provide CMake hints on where to find things.
```
#!/bin/sh
MACPORTS=$HOME/macports
export BOOST_INCLUDEDIR=$BOOST_ROOT/include
export BOOST_LIBRARYDIR=$BOOST_ROOT/lib
cmake \
-DCMAKE_CXX_COMPILER=g++ \
-DCMAKE_C_COMPILER=gcc \
-DCMAKE_Fortran_COMPILER=gfortran \
-DCOMPILE_WITH_TRAPS=YES -DCOMPILE_WITH_DEBUG=YES \
-DCMAKE_INSTALL_PREFIX:PATH=$HOME/opt/modele \
-DNETCDF_INCLUDES=$MACPORTS/include \
-DUSE_FEXCEPTION=YES -DFEXCEPTION_ROOT=$HOME/opt/fexception \
-DRUNDECK=$1 \
$2
```
In this paridigm, Step 1 (the setup stage) was manual. Step 2 was handled by CMake, and then Step 3 by make.
With Spack, Step 1 becomes a little easier. My first thought was to write a script similar to the one above, with a bunch of ``spack location -i`` calls in it. That would (almost) work reliably, and would work across different platforms. So it would have been a big step up from what I was doing before.
But then I realized that writing a bunch of ``spack location -i`` commands is the same amount of work as writing a Spack package, but less functional. Less functional because:
(a) It can't be used to easily distribute my software to others
(b) Unless you have a ``package.py`` file, other software can't depend on your package and be built by Spack. This leads to an ever-increasing list of code, built by you, that you have to build manually.
(c) ``spack location`` can fail if you have more than one version of a package installed.
(d) You don't get the benefits of the Spack concretization algorithm in the setup step. For example, Spack ensures that all your prerequisites use consistent versions of all THEIR prerequisites (for example, they're all built with the same compiler and use the same MPI). If you write a bunch of ``spack location`` calls, you lose all such guarantees.
(e) You have to manually issue the Spack commands to install all the prerequisites listed in your ``spack location`` calls. If you re-build your Spack repo (or move to a new compiler), you have to issue all those commands again (rather than just ``spack spconfig myproject``, which would automatically rebuild all your prerequisites).
For all these reasons, I made the ``spack spconfig`` command, which essentially writes one of those setup scripts for you in a Spack-consistent manner. I'm attaching a sample Spack-generated setup script (``spconfig.py``), which replaces the hand-generated script I shared above.
In any case, I think it's important to understand the setup step as a separate step that happens BEFORE the configure step. Configure/CMake will find the prerequisites needed for your software, but with caveats: (a) they can only find what you've set up for them, and (b) they don't know what to do if more than one version is available. Increasingly, modern systems have multiple versions of packages installed. Which increases the importance of being intentional in the setup step, to make sure the configure step sees the right versions. The sample you shard conflates the setup and build steps, which is a bad idea.
Spack automates the setup step and removes a lot of drudgery. Rather than poking around your filesystem, you can say "spack spec" and see what Spack intends to install. You can fiddle with your Spack specification until you like what you see. Then you say ``spack spconfig`` to complete the setup step --- or ``spack install`` to do the setup, configure and build steps all automatically.
Please, let Spack do its thing. It's not just for installing your prerequisites, it can help you every step of the way in your software development process.
------------------------------------------------
Here are my comments on the sample you shared:
1. **gmp_eigen.patch**: These are good changes, and need to be submitted back to Spack. Please fork the main Spack repo, create a new branch in your forked repo, and submit them as pull requests. There's a small learning curve with this, but I believe it's well worth the effort (and there is plenty of help on-line, or one of us can show you how).
Forking is a good idea because (a) it allows you to submit pull requests, (b) it allows you to make "fixes" or trial fixes to the code, (c) it allows you to maintain a stable version on your own branch, suitable for installing your project. Every time you pull from the main develop branch, you can expect at least a lot of things to rebuilt, just baed on new package versions people have submitted.
2. Do not clone Spack into ``~/.spack``, since that directory is already used for Spack configurations. Once you've set up your own fork of Spack, you won't need this clone-and-patch step anyway (you'll just clone from your own fork on GitHu).
3. If you have commands you want to be available in general, you should use ``spack load`` to load the corresponding environment module (instead of aliasing cmake). Or (since Spack runs slowly)... use Spack once to figure out which modules to use, and then put ``module load`` commands in your ``.bashrc``. Ubuntu 14.04 has environment modules built-in (do ``apt-get install environment-modules``). Or you can have Spack install them (see "Installing Environment Modules" at
https://github.com/LLNL/spack/blob/develop/lib/spack/docs/basic_usage.rst ).
As with GitHub forks... learning environment modules is well worth the effort. They are really super, and becoming pretty widespread in the HPC world. They should work on Mac as well as Linux.
4. I repeat... making your CMake build depend on Spack is a bad idea. Many reasons for this (in no particular order):
a) ``spack location`` is slow.
b) It limits who you can share it with
c) It brings in an unnecessary entanglement
d) Nobody else does it.
e) No one on the CMake mailing list will help you if anything doesn't work with your CMake build, even if the problem is unrelated to Spack.
f) It conflates the setup and configure steps
And last but certainly not least...
g) ``spack location -i eigen`` will fail as soon as you have more than one version of eigen installed. Which will happen as soon as someone updates one of Eigen's dependencies, or you build with an alternate compiler, or a zillion other reasons.
Here is a CMake project that uses Eigen:
I HIGHLY (10 out of 10) recommend you follow the example in that CMake-based project, or something else equivalent. Once you've done that, I VERY MUCH (8 out of 10) recommend that you give ``spack spconfig`` a try. It was designed for exactly your situation. I also recommend you get familiar with environment modules.
-- Elizabeth