Getting started

This tutorial will walk you through building apps for Robots. Regardless of the programming language or the robot you use (provided the OS and CPU is supported), the process of building and submitting applications is very similar.

Repository

The first thing we need is a repository. We support the use of the two most widely used git hosts, Github and Bitbucket. You may use both public and private repositories (we use OAuth2 with read-only permissions) and we do not share your code with anyone if your repository is private!

The way the builder works is the following:

  • we clone the repository you specify
  • we make sure that you have provided a build.yaml which we can use
  • we send the master branch of your repository to an ephemeral VM
  • if the build succeeds, we distribute your application
  • else the build output can be seen from your account menu (build jobs)

What we do not do:

  • check for valid code - if the build fails, you have to fix it
  • check for malicious code - this is an opensource platform and as such we rely on openess
  • check for stable or functional code - see above

What you can do:

  • in addition to building your project, you can also run tests (e.g., make test)
  • you can specify required dependencies (apt-get, npm install, rosdep install, pip install)
  • you can run various build tools to compile and link

Security

We realise that for some it may be tempting to try and be naughty, so be warned:

  • VMs are ephemeral (they are deleted after a build job)
  • We monitor all traffic - and we will report to the authorities malicious activity
  • All VMs are blocked from the internet, meaning you cannot access them, and they cannot connect outside
  • We keep all error and output logs as well as the source code submitted for one year. Although we do not share any of the data with third parties.

Project Tree

As explained in the builder documentation your project (depending on the programming language used) may have different types of directory hierarchies. Regardless of that, you must have a build.yaml in your root directory.

Requirements

  • programming language: choose from cpp, js or python.
  • application version: we use a 3 digit version format: major.minor.patch, e.g. 0.1.1
  • target platform: a single entry or array of entries (discussed later)
  • rapp api: the version of the RAPP API being used
  • files to package: an array of files to distribute (more on that later)

Optionally you may add keywords.

Installing Dependencies

The supported installation instructions are:

  • apt-get as you would normally use it under Ubuntu/Debian
  • npm to install modules (mostly used for running tests - no need to redistribute them)
  • rosdep used to install ROS packages you may need to build or use for tests
  • pip used to install packages (again mostly used for testing - no need to distribute packages)

Installing globally (system-wide) is done like so:

  • sudo apt-get install -y libboost-all-dev will install globally the boost library
  • sudo npm install -g rapp-platform-api will install the rapp-platform-api for all
  • sudo pip install some_package will install the some_package for all

NOTE any types of pipes, redirections or other characters are forbidden. Installation will only accept simple one-line instructions. If you need to export a path, or set something else, you should do it in build instructions.

WARNING you should use install for global or system-wide installation. If you wish to install something inside your project directory (e.g., via npm) it is always better to do so in the build instructions. The scope of install is always

Building Instructions

The instructions you specify to build will be run sequentially and if one of them fails, then the job will be abandoned. The output received from the build job will have all the details of what may have failed (stdout, stderr and return value).

NOTE All build instructions are assumed to be executing inside your repository. For example:

build:
    - mkdir build
    - cd build
    - cmake ..
    - make

Will in effect create a build directory, cd into it, run cmake .. and then make. If any of those commands fails, the build job will terminate.

Packaging

This packaging instruction set defines which files to package for distribution.

  • the files can be any type (binary, yaml, ini, json, etc)
  • the files will be packed and will preserve the hierarchy you specify in your build.yaml
package:
    - build/available_services
    - config.ini

Example

A full example follows, which uses C++ as the programming language. It is of limited functionality, but serves the purpose of demonstrating how we build a binary using CMake and the C++ API.

You may clone the [repository]( https://github.com/ortelio/builder_tutorial) which has the example code shown below:

├── builder_intro/
    ├── CMakeLists.txt
    ├── build.yaml
    └── src/
        └── main.cpp

The actual CmakeLists.txt specifies how to build a binary called available_services.

cmake_minimum_required(VERSION 2.6)
project(builder_intro)
add_executable(available_services source/main.cpp)
set(LIBRARY_PATH ${LIBRARY_PATH} /usr/local/lib)
find_library(RAPP_LIBRARY NAMES rapp REQUIRED)
find_package(OpenSSL REQUIRED)
find_package(Boost COMPONENTS system REQUIRED)
find_package(Threads REQUIRED)
set(RAPP_LIBRARIES ${RAPP_LIBRARY}
                   ${OPENSSL_LIBRARIES}
                   ${Boost_LIBRARIES}
                   ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(config ${RAPP_LIBRARIES})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")

Because we take the somewhat standard approach of building inside a build directory, our instructions are:

build:
    - mkdir build
    - cd build
    - cmake ..
    - make

NOTE: you don not have to call the directory build, it is just a convention. However, because the binary will be compiled in it, when we package it, we will have to specify the build directory.

The actual source code in src/main.cpp is the available_services example from the API:

#include <rapp/cloud/service_controller.hpp>
#include <rapp/cloud/available_services.hpp>
#include <iostream>

int main(int argc, char* argv[])
{
    rapp::cloud::platform info = {"rapp.ee.auth.gr", "9001", "rapp_token"};
    rapp::cloud::service_controller ctrl(info);

    auto cb = [](std::vector<std::pair<std::string, std::string>> services) {
         std::cout << "available services: " << std::endl;
         for (const auto & pair : services) {
            std::cout << pair.first << " " << pair.second << std::endl;
         }
    };

    ctrl.make_call<rapp::cloud::available_services>(cb);
    return 0;
}

The process

First you will have to populate your repository. After that, make sure that your code builds on your computer. Even if you are cross-compiling it is always useful to verify that there is no problem with your project, especially during compilation and linking. Once you have set the project, go to Build App under your user drop-down menu. At this point, you have to specify which of your repositories we are going to build. NOTE you may optionally chose to upload a picture for your app.

If your repository has a build.yaml and if that YAML file is syntactically correct, we will attempt to build the application. This is not going to happen real-time, instead we add a job in a queue, and once the builder resources allow it, your build job will be processed.

You may see your build job history under the Build Jobs page, from the user drop-down menu. If a build job has failed or succeeded, you can view the output (stdout and return values) from the actual virtual machine.

An example of a build job is:

Reading package lists...
Building dependency tree...
Reading state information...
libboost-all-dev is already the newest version (1.58.0.1ubuntu1).
0 to upgrade, 0 to newly install, 0 to remove and 70 not to upgrade.
mkdir build
builder~/available_services:[0] $ cd build
builder~/available_services/build:[0] $ cmake ..
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenSSL: /usr/lib/i386-linux-gnu/libssl.so;/usr/lib/i386-linux-gnu/libcrypto.so (found version "1.0.2g")
-- Boost version: 1.58.0
-- Found the following Boost libraries:
--   system
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Looking for pthread_create
-- Looking for pthread_create - not found
-- Looking for pthread_create in pthreads
-- Looking for pthread_create in pthreads - not found
-- Looking for pthread_create in pthread
-- Looking for pthread_create in pthread - found
-- Found Threads: TRUE  
-- Configuring done
-- Generating done
-- Build files have been written to: /home/builder/available_services/build
builder~/available_services/build:[0] $ make
Scanning dependencies of target available_services
[ 50%] Building CXX object CMakeFiles/available_services.dir/source/available_services.cpp.o
[100%] Linking CXX executable available_services
[100%] Built target available_services
builder~/available_services/build:[0] $

You will not get errors when packaging; if a file is not found then the process automatically terminates

Help

If you need help, the easiest way is to have a chat with us on Gitter, alternatively you can email us at builder@rapp.cloud.