Hi Ben,

On 15/10/14 03:17, Ben Roberts wrote:
Hi list,

I’m trying to install Amber 12 with Easybuild. My current version of the 
framework is the latest checkout of the “develop” branch from git: commit 
3c4976c5f0ea5dad572f6ed3c014380b299e2d7a.

I’m having trouble because the Amber installation process, being inherently 
non-standard, is interacting strangely with the Easybuild process.

An overview of the Amber build process is as follows:

1. Download and extract the Amber tarball (extracts to “amber12”)
2. Download and extract the AmberTools tarball (also extracts into “amber12”)
3. Change into the “amber12” directory
4. Set the AMBERHOME environment variable to the amber12 directory
5. Run “configure” with options for a serial build
6. Run “make install” — note that this combines the functionality of “make” and 
“make install” into a single step, and builds AmberTools and Amber in situ
7. Run “make test”
8. Run “make clean” to delete serial-specific object files, etc.
9. Run “configure” again with options for a parallel build
10. Run “make install”
11. Run “make test.parallel”
12. Run “make clean”
13. Run “configure” again with options for a CUDA build
14. Run “make install”
15. Run “make test.cuda”
16. Optionally, run “make clean”

I’ve attached my easyconfig and easyblock for your information.

The particular issue I’m having is the interplay of three features of this 
build. One is that the build and install directories are the same, so that I’ve 
used the “buildininstalldir” option in my easyconfig. The other is that it’s 
necessary to keep at least some parts of the serial installation around for 
parallel and CUDA builds, so that deleting the install directory between builds 
is not an option. The third is the use of multiple configure calls, to reflect 
the staged nature of the build.

You can probably already see where I’m going with this, which is the method 
“make_builddir” in easybuild-framework/easybuild/framework/easyblock.py. This 
method, if “buildininstalldir” is set, will force a “cleanupoldbuild” and veto 
a “keeppreviousinstall” (line 641ff.), regardless of any options to the 
contrary that I set in the easyconfig.

How can I get around this? Is there an option that can be implemented to deal 
with staged builds of this sort, the prospect of overloading the make_builddir 
method in my easyblock, or some other solution that I haven’t floated yet?
Since you already have a dedicated easyblock for Amber, you should push as much as possible in there, and keep Amber easyconfigs absolutely minimal. That is: move defining the configure options and test targets in the easyblock, set self.build_in_installdir = True in the easyblock (see the WRF easyblock for example), move the custom sanity check to the easyblock, etc.

Combining a custom easyblock together with the support for using a list of strings for configopts/buildopts/installopts (rather a single string) is indeed tricky, and the build_in_installdir requirements isn't exactly helping either. Basically, it boils down to the observation that Amber doesn't fit the step-wise approach for configure/build/install that EasyBuild uses...

Here's what I would do: leave both the configure_step and install_step empty in the easyblock for Amber, and run the whole procedure in the build_step (or, alternatively, in the install_step, and leave the build_step empty). Since only the configure options and the test command are different, you can probably implement this as a simple for-loop.

For example (totally untested, but it should give you an idea):

### START of untested build_step implementation for Amber

# define $AMBERHOME and move to right subdirectory for build
amber_dir = os.path.join(self.installdir, 'amber%s' % self.version)
env.setvar('AMBERHOME', amber_dir)
try:
    os.chdir(amber_dir)
except OSError, err:
    self.log.error("Failed to change to %s: %s" % (amber_dir, err))

# make sure $LIBS is unset, since it may break the build
if 'LIBS' in os.environ:
    del os.environ['LIBS']

# set required environment variables

# note: what if another BLAS/LAPACK lib is used?
imkl_root = get_software_root('imkl')
if imkl_root:
    env.setvar('MKL_HOME', imkl_root)

# note: not sure if this would also work with MPI libs other than impi?
for mpilib in ['impi', 'OpenMPI', 'MVAPICH2', 'MPICH2']:
    mpi_root = get_software_root(mpilib)
    if mpi_root:
        env.setvar('MPI_HOME', mpi_root)

# list of common configure options, including dependency-specific options
common_configopts = ["--no-updates"]
netcdf_root = get_software_root('netCDF')
if netcdf_root:
    common_configopts.append("--with-netcdf %s" % netcdf_root)
python_root = get_software_root('Python')
if python_root:
common_configopts.append("--with-python %s" % os.path.join(python_root, 'bin', 'python'))

# hardcoded for Intel compilers, what if another compiler is used?
# use self.toolchain.comp_family(), compare with toolchain.INTELCOMP, toolchain.GCC, etc?
config_target = "intel"

# list of make targets + corresponding test target
targets = [('', 'test')]
if self.toolchain.options.get('usempi', None):
    targets.append(('-mpi', 'test.parallel'))
cuda_root = get_software_root('CUDA')
if cuda_root:
    env.setvar('CUDA_HOME', cuda_root)
    targets.append(('-cuda', 'test.cuda'))

# configure/build/test/clean for each target
for target_configopt, target_test in targets:
    # configure
self.cfg['configopts'] = ' '.join(common_configopts + [target_configopt, config_target])
    super(EB_Amber, self).configure_step()
    # build (in-situ) using 'make install'
    super(EB_Amber, self).install_step()
    # make test
    self.cfg['runtest'] = target_test
    super(EB_Amber, self).test_step()
    # make clean
    self.cfg['buildopts'] = 'clean'
    super(EB_Amber, self).build_step()

### END of untested build_step implementation for Amber

Other remarks:

* Name the easyblock class 'EB_Amber' rather than 'Amber', that way EB will auto-determine it should use that based on the software name. * I'm not sure what you're trying to achieve with the self.already_extracted check in extract_step? This seemsto mean the 2nd source file will not be unpacked, is that what you're aiming for? * The patchlevels should be part of the versionsuffix somehow, to distinguish between Amber builds with different patch levels? * What's the problem with the currently commented out code in make_module_extra?

Don't hesitate to ask further questions. Maybe it's worthwhile to set up a conf call to discuss this further at some point (if the time of the day is decent on both ends ;-)), let me know.


regards,

Kenneth

Reply via email to