Skip to content

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:

export FSLDIR=${HOME}/fsl/
source ${FSLDIR}/etc/fslconf/fsl.sh

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:

source ${FSLDIR}/bin/activate ${FSLDIR}

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/:

cp -r ${FSLDIR}/src/fsl-avwutils ./
cd ./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:

git clone https://git.fmrib.ox.ac.uk/fsl/avwutils.git
cd avwutils

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:

make
./fslmaths
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:

git clone https://git.fmrib.ox.ac.uk/fsl/newimage.git
cd newimage
make && make install

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:

  1. Install the CUDA Toolkit
  2. Ensure that the <cuda-toolkit-location>/bin/ directory is on your ${PATH}
  3. 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:

export PATH=/usr/local/cuda-11.0/bin:${PATH}

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:

$FSLDIR/bin/conda create -c conda-forge  -p ~/gcc8 "gxx_linux-64=8.*" make

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.:

git clone https://git.fmrib.ox.ac.uk/fsl/eddy.git
cd eddy
make cuda=1

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.:

git clone https://git.fmrib.ox.ac.uk/fsl/ptx2.git
cd ptx2
make gpu=1 CUDA_DYMANIC=1