# Installation, debugging and error messages {#installation}

## Installing SIONlib

SIONlib uses [CMake](https://www.cmake.org/) to generate its build system and requires CMake version 3.12 or newer.
Configuring and generating a build system, starting from the package root directory looks like this:

```
$ mkdir build
$ cd build
$ [CC=<compiler>] cmake .. [-D<option>=<value> ...]
```

Build and install settings can be influenced via options that are either generic for CMake generated build systems or specific to the SIONlib project.

Option                              | Description
------------------------------------|-------------------------------------------------------------------------------------------
`CC` (Environment variable)         | C compiler to use for the build
`CMAKE_INSTALL_PREFIX`              | Installation directory (default: platform specific)
`CMAKE_BUILD_TYPE`                  | Build configuration (default: Release)
`CMAKE_POSITION_INDEPENDENT_CODE`   | Build position-independent code (default: ON)
`BUILD_SHARED_LIBS`                 | Build shared libraries (default: OFF)
`<dependency>_ROOT`                 | Tell CMake where to look for a dependency
`SIONlib_MPI`                       | Build the MPI parallel interface (default: ON)
`SIONlib_OMP`                       | Build the OpenMP parallel interface (default: ON)
`SIONlib_OMPI`                      | Build the MPI+OpenMP hybrid parallel interface (default: ON)
`SIONlib_PARUTILS`                  | Build parallel benchmarking utilities (default: ON)
`SIONlib_HINTS_GPFS`                | Provide hints to GPFS about file system usage (default: ON)
`SIONlib_IME_NATIVE`                | Build a back-end that uses the DDN IME native client library (default: OFF)
`SIONlib_DEBUG`                     | Enable support for printing debug trace messages (default: OFF, ON for "Debug" config)

On systems where multiple compilers are available, you can select which one to use via the `CC` environment variable, e.g. `CC=gcc`.
Similarly, the MPI library can be selected via the `MPI_ROOT` option, e.g. `-DMPI_ROOT=/opt/mpich-3.3.2`.

Like MPI, CMake also tries to detect all of SIONlib's other dependencies.
If it has trouble finding something, you can help by specifying the `<dependency>_ROOT` option, e.g. `-DIMENative_ROOT=/usr/local`.

To build SIONlib run the following command (still inside the `build` directory):

```
$ cmake --build .
```

Optionally, the test suite can be run. This uses CTest, which comes with CMake:

```
$ ctest [--output-on-failure]
```

This always runs tests for the serial interface.
If the parallel interfaces are enabled, they are also tested.
CMake tries to guess how to run MPI parallel programs (with the `mpiexec` command).
On some systems, these settings have to be edited in `tests/parallel/mpirun.defs`.

Finally, to install SIONlib, run:

```
$ cmake --build . --target install
```

## Using SIONlib

There are two ways of propagating SIONlib's usage requirements to downstream projects.
The first is CMake's native "package" format that works with the CMake `find_package` command.
The second is the legacy `sionconfig` utility that mimics the more common `pkg-config` utility.

### CMake package

The CMake build system along with the binary and library files installs a "CMake package".
This is a set of files that can be used from other projects using a CMake based build system through the `find_package` command, e.g.:

```
# In other project's CMakeLists.txt
find_package(SIONlib 2.0.0 REQUIRED)
```

If found, the package provides imported targets for all installed libraries and executables:
`SIONlib::serial[_mt]`, `SIONlib::generic[_mt]`, `SIONlib::mpi[_mt]`, `SIONlib::omp[_mt]`, `SIONlib::ompi[_mt]`, `SIONlib::dump`, `SIONlib::defrag`, `SIONlib::split`, `SIONlib::cat`, `SIONlib::version`, `SIONlib::partest`, `SIONlib::ompi_partest`.
The `_mt` suffix on the library target marks libraries that use Pthreads `mutex`es as a fallback locking mechanism.

Optional parts of SIONlib like the MPI parallel interface can either be checked for after the call to `find_package`

```
find_package(SIONlib 2.0.0 REQUIRED)
if(TARGET SIONlib::mpi)
...
```

or their presence can be required using a "component" of the same name when calling `find_package`:

```
find_package(SIONlib 2.0.0 REQUIRED
  COMPONENTS
  mpi
)
```

A specific SIONlib interface can be used by linking the library target, e.g.:

```
# In other project's CMakeLists.txt
target_link_library(<target> PRIVATE SIONlib::serial)
```

### Legacy pkg-config style utility program

SIONlib historically has shipped with a program `sionconfig` that
mimics the `pkg-config` utility by printing compiler and linker flags
suitable for using various interfaces of SIONlib.
Use of `sionconfig` is **deprecated** and should be replaced by the CMake
style package described above.
`sionconfig` can be used as follows:

```
Usage: sionconfig
Print compiler and linker flags SIONlib.
  (--com|--ser|--omp|--mpi|--ompi|--gen)   select SIONlib API
  (--cflags|--libs|--path)                 select output of sionconfig
  [--c|--f77|--f90|--cxx]                  Language selection
  [-V|--version|-h]                        Version, Help
```

Example:

```
LDFLAGS += `sionconfig --libs --mpi`
CFLAGS += `sionconfig --cflags --mpi`
```

## Debugging SIONlib I/O

If SIONlib is compiled with `-DSIONlib_DEBUG=ON` or `-DCMAKE_BUILD_TYPE=Debug`
the library supports debugging of SIONlib related I/O events. There are four
environment variables steering SIONlib debugging:

- `SION_DEBUG=<file>`
  - Enables debugging, debug messages will be written to `<file>`.
    `stdout` or `stderr` are also possible.

- `SION_DEBUG_MASK=<mask>`
  - Sets binary mask for selecting debug messages. The mask works
    bitwise, following debugging messages levels can be selected, by
    adding levels to the mask:
     mask | description
    ------|------------------------------------------------------------------
        1 | sion user function entries and exits
        2 | sion internal function entries and exits
        8 | high frequently called sion user function entries and exits
       16 | high frequently called sion internal function entries and exits
       32 | internal steps of sion internal function
       64 | internal steps of sion user function
      128 | timings (top level)
      256 | timings (low level)
      512 | print filedesc structure contents
     2048 | higher frequently called sion internal function (internal steps)
    Since it is used as bitmask the values have to be bitwise 'or'ed
    which for powers of 2 is identical to adding them.

    Examples:
    - 65 = 1 + 64 enables messages for enter and exit events of user
      functions and debugging of internal steps of SIONlib user
      functions
    - 1023 = 1 + 2 + ... + 512 shows all lower level debug messages
      including timings (since 4 is not used 1019 would do the same)

- `SION_DEBUG_RANK1=<rank>`
  - Selects first rank of parallel program for printing debug
    messages. Rank number will be appended to filename specified in
    `SION_DEBUG`.

- `SION_DEBUG_RANK2=<rank>`
  - Selects second rank of parallel program for printing debug
    messages. Rank number will be appended to filename specified in
    `SION_DEBUG`.

## Error messages of SIONlib

There are different level of error message levels (`SION_ERROR_RETURN`,
`SION_ERROR_WARN`, `SION_ERROR_ABORT` and `SION_ERROR_UNKNOWN`). Depending
on the level a warning message will be printed, the corresponding call
will be returned with 0 or negative return code, or the program will
be aborted. To limit the messages to one rank of a parallel program
following environment variable could be set:

- `SION_ERROR_MSG_RANK=<rank>`
  - selects one rank of parallel program for printing warning/error
    messages.
