Introduction to Rili libraries

First of all it's very nice to see you here!

How integrate rili with my project?

All logically independent parts of rili are stored on separeted git respositories within rili group. All modules use semantic versioning, so you can check avaliable versions using git tags - looking at tag comments you can check what bugs are fixed within given version, which api parts are depricated or removed, which new functionalities are introduced.

Of course rili modules have dependencies between each other, so to resolve them and deploy we have special tool - hell - you can use it to resolve dependencies in non-rili projects - for example in your own library modules.

But if you don't like hell, then still you can use rili and deploy interesing for you modules by yourself - for example using git submodules.

All rili modules use cmake and have at least install target - after execution install target, all nessesary files required to use given rili module will be installed in location pointed by CMAKE_INSTALL_PREFIX directories:

Resolving and installing project dependencies with hell

So for example if in your project you would like to use rili/service/time + rili/service/compute, and want to use hell, then in your project root directory should create .hell.json config file which contain at least:

{
  "=":[
    {
      "source":"https://gitlab.com/rilis/rili/service/time.git",
      "version":">=0.0.0 <1.0.0",
      "required":["="]
    },
    {
      "source":"https://gitlab.com/rilis/rili/service/compute.git",
      "version":">=0.0.0 <1.0.0",
      "required":["="]
    }
  ]
}

and execute:

hell --install --required "=" --plantUml

Example output can be simmilar to:

Resolving dependencies
  Update https://gitlab.com/rilis/rili/service/time.git
    0.0.0
  Update https://gitlab.com/rilis/rili/service/compute.git
    0.0.0
  Update https://gitlab.com/rilis/rili/compatibility.git
    0.0.0
  Update https://gitlab.com/rilis/rili/promise.git
    0.0.0
Detected solution:
  https://gitlab.com/rilis/rili/compatibility.git @ 0.0.0 -> ["="]
  https://gitlab.com/rilis/rili/promise.git @ 0.0.0 -> ["="]
  https://gitlab.com/rilis/rili/service/compute.git @ 0.0.0 -> ["="]
  https://gitlab.com/rilis/rili/service/time.git @ 0.0.0 -> ["="]
Dependency graph:
@startuml
    [root]
      note right: ["="]
    [https://gitlab.com/rilis/rili/service/time.git@0.0.0]
      note right: ["="]
    [https://gitlab.com/rilis/rili/service/compute.git@0.0.0]
      note right: ["="]
    [https://gitlab.com/rilis/rili/compatibility.git@0.0.0]
      note right: ["="]
    [https://gitlab.com/rilis/rili/promise.git@0.0.0]
      note right: ["="]

    [root] --> [https://gitlab.com/rilis/rili/service/time.git@0.0.0]
    [root] --> [https://gitlab.com/rilis/rili/service/compute.git@0.0.0]
    [https://gitlab.com/rilis/rili/promise.git@0.0.0] --> [https://gitlab.com/rilis/rili/compatibility.git@0.0.0]
    [https://gitlab.com/rilis/rili/service/compute.git@0.0.0] --> [https://gitlab.com/rilis/rili/compatibility.git@0.0.0]
    [https://gitlab.com/rilis/rili/service/time.git@0.0.0] --> [https://gitlab.com/rilis/rili/compatibility.git@0.0.0]
    [https://gitlab.com/rilis/rili/service/compute.git@0.0.0] --> [https://gitlab.com/rilis/rili/promise.git@0.0.0]
    [https://gitlab.com/rilis/rili/service/time.git@0.0.0] --> [https://gitlab.com/rilis/rili/promise.git@0.0.0]
@enduml
Installing solution
  [1/4] https://gitlab.com/rilis/rili/compatibility.git
    Prepareing source and build directories with hash: 67cc9ed2892b8faabccd35aea13ef2f42a2f5508
    Generateing build based on: ["-DCMAKE_INSTALL_PREFIX=/mnt/repo/sample/.hell/install"]
    Building
    Installed!
  [2/4] https://gitlab.com/rilis/rili/promise.git
    Prepareing source and build directories with hash: 963d2d0e795ed7975f7d9b41b196ebd686572e8a
    Generateing build based on: ["-DCMAKE_INSTALL_PREFIX=/mnt/repo/sample/.hell/install"]
    Building
    Installed!
  [3/4] https://gitlab.com/rilis/rili/service/compute.git
    Prepareing source and build directories with hash: 4e6cebd54136d9a2eb18a67a8a9801b5dacf9dbd
    Generateing build based on: ["-DCMAKE_INSTALL_PREFIX=/mnt/repo/sample/.hell/install"]
    Building
    Installed!
  [4/4] https://gitlab.com/rilis/rili/service/time.git
    Prepareing source and build directories with hash: b03d4398bbbb63d2ba776c2ea2c8c8b0ce4a1df7
    Generateing build based on: ["-DCMAKE_INSTALL_PREFIX=/mnt/repo/sample/.hell/install"]
    Building
    Installed!
To build your project use these cmake parameters:
  -DCMAKE_INSTALL_PREFIX=/mnt/repo/sample/.hell/install

So this way hell will:

  1. detect that your project wants rili/service/time in version between 0.0.0 and 1.0.0 and it's dependencies for target =.
  2. clone/fetch rili/service/time
  3. check tags of rili/service/time between 0.0.0 and 1.0.0 to detect whet other dependencies in given version rili/service/time need for target = (and if something is needed try deploy it).
  4. check if required targets for given dependency is not conflicting
  5. iterate over 2-4 steps until all dependencies will be resolved
  6. build and install one by one dependencies using came with CMAKE_INSTALL_PREFIX=.hell/install/ and targets required by upper layer dependencies.

We used additional flag --plantUml which produce dependency graph which can be randered using plantUml: dependency graph

Anyway normally you not need --plantUml to install required modules - however it is usefull to visualise project direct and indirect dependencies.

Using installed rili modules in your cmake project

As you already know hell will install your project dependencies in: .hell/install/ So when you use camke to generate your project build system you should additionally define variables pointed by hell, to point cmake where it should try find modules.

We strongly recommend to use find_package in your cmake when you need some rili module - it's native cmake method and very convinient way - all rili modules support it.

Rili packages names use specific convention - they have exactly the same name as repository but except / use - separator. For example if you need https://gitlab.com/rilis/rili/service/time.git then to get package provided by it, you can use in your CMakeLists.txt:

find_package(rili-service-time REQUIRED)

This will create for you at least variables:

In addition there will be visible rili-service-time target.

Note:

Rili modules not create variables related to definitions - instead special header file is created during install step which holds required definitions and is included by rili modules internally. This prevents using different defines set in different modules / parts of user code.

Summary

Probably the best way to summarize all stuff above is by example. o let's create hello word project which print next fibbonaci numbers with couple milliseconds delays.

.hell.json:

{
  "=":[
    {
      "source":"https://gitlab.com/rilis/rili/service/time.git",
      "version":">=0.0.0 <1.0.0",
      "required":["="]
    },
    {
      "source":"https://gitlab.com/rilis/rili/promise.git",
      "version":">=0.0.0 <1.0.0",
      "required":["="]
    }
  ]
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.0.0)
project(fibbonaci-example)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")

find_package(rili-service-time REQUIRED)
find_package(rili-promise REQUIRED)

include_directories(
  ${CMAKE_CURRENT_SOURCE_DIR}
  ${rili-compatibility_INCLUDE_DIRS}
  ${rili-service-time_INCLUDE_DIRS})

set(SOURCES
   main.cpp
)

add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries(${PROJECT_NAME} rili-service-time rili-promise)

main.cpp:

#include <chrono>
#include <cstdint>
#include <iostream>
#include <limits>
#include <rili/Context.hpp>
#include <rili/service/Time.hpp>

typedef std::chrono::steady_clock Clock;
typedef std::chrono::milliseconds ms;

rili::Promise<std::uint64_t> getSum(std::uintmax_t a, std::uintmax_t b) {
  return rili::service::Time::get().promiseFor(ms(20)).Then(
      [a, b]() -> uintmax_t {
        if (a > std::numeric_limits<std::uintmax_t>::max() - b) {
          throw std::runtime_error("overflow");
        } else {
          return a + b;
        }
      });
}

rili::Promise<void> printFibbonaci(std::uintmax_t oldNumber,
                                   std::uintmax_t currentNumber,
                                   const Clock::time_point startTime) {
  return getSum(oldNumber, currentNumber)
      .Then([currentNumber, startTime](auto const &newNumber) {

        std::cout
            << std::chrono::duration_cast<ms>(Clock::now() - startTime).count()
            << ":\t" << currentNumber << std::endl;

        return printFibbonaci(currentNumber, newNumber, startTime);
      });
}

int main(int /*argc*/, char ** /*argv*/) {

  rili::Context::run([]() {
    printFibbonaci(0, 1, Clock::now()).Finally([]() {
      std::cout << "\nSo these are some first fibonacci numbres." << std::endl;
    });
  });
}

shell commands:

fibbonaci-example$ hell --install -r "=" -G "Ninja"
fibbonaci-example$ mkdir build && cd build
fibbonaci-example/build$ cmake ../ -G "Ninja" -DCMAKE_INSTALL_PREFIX=../.hell/install
fibbonaci-example/build$ ninja
fibbonaci-example/build$ ./fibbonaci-example

result:

20:	1
40:	1
60:	2
81:	3
101:	5
121:	8
141:	13
162:	21
182:	34
202:	55
222:	89
242:	144
263:	233
283:	377
303:	610
323:	987
344:	1597
364:	2584
384:	4181
404:	6765
425:	10946
445:	17711
465:	28657
485:	46368
505:	75025
526:	121393
546:	196418
566:	317811
586:	514229
606:	832040
627:	1346269
647:	2178309
667:	3524578
687:	5702887
708:	9227465
728:	14930352
748:	24157817
768:	39088169
789:	63245986
809:	102334155
829:	165580141
849:	267914296
869:	433494437
890:	701408733
910:	1134903170
930:	1836311903
950:	2971215073
970:	4807526976
991:	7778742049
1011:	12586269025
1031:	20365011074
1051:	32951280099
1072:	53316291173
1092:	86267571272
1112:	139583862445
1132:	225851433717
1153:	365435296162
1173:	591286729879
1193:	956722026041
1213:	1548008755920
1234:	2504730781961
1254:	4052739537881
1274:	6557470319842
1294:	10610209857723
1314:	17167680177565
1335:	27777890035288
1355:	44945570212853
1375:	72723460248141
1395:	117669030460994
1416:	190392490709135
1436:	308061521170129
1456:	498454011879264
1476:	806515533049393
1496:	1304969544928657
1517:	2111485077978050
1537:	3416454622906707
1557:	5527939700884757
1577:	8944394323791464
1598:	14472334024676221
1618:	23416728348467685
1638:	37889062373143906
1658:	61305790721611591
1678:	99194853094755497
1699:	160500643816367088
1719:	259695496911122585
1739:	420196140727489673
1759:	679891637638612258
1779:	1100087778366101931
1800:	1779979416004714189
1820:	2880067194370816120
1840:	4660046610375530309
1860:	7540113804746346429

So these are some first fibonacci numbres.