Installing Octopus with CMake

Building with CMake

This document goes over a few ways to build Octopus using cmake, how to configure it and how to run basic tests

Requirements

Except for the compilers and most libraries, these requirements are toolchain independent (can be compiled by GNU, Intel, etc.) and can also be installed in a virtual environment from PyPI.

tl;dr. Running cmake

The configure, build, test and install steps are all run through the cmake command line interface (CLI). In the project root run:

$ cmake -B ./build -G Ninja --install-prefix=<installation directory>
$ cmake --build ./build
$ ctest --test-dir ./build -L short-run
$ cmake --install ./build

This will configure, build and run the tests in the ./build directory, using the default options, i.e. compiling without parallelization, and with optional dependencies automatically detected. (The -G Ninja option is explained in build-backend)

If you have any problems, see the troubleshooting section.

Easy method: Using presets

If you are using CMake >= 3.23 you can use cmake-presets to simplify this process and use some pre-defined options, e.g.:

$ cmake --preset default
$ cmake --build --preset default
$ ctest --preset default
$ cmake --install ./cmake-build-release

You can find a list of these presets using cmake --list-presets. Note that some presets are customized for the Octopus buildbot, which we use for continuous integration.

$ cmake --list-presets
Available configure presets:

  "default"                   - Default configuration preset
...

You can further add the options defined in Manual method to further customize the build process. If you are using CMake >= 3.25 you can simplify this to a single step (except for install which has no presets):

$ cmake --workflow --preset default
$ cmake --install ./cmake-build-release

You cannot add manual options to workflow presets

See Testing section on how to fine-tune the testing process.

User Presets

Additionally, one can define a custom preset that contain all of these options in /CMakeUserPresets.json, e.g. a debug preset might look like:

{
  "version": 4,
  "configurePresets": [
    {
      "name": "debug",
      "displayName": "Debug configure",
      "inherits": [
        "default"
      ],
      "binaryDir": "build",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug"
      }
    }
  ]
}

We provide commonly used “components” in /cmake/CMakePresets-components.json, such as _min which makes sure no optional dependencies are used, _mpi which enables MPI support, etc. Feel free to use them in the inherits field of your user preset.

In the `inherits` field, the `cacheVariables` take precedence from the first preset in the list that defined them. The `CMakePresets-components.json` are designed to be mixed in arbitrary order. If that is not the case please report it. The `cacheVariables` defined in the current `configurePresets` always take precedence.

Building Documentation

If Doxygen is available on your system, Octopus source code documentation can be built with the custom doxygen CMake target. Configure with the Doxygen support enabled, -DOCTOPUS_DOXYGEN=On, and build the documentation with:

cmake --build ./build --target doxygen

Manual method: Traditional CMake workflow

Configure Step

To configure the build from Octopus root use:

$ cmake -B ./build

The option -B specifies the build directory, which is automatically created. If not provided, the current directory is used as build directory, which is highly discouraged. The user is encouraged to use different build directories for different configurations.

Options, compilers, and packages are cached between subsequent configure steps (as well as build/test/install steps) in the build directory. To remove these caches and start “fresh” use the --fresh flag:

$ cmake -B ./build  --fresh

The best place to find the available configuration options is in the Options section of the root /CMakeLists.txt:

#[==============================================================================================[
#                                            Options                                            #
]==============================================================================================]

option(OCTOPUS_MPI "Octopus: Build with MPI support" OFF)
option(OCTOPUS_OpenMP "Octopus: Build with OpenMP support" OFF)
option(OCTOPUS_INSTALL "Octopus: Install project" ${PROJECT_IS_TOP_LEVEL})
option(OCTOPUS_CUDA "Octopus: Build with CUDA support" OFF)
...

More details about these options, as well as some common CMake-native ones are described below. These options are set at configure time and are typically prefixed by -D as follows:

$ cmake -B build_dir --fresh -G Ninja -DOCTOPUS_MPI=On -DCMAKE_BUILD_TYPE=release

An example how to specify more details for a custom build is:

cmake -B build --fresh -G Ninja \
      -DOCTOPUS_MPI=On -DOCTOPUS_OpenMP=On \
      -DOCTOPUS_TESTS=Off \
      -DLibxc_ROOT="path_to_libxc" \
      -DCMAKE_INSTALL_PREFIX="installation_path \
      -DCMAKE_C_FLAGS="-O3 -g" \
      -DCMAKE_Fortran_FLAGS="-O3 -fallow-argument-mismatch  -fno-var-tracking-assignments -g" \
      -DCMAKE_DISABLE_FIND_PACKAGE_CGAL=On \
      -DCMAKE_BUILD_TYPE="custom"

Build backend

To specify the build backend use the -G flag:

