Name: easybuild-life-sciences
Owner: Fred Hutchinson Cancer Research Center
Description: Howto and implementation documentation
Created: 2015-12-28 22:15:49.0
Updated: 2017-12-05 14:10:46.0
Pushed: 2018-01-11 16:59:12.0
Homepage: null
Size: 11877
Language: Python
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
Please open an issue against this repo to request new softwares!
please follow these simple steps:
adduser --disabled-password --gecos "" eb
sh -c "echo 'eb ALL=(ALL:ALL) NOPASSWD:ALL' > /etc/sudoers.d/zz_eb"
-s https://raw.githubusercontent.com/FredHutch/easybuild-life-sciences/master/easybuild_bootstrap.sh | bash
le load EasyBuild
-3.3.1-foss-2016b.eb --robot
Before and during implementation, we kept the following goals in mind:
module load R
will load R-3.2.1)You need money to make money, and you need software to build software.
build-essentials
/app
/app/easybuild
/app/easybuild/etc
to hold additional centralized configuration files/app/easybuild/fh_easyconfigs
to hold our custom easyconfig files while we are developing themEasyBuild configuration
Configuration is consistent across methods:
Easybuild applies them in that order (meaning command-line overrides everything)
Since we use Modules, it made sense to use Environment Variables in our case
In the easybuild modulefile, I added the following:
!Tcl
set ebDir "/app/easybuild"
setenv EASYBUILD_SOURCEPATH "$ebDir/sources"
setenv EASYBUILD_BUILDPATH "$ebDir/build"
setenv EASYBUILD_INSTALLPATH_SOFTWARE "$ebDir/software"
setenv EASYBUILD_INSTALLPATH_MODULES "$ebDir/modules"
setenv EASYBUILD_REPOSITORYPATH "$ebDir/ebfiles_repo"
setenv EASYBUILD_LOGFILE_FORMAT "$ebDir/logs,easybuild-%(name)s-%(version)s-%(date)s.%(time)s.log"
The modulefile is a tcl snippet and this sets environment variables for us.
!Tcl
# keep group writable bit
setenv EASYBUILD_GROUP_WRITABLE_INSTALLDIR 1
# set umask to preserve group write permissions on modulefiles
setenv EASYBUILD_UMASK 002
# create module dependencies to recursively unload
setenv EASYBUILD_RECURSIVE_MODULE_UNLOAD 1
# add our normal modulefile footer
setenv EASYBUILD_MODULES_FOOTER "$ebDir/etc/fredhutch_modulefile_footer"
# add our own easyconfig directory to robot paths
setenv EASYBUILD_ROBOT_PATHS ":$ebDir/fh_easyconfigs"
# Our licenses
setenv LM_LICENSE_FILE "$ebDir/etc/licenses/intel.lic"
These are more complex, and will be documented soon.
There are a number of manual steps that were performed that can best be described as messy, and also perhaps make up the bulk of the useful information here.
Since we decided to have building be performed by members of a POSIX group, and we want produced software and modules centrally located for the use of everyone, we have to tell Easybuild how to do that.
GROUP_WRITABLE_INSTALLDIR
- this lets our group write to easybuild-created directoriesUMASK 002
- this tells Easybuild to set this umask when writing directories/filesOf course, some manual adjusting was needed:
chgrp -R <build group> /app/easybuild/*
- change to our build group from the default group of the installer accountchmod -R g+s /app/easybuild/*
- setgid bit for dirs created during bootstrapRECURSIVE_MODULE_UNLOAD 1
- this causes Easybuild to create modulefiles that will auto-load and auto-unload dependent modulesROBOT_PATHS <path>
- adds our local easyconfig development dir to robot pathsLM_LICENSE_FILE <file>
- where our licenses are locatedmodule load Easybuild/2.3.0
everytime for everyoneMODULES_FOOTER
- code to include in every modulefile created by EasybuildEx:
!Tcl
set curMod [module-info name]
if { [module-info mode load] } {
system "logger \$USER module load $curMod "
}
To use:
$ module use /app/easybuild/modules/all
$ module load EasyBuild/2.3.0
$ eb --version
This is EasyBuild 2.3.0 (framework: 2.3.0, easyblocks: 2.3.0) on host rhino-d.
Once you have EasyBuild bootstrapped, you can search for and build a package:
Begin by searching:
$ eb -S PCRE
== temporary log file in case of crash /tmp/eb-lz7d_6/easybuild-dKc03x.log
== Searching (case-insensitive) for 'PCRE' in /app/easybuild/software/EasyBuild/2.3.0/lib/python2.7/site-packages/easybuild_easyconfigs-2.3.0-py2.7.egg/easybuild/easyconfigs
== Searching (case-insensitive) for 'PCRE' in /app/easybuild/fh_easyconfigs
CFGS1=/app/easybuild/software/EasyBuild/2.3.0/lib/python2.7/site-packages/easybuild_easyconfigs-2.3.0-py2.7.egg/easybuild/easyconfigs/p/PCRE
* $CFGS1/PCRE-8.12-goalf-1.1.0-no-OFED.eb
* $CFGS1/PCRE-8.12-goolf-1.4.10.eb
* $CFGS1/PCRE-8.12-ictce-4.0.6.eb
* $CFGS1/PCRE-8.12-ictce-5.3.0.eb
* $CFGS1/PCRE-8.12-ictce-5.5.0.eb
* $CFGS1/PCRE-8.35-intel-2014b.eb
* $CFGS1/PCRE-8.36-foss-2015a.eb
* $CFGS1/PCRE-8.36-intel-2015a.eb
* $CFGS1/PCRE-8.37-intel-2015a.eb
== Tmporary log file(s) /tmp/eb-lz7d_6/easybuild-dKc03x.log* have been removed.
== Temporary directory /tmp/eb-lz7d_6 has been removed.
We found 9 different easyconfigs for PCRE. Let's build this one:
PCRE-8.36-foss-2015a.eb
You probably figured out that 8.36
is the version of PCRE we will build, but what is foss
?
That is the Easybuild toolchain for this easyconfig. You can get a list of toolchains with:
eb --list-toolchains
I prefer to just browse the repo - toolchains are just another easyconfig to Easybuild.
Once we have decided what to build, you can do a dry-run like this:
$ eb PCRE-8.36-foss-2015a.eb --robot --dry-run
== temporary log file in case of crash /tmp/eb-08QTaF/easybuild-r5D8gf.log
Dry run: printing build status of easyconfigs and dependencies
CFGS=/app/easybuild/software/EasyBuild/2.3.0/lib/python2.7/site-packages/easybuild_easyconfigs-2.3.0-py2.7.egg/easybuild/easyconfigs
* [x] $CFGS/g/GCC/GCC-4.9.2.eb (module: GCC/4.9.2)
* [x] $CFGS/o/OpenBLAS/OpenBLAS-0.2.13-GCC-4.9.2-LAPACK-3.5.0.eb (module: OpenBLAS/0.2.13-GCC-4.9.2-LAPACK-3.5.0)
* [x] $CFGS/l/libtool/libtool-2.4.2-GCC-4.9.2.eb (module: libtool/2.4.2-GCC-4.9.2)
* [x] $CFGS/m/M4/M4-1.4.17-GCC-4.9.2.eb (module: M4/1.4.17-GCC-4.9.2)
* [x] $CFGS/a/Autoconf/Autoconf-2.69-GCC-4.9.2.eb (module: Autoconf/2.69-GCC-4.9.2)
* [x] $CFGS/a/Automake/Automake-1.15-GCC-4.9.2.eb (module: Automake/1.15-GCC-4.9.2)
* [x] $CFGS/n/numactl/numactl-2.0.10-GCC-4.9.2.eb (module: numactl/2.0.10-GCC-4.9.2)
* [x] $CFGS/h/hwloc/hwloc-1.10.0-GCC-4.9.2.eb (module: hwloc/1.10.0-GCC-4.9.2)
* [x] $CFGS/o/OpenMPI/OpenMPI-1.8.4-GCC-4.9.2.eb (module: OpenMPI/1.8.4-GCC-4.9.2)
* [x] $CFGS/g/gompi/gompi-2015a.eb (module: gompi/2015a)
* [x] $CFGS/f/FFTW/FFTW-3.3.4-gompi-2015a.eb (module: FFTW/3.3.4-gompi-2015a)
* [x] $CFGS/s/ScaLAPACK/ScaLAPACK-2.0.2-gompi-2015a-OpenBLAS-0.2.13-LAPACK-3.5.0.eb (module: ScaLAPACK/2.0.2-gompi-2015a-OpenBLAS-0.2.13-LAPACK-3.5.0)
* [x] $CFGS/f/foss/foss-2015a.eb (module: foss/2015a)
* [ ] $CFGS/p/PCRE/PCRE-8.36-foss-2015a.eb (module: PCRE/8.36-foss-2015a)
== Tmporary log file(s) /tmp/eb-08QTaF/easybuild-r5D8gf.log* have been removed.
== Temporary directory /tmp/eb-08QTaF has been removed.
By giving the -r
flag to Easybuild:
X
And finally, you can remove the '-D' and build the software:
$ eb PCRE-8.36-foss-2015a.eb --robot --force
== temporary log file in case of crash /tmp/eb-1TnpU8/easybuild-3J4ttj.log
== resolving dependencies ...
== processing EasyBuild easyconfig /app/easybuild/software/EasyBuild/2.3.0/lib/python2.7/site-packages/easybuild_easyconfigs-2.3.0-py2.7.egg/easybuild/easyconfigs/p/PCRE/PCRE-8.36-foss-2015a.eb
== building and installing PCRE/8.36-foss-2015a...
== fetching files...
== creating build dir, resetting environment...
== unpacking...
== patching...
== preparing...
== configuring...
== building...
== testing...
== installing...
== taking care of extensions...
== postprocessing...
== sanity checking...
== cleaning up...
== creating module...
== permissions...
== packaging...
== COMPLETED: Installation ended successfully
== Results of the build can be found in the log file /app/easybuild/logs/easybuild-PCRE-8.36-20160104.164159.log
== Build succeeded for 1 out of 1
== Tmporary log file(s) /tmp/eb-1TnpU8/easybuild-3J4ttj.log* have been removed.
== Temporary directory /tmp/eb-1TnpU8 has been removed.
Again, RTFM - it is very good!
There are two reason rou might want to modify or build an easyconfig file:
I'll demonstrate creating a new easyconfig as the procedure is the same, only generally easier for version updates.
Easybuild logic is contained in easyblocks - these are what execute the build. You can get a list of easyblocks with: eb --list-easyblocks
.
There are a number of mandatory parameters for each easyblock, which can be displayed with:
eb -a -e <easyblock>
For this explanation, we will use the ConfigureMake
easyblock, which should be familiar to anyone who has manually built software: ./configure && make && make install
.
The naming convention is typically <name>-<version>-<toolchain name>-<toolchain version>.eb
.
This is a skeleton ConfigureMake easyconfig with all mandatory parameters:
!python
easyblock = 'ConfigureMake'
name =
version =
toolchain =
description =
homepage =
docurls =
software_license =
software_license_urls =
Except for easyblock, these will all default to None
if not supplied in the file (so I guess they are not really mandatory, huh?)
name
This name is the name of the software package, will be the name of the modulefile, and will be in the path of the software install directory. It is sometimes referenced later in the easyconfig file.
Ex:
!python
name = 'zlib'
version
This is the version of the software to build. It is referenced later in the easyconfig file.
Ex:
!python
version = '1.2.8'
toolchain
This is the toolchain (compilers, supplemental libraries, etc.) that easybuild will use to build the software. It must be specified in an existing easyconfig (though does not need to be pre-built - easybuild will take care of building it).
Ex:
!python
toolchain = {'name': 'foss', 'version': '2015b'}
This is a python dict specifying the name and version of the toolchain.
description
This is a generally free-form description that will appear as metadata in the modulefile, and therefore be availabe to users through the module
command.
Ex:
!python
description = """zlib is designed to be a free, general-purpose, legally
unencumbered -- that is, not covered by any patents --
lossless data-compression library for use on virtually any
computer hardware and operating system."""
homepage
This is a URL also included in modulefile metadata. It should be the homepage of the software.
Ex:
!python
homepage = 'http://www.zlib.net/'
We will need to specify a few more parameters for easybuild to handle things correctly:
!python
sources =
source_urls =
These will specify where easybuild should find the sourcecode for the software package. There are some shortcuts:
[SOURCELOWER_TAR_GZ]
to produce <name>-<version>.tar.gz
%{version}s
and %{name}s
to use name
and version
from the easyconfigEx:
!python
sources = [SOURCELOWER_TAR_GZ]
source_urls = ['http://sourceforge.net/projects/libpng/files/zlib/%(version)s']
These are python lists.
That should be sufficient to build a basic package. Let's see what a failure looks like.
Here is my perfect easyconfig for rsync:
!python
easyblock = 'ConfigureMake'
name = 'rsync'
version = '3.1.2'
toolchain = {'name': 'foss', 'version': '2015b'}
description = """rsync is an open source utility that provides fast incremental file transfer"""
homepage = 'https://rsync.samba.org'
sources = [SOURCELOWER_TAR_GZ]
source_urls = ['https://download.samba.org/pub/rsync/src/rsync-3.1.2.tar.gz']
I save this as rsync-3.1.2-foss-2015b.eb
and it should build!
$ eb rsync-3.1.2-foss-2015b.eb
== temporary log file in case of crash /tmp/eb-j_sVge/easybuild-cY3SFZ.log
== processing EasyBuild easyconfig /app/easybuild/fh_easyconfigs/rsync-3.1.2-foss-2015b.eb
== building and installing rsync/3.1.2-foss-2015b...
== fetching files...
== creating build dir, resetting environment...
== unpacking...
== patching...
== preparing...
== configuring...
== building...
== testing...
== installing...
== taking care of extensions...
== postprocessing...
== sanity checking...
== FAILED: Installation ended unsuccessfully (build directory: /app/easybuild/build/rsync/3.1.2/foss-2015b): build failed (first 300 chars): Sanity check failed: no dir of ('lib', 'lib64') in /app/easybuild/software/rsync/3.1.2-foss-2015b
== Results of the build can be found in the log file /tmp/eb-j_sVge/easybuild-rsync-3.1.2-20160107.110632.Lepgl.log
ERROR: Build of /app/easybuild/fh_easyconfigs/rsync-3.1.2-foss-2015b.eb failed (err: "build failed (first 300 chars): Sanity check failed: no dir of ('lib', 'lib64') in /app/easybuild/software/rsync/3.1.2-foss-2015b")
We can look into the logfile mentioned (Results of the build can be found in the log file /tmp/eb-j_sVge/easybuild-rsync-3.1.2-20160107.110632.Lepgl.log
') but in this case, the error is shown:
Sanity check failed: no dir of ('lib', 'lib64') in /app/easybuild/software/rsync/3.1.2-foss-2015b
And a quick search of sanity check
in the Easybuild docs reveals that by default bin
and lib
or lib64
must not be empty after install. Rsync builds no lib
directory, so we add the following to the easyconfig file:
sanity_check_paths = {'dirs': ['bin','share'], 'files': ['bin/rsync']}
And now it builds (trust me).
An interesting note I expected this build to fail as version 3.1.2
of rsync is distributed in rsync-3.1.2.tar.gz
but is not actually compressed, only a tarball. Easybuild built it anyway!