Do stuff with Wire-Cell in a Singularity container.
Download/copy the following script somewhere in your $PATH
and make sure it is executable.
To assist in getting updates you may wish to clone this repository and
symlink wcdo.sh
into a directory in your $PATH
.
Pick a directory with several GB of space to work in and run a few
wcdo.sh
commands run in your native OS (the container host OS):
$ mkdir -p ~/wcdo/example $ cd ~/wcdo/example $ wcdo.sh init $ wcdo.sh wct $ wcdo.sh get-image sl7 $ wcdo.sh make-project myproj sl7 $ ./wcdo-myproj.sh
With this last command, you are now inside the container environment. Many bash functions are available and may be discovered with tab-completion:
[sl7]bviren@hierocles:example> wcdo-TAB
Most have a ”wcdo-*-help
” function that will print some help:
[sl7]bviren@hierocles:example> wcdo-wirecell-path-help Set or display the WIRECELL_PATH usage: wcdo-wirecell-path [ default <path> <path> ... ] With no argument, print the current path. A special "<path>" given as the literal string "default" will cause the default directories for the container to be used. Otherwise a <path> argument is prepended. Note: the UPS product "wirecell" destroys the WIRECELL_PATH so this function will be useful after any "setup" of "wirecell" UPS product.
Each of the wcdo.sh
native OS commands above are now described.
Most importantly, users should read the last section describing the
make-project
command and customizing the files it produces.
$ wcdo.sh init
This prepares your current working directory to follow some conventions.
- makes some sub-directory stubs
- initializes an empty UPS products directory
- downloads a recent copy of wcdo.rc for later use
This command downloads Wire-Cell Toolkit source and data/cfg packages.
$ wcdo.sh wct [access branch]
Running this is the same as individually running:
$ wcdo.sh wct-data [access branch] $ wcdo.sh wct-cfg [access branch] $ wcdo.sh wct-source [access branch]
The optional [access branch]
arguments control which GitHub URL is
used and which branch of the packages is checked out.
The access
option is one of:
anonymous
- (default) anonymous (non-authenticated) HTTP Git access to GitHub is used.
developer
- use authenticated access requiring user to supply credentials.
The branch
specifies which point in the code history to retrieve:
~ master
:: (default) tip of the master branches are retrieved
X.Y.x
- (the
.x
is literal) a release branch is retrieved.
The results of these commands are just normal local git
repositories. You are free to evolve them as you wish either on in
your native OS or in the container.
This downloads a Singularity image based on its name. By default it simply downloads the image to the current working directory. You may instead supply a local cache directory in order to avoid redownloading the same image. A cache directory also results in the image being symlinked so you can save disk space. Finally, you can provide some other URL from which to find images. Get a little help by running with no arguments:
$ ./wcdo.sh get-image usage: wcdo get-image <name> [dir [url]] <name> an Singularity image name <dir> a local directory to find images <url> base URL to find images
This command generates files in the current working directory. Some
of these files should be modified by the user and some should not.
Scripts (ending in .sh
) contain code that executes inside your
native OS. RC files (.rc
) contain code that executes inside the
container.
These generated files should not be modified manually:
wcdo.rc
- a downloaded file holding many helpful bash functions.
wcdo-<name>.rc
- a generated RC file which defines shell environment for the project.
wcdo-<name>.sh
- a generated script which is used to enter the project of the given name.
These files are either generated or may be created by the user. The
user should modify them. They will not be overwritten by wcdo
.
wcdo-local.sh
- Any shell code written here will be run by any
wcdo-<name>.sh
script. wcdo-local-<name>.sh
- Any shell code written here will be only by the matching
wcdo-<name>.sh
script. wcdo-local.rc
- Any shell code written here will be run in the container for any project.
wcdo-local-<name>.rc
- Any shell code written here will be run in the container for only the matching project.
As already introduced, using the container is organized around the concept of a “project”. The idea is to bundle all the information for a particular task so that you may easily return to it days or weeks later after all the annoying details have long left your mind.
A wcdo
project is defined by the working directory and the set of
wcdo-*.{rc,sh}
scripts as described above.
In principle, one may produce multiple sets of the wcdo-*.{rc,sh}
files in the same working directory. However, it is possible (even
easy) to produce conflicting configurations which can not share the
same /wcdo
working directory. For example, there is a single
MRB-controlled development area mounted under /wcdo/src/mrb
which
can not support multiple sets of source packages that different wcdo
projects may want.
To assure no conflicts, it is recommended to maintain only one wcdo
working directory per project. The amount of extra storage required
to maintain this separation is minimal assuming /cvmfs
or a local
UPS “products” area is shared between the projects.
When making many projects it can help to customize some defaults, for
example the use of an image cache. This can be done in
$HOME/.wcdo/main-local.sh
. For example:
$ cat ~/.wcdo/main-local.sh # Stuff here can override wcdo.sh operation. wcdo_image_cache="$HOME/public_html/simg"
When can customize how a project’s generated start script
wcdo-<name>.sh
behaves in three places:
wcdo-local-<name>.sh
- this should hold any customization for the
particular project. It will only be included from
wcdo-<name>.sh
. wcdo-local.sh
- in a
wcdo
project workspace this file will be included in everywcdo-<name>.sh
. It is ideal for any commonalities between otherwise variations which may otherwise be expressed inwcdo-local-<name>.sh
. $HOME/.wcdo/project-local.sh
- if existing, this is included in
every
wcdo-<name>.sh
and is the place to provide global settings. For example, if directory holding thesingularity
command is not normally in your$PATH
that variable could be updated here.
You may wish to modify or augment the environment provided already by
wcdo.rc
and wcdo-<name>.rc
. Making a project creates a skeleton
of wcdo-local-<name>.rc
which names several variable which help to
reduce how many things you have to remember. You may also want to
call a few commands each time you enter the project’s container.
For example, here is a modified version of a generated
wcdo-local-<name>.rc
stub which I use for testing Clang-based
builds:
$ cat wcdo-local-cldev.rc #!/bin/bash # This is a local wcdo rc file for project cldev. # It was initally generated but is recomended for customizing by you, dear user. # It is included at the end of the main RC files. # These are optional but required if wcdo-mrb-* commands are to be used. wcdo_mrb_project_name="larsoft" wcdo_mrb_project_version="v07_07_00" wcdo_mrb_project_quals="c2:prof" # Additional variables may be usefully set since this file was # first generated. # It is perhaps useful to end this with some command to be called # on each entry to the contaner. # The wcdo-* functions try to be idempotent. source /cvmfs/larsoft.opensciencegrid.org/products/setup path-prepend $wcdo_ups_products PRODUCTS wcdo-mrb-init wcdo-mrb-add-source larwirecell bviren_v070200 v07_02_00
I have another almost identical “project” which is for testing
GCC-based builds. The only difference besides the “project” name is
the wcdo_mrb_project_quals
setting.
More examples of configuration are given below.
The directory structure is opinionated in order to reduce options/complexity. All user-accessible files are mounted at:
/wcdo
This is the same directory as used wcdo.sh init
etc in the section
Getting started. The user’s home directory is also typically mounted
by Singularity and additional directories may be mounted by modifying
the native-side .sh
files.
As mentioned above, the environment is populated with various wcdo-*
functions to try to make life with UPS/mrb easier. TAB-completion
will show a list. Running a function ending in -help
will provide
some guidance for using its associated function. You can also dump
their function bodies to see exactly what they do with the usual Bash
type
command:
$ type wcdo-mrb-goto wcdo-mrb-goto is a function wcdo-mrb-goto () { if [ -z "$MRB_TOP" ]; then wcdo-mrb-init; fi; goto $MRB_TOP }
Any global environment variables are named wcdo_*
and are kept to a
minimum and are meant to hold some static “wcdo project” information
as typically set inside the native-side .sh
files.
Here we modify the generated “stub” file wcdo-local-<name>.rc
.
Replace ”<name>
” here and below with the project name you chose.
Configure some variables that will be used to operate on the
MRB-controlled source area and to set up UPS. With the comments
deleted we have something like:
wcdo_mrb_project_name="larsoft" wcdo_mrb_project_version="v07_07_00" wcdo_mrb_project_quals="e17:prof" wcdo-ups-init path-append $wcdo_ups_products PRODUCTS
One can then run the container:
$ ./wcdo-<name>.sh
To start clean I remove any previous UPS products named “wirecell” that I might have made prior:
[sl7]bviren@hierocles:example> rm -rf /wcdo/lib/ups/wirecell [sl7]bviren@hierocles:example> setup wirecell v0_9_1a -q e17:prof [sl7]bviren@hierocles:example> wcdo-ups-declare wirecell DEVEL [sl7]bviren@hierocles:example> setup wirecell DEVEL -q e17:prof
At this point, take note that UPS does not setup up the environment
properly. In particular, LD_LIBRARY_PATH
has no entry. But, one
can go on to configure, build and install:
[sl7]bviren@hierocles:example> wcdo-ups-wct-configure-source [sl7]bviren@hierocles:wct> ./wcb -p --notests install
At this point the lib
directory exists and one must re-~setup~ the
wirecell
UPS “product” in order to unbreak the UPS environment. You
also must reset the WIRECELL_PATH
because the UPS “product” breaks
it. UPS actively hates its users.
[sl7]bviren@hierocles:wct> echo $LD_LIBRARY_PATH |tr ':' '\n'|grep wirecell [sl7]bviren@hierocles:wct> setup wirecell DEVEL -q e17:prof [sl7]bviren@hierocles:wct> echo $LD_LIBRARY_PATH |tr ':' '\n'|grep wirecell /wcdo/lib/ups/wirecell/DEVEL/Linux64bit+4.4-2.17-sl7-5-e17-prof/lib64 [sl7]bviren@hierocles:wct> wcdo-wirecell-path default [sl7]bviren@hierocles:wct> ./wcb -p --alltests ... tests that fail 0/109
In some cases you want to enter a container and assure some complex state. However, you don’t want laboriously retype command. Nor do you want to simply replay them in a simple script as rerunning them may not be needed and it wastes time.
Here is an example of a wcdo-local-<name>.rc
file which has commands
written in an “idempotent” manner. When placed in the workspace, its
commands will be replayed every time the project container is entered
and on subsequent entries the commands will complete quickly. In this
example, the commands assure that the Wire-Cell Toolkit is built
against a version of the externals from UPS. It also handles many of
the anoyingly stateful UPS setup and resetup.
wcdo_mrb_project_name="larsoft" wcdo_mrb_project_version="v07_07_00" wcdo_mrb_project_quals="c2:prof" wcdo_mrb_project_qualsm=$(echo $wcdo_mrb_project_quals | tr : -) wcdo_mrb_project_quals_=$(echo $wcdo_mrb_project_quals | tr : _) wcdo-ups-init bv_wct_ups_version=v0_9_1a bv_wct_dev_version=v091a_devel bv_wct_ups_dir=/wcdo/lib/ups/wirecell/$bv_wct_dev_version bv_wct_ups_bin_dir=$bv_wct_ups_dir/$(ups flavor)-${wcdo_mrb_project_qualsm}/bin path-append $wcdo_ups_products PRODUCTS if [ ! -d $bv_wct_ups_dir ] ; then setup wirecell $bv_wct_ups_version -q $wcdo_mrb_project_quals wcdo-ups-declare wirecell $bv_wct_dev_version fi setup wirecell $bv_wct_dev_version -q $wcdo_mrb_project_quals cd /wcdo/src/wct/ if [ ! -d /wcdo/src/wct/build ] ; then wcdo-ups-wct-configure-source fi if [ ! -f /wcdo/src/wct/build/apps/wire-cell ] ; then ./wcb -p --notests fi if [ ! -f $bv_wct_ups_bin_dir/wire-cell ] ; then ./wcb -p --notests install fi setup wirecell $bv_wct_dev_version -q $wcdo_mrb_project_quals wcdo-wirecell-path default if [ ! -f build/apps/test_dlopen ] ; then ./wcb -p --alltests fi echo "wire-cell --help" wire-cell --help
Going further, the above commands can be factored into a single Bash
function, added to $HOME/wcdo/project-local.rc
so that it may be
easily reused in many different wcdo-local-<name>.rc
files. Here’s
how that might look:
Now the wcdo-local-<name>.rc
file in its entirety is just a couple lines:
#!/bin/bash wcdo-ups-init bv-ups-wct-build v0_9_1a v091a_devel c2:prof
The $HOME/.wcdo/project-local.rc
then receives idempotent script
from above cleaned up a bit.
bv-ups-wct-build () { if [ -z "$SETUP_UPS" ] ; then echo "bv-ups-wct-build: need ups set up" return fi local oldver="$1" ; shift local newver="$1" ; shift local quals="$1"; shift local qualsm="$(echo $quals | tr : -)" local instdir=/wcdo/lib/ups/wirecell/$newver local bindir=$instdir/$(ups flavor)-${qualsm}/bin path-append $wcdo_ups_products PRODUCTS if [ ! -d $instdir ] ; then setup wirecell $oldver -q $quals wcdo-ups-declare wirecell $newver fi setup wirecell $newver -q $quals cd /wcdo/src/wct/ if [ ! -d /wcdo/src/wct/build ] ; then wcdo-ups-wct-configure-source fi if [ ! -f /wcdo/src/wct/build/apps/wire-cell ] ; then ./wcb -p --notests fi if [ ! -f $bindir/wire-cell ] ; then ./wcb -p --notests install fi setup wirecell $newver -q $quals wcdo-wirecell-path default if [ ! -f build/apps/test_dlopen ] ; then ./wcb -p --alltests fi echo "wire-cell --help" wire-cell --help }
The wcdo
system greatly helps to capture the state of complex
software development in a small set of text files. In particular,
when a problem (or a solution!) is discovered, it may be reproduced,
bundled up and communicated to others.
Some steps to capture your work and share it may go like:
- Reproduce the problem starting again in a clean work space.
- Reproduce the problem entirely by adding commands to your native
or container side “local” files
wcdo-local-<name>.{rc,sh}
and without relying on any customization in files under$HOME/.wcdo/
. - Bundle the state of your
wcdo
files by running./wcdo-<name>.sh bundle
. - Provide the small wcdo-bundle-<name>.* files to others.