Compiling FSL C++ projects locally
This page describes how to set up a local development environment for compiling FSL C/C++ projects.
Many core FSL tools are written in C++. These tools are arranged into a collection of projects - some of these projects provide libraries, and other projects provide executables. All of these projects are compiled using a simple Makefile
-based build system. FSL C++ libraries are compiled as shared libraries, and FSL executables are compiled so as to be dynamically linked to the libraries they depend upon.
A standard FSL installation comes with a C/C++ compiler and the Makefile
machinery required to compile FSL C/C++ projects. FSL C/C++ conda packages are compiled using the conda-forge compiler toolchain, and it is recommended that the same compiler toolchain is used for local development.
Info
You can use your operating system compiler if you wish, but be warned that doing so will potentially compile your code in a different way to how the official FSL conda packages have been compiled.
Setting up your environment
When you want to work on a FSL project, you need to configure your shell environment. First of all, your environment must be set up for normal FSL usage. There is a good chance that this is already taken care of in your shell profile:
Next, you need to configure your environment for FSL development. When you have compiled a FSL library/executable locally, a good idea is to install it into a location separate from your main FSL installation, so that you don't overwrite the official binaries. The ${FSLDEVDIR}
environment variable allows you to specify where you would like your "development" libraries/executables to be installed into. Once you have set ${FSLDEVDIR}
, you need to source
the fsl-devel.sh
script:
export FSLDEVDIR=${HOME}/fsl-dev/
export PATH=${FSLDEVDIR}/bin/:${PATH}
source ${FSLDIR}/etc/fslconf/fsl-devel.sh
Tip
Setting the ${FSLDEVDIR}
variable is strongly recommended - if you do not set this variable, you may accidentally overwrite the official copies of FSL binaries in ${FSLDIR}
with your own versions!
Now, in order to use the conda-forge compiler toolchain, you need to "activate" the ${FSLDIR}
conda environment. An FSL installation may be based on conda
or micromamba
- if you have a file called ${FSLDIR}/bin/micromamba
, then your installation is based on micromamba
, otherwise it is based on conda
.
If your installation is based on micromamba
, run these commands:
eval $(${FSLDIR}/bin/micromamba shell hook --shell $(basename ${SHELL}))"
micromamba ${FSLDIR}/bin/activate ${FSLDIR}
Otherwise, if your installation is based on conda
, run this command:
Getting a copy of the source code
When you install a particular version of FSL, a copy of the source code for all FSL C/C++ projects, for that FSL version, is installed into ${FSLDIR}/src/
. For example, if you wish to compile avwutils
(which provides the fslmaths
command), you can create a copy of the source code from ${FSLDIR}/src/fsl-avwutils/
:
Alternatively, if you would like to work with the latest version of the source code, you can clone the project repository from our GitLab:
Compiling the code
To compile most FSL projects, you simply need to run make
. Once the code has been compiled, you can run the executables in place (if the project provides any executables), or install the library and executable files into your ${FSLDEVDIR}
by running make install
:
Compiling dependencies
If you are trying to compile a version of a project which is different from the version that was released with your FSL installation, you may also need to clone and compile the dependencies of that project. For example, the avwutils
project depends on the newimage
project, which provides C++ abstractions and utilities for working with N-dimensional volumes. So before you can compile a development version of avwutils
, you may need to compile and install the latest version of newimage
:
After doing this, you will be able to compile the avwutils
source code - the FSL Makefile
system is set up so that libraries installed into ${FSLDEVDIR}
will be preferentially used over those installed in ${FSLDIR}
, so when you compile avwutils
, the resulting binaries will link against the libraries in ${FSLDEVDIR}
.
Info
The avwutils
project depends on some other projects in addition to newimage
. In order to find out the dependencies of a FSL project, you can check the corresponding conda recipe - recipes for all FSL projects are hosted on the FMRIB GitLab - for example, the avwutils
conda recipe can be found at https://git.fmrib.ox.ac.uk/fsl/conda/fsl-avwutils/.
Compiling CUDA projects
If you wish to compile a FSL project which uses CUDA (e.g. eddy
), you need to:
- Install the CUDA Toolkit
- Ensure that the
<cuda-toolkit-location>/bin/
directory is on your${PATH}
- Ensure that the correct version of GCC is installed.
Note that you do not need a GPU in order to compile CUDA code.
Install the CUDA Toolkit
At the moment, we are not using versions of the CUDA Toolkit that are published on https://anaconda.org. This is so that FSL installations are not tightly coupled to a specific version of CUDA. Instead, we recommend downloading and installing the CUDA Toolkit from https://developer.nvidia.com/cuda-toolkit.
Note that it is possible to have multiple versions of the CUDA Toolkit installed alongside each other - you simply need to keep track of where each version is installed (e.g. /usr/local/cuda-10.2
, /usr/local/cuda-11.0
, etc).
Once you have installed the CUDA Toolkit, make sure that the nvcc
compiler is available on your ${PATH}
, for example:
Use a compatible version of GCC
You also need to ensure that you have an appropriate version of GCC for the CUDA version you are compiling against. Different versions of the CUDA toolkit require different versions of GCC, as outlined in the following table:
CUDA Toolkit version | Required GCC version |
---|---|
10.2 | >=5,<=8 |
11.0 | >=5,<=9 |
11.1 | >=5,<=9 |
11.2 | >=5,<=9 |
11.3 | >=6,<=9 |
11.4 | >=6,<=11 |
11.5 | >=6,<=11 |
11.6 | >=6,<=11 |
11.7 | >=6,<=11 |
11.8 | >=6,<=11 |
12.0 | >=6,<=12.1 |
12.1 | >=6,<=12.2 |
12.2 | >=6,<=12.2 |
12.3 | >=6,<=12.2 |
12.4 | >=6,<=13.2 |
12.5 | >=6,<=13.2 |
To compile FSL code with a different compiler version than that which is installed in $FSLDIR
, you have the option of creating a separate conda environment with the appropriate GCC version. For example:
Warning
You may also need to install a specific version of glibc, to match the version that the CUDA toolkit was compiled against - for example, for CUDA 11.4, you also need to install "sysroot_linux-64=2.17"
.
Then in order to use this environment for compiling FSL projects:
# Configure your environment for FSL development
export FSLDIR=${HOME}/fsl
export FSLDEVDIR=${HOME}/fsl-dev
source ${FSLDIR}/etc/fslconf/fsl-devel.sh
# Activate the compiler toolchain environment
source ${FSLDIR}/bin/activate ~/gcc8
If you need to compile against different versions of CUDA, you can create a separate conda environment for each version of GCC that you will need.
Compiling FSL CUDA projects
Makefiles for FSL CUDA projects may require options to be specified when calling make
. For example, eddy
can be compiled as a CPU version, or as a GPU version. In order to compile the GPU version, it is necessary to specify cuda=1
when calling make, i.e.:
Refer to the Makefile
for each FSL CUDA project for usage information.
CUDA executables in the official FSL conda packages contain a statically-linked copy of the required CUDA Toolkit libraries. This is to maximise compatibility with different hardware, and to comply with CUDA license requirements.
However, when compiling a FSL CUDA project locally, you may wish to dynamically link against your installed CUDA libraries. You can accomplish this by passing the CUDA_DYNAMIC
flag when calling make
, e.g.: