How to use and develop liblinkahead
================================

Dependencies
------------

- See the `dependencies <DEPENDENCIES.md>`__ file, install with ``pip install -r requirements.txt``.

Build
-----

Building with ``make`` and Conan
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Make sure that the dependencies (see above) are fulfilled. On systems
which have ``make`` installed, type this in your command line terminal:

.. code:: console

   make conan

Manual build with Conan
~~~~~~~~~~~~~~~~~~~~~~~

We use `cmake <https://cmake.org>`__ as build tool, with Conan as
package manager. The compiler must support the C++17 standard.

1. clone/update the subrepo ``git submodule update --init proto``
2. ``conan install . -s build_type=Release --build=missing``
3. ``cd build/Release``
4. ``cmake -S ../.. -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=generators/conan_toolchain.cmake  -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_BUILD_TYPE=Release``
5. ``cmake --build .``

You may also want to install liblinkahead system-wide to
``CMAKE_INSTALL_PREFIX/lib`` by

1. ``cmake --install .``

The default install prefix is ``~/.local``. It can be set by adding
``-DCMAKE_INSTALL_PREFIX=/path/to/install/prefix`` to the first cmake
command (4.).

.. Note::

   The C++ LinkAhead library links against other libraries which are installed by Conan. So if you want
   to switch to newer versions of those libraries (possible reasons may be security releases or bug
   fixes), it is not sufficient to update your system libraries, but you have to update your Conan
   content and then rebuild liblinkahead.

If you want to build or install liblinkahead without the use of Conan, feel
free to rewrite the CMakeLists.txt as needed. The LinkAhead project is open
to merge requests which support multiple ways of installation.

Optional: Building with ``vcpkg``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Next to Conan, you also have the option to use the vcpkg package manager to install the
dependencies (`vcpkg.json`). Note, however, *vcpkg is not fully supported and tested*. It's
included as a submodule in the project. To install the dependencies, run the following
commands:

.. code:: console

   ./vcpkg/bootstrap-vcpkg.<sh/bat> -disableMetrics
   vcpkg/vcpkg install


Copy the ``grpc-cpp-plugin`` to the build directory (TODO: This should ideally be done automatically by CMake): 

.. code:: console

   mkdir -p build/build_tools
   cp vcpkg_installed/<os>/tools/grpc/grpc_cpp_plugin build/build_tools

Then compile the project with CMake by including the vcpkg toolchain file:

.. code:: console

   cd build
   cmake -S .. -B . -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-linux -DCMAKE_BUILD_TYPE=Release
   cmake --build .

Alternatively, on Linux, you can use the provided `Makefile` targets

.. code:: console
         
   make vcpkg-build-release



How to build on MacOS
~~~~~~~~~~~~~~~~~~~~~

... is currently untested.

Problems and solutions
^^^^^^^^^^^^^^^^^^^^^^

-  Make sure that your Conan version supports your XCode version. A
   typical symptom of version mismatch is for example conan complaining
   about incompatible ``compiler.version`` settings. You may need to
   rerun any conan and cmake commands (and delete cache files first)
   after compiler updates.

How to build on Windows
~~~~~~~~~~~~~~~~~~~~~~~

We use `Visual Studio
2022 <https://visualstudio.microsoft.com/de/vs/features/cplusplus/>`__
as compiler. We use `cmake <https://cmake.org/download/>`__ as build
tool, which can be installed together with Visual Studio. 

1. Install Python and create a virtual environment with the dependencies in
   `requirements.txt`.
2. In a PowerShell, activate the environment and run the following commands from the
   repository root:
3. ``conan profile detect --force`` (and check the output)
3. ``make.ps1 conan-install``
4. ``make.ps1 build``

You'll find the shared libraries and cli clients in ``.\build\Release\``. To run the tests,
use ``make.ps1 test``. As a shortcut to run all steps, use ``make.ps1 all``.


Troubleshooting
~~~~~~~~~~~~~~~

ERROR: The default build profile '~/.conan2/profiles/default' doesn't exist
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Follow the instructions and run 

.. code:: console

   conan profile detect

Check the output and adjust settings if necessary.

Warning: WARNING: GCC OLD ABI COMPATIBILITY
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Just do what it says. Either run

.. code:: console

   conan profile update settings.compiler.libcxx=libstdc++11 default

or change `~/.conan/profiles/default` or use another conan profile.

/bin/sh: line 1: cmake: command not found
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Install cmake.

``conan install`` fails due to missing prebuilts
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

When ``conan install`` fails during the installation of the dependencies
because a precompiled package is not available for your specific
settings, try adding the ``--build=missing`` option:
``conan install .. [ other options ] --build=missing``. This should
download and compile the sources of the dependencies.

cmake fails when using the debug flag
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Depending on the clang version it might be necessary to additionally use
the following flag: ``-DCMAKE_CXX_FLAGS="-Wno-unused-parameter"``

conan uses outdated cppstd during install
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If you experience compiler errors during a ``conan install`` process due
to, e.g., ``std::string_view`` being unavailable, try specifying the cpp
standard manually by
``conan install .. [other options] -s "compiler.cppstd=17"``.

Client Configuration
--------------------

You can use a json file for the configuration of the client. See
``test/test_data/test_linkahead_client.json`` for an example. You may use
``linkahead-client-configuration-schema.json`` to validate your schema.
Typically, you will need to provide the path to your SSL certificate.

The client will load the configuration file from the first existing file
in the following locations (precedence from highest to lowest):

1. A file specified by the environment variable ``$LINKAHEAD_CLIENT_CONFIGURATION``.
2. ``$PWD/linkahead_client.json``
3. ``$PWD/linkahead-client.json``
4. ``$PWD/.linkahead_client.json``
5. ``$PWD/.linkahead-client.json``
6. ``$HOME/linkahead_client.json``
7. ``$HOME/linkahead-client.json``
8. ``$HOME/.linkahead_client.json``
9. ``$HOME/.linkahead-client.json``
10. A file specified by the environment variable ``$CAOSDB_CLIENT_CONFIGURATION``.
11. ``$PWD/caosdb_client.json``
12. ``$PWD/caosdb-client.json``
13. ``$PWD/.caosdb_client.json``
14. ``$PWD/.caosdb-client.json``
15. ``$HOME/caosdb_client.json``
16. ``$HOME/caosdb-client.json``
17. ``$HOME/.caosdb_client.json``
18. ``$HOME/.caosdb-client.json``

Develop
-------

Unit tests
~~~~~~~~~~

.. _build-1:

Build
^^^^^

For the tests the build type has to be Debug. As a shorthand you can run ``make
test``. If you want to build manually, follow these steps:

1. ``conan install . -s build_type=Debug --build=missing``
2. ``cd build/Debug`` 
3. ``cmake -S ../.. -G "Unix Makefiles" -DCMAKE_TOOLCHAIN_FILE=generators/conan_toolchain.cmake  -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_BUILD_TYPE=Debug``
    - If your clang-format version is too old, formatting, linting etc. can
      be skipped:
      ``cmake -B . -D CMAKE_BUILD_TYPE=Debug -D SKIP_LINTING=ON ..``
    - Depending on the clang version it may be necessary to also add
      ``-DCMAKE_CXX_FLAGS="-Wno-unused-parameter"``
5. ``cmake --build . ``
    - If this fails with ``Error running '': No such file or directory``, you may want to try
      CMake's ``-D SKIP_LINTING=ON``. (See previous step.)

Run
^^^

In the build directory, run ``ctest``.  For more verbose output of a single test:
``ctest -R test_value.test_list -V``

Framework
^^^^^^^^^

We use `GoogleTest <https://google.github.io/googletest/>`__ for unit
testing.

Test coverage
^^^^^^^^^^^^^

We use `gcov <https://gcc.gnu.org/onlinedocs/gcc/Gcov.html>`__ and
`lcov <https://github.com/linux-test-project/lcov>`__ for generating
test coverage reports.

In the build directory, generate the coverage report by running
``cmake --build . --target unit_test_coverage``.

Note that this special target will run the tests again. Thus it is not
necessary to run ``ctest`` prior to this target.

The coverage report can be viewed in a browser by opening
``<build_directory>/unit_test_coverage/index.html``.

Code formatting
~~~~~~~~~~~~~~~

-  install clang-format on your system.
-  ``clang-format -i --verbose $(find test/ src/ include/ -type f -iname "*.cpp" -o -iname "*.h" -o -iname "*.h.in")``

Naming conventions
~~~~~~~~~~~~~~~~~~

Please adhere to `Google’s C++ naming
conventions <https://google.github.io/styleguide/cppguide.html#Naming>`__.

Documentation
~~~~~~~~~~~~~

To build the documentation, run in the build directory

-  ``cmake --build . --target doc-doxygen`` (generate Doxygen)
-  ``cmake --build . --target doc-sphinx`` (generate Sphinx)