$ cmake -B ./build -G Ninja --fresh

The default is make, but we highly encourage to use ninja instead. When using GNU compilers, ninja is required.

As of writing this guide (cmake 3.28), `gfortran` and `make` are incompatible due to the custom Octopus pre-processing of the Fortran code. Please use `ninja` instead.

Compilers

CMake automatically detects the compilers on the system, however one can explicitly specify which compiler(s) cmake should use, by passing a cmake flag to specify the compiler (with full path):

External Dependencies

By default, all external dependencies are searched at the first configuration. The system installed packages take precedence. To fine-tune the optional external packages use the following options:

CMake Flag Default Description
CMAKE_DISABLE_FIND_PACKAGE_<Name> Off Disable optional external package <Name>
CMAKE_REQUIRE_FIND_PACKAGE_<Name> Off Require optional external package <Name>

<Name> is case-sensitive! See External Dependencies for package names used.

Fortran libraries (and modules) are **NOT** compatible between different compilers, unlike C and to a high extent C++ libraries and headers. CMake does not have a functionality to re-build Fortran modules when a different compiler was used in the external package. This functionality might come soon given the recent support for C++ modules. This can be especially problematic when using `homebrew`.

  • mkl and fftw have a custom logic described [below][Other options].
  • Other external package support that drastically change the behavior of Octopus, e.g. MPI, OpenMP, etc. are controlled by OCTOPUS_<NAME> flags. See [Other options][]

The required packages have fallbacks to external sources (downloaded using FetchContent) if the system does not contain the package. This fallback behavior can be controlled as follows:

Setting Behavior
<default> Check for system installed, if not found download it
CMAKE_REQUIRE_FIND_PACKAGE_<Name>=On Use only system installed
CMAKE_DISABLE_FIND_PACKAGE_<Name>=On Do not check for system installed, use downloaded version
FETCHCONTENT_SOURCE_DIR_<UPPER_NAME> Use a local path source

Other Options

In the following table we present a comprehensive but not exhaustive list of configure time options that can be passed to Octopus cmake. All should be prepended with -D and appended with =<OPTION>. For boolean flags, this corresponds to On/True/1 or Off/False/0. For example, to compile Octopus with MPI support, one would use -DOCTOPUS_MPI=On. Everything else is treated as plain string. For example, to specify the Fortran compiler, one would use -DCMAKE_Fortran_COMPILER=/path/to/gfortran.

CMake Flag Default Description Notes
OCTOPUS_MPI Off Compile with MPI Support
OCTOPUS_OpenMP Off Compile with OMP Support
OCTOPUS_CUDA Off Compile with CUDA Support
OCTOPUS_HIP Off Compile with HIP Support
OCTOPUS_OpenCL Off Compile with openCL Support
OCTOPUS_NATIVE Off Build for native architecture
OCTOPUS_UNIT_TESTS Off Build with unit-tests
OCTOPUS_TESTS_FULL On Build with full test-suite
OCTOPUS_TESTS_REPORT Off Export test report
OCTOPUS_TESTS_RUN_SERIAL Off Run internal Octopus tests in Serial
OCTOPUS_MKL Off Build with MKL support MKL is still searched and preferred unless OCTOPUS_FFTW=On
OCTOPUS_FFTW Off Build with FFTW support Set this option to prefer FFTW over MKL
OCTOPUS_ScaLAPACK Off Build with ScaLAPACK support

Other useful CMake-native settings

CMake Flag Default Description Notes
CMAKE_BUILD_TYPE Release Build Type - See ${buildir}/CMakeCache.txt for built-in defaults
- Use Custom to remove all built-in flags
CMAKE_PREFIX_PATH <system default> Search path for external dependencies Usually the parent folder containing bin, lib, etc. folders
<Name>_ROOT <empty> Search the specified path for package <Name>
CMAKE_INSTALL_PREFIX <system default> Path where to install Octopus
CMAKE_<Lang>_COMPILER <system default> <Lang> (Fortran/C/CXX) Compiler
CMAKE_<Lang>_FLAGS <empty> Global <Lang> (Fortran/C/CXX) Compiler Flags - Whenever possible use OCTOPUS_ defined variables
- CMAKE_<Lang>_FLAGS_<BuildType> are automatically appended
- These flags are propagated to third-party libraries compiled by Octopus

Additional options are found in <#external-dependencies>.

If you are using downloaded external dependencies, you can configure those packages by simply adding those options e.g.: SPGLIB_DEBUG=On Note these options are passed unaltered to the dependencies so be aware of name-clashes. See the relevant upstream packages for available configure options.

You can view the defined options after the first configure run using

$ ccmake

Beware that this does not show options that have not been set and do not have a default

