# How to build Clio

`Clio` is built with [CMake](https://cmake.org/) and uses [Conan](https://conan.io/) for managing dependencies.
`Clio` is written in C++23 and therefore requires a modern compiler.

## Minimum Requirements

- [Python 3.7](https://www.python.org/downloads/)
- [Conan 1.55, <2.0](https://conan.io/downloads.html)
- [CMake 3.20, <4.0](https://cmake.org/download/)
- [**Optional**] [GCovr](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html): needed for code coverage generation
- [**Optional**] [CCache](https://ccache.dev/): speeds up compilation if you are going to compile Clio often

| Compiler    | Version |
| ----------- | ------- |
| GCC         | 12.3    |
| Clang       | 16      |
| Apple Clang | 15      |

### Conan Configuration

Clio requires `compiler.cppstd=20` in your Conan profile (`~/.conan2/profiles/default`).

> [!NOTE]
> Although Clio is built using C++23, it's required to set `compiler.cppstd=20` for the time being as some of Clio's dependencies are not yet capable of building under C++23.

**Mac apple-clang 16 example**:

```text
[settings]
arch={{detect_api.detect_arch()}}
build_type=Release
compiler=apple-clang
compiler.cppstd=20
compiler.libcxx=libc++
compiler.version=16
os=Macos

[conf]
grpc/1.50.1:tools.build:cxxflags+=["-Wno-missing-template-arg-list-after-template-kw"]
```

**Linux gcc-12 example**:

```text
[settings]
arch={{detect_api.detect_arch()}}
build_type=Release
compiler=gcc
compiler.cppstd=20
compiler.libcxx=libstdc++11
compiler.version=12
os=Linux

[conf]
tools.build:compiler_executables={'c': '/usr/bin/gcc-12', 'cpp': '/usr/bin/g++-12'}
```

#### Artifactory

Make sure artifactory is setup with Conan.

```sh
conan remote add --index 0 ripple http://18.143.149.228:8081/artifactory/api/conan/dev
```

Now you should be able to download the prebuilt `xrpl` package on some platforms.

> [!NOTE]
> You may need to edit the `~/.conan2/remotes.json` file to ensure that this newly added artifactory is listed last. Otherwise, you could see compilation errors when building the project with gcc version 13 (or newer).

Remove old packages you may have cached interactively.

```sh
conan remove xrpl
```

#### Conan lockfile

To achieve reproducible dependencies, we use [Conan lockfile](https://docs.conan.io/2/tutorial/versioning/lockfiles.html).

The `conan.lock` file in the repository contains a "snapshot" of the current dependencies.
It is implicitly used when running `conan` commands, you don't need to specify it.

You have to update this file every time you add a new dependency or change a revision or version of an existing dependency.

To do that, run the following command in the repository root:

```bash
conan lock create . -o '&:tests=True' -o '&:benchmark=True'
```

## Building Clio

Navigate to Clio's root directory and run:

```sh
mkdir build && cd build
conan install .. --output-folder . --build missing --settings build_type=Release -o '&:tests=True'
# You can also add -GNinja to use Ninja build system instead of Make
cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build . --parallel 8 # or without the number if you feel extra adventurous
```

> [!TIP]
> You can omit the `-o '&:tests=True'` if you don't want to build `clio_tests`.

If successful, `conan install` will find the required packages and `cmake` will do the rest. You should see `clio_server` and `clio_tests` in the `build` directory (the current directory).

> [!TIP]
> To generate a Code Coverage report, include `-o '&:coverage=True'` in the `conan install` command above, along with `-o '&:tests=True'` to enable tests.
> After running the `cmake` commands, execute `make clio_tests-ccov`.
> The coverage report will be found at `clio_tests-llvm-cov/index.html`.

<!-- markdownlint-disable-line MD028 -->

> [!NOTE]
> If you've built Clio before and the build is now failing, it's likely due to updated dependencies. Try deleting the build folder and then rerunning the Conan and CMake commands mentioned above.

### Generating API docs for Clio

The API documentation for Clio is generated by [Doxygen](https://www.doxygen.nl/index.html). If you want to generate the API documentation when building Clio, make sure to install Doxygen 1.12.0 on your system.

To generate the API docs:

1. First, include `-o '&:docs=True'` in the conan install command. For example:

   ```sh
   mkdir build && cd build
   conan install .. --output-folder . --build missing --settings build_type=Release -o '&:tests=True' -o '&:docs=True'
   ```

2. Once that has completed successfully, run the `cmake` command and add the `--target docs` option:

   ```sh
   cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release ..
   cmake --build . --parallel 8 --target docs
   ```

3. Go to `build/docs/html` to view the generated files.

   Open the `index.html` file in your browser to see the documentation pages.

   ![API index page](./img/doxygen-docs-output.png "API index page")

## Building Clio with Docker

It is also possible to build Clio using [Docker](https://www.docker.com/) if you don't want to install all the dependencies on your machine.

```sh
docker run -it ghcr.io/xrplf/clio-ci:latest
git clone https://github.com/XRPLF/clio
mkdir build && cd build
conan install .. --output-folder . --build missing --settings build_type=Release -o '&:tests=True'
cmake -DCMAKE_TOOLCHAIN_FILE:FILEPATH=build/generators/conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build . --parallel 8 # or without the number if you feel extra adventurous
```

## Developing against `rippled` in standalone mode

If you wish to develop against a `rippled` instance running in standalone mode there are a few quirks of both Clio and `rippled` that you need to keep in mind. You must:

1. Advance the `rippled` ledger to at least ledger 256.
2. Wait 10 minutes before first starting Clio against this standalone node.

## Building with a Custom `libxrpl`

Sometimes, during development, you need to build against a custom version of `libxrpl`. (For example, you may be developing compatibility for a proposed amendment that is not yet merged to the main `rippled` codebase.) To build Clio with compatibility for a custom fork or branch of `rippled`, follow these steps:

1. First, pull/clone the appropriate `rippled` version and switch to the branch you want to build.
   The following example uses a `2.5.0-rc1` tag of rippled in the main branch:

   ```sh
   git clone https://github.com/XRPLF/rippled/
   cd rippled
   git checkout 2.5.0-rc1
   ```

2. Export a custom package to your local Conan store using a user/channel:

   ```sh
   conan export . --user=my --channel=feature
   ```

3. Patch your local Clio build to use the right package.

   Edit `conanfile.py` in the Clio repository root. Replace the `xrpl` requirement with the custom package version from the previous step. This must also include the current version number from your `rippled` branch. For example:

   ```py
   # ... (excerpt from conanfile.py)
   requires = [
       'boost/1.83.0',
       'cassandra-cpp-driver/2.17.0',
       'fmt/10.1.1',
       'protobuf/3.21.9',
       'grpc/1.50.1',
       'openssl/1.1.1v',
       'xrpl/2.5.0-rc1@my/feature', # Use your exported version here
       'zlib/1.3.1',
       'libbacktrace/cci.20210118'
   ]
   ```

4. Build Clio as you would have before.

   See [Building Clio](#building-clio) for details.

## Using `clang-tidy` for static analysis

The minimum [clang-tidy](https://clang.llvm.org/extra/clang-tidy/) version required is 19.0.

Clang-tidy can be run by CMake when building the project.
To achieve this, you just need to provide the option `-o '&:lint=True'` for the `conan install` command:

```sh
conan install .. --output-folder . --build missing --settings build_type=Release -o '&:tests=True' -o '&:lint=True'
```

By default CMake will try to find `clang-tidy` automatically in your system.
To force CMake to use your desired binary, set the `CLIO_CLANG_TIDY_BIN` environment variable to the path of the `clang-tidy` binary. For example:

```sh
export CLIO_CLANG_TIDY_BIN=/opt/homebrew/opt/llvm@19/bin/clang-tidy
```
