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:
include
- will contain headerslib
- will contain compiled librarieslib/cmake/<module_name>/
- will contain cmake files which can be used byfind_package
and related cmake functions.
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:
- detect that your project wants
rili/service/time
in version between0.0.0
and1.0.0
and it's dependencies for target=
. - clone/fetch
rili/service/time
- check tags of
rili/service/time
between0.0.0
and1.0.0
to detect whet other dependencies in given versionrili/service/time
need for target=
(and if something is needed try deploy it). - check if required targets for given dependency is not conflicting
- iterate over 2-4 steps until all dependencies will be resolved
- 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:
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:
rili-service-time_FOUND
- you can use it to check if library was found (anyway ifREQUIRED
was used in find_package, then you not need to check it - cmake will fail anyway)rili-service-time_INCLUDE_DIRS
- you can use it to define needed include paths needed to use given module (with dependencies include paths)
In addition there will be visible rili-service-time
target.
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.