Build Step

Once configured, simply run cmake --build pointing to the appropriate build directory:

$ cmake --build ./build -j $(nproc)

This command is build-backend-agnostic (it calls make and ninja on your behalf). Alternatively, one can call these manually via make -j or ninja -j 0 in the build directory.

Testing step

Simply run ctest pointing to the appropriate build directory

$ ctest --test-dir ./build

See Testing section for more details

Install step

After you are satisfied with the build and test results, you can install Octopus for production use via cmake --install, pointing to the appropriate build directory

$ cmake --install ./build

⚠️ Warning

Due to octopus design you cannot currently redirect the install using

$ cmake --install ./build --prefix /new/path/to/octopus

Please make sure CMAKE_INSTALL_PREFIX was specified at the configure step

Testing

Regardless of CMake method you’ve used to build Octopus, you can configure and run individual tests using ctest, and pointing to the appropriate build directory

$ ctest --test-dir ./cmake-build-release

Make sure you run ctest in parallel, especially when Octopus is built with MPI support. The following methods are equivalent:

$ ctest --test-dir ./cmake-build-release -j $(nproc)
$ CTEST_PARALLEL_LEVEL="$(nproc)" ctest --test-dir ./cmake-build-release

All the MPI/OpenMP parallelization is handled by ctest and it is configured at configure time. Just make sure your desired OMP_NUM_THREADS environment variable is set appropriately at the configure step.

The default ctest will run all available tests, but you can select the tests you want using labels:

$ ctest --test-dir ./cmake-build-release --print-labels
Test project /octopus/cmake-build-release
All Labels:
  components
  errors
  long-run
  short-run
...
$ ctest --test-dir ./cmake-build-release -L short-run
Test project /octopus/cmake-build-release
  Test   #1: components/01-derivatives_1d
  Test   #2: components/02-derivatives_2d
  Test   #3: components/03-derivatives_3d
...

or regex of the specific test name, e.g. to run only the tests for dftbplus:

$ ctest --test-dir ./cmake-build-release -R "-dftbplus_"
Test project /octopus/cmake-build-release
  Test #150: multisystem/10-dftbplus_verlet
  Test #151: multisystem/11-dftbplus_ehrenfest
...

Use -N to simply view the tests that are meant to be run instead of running them

Troubleshooting

Here are some common problems, which might occur if you try to install on your system:

Incompatibilities

gfortran is incompatible with the make backend. This is a limitation of cmake, and results from the Octopus’s reliance on the c-preprocessor.

Compilation Failure at First Macro Instance

Cmake can sometimes configure without problems, but fail early in the compilation step. If cmake fails with an error pointing to an Octopus macro, such as ASSERT (macros are non-standard fortran, written in all caps):

/Users/mainuser/octopus/src/basic/mpi.F90:370:32:

  370 |     ASSERT(not_in_openmp())
      |                                1
Error: Syntax error in IF-clause after (1)

this can be due to dangling files from a prior autotools build. We first recommend running:

make clean
make distclean

with autotools. This should remove the main culprit files:

src/include
  config_F90.h
  defaults.h
  options.h

Deleting these files and reconfiguring with cmake should resolve the problem. If the problem still persists, we recommend cloning a fresh version of the repository. Additional autotools-generated files include:

build-aux
autom4te.cache
config.h
config.h.in
config.log
config.status
Makefile
Makefile.in

share/
  Makefile
  Makefile.in
  variables
  varinfo
  varinfo_orig
  
external_libs
  Makefile/
  Makefile.in/

scripts/
  Makefile
  Makefile.in

and can all be safely removed.

Compilation Fails due to LibXC

If your system still has a system-installed libxc version 4, this would be picked up by CMake before looking for a different version that you might have installed manually. In order to instruct CMake to use a specific version, add -DLibxc_ROOT=<libxc-install-prefix> (not the lib/ path!). If this still fails you can instead, either:

a) instruct CMake to fetch and build libxc from source:

-DCMAKE_DISABLE_FIND_PACKAGE_Libxc=ON

or b) Use git submodule to fetch libxc, and point to this package:

# Prior running the configure step:
git submodule update --init
# Append to configure options
-DFETCHCONTENT_SOURCE_DIR_LIBXC=third_party/Libxc.

Incompatible Optional Library (e.g. BerkeleyGW)

If you have an older version of an optional library installed on your system, CMake will automatically detect and use it, but fail at compilation.

You can either try to upgrade the library or instruct CMake to skip this package with -DCMAKE_DISABLE_FIND_PACKAGE_<name>=ON.

Debugging Cmake

If there are other issues finding libraries, you can request more verbose information from CMake by adding --debug-find-pkg=<package-name> to the command line.