From 311473851ac94c1a70d9716f09f39329fbe30f02 Mon Sep 17 00:00:00 2001 From: Ali Tariq Date: Wed, 17 Apr 2024 12:19:12 +0500 Subject: [PATCH] Added qemu-system-arm and arm gnu --- docs/404.html | 26 +- .../index.html | 151 -------- docs/Booting_ubuntu22.04_riscv64/index.html | 189 ---------- docs/Building_Jenkins_github_repo/index.html | 156 -------- docs/Building_Linux_Kernel/index.html | 352 ------------------ docs/Building_qemu/index.html | 247 ------------ docs/Creating_CI_CD_pipeline/index.html | 28 +- docs/Creating_Jenkins_Node_on_LXC/index.html | 254 ------------- docs/Creating_jenkinsfile/index.html | 28 +- .../Cross_compiling python3.8.15/index.html | 150 -------- .../Cross_compiling_coremark/index.html | 177 --------- .../Cross_compiling_dhrystone/index.html | 156 -------- .../Cross_compiling_go/index.html | 159 -------- .../Cross_compiling_jdk/index.html | 150 -------- .../Cross_compiling_ninja-build/index.html | 164 -------- .../Cross_compiling_openssl/index.html | 197 ---------- .../Cross_compiling_ruby/index.html | 209 ----------- .../Cross_compiling_rust/index.html | 175 --------- docs/Cross_Compiling/Overview/index.html | 148 -------- .../index.html | 157 -------- docs/Multinode_Pipelines/index.html | 28 +- docs/Software_Developer_Guide/index.html | 28 +- docs/Tooling/index.html | 30 +- .../Integrating_prometheus_grafana/index.html | 164 -------- .../Prometheus_Grafana/index.html | 180 --------- docs/css/theme.css | 6 +- docs/index.html | 32 +- .../Github_PR_webhook_integration/index.html | 226 ----------- .../Github_push_webhook/index.html | 240 ------------ docs/jenkins_gitlab_integration/index.html | 28 +- docs/runner_specs/index.html | 28 +- docs/search.html | 28 +- docs/search/search_index.json | 2 +- docs/sitemap.xml | 170 --------- docs/sitemap.xml.gz | Bin 217 -> 127 bytes docs/tooling_J-HF-1/index.html | 30 +- docs/tooling_J-QMS-1/index.html | 30 +- docs/tooling_J-QMU-1J-VM-1/index.html | 51 ++- docs/tooling_J-VF1-x/index.html | 32 +- docs/tooling_J-VF2-x/index.html | 30 +- mkdocs_src/docs/tooling_J-QMU-1J-VM-1.md | 3 + 41 files changed, 246 insertions(+), 4393 deletions(-) delete mode 100644 docs/Adding_Custom-build_packages_in_Jenkins/index.html delete mode 100644 docs/Booting_ubuntu22.04_riscv64/index.html delete mode 100644 docs/Building_Jenkins_github_repo/index.html delete mode 100644 docs/Building_Linux_Kernel/index.html delete mode 100644 docs/Building_qemu/index.html delete mode 100644 docs/Creating_Jenkins_Node_on_LXC/index.html delete mode 100644 docs/Cross_Compiling/Cross_compiling python3.8.15/index.html delete mode 100644 docs/Cross_Compiling/Cross_compiling_coremark/index.html delete mode 100644 docs/Cross_Compiling/Cross_compiling_dhrystone/index.html delete mode 100644 docs/Cross_Compiling/Cross_compiling_go/index.html delete mode 100644 docs/Cross_Compiling/Cross_compiling_jdk/index.html delete mode 100644 docs/Cross_Compiling/Cross_compiling_ninja-build/index.html delete mode 100644 docs/Cross_Compiling/Cross_compiling_openssl/index.html delete mode 100644 docs/Cross_Compiling/Cross_compiling_ruby/index.html delete mode 100644 docs/Cross_Compiling/Cross_compiling_rust/index.html delete mode 100644 docs/Cross_Compiling/Overview/index.html delete mode 100644 docs/Installing_ssl_certificates_new/index.html delete mode 100644 docs/Usage_Monitoring/Integrating_prometheus_grafana/index.html delete mode 100644 docs/Usage_Monitoring/Prometheus_Grafana/index.html delete mode 100644 docs/jenkins_github_integration/Github_PR_webhook_integration/index.html delete mode 100644 docs/jenkins_github_integration/Github_push_webhook/index.html diff --git a/docs/404.html b/docs/404.html index f16474a..014780d 100644 --- a/docs/404.html +++ b/docs/404.html @@ -8,14 +8,13 @@ Cloud-V Docs - + - - - + + @@ -27,7 +26,7 @@ Cloud-V Docs
- +
@@ -77,7 +76,7 @@
    -
  • »
  • +
@@ -118,14 +117,15 @@

404

- - - - - + + + + + diff --git a/docs/Adding_Custom-build_packages_in_Jenkins/index.html b/docs/Adding_Custom-build_packages_in_Jenkins/index.html deleted file mode 100644 index 9e4fb34..0000000 --- a/docs/Adding_Custom-build_packages_in_Jenkins/index.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - Adding Custom-build packages in Jenkins - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Adding Custom-build packages in Jenkins
  • -
  • -
  • -
-
-
-
-
- -

Adding Custom-build packages in Jenkins

-

__NOTE: For this documentation, Ubuntu 22.04 and Jenkins version 2.371 is used.

-

While working open-source, many times one may need to build the package from source code. While working on the local machine, the built package may be accessible by adding it to the $PATH environment variable. But while working with Jenkins, This may not work.

-

Where to install package for Jenkins job

-

In Jenkins job, the package is installed on the node (or agent) on which the specific job is being used and NOT on the node where the jenkins controller node is installed. For example if the Jenkins controller node is on computer1 and slave node on which the job is destined to run is on computer2 then computer2 should have all the packages used by the job and not the computer1.

-

Adding the package to Jenkins

-

Considering there is a node with name Runner1 in jenkins on which the job is destined to run and that job uses a toolchain riscv64-unknown-elf-gcc to run properly and that toolchain is present in directory /home/runner1/path_to_install/bin, then the following procedure is used to add the toolchain in Jenkins.

-
    -
  • Go to Dashboard > Manage Jenkins > Nodes > Runner1.
  • -
  • Scroll down and check Environment variables.
  • -
  • Under section List of variables add:
  • -
  • Name as PATH
  • -
  • Value as $PATH:/home/runner1/path_to_install/bin.
  • -
  • Click on Save. -After this, the package should be available to be used.
  • -
- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Booting_ubuntu22.04_riscv64/index.html b/docs/Booting_ubuntu22.04_riscv64/index.html deleted file mode 100644 index 183ca05..0000000 --- a/docs/Booting_ubuntu22.04_riscv64/index.html +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - Booting RISC-V Ubuntu 22.04 on `qemu-system-riscv64` - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Booting RISC-V Ubuntu 22.04 on `qemu-system-riscv64`
  • -
  • -
  • -
-
-
-
-
- -

Booting RISC-V Ubuntu 22.04 on qemu-system-riscv64

-

Pre-requisites

-

Following are the pre-requisites which are needed to be installed before booting ubuntu 22.04 for RISC-V on qemu.

-

Note: Make sure RISC-V GNU Toolchain is installed before proceeding

-
    -
  1. U-boot
  2. -
  3. Qemu version 7.0 or greater with networking
  4. -
  5. Ubuntu 22.04 pre-built image for RISC-V
  6. -
-

1. Installing U-boot

-

Note: If you plan on installing U-boot from apt or some system repository, install the one which comes with ubuntu 22.04. Older will not work with this process. Also, be sure to checkout a latest Stable version instead of development version.

-
    -
  • Get source code of u-boot and checkout stable version using commands below.
  • -
-
git clone https://github.com/qemu/u-boot.git
-cd u-boot
-git checkout v2022.10
-
-
    -
  • Generate configurations for supervisor mode with following command.
  • -
-
make qemu-riscv64_smode_defconfig CROSS_COMPILE=riscv64-unknown-linux-gnu-
-
-
    -
  • Execute following command to start build process.
  • -
-
make CROSS_COMPILE=riscv64-unknown-linux-gnu-
-
-
    -
  • This should install u-boot.bin in the source directory. This file will be used later so its path must be kept remember. Here it will be refered to as $UBOOTPATH.
  • -
-

2. Installing Qemu

-

Qemu version 7.0 or greater should be installed with networking for ubuntu 22.04 to work. See Installing Qemu for RISC-V for instructions on installing qemu-system-riscv64.

-

3. Getting Ubuntu 22.04 pre-build image for RISC-V

-

Ubuntu 22.04 image can be downloaded from https://ubuntu.com/download/risc-v.

-

Booting Ubuntu 22.04 Image on qemu

-

In the directory where ubuntu 22.04 image is present, execute following command to boot into ubuntu 22.04 with qemu-system-riscv64.

-

If you need more space, you can use following command.

-
qemu-img resize -f raw ubuntu-22.04.1-preinstalled-server-riscv64+unmatched.img +5G
-
-

This will increase storage size of the image by 5GB.

-
qemu-system-riscv64 \
--machine virt -nographic -m 2048 -smp 4 \
--kernel $UBOOTPATH/u-boot.bin \
--device virtio-net-device,netdev=eth0 -netdev user,id=eth0,hostfwd=::<host_port>-:<VM_port> \
--drive file=ubuntu-22.04.1-preinstalled-server-riscv64+unmatched.img,format=raw,if=virtio
-
-

Here -m is the memory in Megabytes and -smp is number of cores. -nographic means qemu will use same terminal instance instead of opening a new window of its own (which is beneficial while running servers without gui). Whereas hostfwd=::<host_port>-:<VM_port> will forward traffic going to port <host_port> to port VM_port. Due to this port <host_port> will be used to access ssh on qemu machine.

-

This should boot ubuntu 22.04. But it will take a while on first start.

-

On start, credentials will be as follows.

-
Username: ubuntu
-Password: ubuntu
-
-

After entering credentials, terminal will prompt for change of password after which ubuntu will be ready to use.

- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Building_Jenkins_github_repo/index.html b/docs/Building_Jenkins_github_repo/index.html deleted file mode 100644 index 2a801f1..0000000 --- a/docs/Building_Jenkins_github_repo/index.html +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - - - Building Github Repository of Jenkins - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Building Github Repository of Jenkins
  • -
  • -
  • -
-
-
-
-
- -

Building Github Repository of Jenkins

-

Linux kernel version, distribution and release at the time of build process

-

Linux Kernel: 5.15.0-46-generic (can be checked using uname -r in ubuntu)
-Distribution: Ubuntu
-Release: focal (20.04); also works without issue on ubuntu 22.04 (release can be checked using lsb_release -a in ubuntu)

-

Cloning the github repository

-

First clone the repository using the command below (here it is assumed to be cloned at user's home directory: ~/)
-git clone https://github.com/jenkinsci/jenkins.git

-

Resolving the dependencies

-

After cloning the repository at ~/, the file CONTRIBUTING.md should be available in ~/jenkins/. This file contains all the information to resolve the dependencies and building the repository. -Some notable dependencies are Java Development Kit (JDK), Apache Maven (latest version will be preferable) and git. Running Following command will resolve the mentioned dependencies.

-
sudo apt update && sudo apt install default-jdk default-jre maven git -y
-
-

Building Jenkins using maven on linux

-

For having the jenkins build up as fast as possible, following command can be used in ~/jenkins/.
-mvn -am -pl war,bom -Pquick-build clean install

-

Executing Jenkins

-

After the above commands successfully completes execution, jenkins.war should be present in ~/jenkins/war/target and can be executed to run at port 8080 on localhost using following command.
-java -jar ~/jenkins/war/target/jenkins.war --httpPort=8080 #Considering jenkins repo is cloned at ~/

-

After this process jenkins UI can be accessed using http://localhost:8080 in a browser and a password will be shown on terminal to login to jenkins first time
-After this, Jenkins UI will go through a very simple post installation process which one can configure according to his needs.

- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Building_Linux_Kernel/index.html b/docs/Building_Linux_Kernel/index.html deleted file mode 100644 index 93eb898..0000000 --- a/docs/Building_Linux_Kernel/index.html +++ /dev/null @@ -1,352 +0,0 @@ - - - - - - - - Building a RISCV Linux kernel and booting it in QEMU inside LXC container - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Building a RISCV Linux kernel and booting it in QEMU inside LXC container
  • -
  • -
  • -
-
-
-
-
- -

Building a RISCV Linux kernel and booting it in QEMU inside LXC container

-

This documentation covers how to build a linux kernel with RISCV linux toolchain inside an un-privileged LXC container and then boot it on qemu. -Doing this process on privileged lxc container makes life easier, but privileged containers always have security loop holes. For instance, their root id is mapped to root id of host machine. On the other hand un-privileged containers are the safest (see link).

-

Machine's and LXC Container's Operating System Specifications

-

At the time of creating this documentation, following is the specification of host machine and operating system.

-
    -
  • Host Machine: Ubuntu focal (20.04) 64-bit.
  • -
  • LXC Container: Ubuntu jammy (22.04) 64-bit.
  • -
  • LXC Container is unprivileged with non-sudo user.
  • -
-

NOTE: Throughout this documentation, name of the lxc container will be qemu_container or qemucontainer with non-sudo user as qemu-user which is running on ubuntu 22.04 and host machine x86. Do not confuse the name with assumption that it is booting on qemu emulator. It is just a naming convention.

-

Pre-requisites

-

Following programs may also have their own pre-requisites.

-
    -
  1. Git: For cloning repositories of following programs. Install it with [sudo] apt install git.
  2. -
  3. TMUX: For convenience of multiple terminals. Install it using [sudo] apt install tmux
  4. -
  5. RISCV GNU toolchain built as linux: For compiling the linux kernel.
  6. -
  7. Busybox: For Generating the binaries for linux kernel boot.
  8. -
  9. QEMU Emulator: For booting the linux kernel
  10. -
  11. Linux Kernel (latest version which is used at point of writing this documentation is 6.0.0)
  12. -
-

The working directory inside lxc container for all of this documentation will be ~/riscv-linux or /home/qemu-user/riscv-linux.

-

NOTE: Busybox will not be built inside the lxc container rather it will be built in (any) host linux machine with sudo privileges.

-

3. RISCV GNU Toolchain

-
    -
  • Log in the lxc container to the non-sudo user (here SSH is used to log in).
  • -
  • Install the prerequisites for building RISCV GNU TOOLCHAIN inside lxc container with root user using command below.
  • -
-
apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev libncurses-dev
-
-
    -
  • Clone the GNU toolchain using the command below.
  • -
-
git clone https://github.com/riscv-collab/riscv-gnu-toolchain.git
-
-
    -
  • Create a directory in which the RISCV GNU toolchain is desired to be installed (here it will be /home/qemu-user/riscv-linux/riscv-gnu-installed)
  • -
  • Execute following command inside cloned repository with --prefix as the absolute directory path to where the RISCV toolchain is to be installed
  • -
-
./configure --prefix=/home/qemu-user/riscv-linux/riscv-gnu-installed
-
-
    -
  • Execute following inside cloned repository (execution of this command will take a while to complete)
  • -
-
make linux -j$(nproc) # 'nproc' is the command used to determine the number of processors in machine so that 'make' can use parallelism.
-
-
    -
  • After the execution of command is complete, add bin directory created inside the riscv installation directory to the $PATH and add the expression to .bashrc. According to this documentation, following expression will be added to .bashrc.
  • -
-

PATH="/home/qemu-user/riscv-linux/riscv-gnu-installed/bin:$PATH"

-
    -
  • Check if the toolchain is installed by executing following commands.
  • -
-
exec $SHELL
-riscv64-unknown-linux-gnu-gcc
-
-

Expected Output:

-
fatal error: no input files
-compilation terminated.
-
-
    -
  • Now RISCV linux toolchain is ready !
  • -
-

4. Busybox

-

Busybox is the package for creating linux binutils and set of directories for linux to boot into. Busybox will be installed in host machine instead of lxc container. The reason for this is linux kernel requires block oriented device and character oriented device for it to boot. Those devices can be created using mknod command which can only be created inside a host machine with sudo privileges. Busybox will be used in creating initial ram disk file (in gz format) which is used to boot kernel. It does not matter at which operating system or on which machine this file is created. But the machine on which it is compiled, must also have RISCV GNU toolchain installed above.

-
    -
  • Clone Busybox using the command below.
  • -
-
git clone https://git.busybox.net/busybox
-
-
    -
  • Navigate to cloned directory.
  • -
-
cd busybox
-
-
    -
  • Before building busybox, we need to produce a configuration (.config file) for busybox. It is better to apply default configurations and then change only those which are desired.
  • -
-
make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- defconfig
-
-
    -
  • After the command is executed, a .config file will be present in the busybox cloned directory.
  • -
  • Now, an additional option is to be enabled which enables busybox to build the libraries in the executable instead of separate shared libraries. For this purpose, execute the following command to access the configuration menu. Then go to Settings menu by pressing enter and from there, enable [ ] Build static binary (no shared libs) by pressing space. After the option is enabled, exit by pressing esc twice two times and press yes to the prompt about file saving.
  • -
-
make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- menuconfig
-
-

Selection_005 -Selection_007

-
    -
  • Now that configuration is complete, build busybox by executing following command.
  • -
-
make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- -j$(nproc)
-
-
    -
  • Execute following command which will produce all the basic linux utilities in _install directory in busybox repo directory.
  • -
-
make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- -j$(nproc) install
-
-
    -
  • Navigate to _install directory and create dev directory.
  • -
-
cd _install
-mkdir dev
-
-
    -
  • Now, a linux console and a ram devices are to be created inside dev directory. A fact to understand here is that, every device is a file in linux but they are special kind of files. A detail of these devices can be found here. In this documentation mknod command is used to create these devices.
  • -
-
sudo mknod dev/console c 5 1
-sudo mknod dev/ram b 1 0
-
-
    -
  • After executing above commands, following files with names ram and console will be created as shown in the image below.
  • -
-

Screenshot from 2022-10-02 21-45-00

-
    -
  • Now an init file is needed because linux kernel does not boot itself, it rather searches for init file in the directories (read linux kernel messages during build procedure). init file contains commands to mount some directories during boot (more information can be found here). In busybox/_install, create a file with following contents (be sure to make it executable with chmod +x init).
  • -
-
vim init
-
-
#!/bin/sh
-echo "### INIT SCRIPT ###"
-mkdir /proc /sys /tmp 
-mount -t proc none /proc #For processes
-mount -t sysfs none /sys #For all the devices on the machine
-mount -t tmpfs none /tmp #For virtual memory
-echo -e "\nThis boot took $(cut -d' ' -f1 /proc/uptime) seconds\n"
-exec /bin/sh
-
-
    -
  • Now that all the files are ready for linux to boot into, pack them in cpio format and then to gz format. It is because cpio format is in "Early userspace support" in linux kernel (see link) whereas gz format is needed because it is one of the formats needed by qemu emulator. Following command produces a qemu-compatible initramfs file for linux kernel to boot in.
  • -
-
find -print0 | cpio -0oH newc | gzip -9 > ../initramfs.cpio.gz 
-
-
    -
  • Command Details:
  • -
  • find -print0 separates the file names with null character
  • -
  • cpio -0oH newc produces an archive file in newc format
  • -
  • gzip -9 creates a gz format zip file. -9 represents the best compression level at the slowest speed
  • -
  • ../initramfs.cpio.gz represents the output file which is created in parent directory to present working directory.
  • -
  • At this point, our work with busybox is done.
  • -
  • Copy the produced file into the lxc container (use scp command if it is on ssh).
  • -
-

5. QEMU Emulator

-
    -
  • Install the pre-requisites of qemu emulator on lxc container with root user with following command (see link).
  • -
-
apt-get install git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build
-
-
    -
  • Clone the QEMU Emulator repository using the command below with root user:
  • -
-
git clone https://github.com/qemu/qemu.git
-
-
    -
  • Build QEMU for RISCV with root user using commands below (see link).
  • -
-
./configure --target-list=riscv64-softmmu
-make -j$(nproc)
-
-
    -
  • For system-wide installation of QEMU Emulator, run following command with root user.
  • -
-
make -j$(nproc) install
-
-
    -
  • After execution of this command, work with QEMU Emulator is done and its commands can be accessed anywhere.
  • -
-

6. Linux Kernel

-
    -
  • Clone the linux kernel from Linus Torvalds' repository using the command below.
  • -
-
git clone https://github.com/torvalds/linux.git
-
-
    -
  • Navigate to cloned repository.
  • -
-
cd linux
-
-

Building Linux kernel with riscv64-unknown-linux-gnu-gcc

-
    -
  • Before building linux kernel with RISCV toolchain a configuration file (.config) must be produced in its directory. First, produce a file with default configurations, then change configurations according to needs.
  • -
-
make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- defconfig
-make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- menuconfig
-
-
    -
  • Above command will open configuration menu. Enter General setup, scroll down and enable Initial RAM filesystem and RAM disk (initramfs/initrd) support using Space key. Then enter () Initramfs source file(s) and here put the absolute path to initramfs.cpio.gz file which was just created using busybox. For this documentation, it is /home/qemu-user/riscv-linux/initramfs.cpio.gz. Double-press esc and save the file.
  • -
-

Selection_008

-

Selection_009

-

Selection_011

-
    -
  • Now linux kernel is ready to be compiled with riscv64-linux-gnu-gcc toolchain. So execute the command below.
  • -
-
make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- -j$(nproc)
-
-
    -
  • If the above command successfully executed without any errors, there must be Kernel: arch/riscv/boot/Image.gz is ready printed on terminal. On newer linux kernels, it might be scrolled up a little, use Ctrl-shift-f to find it.
  • -
-

Booting into the linux kernel using QEMU emulator

-

Now that everything is ready, execute the following command in linux/arch/riscv/boot/ directory to boot linux on sifive's unleashed.

-
qemu-system-riscv64 -kernel Image -machine sifive_u -nographic
-
-
    -
  • Command Details
  • -
  • qemu-system-riscv64 is the qemu built for riscv64
  • -
  • -kernel takes the image produced by linux kernel compilation and is present in linux/arch/riscv/boot/ directory.
  • -
  • -machine takes one of the machine names as arguments available in qemu-system-riscv64. Available machines can be listed on terminal using command qemu-system-riscv64 -machine help.
  • -
  • -nographic restricts the use of GUI (which is a better option considering lxc container does not support gtk initialization).
  • -
  • If everything goes on right, the kernel will boot successfully as shown in the picture below. -Selection_012
  • -
- -
    -
  1. https://risc-v-getting-started-guide.readthedocs.io/en/latest/linux-qemu.html
  2. -
  3. https://hackernoon.com/how-to-set-up-the-environment-for-riscv-64-linux-kernel-development-in-ubuntu-2004-si5p35kv
  4. -
- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Building_qemu/index.html b/docs/Building_qemu/index.html deleted file mode 100644 index 81492b0..0000000 --- a/docs/Building_qemu/index.html +++ /dev/null @@ -1,247 +0,0 @@ - - - - - - - - Installing `QEMU` for emulating riscv64 - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Installing `QEMU` for emulating riscv64
  • -
  • -
  • -
-
-
-
-
- -

Installing QEMU for emulating riscv64

-

QEMU is an open-source emulator. It can be used to emulate different architectures on a single machine. In RISC-V CI there are various programs which run on RISC-V architecture. But instead of porting them to a dedicated board of riscv architecture, they can be run readily on qemu emulator. Here two types of QEMU emulators will be used for RISC-V applications:

-
    -
  1. qemu-system-riscv64: It can be used to load a complete linux operating system image.
  2. -
  3. qemu-riscv64: It can be used to execute program's binary directly without need of a complete operating system.
  4. -
-

Installing Pre-requisites

-

Execute the following command to install the pre-requisites for installing qemu on ubuntu 22.04 (jammy)

-
sudo apt-get install meson git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build
-
-

qemu-slirp is important for enabling user-level networking with qemu-system-riscv64 qemu-system-riscv64 while loading image of server installation of ubuntu. So it needs to be installed first.

-

Get the source code of qemu-slirp using following command:

-
git clone https://github.com/openSUSE/qemu-slirp.git
-
-

Then Execute following commands to install slirp in meson, which can later be used by qemu during build.

-
meson build
-ninja -C build install
-
-

Note: Make sure you have riscv64-unknown-linux-gnu toolchain installed for compiling program and executing them on qemu later.

-

There are some optional dependencies which one can download, but they are actually not needed for installing qemu and make it work.

-

Installing qemu-system-riscv64

-

What is qemu-system-riscv64

-

qemu-system-riscv64 is qemu executable program. It can load a complete linux distribution. It cannot take program's executable binary as argument and run it without a dedicated linux distribution.

-

Installing qemu-system-riscv64 on ubuntu

-
    -
  • Get source code of qemu from github using the command below
  • -
-
git clone https://github.com/qemu/qemu.git
-
-
    -
  • Configure qemu for riscv64-softmmu with following command (replace $PREFIX with valid location of installation).
  • -
-
./configure --prefix=$PREFIX --target-list=riscv64-linux-user,riscv64-softmmu --enable-slirp  
-
-
    -
  • Execute following command to start the build.
  • -
-
make
-
-
    -
  • Execute following command to install the binaries at $PREFIX location.
  • -
-
make install
-
-

Note: After the installation with slirp following error can be encountered on some systems.

-
qemu-system-riscv64: symbol lookup error: qemu-system-riscv64: undefined symbol: slirp_new, version SLIRP_4.0
-
-

Solution: This can be solved by executing following command in source directory of qemu (which is cloned from github).

-
[sudo] ldconfig
-
-

Testing qemu-system-riscv64

-

qemu-system-riscv64 can only be tested by booting a linux operating system. See Booting RISC-V Ubuntu 22.04 on qemu-system-riscv64.

-

Installing qemu-riscv64

-

What is qemu-riscv64

-

qemu-riscv64 is qemu executable program. But instead of porting a complete operating system (like qemu-system-riscv64), it can readily execute binaries.
-Throughout cross-compiling section, qemu-riscv64 will be used with linux-user and executable of every program can be tested on qemu (e.g. python, ruby etc.).

-

Installing qemu-riscv64 on ubuntu 22.04

-
    -
  • Get source code of qemu using the command below
  • -
-
git clone https://github.com/qemu/qemu.git
-
-
    -
  • Use following command in the root directory of repository to configure qemu for riscv64-linux-user
  • -
-
./configure --target-list=riscv64-linux-user --prefix=$PREFIX # Replace $PREFIX with a valid location to install at  
-
-

Note: If this is not your architecture/platform, you can see a list of available platform/architecture by executing following command.

-
./configure --help
-
-
    -
  • Use the following command to start the build process
  • -
-
make -j$(nproc)
-
-
    -
  • After the builld is complete without any error, use the following command to install binaries at $PREFIX location
  • -
-
make install
-
-
    -
  • -

    Add the $PREFIX/bin to $PATH variable so that it may be recognized as a command.

    -
  • -
  • -

    Using this method causes the qemu-riscv64 to have an issue with sysroot. It starts searching for libraries in the root folder of the machine which is based on x86_64-linux-gnu. A simple workaround is to give path of the sysroot/ folder where riscv64-unknown-linux-gnu toolchain is installed. Here that directory will be denoted as $RISCV_SYSROOT

    -
  • -
-

Testing qemu-riscv64

-
    -
  • Create a C file in your favorite editor or by using the commands below:
  • -
-
echo "#include<stdio.h>" > helloworld.c
-echo "int main(){" >> helloworld.c
-echo "printf("Hello World !");" >> helloworld.c
-echo '}' >> helloworld.c
-
-
    -
  • Execute following command to compile C program with riscv gnu toolchain
  • -
-
riscv64-unknown-linux-gnu-gcc helloworld.c -o helloworld
-
-
    -
  • Execute following command to execute the compiled binary on qemu-riscv64
  • -
-
qemu-riscv64 -L $RISCV_SYSROOT ./helloworld
-
-
    -
  • If everything went right, following output will be shown.
  • -
-
Hello World !
-
- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Creating_CI_CD_pipeline/index.html b/docs/Creating_CI_CD_pipeline/index.html index b7ca540..3d2a21e 100644 --- a/docs/Creating_CI_CD_pipeline/index.html +++ b/docs/Creating_CI_CD_pipeline/index.html @@ -8,7 +8,7 @@ Creating a CI/CD pipeline in Jenkins - Cloud-V Docs - + - - - + + @@ -34,7 +33,7 @@ Cloud-V Docs
- +
@@ -84,8 +83,8 @@
    -
  • »
  • -
  • Creating a CI/CD pipeline in Jenkins
  • +
  • +
@@ -171,14 +170,15 @@

Steps for Jenkins pipeline creation

- - - - - + + + + + diff --git a/docs/Creating_Jenkins_Node_on_LXC/index.html b/docs/Creating_Jenkins_Node_on_LXC/index.html deleted file mode 100644 index ad661e5..0000000 --- a/docs/Creating_Jenkins_Node_on_LXC/index.html +++ /dev/null @@ -1,254 +0,0 @@ - - - - - - - - Creating a Jenkins Node on LXC Container - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Creating a Jenkins Node on LXC Container
  • -
  • -
  • -
-
-
-
-
- -

Creating a Jenkins Node on LXC Container

-

What is a container

-

A container is a virtualization method for isolating the applications (or even operating systems) from each other.

-

Why do we need a container for Jenkins node

-

In Jenkins, node is a location where our jobs run. One user can use one node for all of his processes and multiple users may also use one node for all of their processes. In Jenkins freestyle project, we can use bash shell or windows command shell due to which there is a possibility to navigate anywhere in the server machine. This possibility can lead to various security and integrity issues for server administrators and also for other users using that webserver. So one must isolate each node and allocate each node to each user separately.

-

What is LXC Container

-

LXC stands for Linux Containers. LXC is a package for linux operating systems and provides linux users with containers which may contain a whole linux operating system while also being lightweight than a virtual machine. More information regarding LXC can be found at -https://linuxcontainers.org/lxc/introduction/

-

On ubuntu 20.04 one can install LXC using command
-[sudo] apt-get install lxc

-

Creating a container with LXC

-

NOTE: Throughout this document, the name of the container will be my-container and the name of the user will be user1. So wherever my-container is written, one may change the name to whatever one wants to give it.

-

Pre-requisites

-

Before proceeding, it is important to mention that at the point of writing this document following are the specifications for linux kernel and distribution:

-

Linux Kernel: 5.15.0-46-generic (can be checked on ubuntu by command uname -r)
-Distribution: Ubuntu focal (20.04) (can be checked on ubuntu by command lsb_release -a)

-

By default linux users are not allowed to create any network device on the machine. For doing that, one must add uid and gid in the /etc/lxc/lxc-usernet. The uid and gid of the user you want to use can be found in the files /etc/uid and /etc/gid respectively.

-

After getting the gid and uid of the user you want to allow for creating the network devices, one must go to /etc/lxc/lxc-usernet and add the uid and gid in the following format:

-

<username> veth lxcbr0 10
-e.g.
-jenkins veth lxcbr0 10

-

In above example jenkins is the username, veth is the command used for creating the bridges between virtual network devices and physical network devices (you will be able to see that ethernet device in our container will be lxcbr0) and lxbr0 is the network device we want to create. ‘10’ represents the number of devices we want to create using our specified user.

-

According lxc documentation, in ubuntu 20.04 an additional command is required before creating lxc container:
-export DOWNLOAD_KEYSERVER="hkp://keyserver.ubuntu.com"

-

Creating image

-

After this, one can create container using following command

-

systemd-run --unit=my-unit --user --scope -p "Delegate=yes" -- lxc-create -t download -n my-container

-

This runs lxc container with unit name my-unit, container name my-container and delegates a control group (also known as the cgroup) which is needed for resource allocation for processes in container.

-

This will output the list of available linux distributions in which one may want to run the container and will prompt for Distribution as shown in the following image.

-

unnamed (4)

-

After selecting the suitable distribution, release and architecture (which is also mentioned in the table), the container may be created as shown in the image below:

-

unnamed (5)

-

Next thing is to start a container which will change its state from STOPPED to RUNNING using the following command.

-

lxc-start -n my-container

-

Above command will have no output if it succeeds.
-The state of the container can be checked using the following command.

-

lxc-info -n my-container

-

After starting the container, its state will be set as running and is just like turning a linux machine ON.

-

From this point onwards, if one wants to use the machine in the terminal then use the following command and this will switch the terminal to the root of the container.

-

lxc-attach my-container

-

unnamed (6)

-

Now the container is ready to be used and is completely isolated from the host machine.

-

Using SSH to access container with username and password

-

The above mentioned method can be used to attach the host machine terminal to the container and this can be used to access the container. But if one wants to access the machine remotely then one possible and well-known method will be to configure and use SSH on the container.

-

As it is an out of the box linux distro and only the root user is present, so first create another user using the following command and then manage its permissions for /home folder.

-
#Considering you remain the root user for execution of all the  following #commands
-
-useradd user1
-cd /home
-mkdir user1    #Creating home directory for user1
-chown user1:user1 user1  #Giving ownership of home directory to new user
-
-#For adding the same shell and bashrc configurations for new user, use #following
-#command, otherwise the shell will be very basic for new user and will be #very inconvenient to use.
-
-usermod -s /bin/bash user1
-
-

For the sake of simplicity of this document the name used for the new user is user1 here. -(You may want to set the password for user1 by executing the passwd command in root.)

-

At this point user1 is not in sudoers. For adding it to the sudoers, it must be added in the sudo group which can be done by using the following command.

-

usermod -a -G sudo user1

-

Now switch to the user1 using the following command.

-

su - user

-

Now install openssh-server for configuring the ssh on user1.

-

sudo apt install openssh-server

-

After that one must find the ip of the container we are using, for this either run following command while in container with user1,

-
sudo apt-install net-tools
-
-#Because ifconfig is part of net-tools which are by default not installed on new #container
-
-Ifconfig -a
-
-

unnamed (7)

-

OR open a new terminal in the host machine and execute the following command.

-

lxc-info my-container -iH

-

unnamed (8)

-

So, the ip of the container is 10.0.3.127. -The command for establishing an ssh connection to a remote machine is mentioned below and it will ask for the password of the remote machine which is actually the container in our case.

-

ssh user1@10.0.3.127

-

After entering the password, terminal will switch to the container’s user1 as can be seen in the following image.

-

unnamed (9)

-

Using SSH to access Jenkins agents on the container

-

First install some initial dependencies (git, jdk, jre) on the containers for running agents on the container.

-
sudo apt update
-sudo apt install default-jdk default-jre git maven
-
-

Now login to jenkins with administrator privileges and create a node in it from Dashboard > Manage Jenkins > Nodes and press + New Node. Enter a name for the node and select the desirable node type. -For this documentation, the node will be a permanent type and the name will be temp_node.

-

unnamed (10)

-

After this click on Create which will display the configuration page of the node.

-
    -
  1. Write the description of the node as desired.
  2. -
  3. Number of executors means number of threads running at a time (it will be better to set it to the number of processors present on the machine which is running this node).
  4. -
  5. Remote root directory will be the directory where the jobs will run by default on the node. In our case this will be a specified directory inside the container.
  6. -
  7. Labels indicate that this node will run only when a job with specified labels is run, otherwise this node will not be used (also depends on the usage method in the next option). If the purpose is to use the node by default for every job, then leave it empty.
  8. -
  9. Select a desired usage option.
  10. -
  11. In launch methods, select “Launch agents via SSH”
      -
    • In “Host” enter the ip address of the container which is 10.0.3.127 in our case.
    • -
    • In “Credentials”, click Add and this will open another sub dialog for entering credentials information.
    • -
    • Select the kind as “Username wih password”.
    • -
    • Leave other options as is and write the username and password of the container user, in our case the username will be user1 and password will be the password which was set for user1.
    • -
    • “ID” and “Description” are optional.
    • -
    • Click on “Add”.
    • -
    • Now as the credentials are added, click on the dropdown menu and select the username you just added. In our case it is user1 as the username added was user1.
    • -
    -
  12. -
  13. After this rest of the options need not to be changed if this node is going to be a default node.
  14. -
  15. Click on “Save”.
    -After complete setup, the configuration for this node will look something like this.
  16. -
-

unnamed (11)

-

unnamed (12)

-

unnamed (13)

-

If no issue is encountered during this whole setup, jenkins will take us to the log and after sometime (when the ssh connection is established) we can see “Agent successfully connected and online” at the bottom of the log as can be seen in the screenshot below.

-

unnamed (14)

-

After this point, node will be able to run jobs from the container directory.

- -

Documentation for LXC containers can be found at: https://linuxcontainers.org
-Details regarding Jenkins ssh agents can be found at: https://acloudguru.com/blog/engineering/adding-a-jenkins-agent-node

- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Creating_jenkinsfile/index.html b/docs/Creating_jenkinsfile/index.html index a626d40..148f367 100644 --- a/docs/Creating_jenkinsfile/index.html +++ b/docs/Creating_jenkinsfile/index.html @@ -8,7 +8,7 @@ Creating a CI pipeline file - Cloud-V Docs - + - - - + + @@ -34,7 +33,7 @@ Cloud-V Docs
- +
@@ -108,8 +107,8 @@
    -
  • »
  • -
  • Creating a CI pipeline file
  • +
  • +
@@ -256,14 +255,15 @@
- - - - - + + + + + diff --git a/docs/Cross_Compiling/Cross_compiling python3.8.15/index.html b/docs/Cross_Compiling/Cross_compiling python3.8.15/index.html deleted file mode 100644 index ecf6926..0000000 --- a/docs/Cross_Compiling/Cross_compiling python3.8.15/index.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - Cross compiling python3.8.15 for `riscv64` - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Cross compiling python3.8.15 for `riscv64`
  • -
  • -
  • -
-
-
-
-
- -

Cross compiling python3.8.15 for riscv64

-

This document will include how to build python3.8.15 for riscv64 architecture while using build machine as x86_64.

-

Building Python

-

Get the python source code of python 3.8.15 in form of tarball from this link.

-

Once a tarball is obtained, extract it and use following command in its root folder to configure it.

-
# Here $PREFIX is the directory where the binaries are desired to be installed.
-./configure --host=riscv64-unknown-linux-gnu --build=x86_64-linux-gnu --prefix="$PREFIX" --disable-ipv6 ac_cv_file__dev_ptmx=no ac_cv_file__dev_ptc=no
-
-

After the above command is executed, use following command to start the build.

-
make -j$(nproc)
-
-

Now to install binaries on the location where PREFIX, use following command.

-
make install
-
-

This will install binaries for python3.8.15 in the $PREFIX directory and it can be checked using qemu-riscv64.

- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Cross_Compiling/Cross_compiling_coremark/index.html b/docs/Cross_Compiling/Cross_compiling_coremark/index.html deleted file mode 100644 index 879dc81..0000000 --- a/docs/Cross_Compiling/Cross_compiling_coremark/index.html +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - - - Cross-compiling Coremark - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Cross-compiling Coremark
  • -
  • -
  • -
-
-
-
-
- -

Cross-compiling Coremark

-

Coremark is another benchmarking tool. Here coremark will be cross-compiled for riscv64-unknown-linux-gnu and will be run on qemu-riscv64. The github source code commit at the time of build is eefc986ebd3452d6adde22eafaff3e5c859f29e4 and branch is main.

-

Getting the source code

-

Execute the following command to get the source code of coremark.

-
git clone https://github.com/eembc/coremark.git
-
-

Tweaking source files for riscv64-unknown-linux-gnu

-

At the time of this documentation, linux is being used for this test. First of all core_portme.mak will be changed.

-
    -
  1. Navigate to linux/ directory in source repository.
  2. -
  3. Open core_portme.mak. Here a single line will be used to include core_portme.mak from posix directory. So, navigate to posix/ directory in source folder
  4. -
  5. Open core_portme.mak in posix/ directory and do the following changes to variables here.
      -
    1. Change CC?=cc to CC=riscv64-unknown-linux-gnu-gcc.
    2. -
    3. Scroll down and change EXE=.exe to EXE= (it should be blank).
    4. -
    5. Scroll down and change LD=gcc to LD=riscv64-unknown-linux-gnu-ld.
    6. -
    7. As we are using qemu-riscv64, so change RUN= to RUN=qemu-riscv64 -L "$$RISCV_SYSROOT"
    8. -
    9. Save changes and exit this file.
    10. -
    -
  6. -
  7. Now open core_portme.h and change #define USE_CLOCK 0 to #define USE_CLOCK 1 and save.
  8. -
  9. Navigate to source directory of repository and execute following command
  10. -
-
make PORT_DIR=linux/
-
-

If everything went right, the output result will be stored in run1.log and run2.log and will be of the form as shown below.

-
2K validation run parameters for coremark.
-CoreMark Size    : 666
-Total ticks      : 12368459
-Total time (secs): 12.368459
-Iterations/Sec   : 8893.589735
-Iterations       : 110000
-Compiler version : GCC12.2.0
-Compiler flags   : -O2 -DPERFORMANCE_RUN=1  -lrt
-Memory location  : Please put data memory location here
-            (e.g. code in flash, data on heap etc)
-seedcrc          : 0x18f2
-[0]crclist       : 0xe3c1
-[0]crcmatrix     : 0x0747
-[0]crcstate      : 0x8d84
-[0]crcfinal      : 0x0956
-Correct operation validated. See README.md for run and reporting rules.
-
- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Cross_Compiling/Cross_compiling_dhrystone/index.html b/docs/Cross_Compiling/Cross_compiling_dhrystone/index.html deleted file mode 100644 index dfd23b1..0000000 --- a/docs/Cross_Compiling/Cross_compiling_dhrystone/index.html +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - - - Cross-compiling `dhrystone` - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Cross-compiling `dhrystone`
  • -
  • -
  • -
-
-
-
-
- -

Cross-compiling dhrystone

-

Dhrystone is a benchmarking tool. Here dhrystone will be compiled from source and run on qemu-riscv64.
-Dhrystone is comparable to VAX 11/780 in a way that VAX 11/780 achieves 1757 dhrystones per second which is also referred to as 1 MIPS of VAX11/780. So number of dhrystones per seconds are obtained and then divided by 1757 to get MIPS. See this link for more details.

-

Cross-compiling for riscv64-unknown-linux-gnu

-
    -
  • Get the source code of dhrystone using the command below
  • -
-
git clone https://github.com/sifive/benchmark-dhrystone.git
-
-
    -
  • Navigate to root directory of repository and compile program with riscv64-unknown-linux-gnu-gcc instead of native gcc
  • -
-
cd benchmark-dhrystone
-make CC=riscv64-unknown-linux-gnu-gcc
-
-
    -
  • Execute following command to execute dhrystone binary
  • -
-
qemu-riscv64 -L $RISCV_SYSROOT ./dhrystone
-
-

Note: You may want to tweak Makefile and dhry_1.c a little bit to get the correct results.

- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Cross_Compiling/Cross_compiling_go/index.html b/docs/Cross_Compiling/Cross_compiling_go/index.html deleted file mode 100644 index 06bd9e0..0000000 --- a/docs/Cross_Compiling/Cross_compiling_go/index.html +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - - - Cross compiling `Go` - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Cross compiling `Go`
  • -
  • -
  • -
-
-
-
-
- -

Cross compiling Go

-

Go currenlty has support for riscv64 architecture. This document will cover how to compile go on x86 for riscv64 architecture.

-

Note: Right now, go can be cross-compiled on x86 but it cannot be executed on x86 with qemu-riscv64 because it needs to execute goroot/pkg/tool/compile and qemu-riscv64 can only execute one binary at a time.

-

Pre Requisites

-

On ubuntu, following pre-requisites should be installed.

-
    -
  • Snap
  • -
  • qemu-riscv64 (linux-user)
  • -
-

Go source code is written in go. That means a go toolchain is needed to compile the source code (see link ). As this document cross-compiles the code, first of all install a go language on build machine. Use following command on ubuntu to install a go language compiler.

-
sudo snap install go --classic
-
-

After this, get the source code of go from following command.

-
git clone https://go.googlesource.com/go goroot
-
-

Now set the environment variable as follows.

-
export GOROOT_BOOTSTRAP=/snap
-export GOARCH=riscv64
-export GOOS=linux
-
-

Navigate to goroot/src and execute following command.

-
./all.bash
-
-

After this, an executable file will be located in folder goroot/bin/linux_riscv64.

- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Cross_Compiling/Cross_compiling_jdk/index.html b/docs/Cross_Compiling/Cross_compiling_jdk/index.html deleted file mode 100644 index 3272151..0000000 --- a/docs/Cross_Compiling/Cross_compiling_jdk/index.html +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - Cross-compiling JDK for `riscv64-unknown-linux-gnu` - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Cross-compiling JDK for `riscv64-unknown-linux-gnu`
  • -
  • -
  • -
-
-
-
-
- -

Cross-compiling JDK for riscv64-unknown-linux-gnu

-

JDK is abbreviation of 'Java Development Kit'. It is used for compiling and executing java-based programs and applications.

-

All the information regarding building jdk and relevant dependencies are given at
-https://github.com/openjdk/jdk/blob/master/doc/building.md

-

Make sure to have riscv64-unknown-linux-gnu toolchain installed on machine.

-

Getting source code

-

The source code of jdk can be obtained using command below

-
git clone https://github.com/openjdk/jdk.git
-
-

Building the source code for

-
    -
  • First of all configure the source code using the command below
  • -
-
bash configure --host=riscv64-unknown-linux-gnu --build=x86_64-linux-gnu --target=riscv64-unknown-linux-gnu --prefix=/home/ali/custom_installed/RISCV/jdk/967a28c3d85fdde6d5eb48aa0edd8f7597772469 --with-cups=/home/ali/custom_installed/cups --with-fontconfig=/home/ali/custom_installed/fontconfig/e291fda7d42e5d64379555097a066d9c2c4efce3 --x-includes=/usr/include --x-lib=/usr/lib
-
- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Cross_Compiling/Cross_compiling_ninja-build/index.html b/docs/Cross_Compiling/Cross_compiling_ninja-build/index.html deleted file mode 100644 index 406b17b..0000000 --- a/docs/Cross_Compiling/Cross_compiling_ninja-build/index.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - - Cross-compiling ninja-build for RISC-V - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Cross-compiling ninja-build for RISC-V
  • -
  • -
  • -
-
-
-
-
- -

Cross-compiling ninja-build for RISC-V

-

Ninja is a small build system with a focus on speed. It differs from other build systems in two major respects: it is designed to have its input files generated by a higher-level build system, and it is designed to run builds as fast as possible.

-

This document will cover how to compile ninja to work on 64-bit RISC-V architecture.

-

Getting source code

-

Use following command to get source code of ninja-build and navigate to source directory.

-
git clone git://github.com/ninja-build/ninja.git
-cd ninja
-git checkout release
-
-

Create following cmake file inside the root directory of ninja-build repository.

-
# the name of the target operating system
-set(CMAKE_SYSTEM_NAME Linux)
-
-# which compilers to use for C and C++
-set(CMAKE_C_COMPILER   riscv64-unknown-linux-gnu-gcc)
-set(CMAKE_CXX_COMPILER riscv64-unknown-linux-gnu-g++)
-
-# where is the target environment located
-set(CMAKE_FIND_ROOT_PATH  /softwares/RISCV/riscv64-unknown-linux-gnu/50c1b734e889e5cbb88bcc7f14975ea9a1d0b936/sysroot
-    )
-
-# adjust the default behavior of the FIND_XXX() commands:
-# search programs in the host environment
-set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
-
-# search headers and libraries in the target environment
-set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
-set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
-
- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Cross_Compiling/Cross_compiling_openssl/index.html b/docs/Cross_Compiling/Cross_compiling_openssl/index.html deleted file mode 100644 index 02d8e60..0000000 --- a/docs/Cross_Compiling/Cross_compiling_openssl/index.html +++ /dev/null @@ -1,197 +0,0 @@ - - - - - - - - Cross-compiling openssl - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Cross-compiling openssl
  • -
  • -
  • -
-
-
-
-
- -

Cross-compiling openssl

-

What is openssl

-

Openssl is a software library which is used inside many high level languages (e.g. Python, Ruby etc.) and also in linux itself. It is used for security and other cryptography applications.

-

Building openssl v1.0.1 for riscv64 architecture

-

Following are the steps used to build openssl for riscv64 architecture.

-
    -
  • Get the source code of openssl and navigate inside the cloned repository using the commands below
  • -
-
git clone https://github.com/openssl/openssl.git
-cd openssl
-
-
    -
  • Configure openssl for building. In openssl there are some os/compiler choices which one can use to build for his architecture. But in our case there is no support for building with riscv64. As it is written in C language, so it can be compiled whether or not the support is given. Use the following command to generate a Makefile for linux-generic64
  • -
-
./Configure linux-generic64 --prefix=$PREFIX # Prefix is the directory where you want binaries to be installed at the end
-
-
    -
  • After the above command is successfully completed, run the following command to build openssl using riscv64-unknown-linux-gnu-gcc compiler instead of native gcc compiler.
  • -
-
make -j$(nproc) CC=riscv64-unknown-linux-gnu-gcc
-
-
    -
  • Install the binaries in the specified --prefix using the command below
  • -
-
make -j$(nproc) install CC=riscv64-unknown-linux-gnu-gcc
-
-

The installed binary can be tested on qemu-riscv64 using the command below:

-
qemu-riscv64 -L $RISCV_SYSROOT ./openssl
-
-

Here $RISCV_SYSROOT is the sysroot/ folder located inside the riscv gnu toolchain installed directory.

-

The above mentioned command will start the openssl console if everything went right.

-

Note: Do not change the directory of openssl or rename it, as it some files inside it are inferred with absolute paths, changing the directory or renaming it will cause other packages to not configure openssl for them when cross-compiling.

-

Building openssl v1.1.1r for riscv64 architecture

-

In openssl v1.1.1r, there is a support for linux64-riscv64. Following is the procedure for cross-compilation.

-
    -
  • Checkout the v1.1.1r of openssl by executing following command in the repository directory.
  • -
-
git checkout OpenSSL_1_1_1r
-
-
    -
  • Execute following command to configure for riscv64 architecture and generate a Makefile.
  • -
-
./Configure linux64-riscv64 --prefix=$PREFIX # Replace $PREFIX with where you want to install binaries
-
-
    -
  • Execute following command to cross-compile for riscv64-unknown-linux-gnu.
  • -
-
make CROSS_COMPILE=riscv64-unknown-linux-gnu-
-
-
    -
  • Then install binaries at $PREFIX with following command.
  • -
-
make install
-
-

Solving post-installation errors

-

On some operating systems, the installed binaries may not run properly and will give following error.

-
./openssl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory
-
-

This means that shared libraries cannot be found in the path where the system is looking for them. This can be solved by setting LD_LIBRARY_PATH variable as follows.

-
export LD_LIBRARY_PATH=$PREFIX/lib:$LD_LIBRARY_PATH
-
-

It will be a good practice to include the above in the bashrc for debian users.

- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Cross_Compiling/Cross_compiling_ruby/index.html b/docs/Cross_Compiling/Cross_compiling_ruby/index.html deleted file mode 100644 index 4d82ca8..0000000 --- a/docs/Cross_Compiling/Cross_compiling_ruby/index.html +++ /dev/null @@ -1,209 +0,0 @@ - - - - - - - - Cross Compilation of Ruby - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Cross Compilation of Ruby
  • -
  • -
  • -
-
-
-
-
- -

Cross Compilation of Ruby

-

System Specifications

-

Build Architecture: x86_64-linux-gnu
-Host Architecture: riscv64-unknown-linux-gnu
-Operating System for Installation Procedure: Ubuntu 20.04

-

Pre-requisites

-

Pre-requisites for installing ruby from source can be installed using the following command

-
sudo apt-get -y install libc6-dev libssl-dev libmysql++-dev libsqlite3-dev make build-essential libssl-dev libreadline6-dev zlib1g-dev libyaml-dev
-
-

Other than this, ruby itself is needed for building ruby from source.

-
sudo apt install ruby
-
-

There is another thing which needs to be taken care of before building ruby from source. If ruby is installed on system itself using apt, then cross compiling ruby will end up in an error as shown in the image below. This error is seen in ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux-gnu].

-

ruby_system_error

-

To tackle this issue, one workaround is to install build ruby for native system, then delete ruby which was installed through apt. This procedure will be added in the Build section.

-

Getting source code

-

Source code of ruby can be obtained from github repository using the command below:

-
git clone https://github.com/ruby/ruby.git
-
-

Build

-

Installing ruby for native architecture

-

Before cross-compiling, one must install ruby from source on the native machine which will solve the error described in Pre-requisites section above.

-
    -
  • (THIS STEP IS STRONGLY RECOMMENDED !)In the source directory, create a folder with any name in which Makefile will be generated otherwise there will be a lot of files made in the source directory (possibly create copy of repo directory).
  • -
  • In the source directory of ruby run following command to generate configure file.
  • -
-
./autogen.sh
-
-
    -
  • After this, run the following configure command to generate Makefile.
  • -
-
../configure --prefix=$PREFIX #$PREFIX is where you want to install binary files at the end, so replace it.
-
-
    -
  • After the above command is completed, run following command to start the build
  • -
-
make -j$(nproc) #-j$(nproc) uses parallelism for make
-
-
    -
  • After the above command is complete, run following command to install the binaries on the specified path mentioned in --prefix above
  • -
-
make install
-
-
    -
  • Now ruby should be available in the $PREFIX path (also in the .bashrc). Add $PREFIX path to $PATH variable and uninstall the the ruby installed using apt otherwise, the source will keep using that one for building and the error will persist.
  • -
-
sudo apt purge ruby
-
-

Cross-Compiling Ruby for riscv64-unknown-linux-gnu

-
    -
  • After the ruby installed using apt is uninstalled from the system, clean the working directory with following command.
  • -
-
make clean
-
-
    -
  • After cleaning the working directory, generate the Makefile again for cross-compiling ruby for riscv64-unknown-linux-gnu target and host using the command below
  • -
-
../../configure --prefix=$PREFIX --build=x86_64-linux-gnu --host=riscv64-unknown-linux-gnu --target=riscv64-unknown-linux-gnu
-
-
    -
  • After the above command is successful, start build with following command
  • -
-
make -j(nproc)
-
-
    -
  • Install the binaries in path mentioned with --prefix above with following command
  • -
-
make install
-
-
    -
  • After this process, ruby will be installed inside $PREFIX/ directory.
  • -
-

Note: Currently, this process (as checked on version 3.1.2) installs ruby without extensions shown in the following image

-

ruby_extensions

- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Cross_Compiling/Cross_compiling_rust/index.html b/docs/Cross_Compiling/Cross_compiling_rust/index.html deleted file mode 100644 index ccb4b33..0000000 --- a/docs/Cross_Compiling/Cross_compiling_rust/index.html +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - - - Cross-compiling rust - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Cross-compiling rust
  • -
  • -
  • -
-
-
-
-
- -

Cross-compiling rust

-

Rust is a programming language just like C but it focuses on safety of programs. This document describes how one can build rust for x86_64 and then add support to compile code for riscv64 architecture. The executable for RISC-V architecture will be able to run on qemu-riscv64.

-

Note: Make sure riscv64-unknown-linux-gnu toolchain is installed on the machine.

-

Getting source code

-

Here the code will be taken from rustup GitHub repository. This is because instead of installing cargo, rustup and rustc, just compiling rustup will compile them along with itself.

-

Get the source code using the command below:

-
git clone https://github.com/rust-lang/rustup.git
-
-

Before starting installation process, if you want to install rust in a specific location, then set CARGO_HOME and RUSTUP_HOME variable in the directory where you want to install rustup.

-

After that, considering you are in the repository directory, start the installation process using the command below:

-
sh rustup-init.sh -y
-
-

After execution above command, follow the prompts as desired and complete the installation process.

-

Now add riscv64 library support in rust using the command below:

-
rustup target add riscv64gc-unknown-linux-gnu
-
-

Once this is complete, go to the desired location where a new project is to be created and use following command to create a project's directory structure.

-
cargo new project_name # Use a meaningful project name
-
-

A directory with name project_name will be created as soon as the above command is executed successfully. This project will contain a main.rs which initially contains a Hello World program.

-

Navigate to the project_name directory and create a folder with name .cargo, this will include a config.toml file inside it, which will tell it cargo during build that what is the target for which the compilation is to be done. The contents of the project_name/.cargo/config.toml will be as follows:

-
[build]
-target = "riscv64gc-unknown-linux-gnu"
-
-[target.riscv64gc-unknown-linux-gnu]
-linker = "riscv64-unknown-linux-gnu-gcc"
-
-

Now the project will be ready to build. Get back to the project_name/ directory and use following command to build the main.rs file:

-
cargo build
-
-

The output of the above command should as follows:

-
   Compiling myproject v0.1.0 (project_name)
-    Finished dev [unoptimized + debuginfo] target(s) in 0.27s
-
-

After the above command, the executable with the name project_name will be available at following location:

-
project_name/target/riscv64gc-unknown-linux-gnu/debug
-
-

Now the produced executable can be executed using qemu usermode. Use the following command to execute binary:

-
qemu-riscv64 -L $RISCV_SYSROOT ./project_name
-
- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Cross_Compiling/Overview/index.html b/docs/Cross_Compiling/Overview/index.html deleted file mode 100644 index c2d8729..0000000 --- a/docs/Cross_Compiling/Overview/index.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - - - Cross Compilation - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Cross Compilation
  • -
  • -
  • -
-
-
-
-
- -

Cross Compilation

-

Need of Cross Compilation

-

Lets say you have a computer A having processor with architecture a and another computer B having processor with architecture b. Assume computer A has all the necessary tools and softwares whereas computer B does not have any software, tools, compilers and also the dependencies needed to install these tools and softwares. In this scenario, you cannot download the software setups (say tarballs) directly on computer B and have them installed/compiled because they will not be able to get compiled by computer B and will be completely useless.

-

Basic concept

-

The basic workflow in such a condition will be as follows:

-
    -
  1. Install a compiler on computer A such that it runs on computer A and compiles code for architecture a.
  2. -
  3. Using the above installed compiler, install a compiler on computer A such that it runs on computer A but compiles code for architecture b. Such a compiler is called cross compiler. One example of such a cross-compiler is RISC-V GNU TOOLCHAIN.
  4. -
  5. Using the above compiled cross compiler, compile all the programs and also the compiler itself for architecture b.
  6. -
  7. Port all the compiled binaries to the computer B.
  8. -
-

Such a process is beneficial if you have created a custom architecture and there is no support available for it.
-Throughout this documentation, the cross compiler used will be RISCV GNU Toolchain mentioned with riscv64-unknown-linux-gcc running on x86_64 and compiling code for riscv64 architecture whereas the native compiler will be gcc running on x86_64 and compiling code for x86_64 unless otherwise specified.

- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Installing_ssl_certificates_new/index.html b/docs/Installing_ssl_certificates_new/index.html deleted file mode 100644 index d4a5b81..0000000 --- a/docs/Installing_ssl_certificates_new/index.html +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - - - Configure `letsencrypt` with jenkins - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Configure `letsencrypt` with jenkins
  • -
  • -
  • -
-
-
-
-
- -

Configure letsencrypt with jenkins

-

SSL certificates allow a website to run on HTTPS protocol which makes sure that data transfer between user and server cannot be intercepted between them. When using HTTPS protocol the data transfer is encrypted between user and server being used.

-

NOTE: Keep the fact in mind that letsencrypt does not generate certificates for bare IP. It needs a domain name.

-

Installing SSL certificates with letsencrypt

-

In unix, letsencrypt package is called certbot. This can be installed using following command:

-
sudo apt install certbot
-
-

Here standalone mode will be used for generating certificates which authenticates the machine's ownership by hosting a temporary server on port 80. This is because ports less than 1024 are privileged and require root/sudo access. So make sure that port 80 is open in firewall and there is no application already running on it. Also if this process is being done on container, make sure port 80 is forwarded properly. One can also use webroot mode to generate certificates. See this link for more information.

-

Use following command to generate certificate files and keys in /etc/letsencrypt/live/your.domain.name/

-
certbot certonly --standalone -d your.domain.name
-
-

This will produce cert.pem, fullchain.pem and privkey.pem.

-

Copy these files to location where .war of jenkins is located. Make sure to change the permission from root to jenkins' user. After that, use following command to convert certificate files to pkcs12 format.

-
openssl pkcs12 -inkey privkey.pem -in fullchain.pem -export -out keys.pkcs12
-keytool -importkeystore -srckeystore keys.pkcs12 -srcstoretype pkcs12 -destkeystore keystore
-
-
-

This will ask for a password. Here it will be denoted as <password>.
-Use following command to start jenkins server with generated SSL certificates.

-
java -jar jenkins.war --httpPort=-1 --httpsPort=<your_port> --httpsKeyStore=keystore --httpsKeyStorePassword=<password>
-
-

After this, go to browser and type your.domain.name:<your_port> to start jenkins with https protocol.

- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Multinode_Pipelines/index.html b/docs/Multinode_Pipelines/index.html index 8346314..032f580 100644 --- a/docs/Multinode_Pipelines/index.html +++ b/docs/Multinode_Pipelines/index.html @@ -8,7 +8,7 @@ Multinode Pipelines - Cloud-V Docs - + - - - + + @@ -34,7 +33,7 @@ Cloud-V Docs
- +
@@ -84,8 +83,8 @@
    -
  • »
  • -
  • Multinode Pipelines
  • +
  • +
@@ -182,14 +181,15 @@

Creating mult

- - - - - + + + + + diff --git a/docs/Software_Developer_Guide/index.html b/docs/Software_Developer_Guide/index.html index d668a06..a0425d7 100644 --- a/docs/Software_Developer_Guide/index.html +++ b/docs/Software_Developer_Guide/index.html @@ -8,7 +8,7 @@ Getting Started - Cloud-V Docs - + - - - + + @@ -34,7 +33,7 @@ Cloud-V Docs
- +
@@ -104,8 +103,8 @@
    -
  • »
  • -
  • Getting Started
  • +
  • +
@@ -273,14 +272,15 @@

Requirements for administrator

- - - - - + + + + + diff --git a/docs/Tooling/index.html b/docs/Tooling/index.html index f38be06..e931d84 100644 --- a/docs/Tooling/index.html +++ b/docs/Tooling/index.html @@ -8,7 +8,7 @@ Using Environment Modules - Cloud-V Docs - + - - - + + @@ -34,7 +33,7 @@ Cloud-V Docs
- +
@@ -88,9 +87,9 @@
    -
  • »
  • -
  • Tooling on Compute Instances »
  • -
  • Using Environment Modules
  • +
  • + +
@@ -146,14 +145,15 @@

Using Environment Modules

- - - - - + + + + + diff --git a/docs/Usage_Monitoring/Integrating_prometheus_grafana/index.html b/docs/Usage_Monitoring/Integrating_prometheus_grafana/index.html deleted file mode 100644 index 2919fd5..0000000 --- a/docs/Usage_Monitoring/Integrating_prometheus_grafana/index.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - - Integrating Prometheus with Grafana - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Integrating Prometheus with Grafana
  • -
  • -
  • -
-
-
-
-
- -

Integrating Prometheus with Grafana

-

Before starting to integrate Prometheus with Grafana make sure they are set up properly. See this document for setting up Prometheus and Grafana as standalone tools.

-

Configuration in Prometheus

-

Make sure all the node_exporter are running properly and the compute instances are discoverable by prometheus. Use following command for checking if the instances are accessible:

-
telnet COMPUTE_INSTANCE_IP COMPUTE_INSTANCE_PORT
-
-

If you get following response, then it means there is something wrong with firewall of compute instances as they are not accessible.

-
Name or service not known
-
-

Configuration in Grafana

-

Enter the grafana IP in browser and login with credentials.

-

Use following steps to integrate Grafana with Prometheus and creating dashbaords in Grafana

-
    -
  • Go to Grafana settings
  • -
  • Go to Data sources tab
  • -
  • Click on Add data source
  • -
  • In HTTP section, add IP of machine on which Prometheus is running along with the port on which Prometheus is hosted (it is recommended to host Prometheus on the machine where Grafana is hosted, in that case, Prometheus will be accessed using LAN IP).
  • -
  • In Type and version section, select Prometheus from drop down menu and choose a version of Prometheus in the next field.
  • -
  • Click on Save and test
  • -
-

If everything goes right, then it will say Data source is working.

-

Creating a dashboard in Grafana

-
    -
  • For creating a dashboard, click on Dashboards
  • -
  • Click on New and then New Dashboard
  • -
  • Then add a panel inside the dashbaord
  • -
  • If you know the mathemtical expressions (which are easier and more verbose) then select Code while creating the panels instead of Builder.
  • -
-

Note: Be sure to save the dashbaord because otherwise, it will not make changes on its own and dashboard will be lost.

- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/Usage_Monitoring/Prometheus_Grafana/index.html b/docs/Usage_Monitoring/Prometheus_Grafana/index.html deleted file mode 100644 index 8417820..0000000 --- a/docs/Usage_Monitoring/Prometheus_Grafana/index.html +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - - - Setting up Promtheus and Grafana - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Setting up Promtheus and Grafana
  • -
  • -
  • -
-
-
-
-
- -

Setting up Promtheus and Grafana

-

What are Prometheus and Grafana

-

Prometheus is a tool for monitoring usage of memory, CPU etc. It takes queries as mathematical expressions (like SQL) and returns the interactive graphical usage stats. It collects data using node_exporter, which is used to get raw data from the compute instances

-

Grafana is used for creating dashboards in which there can be different panels containing the graphical statistics from Prometheus. Grafana dashboards are more interactive and user-friendly than Prometheus.

-

Setting up Node Exporters

-

Node exporters are needed for prometheus to get data from the compute instances.
-Download pre-compiled tarball of node_exporters from this link and place the tarballs on compute instances.

-

Once node_exporter tarball is downloaded, extract it using following command:

-
tar -xvf node_exporter-x.x.x.linux-amd64.tar.gz
-
-

Run node_exporter on compute instances using command below (which will run node_exporter on port 9100 by default):

-
./node_exporter
-
-

Follow this procedure on every compute instance which is desired to be monitored using Prometheus.

-

Note: Make sure that compute instances can be accessed in the machine in which prometheus is installed.

-

Configuring Prometheus

-

Use this link to get pre-compiled tarball of Prometheus.

-

Once Prometheus is downloaded, extract it using following command:

-
tar -xvf prometheus-x.xx.x.linux-amd.tar.gz
-
-

Now either configure prometheus.yml file or create another yml file which will include the addresses of node_exporters. Following is an example template for yml file:

-
global:
-    scrape_interval: 15s
-
-scrape_configs: 
-- job_name: node
-  static_configs: 
-  - targets: ['node_exporter_ip1:node_exporter_port1']
-  - targets: ['node_exporter_ip2:node_exporter_port2']
-
-

Running Prometheus

-

Once prometheus is configured properly, use following command to run prometheus.

-
./prometheus
-
-

Note: By default Prometheus looks for prometheus.yml, if you want to use some other file for configuration, you will need to specify explicitly with --config.file option.

-

Running Grafana

-

Once Prometheus is up and running, Grafana can be used to create dashboards with graphical interface in various panels inside dashboards.

-

Use this to get pre-compiled tarball of Grafana

-

After Grafana is ready to be run, use following command to run Grafana:

-
./grafana-server #By default it will run on port 3000
-
-

The default username and password of Grafana will be admin.

-

Once Grafana is installed, a dashboard can be created to with multiple panels which will show data from Prometheus.

- -

https://grafana.com/docs/grafana/latest/getting-started/get-started-grafana-prometheus/

- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/css/theme.css b/docs/css/theme.css index 7e03995..ad77300 100644 --- a/docs/css/theme.css +++ b/docs/css/theme.css @@ -6,8 +6,8 @@ * https://github.com/readthedocs/sphinx_rtd_theme */ - /* sphinx_rtd_theme version 1.0.0 | MIT license */ -html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,.wy-nav-top a,.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*! + /* sphinx_rtd_theme version 1.2.0 | MIT license */ +html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*! * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs li{display:inline-block}.wy-breadcrumbs li.wy-breadcrumbs-aside{float:right}.wy-breadcrumbs li a{display:inline-block;padding:5px}.wy-breadcrumbs li a:first-child{padding-left:0}.rst-content .wy-breadcrumbs li tt,.wy-breadcrumbs li .rst-content tt,.wy-breadcrumbs li code{padding:5px;border:none;background:none}.rst-content .wy-breadcrumbs li tt.literal,.wy-breadcrumbs li .rst-content tt.literal,.wy-breadcrumbs li code.literal{color:#404040}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search>a:hover{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.field-list>dt:after,html.writer-html5 .rst-content dl.footnote>dt:after{content:":"}html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.footnote>dt>span.brackets{margin-right:.5rem}html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{font-style:italic}html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.footnote>dd p,html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{font-size:inherit;line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.field-list)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dl:not(.field-list)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.field-list)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) dl:not(.field-list)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel{border:1px solid #7fbbe3;background:#e7f2fa;font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block} + */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs>li{display:inline-block;padding-top:5px}.wy-breadcrumbs>li.wy-breadcrumbs-aside{float:right}.rst-content .wy-breadcrumbs>li code,.rst-content .wy-breadcrumbs>li tt,.wy-breadcrumbs>li .rst-content tt,.wy-breadcrumbs>li code{all:inherit;color:inherit}.breadcrumb-item:before{content:"/";color:#bbb;font-size:13px;padding:0 6px 0 3px}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search>a:hover{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content p a{overflow-wrap:anywhere}.rst-content .wy-table td p,.rst-content .wy-table td ul,.rst-content .wy-table th p,.rst-content .wy-table th ul,.rst-content table.docutils td p,.rst-content table.docutils td ul,.rst-content table.docutils th p,.rst-content table.docutils th ul,.rst-content table.field-list td p,.rst-content table.field-list td ul,.rst-content table.field-list th p,.rst-content table.field-list th ul{font-size:inherit}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .citation-reference>span.fn-bracket,.rst-content .footnote-reference>span.fn-bracket{display:none}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:auto minmax(80%,95%)}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{display:inline-grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{display:grid;grid-template-columns:auto auto minmax(.65rem,auto) minmax(40%,95%)}html.writer-html5 .rst-content aside.citation>span.label,html.writer-html5 .rst-content aside.footnote>span.label,html.writer-html5 .rst-content div.citation>span.label{grid-column-start:1;grid-column-end:2}html.writer-html5 .rst-content aside.citation>span.backrefs,html.writer-html5 .rst-content aside.footnote>span.backrefs,html.writer-html5 .rst-content div.citation>span.backrefs{grid-column-start:2;grid-column-end:3;grid-row-start:1;grid-row-end:3}html.writer-html5 .rst-content aside.citation>p,html.writer-html5 .rst-content aside.footnote>p,html.writer-html5 .rst-content div.citation>p{grid-column-start:4;grid-column-end:5}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{margin-bottom:24px}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.citation>dt>span.brackets:before,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.citation>dt>span.brackets:after,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a{word-break:keep-all}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a:not(:first-child):before,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.citation>dd p,html.writer-html5 .rst-content dl.footnote>dd p{font-size:.9rem}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{padding-left:1rem;padding-right:1rem;font-size:.9rem;line-height:1.2rem}html.writer-html5 .rst-content aside.citation p,html.writer-html5 .rst-content aside.footnote p,html.writer-html5 .rst-content div.citation p{font-size:.9rem;line-height:1.2rem;margin-bottom:12px}html.writer-html5 .rst-content aside.citation span.backrefs,html.writer-html5 .rst-content aside.footnote span.backrefs,html.writer-html5 .rst-content div.citation span.backrefs{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content aside.citation span.backrefs>a,html.writer-html5 .rst-content aside.footnote span.backrefs>a,html.writer-html5 .rst-content div.citation span.backrefs>a{word-break:keep-all}html.writer-html5 .rst-content aside.citation span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content aside.footnote span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content div.citation span.backrefs>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content aside.citation span.label,html.writer-html5 .rst-content aside.footnote span.label,html.writer-html5 .rst-content div.citation span.label{line-height:1.2rem}html.writer-html5 .rst-content aside.citation-list,html.writer-html5 .rst-content aside.footnote-list,html.writer-html5 .rst-content div.citation-list{margin-bottom:24px}html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content aside.footnote-list aside.footnote,html.writer-html5 .rst-content div.citation-list>div.citation,html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content aside.footnote-list aside.footnote code,html.writer-html5 .rst-content aside.footnote-list aside.footnote tt,html.writer-html5 .rst-content aside.footnote code,html.writer-html5 .rst-content aside.footnote tt,html.writer-html5 .rst-content div.citation-list>div.citation code,html.writer-html5 .rst-content div.citation-list>div.citation tt,html.writer-html5 .rst-content dl.citation code,html.writer-html5 .rst-content dl.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040;overflow-wrap:normal}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl dd>ol:last-child,.rst-content dl dd>p:last-child,.rst-content dl dd>table:last-child,.rst-content dl dd>ul:last-child{margin-bottom:0}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel{border:1px solid #7fbbe3;background:#e7f2fa;font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>.kbd,.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>kbd{color:inherit;font-size:80%;background-color:#fff;border:1px solid #a6a6a6;border-radius:4px;box-shadow:0 2px grey;padding:2.4px 6px;margin:auto 0}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block} diff --git a/docs/index.html b/docs/index.html index 784dfbc..8d0e623 100644 --- a/docs/index.html +++ b/docs/index.html @@ -8,7 +8,7 @@ Cloud-V Docs - + - - - + + @@ -34,7 +33,7 @@ Cloud-V Docs
- +
@@ -86,8 +85,8 @@
    -
  • »
  • -
  • Home
  • +
  • +
@@ -132,20 +131,21 @@

Cloud-V Documentation

- - - - - + + + + + diff --git a/docs/jenkins_github_integration/Github_PR_webhook_integration/index.html b/docs/jenkins_github_integration/Github_PR_webhook_integration/index.html deleted file mode 100644 index a804dd8..0000000 --- a/docs/jenkins_github_integration/Github_PR_webhook_integration/index.html +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - - - GitHub Pull Request hook integration with Jenkins - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • GitHub Pull Request hook integration with Jenkins
  • -
  • -
  • -
-
-
-
-
- -

GitHub Pull Request hook integration with Jenkins

-

Reference Link: https://plugins.jenkins.io/ghprb/

-

General Guidline

-

If facing an issue, it is better to launch the Jenkins from running the .war file (which is obtained by building the Jenkins github repository) in terminal (which is mostly bash in case of linux) and observing the terminal's output. For example if a webhook is not created, the GUI may not show anything but the terminal will most probably print a message showing the reason for this behavior.

-

GitHub Pull Request Builder Plugin

-

In version control, it is better to check the changes and run tests before the changes are merged into main branch. Sometimes those changes can be enormous to check. So it becomes difficult for requested reviewer of the pull request to check all the changes and run tests on them manually. For that purpose, it is better to automate the process so that whenever a pull request is generated, all the tests are triggered and based on the results, the reviewer decides whether or not to merge the branch with main.

-

This can be achieved using Jenkins' Github Pull Request Builder plugin.

-

Specifications at the time of documentation

-

Operating System: Linux
-Distribution: Ubuntu
-Release: Focal (also known as 20.04)
-Jenkins version: 2.371 (can be seen in config.xml) -Github Webhook Builder version: 1.42.2

-

Pre-Requisites

-
    -
  • Jenkins.
  • -
  • Git Plugin
  • -
  • GitHub Plugin
  • -
  • Github Pull Request Builder Plugin
  • -
  • Github account and repository with permission to generate a pull request to merge the branch.
  • -
-

Setting up Jenkins configuration

-
    -
  • Install the above mentioned plugins from Dashboard > Manage Jenkins > Manage Plugins > Available Plugins.
  • -
  • Go to Dashboard > Manage Jenkins > Configure System.
  • -
  • Scroll down to Github Pull Request Builder.
  • -
  • Leave GitHub Server API URL and Jenkins URL override as it is.
  • -
  • In Credentials, click on add and select Jenkins from drop down.
  • -
  • Select Kind as Secret text.
  • -
  • In Secret, add GitHub Personal authentication token which can be acquired from GitHub account settings.
  • -
  • Add some safe description to remind what these credentials are about otherwise jenkins use a lot of credentials and it gets difficult to keep account of them.
  • -
  • Leave ID empty.
  • -
  • Click on Add.
  • -
  • Now select the added credentials from the drop down menu of Credentials.
  • -
  • Click on Test Credentials....
  • -
  • Check Test basic connection to GitHub.
  • -
  • Click on Connect to API. This will show the message Connected to <API_URL> as <Name_of_GitHub_user>.
  • -
  • Other settings can be left empty.
  • -
  • Click on save.
  • -
-

Setting up Jenkins job

-

In this documentation, Pipeline job will be used, but any job is expected to work fine with these settings. For this documentation it is considered that the jenkinsfile for building the pipeline is present in the repository which is to be built.

-
    -
  • Go to Dashboard and click New Item.
  • -
  • Enter a Job name (here it will be github_PR_webhook).
  • -
  • Click OK. It will navigate to the job's configuration page.
  • -
  • Add a Description of choice.
  • -
  • Scroll down and check GitHub project. Add the URL of GitHub repository. Here the URL of the repository should be added without .git extention. This is important that the person who is creating pull request should be either in admin list or whitelist because otherwise, the webhook will not be created.
  • -
  • Scroll down to Build Triggers section.
  • -
  • Check GitHub Pull Request Builder. This will open further configurations for this option.
      -
    • Leave GitHub API credentials.
    • -
    • Add a GitHub admin's username in the Admin list. This is important becaue otherwise, the checks will not run on generating a pull request.
    • -
    • Check Use github hooks for build triggering.
    • -
    • Click on Advanced and in Whitelist Target Branches add the branch name for which, when a pull request is generated, the job is supposed to be trigger (here it is main).
    • -
    -
  • -
  • Scroll down to Pipeline section.
  • -
  • In Definition, select Pipeline script from SCM.
      -
    • Select SCM as Git from drop down.
    • -
    • Enter the Repository URL from GitHub.
    • -
    • Enter Credentials with access to this repository (This is optional if the repository is public).
    • -
    • Under Advanced, enter Refspec as +refs/pull/*:refs/remotes/origin/pr/*[^note].
    • -
    • If the tests are to be run on actual commit in the pull request then, under Branches to build section, in Branch Specifier, enter ${ghprbActualCommit}[^note].
    • -
    • Leave other settings as it is.
    • -
    -
  • -
  • In Script Path, add the path and name of the jenkinsfile which is present in GitHub repository.
  • -
  • Uncheck Lightweight checkout[^note1]
  • -
  • Click Apply and then Save.
  • -
  • After saving the job, a webhook should be created automatically in GitHub if the credentials provided in the settings are correct.
  • -
-

Verifying if the procedure

-
    -
  • In the GitHub repository, add another branch aside from main.
  • -
  • For this, expand main and click on View all branches.
  • -
  • Click on New Branch, and insert a name.
  • -
  • After a new branch is created, select new branch instead of main in repository page.
  • -
  • Add some changings to either of the file (even adding a space is enough).
  • -
  • Commit Changes.
  • -
  • Create a Pull request.
  • -
  • Now after checking the merge conflicts, the checks will run their results will be shown with pull request (as can be seen in the image below).
    -NOTE: The Jenkinfile will run present in the pull request and not in the main branch.
  • -
-

Selection_013

-
    -
  • Clicking on the Details navigates the user to the Jenkins Job result page where the console output and each stage can be seen.
  • -
-

[^note]: - This point is taken from the jenkins GitHub Pull Request Builder plugin documentation at https://plugins.jenkins.io/ghprb/
-[^note1]: - This is an issue mentioned in the documentation of Github Pull Request Builder plugin at https://plugins.jenkins.io/ghprb/.

- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/jenkins_github_integration/Github_push_webhook/index.html b/docs/jenkins_github_integration/Github_push_webhook/index.html deleted file mode 100644 index a072c19..0000000 --- a/docs/jenkins_github_integration/Github_push_webhook/index.html +++ /dev/null @@ -1,240 +0,0 @@ - - - - - - - - Github 'Push' webhook integration with Jenkins - Cloud-V Docs - - - - - - - - - - - - - - -
- - -
- -
-
-
    -
  • »
  • -
  • Github 'Push' webhook integration with Jenkins
  • -
  • -
  • -
-
-
-
-
- -

Github 'Push' webhook integration with Jenkins

-

Purpose of using github webhook integration with jenkins

-

Most of the time, after a push on the upstream repository, one may want to check the result of all the checks on the repository defined by CI/CD pipeline. This tells whether there is some issue with push and whether or not the defined checks/tests have passed. This can be achieved using github push webhook integration with jenkins.

-

Jenkins version and operating system specifications

-

The version of Jenkins and operating system specifications at the time of writing this documentation are mentioned below:
-Jenkins version: 2.370
-Operating System: Linux
-Distribution: Ubuntu
-Release: Focal (also called 20.04)

-

Pre-requisites

-
    -
  • Jenkins
  • -
  • ngrok (only if a public IP is not available)
  • -
-

Setting up the ngrok

-

The localhost cannot be used for github webhook integration as it cannot be detected by online webservers. For this reason, a public ip must be used. For the sake of this documentation, ngrok is being used, which maps localhost to some public ip which can then be accessed publicly on the internet.

-

Following steps can be used for setting up ngrok on ubuntu:

-
    -
  • Install ngrok.
  • -
-
sudo apt install ngrok
-
-
    -
  • For using html content, a sign up is required on ngrok. So sign up on ngrok.
  • -
  • Execute the following command to run ngrok which will provide a public ip mapped to localhost.
  • -
-
ngrok http <port number>  
-
-

This will setup ngrok and provide a public ip for working online.

-

Setting up Jenkins for github webhook

-

Pre-requisites

-

Following plugins should be installed in jenkins:

-
    -
  • Git Plugin
  • -
  • GitHub API Plugin
  • -
  • GitHub Plugin
  • -
-

Jenkins Configuration in Settings

-
    -
  • Go to Manage Jenkins > Configure System and scroll down to GitHub section.
  • -
  • Click on Add GitHub Server
  • -
  • Add a name for the Github server.
  • -
  • Leave API URL as is.
  • -
  • In Credentials, click on Add. Jenkins will appear in drop down, click on it.
      -
    • Select Kind as Secret text
    • -
    • Scroll down to the Secret and here, put down the github personal authentication token (PAT) which can be acquired from github account.
    • -
    • Other options can be left unattended.
    • -
    • Click on Add. Now the credentials should be added.
    • -
    -
  • -
  • In the Credentials drop down, select Secret text.
  • -
  • Check Manage hooks.
  • -
  • Now the connection can be established and can be checked by clicking the Test Connection.
  • -
  • Click Save.
  • -
-

Jenkins job setup for Github Webhook

-

Create a new jenkins freestyle job and proceed with following settings on the configurations along with desired settings.

-
    -
  • Check GitHub project in General section and provide GitHub repository URL.
  • -
  • In Source Code Management section, select Git.
  • -
  • Give Repository URL
  • -
  • In Credentials (if the credentials are not created already), click on Add, click on Jenkins from the drop down.
      -
    • Select Kind as Username with password.
    • -
    • In Username, enter github username.
    • -
    • In Password, enter github personal authentication token (PAT) which can be acquired from github account.
    • -
    • Other fields can be left unattended.
    • -
    • Click on Add
    • -
    -
  • -
  • From Credentials drop down, select your added credentials.
  • -
  • In Branches to build section, in Branch Specifier field, enter the name of branch of github repository which needs to be built.
  • -
  • In Build Triggers section, check GitHub hook trigger for GITScm polling.
    -(Following step is for checking the commit status according to the Jenkins job status, means if Jenkins job fails, commit status is also Failure)
  • -
  • Scroll down to the bottom and Add post-build action. From drop down, select Set GitHub commit status.
  • -
  • Leave other settings as is and click on Advanced.
  • -
  • Check Handle errors
  • -
  • Under drop down Result on failure, select FAILURE
  • -
  • Click on Apply and Save
  • -
  • By this point, Jenkins is setup for github webhooks.
  • -
-

Setting up github repository webhook

-

For the sake of this documentation, I have created a simple repository called jenkins_hello_world_integrated.

-
    -
  • Go to GitHub repository's settings
  • -
-

Screenshot from 2022-09-26 16-39-29

-
    -
  • In Webhooks section, click on Add webhook
  • -
-

Screenshot from 2022-09-26 16-39-29

-
    -
  • In Webhooks settings:
  • -
  • Add Payload URL as the URL of jenkins and append /github-webhook/ at the end of it.
  • -
  • Select Content type application/jason.
  • -
  • It is recommended to add Secret which can be generated by jenkins API Token by going to account configuration.
  • -
  • It is recommended to Enable SSL verification.
  • -
  • Select the events which should trigger the build in jenkins.
  • -
  • Check Active.
  • -
  • -

    Click on Add Webhook.

    -

    Screenshot from 2022-09-26 16-39-29

    -
  • -
-

After this point each time the github repository is commited with a change, jenkins job will start the build and will also denote on the repository if the build has passed or failed (as can be seen in the below screenshot).

-

Screenshot from 2022-09-26 16-39-29

- -
-
- -
-
- -
- -
- -
- - - - - -
- - - - - - - - diff --git a/docs/jenkins_gitlab_integration/index.html b/docs/jenkins_gitlab_integration/index.html index 74c104f..55ea32f 100644 --- a/docs/jenkins_gitlab_integration/index.html +++ b/docs/jenkins_gitlab_integration/index.html @@ -8,7 +8,7 @@ Integrating GitLab with Jenkins - Cloud-V Docs - + - - - + + @@ -34,7 +33,7 @@ Cloud-V Docs
- +
@@ -84,8 +83,8 @@
    -
  • »
  • -
  • Integrating GitLab with Jenkins
  • +
  • +
@@ -178,14 +177,15 @@

Configuring Jenkins Job

- - - - - + + + + + diff --git a/docs/runner_specs/index.html b/docs/runner_specs/index.html index 7886c71..d854130 100644 --- a/docs/runner_specs/index.html +++ b/docs/runner_specs/index.html @@ -8,7 +8,7 @@ Compute Instance Specifications - Cloud-V Docs - + - - - + + @@ -34,7 +33,7 @@ Cloud-V Docs
- +
@@ -86,8 +85,8 @@
    -
  • »
  • -
  • Compute Instance Specifications
  • +
  • +
@@ -245,14 +244,15 @@

Specifications of comput

- - - - - + + + + + diff --git a/docs/search.html b/docs/search.html index 48667ac..fae2139 100644 --- a/docs/search.html +++ b/docs/search.html @@ -8,14 +8,13 @@ Cloud-V Docs - + - - - + + @@ -27,7 +26,7 @@ Cloud-V Docs
- +
@@ -77,7 +76,7 @@
    -
  • »
  • +
@@ -91,7 +90,7 @@

Search Results

@@ -125,14 +124,15 @@

Search Results

- - - - - + + + + + diff --git a/docs/search/search_index.json b/docs/search/search_index.json index dfa6366..2b874bc 100644 --- a/docs/search/search_index.json +++ b/docs/search/search_index.json @@ -1 +1 @@ -{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"Cloud-V Documentation This documentation lists the tooling and necessary information to use Cloud-V for RISC-V application development on RISC-V compute instances provided by Cloud-V Overview Slides: link Youtube Channel: youtube.com/@Cloud-V","title":"Home"},{"location":"#cloud-v-documentation","text":"This documentation lists the tooling and necessary information to use Cloud-V for RISC-V application development on RISC-V compute instances provided by Cloud-V Overview Slides: link Youtube Channel: youtube.com/@Cloud-V","title":"Cloud-V Documentation"},{"location":"Adding_Custom-build_packages_in_Jenkins/","text":"Adding Custom-build packages in Jenkins __NOTE: For this documentation, Ubuntu 22.04 and Jenkins version 2.371 is used. While working open-source, many times one may need to build the package from source code. While working on the local machine, the built package may be accessible by adding it to the $PATH environment variable. But while working with Jenkins, This may not work. Where to install package for Jenkins job In Jenkins job, the package is installed on the node (or agent) on which the specific job is being used and NOT on the node where the jenkins controller node is installed. For example if the Jenkins controller node is on computer1 and slave node on which the job is destined to run is on computer2 then computer2 should have all the packages used by the job and not the computer1 . Adding the package to Jenkins Considering there is a node with name Runner1 in jenkins on which the job is destined to run and that job uses a toolchain riscv64-unknown-elf-gcc to run properly and that toolchain is present in directory /home/runner1/path_to_install/bin , then the following procedure is used to add the toolchain in Jenkins. Go to Dashboard > Manage Jenkins > Nodes > Runner1 . Scroll down and check Environment variables . Under section List of variables add: Name as PATH Value as $PATH:/home/runner1/path_to_install/bin . Click on Save . After this, the package should be available to be used.","title":"Adding Custom-build packages in Jenkins"},{"location":"Adding_Custom-build_packages_in_Jenkins/#adding-custom-build-packages-in-jenkins","text":"__NOTE: For this documentation, Ubuntu 22.04 and Jenkins version 2.371 is used. While working open-source, many times one may need to build the package from source code. While working on the local machine, the built package may be accessible by adding it to the $PATH environment variable. But while working with Jenkins, This may not work.","title":"Adding Custom-build packages in Jenkins"},{"location":"Adding_Custom-build_packages_in_Jenkins/#where-to-install-package-for-jenkins-job","text":"In Jenkins job, the package is installed on the node (or agent) on which the specific job is being used and NOT on the node where the jenkins controller node is installed. For example if the Jenkins controller node is on computer1 and slave node on which the job is destined to run is on computer2 then computer2 should have all the packages used by the job and not the computer1 .","title":"Where to install package for Jenkins job"},{"location":"Adding_Custom-build_packages_in_Jenkins/#adding-the-package-to-jenkins","text":"Considering there is a node with name Runner1 in jenkins on which the job is destined to run and that job uses a toolchain riscv64-unknown-elf-gcc to run properly and that toolchain is present in directory /home/runner1/path_to_install/bin , then the following procedure is used to add the toolchain in Jenkins. Go to Dashboard > Manage Jenkins > Nodes > Runner1 . Scroll down and check Environment variables . Under section List of variables add: Name as PATH Value as $PATH:/home/runner1/path_to_install/bin . Click on Save . After this, the package should be available to be used.","title":"Adding the package to Jenkins"},{"location":"Booting_ubuntu22.04_riscv64/","text":"Booting RISC-V Ubuntu 22.04 on qemu-system-riscv64 Pre-requisites Following are the pre-requisites which are needed to be installed before booting ubuntu 22.04 for RISC-V on qemu . Note: Make sure RISC-V GNU Toolchain is installed before proceeding U-boot Qemu version 7.0 or greater with networking Ubuntu 22.04 pre-built image for RISC-V 1. Installing U-boot Note: If you plan on installing U-boot from apt or some system repository, install the one which comes with ubuntu 22.04. Older will not work with this process. Also, be sure to checkout a latest Stable version instead of development version. Get source code of u-boot and checkout stable version using commands below. git clone https://github.com/qemu/u-boot.git cd u-boot git checkout v2022.10 Generate configurations for supervisor mode with following command. make qemu-riscv64_smode_defconfig CROSS_COMPILE=riscv64-unknown-linux-gnu- Execute following command to start build process. make CROSS_COMPILE=riscv64-unknown-linux-gnu- This should install u-boot.bin in the source directory. This file will be used later so its path must be kept remember. Here it will be refered to as $UBOOTPATH . 2. Installing Qemu Qemu version 7.0 or greater should be installed with networking for ubuntu 22.04 to work. See Installing Qemu for RISC-V for instructions on installing qemu-system-riscv64 . 3. Getting Ubuntu 22.04 pre-build image for RISC-V Ubuntu 22.04 image can be downloaded from https://ubuntu.com/download/risc-v . Booting Ubuntu 22.04 Image on qemu In the directory where ubuntu 22.04 image is present, execute following command to boot into ubuntu 22.04 with qemu-system-riscv64 . If you need more space, you can use following command. qemu-img resize -f raw ubuntu-22.04.1-preinstalled-server-riscv64+unmatched.img +5G This will increase storage size of the image by 5GB. qemu-system-riscv64 \\ -machine virt -nographic -m 2048 -smp 4 \\ -kernel $UBOOTPATH/u-boot.bin \\ -device virtio-net-device,netdev=eth0 -netdev user,id=eth0,hostfwd=::-: \\ -drive file=ubuntu-22.04.1-preinstalled-server-riscv64+unmatched.img,format=raw,if=virtio Here -m is the memory in Megabytes and -smp is number of cores. -nographic means qemu will use same terminal instance instead of opening a new window of its own (which is beneficial while running servers without gui). Whereas hostfwd=::-: will forward traffic going to port to port VM_port . Due to this port will be used to access ssh on qemu machine. This should boot ubuntu 22.04. But it will take a while on first start. On start, credentials will be as follows. Username: ubuntu Password: ubuntu After entering credentials, terminal will prompt for change of password after which ubuntu will be ready to use.","title":"Booting RISC-V Ubuntu 22.04 on `qemu-system-riscv64`"},{"location":"Booting_ubuntu22.04_riscv64/#booting-risc-v-ubuntu-2204-on-qemu-system-riscv64","text":"","title":"Booting RISC-V Ubuntu 22.04 on qemu-system-riscv64"},{"location":"Booting_ubuntu22.04_riscv64/#pre-requisites","text":"Following are the pre-requisites which are needed to be installed before booting ubuntu 22.04 for RISC-V on qemu . Note: Make sure RISC-V GNU Toolchain is installed before proceeding U-boot Qemu version 7.0 or greater with networking Ubuntu 22.04 pre-built image for RISC-V","title":"Pre-requisites"},{"location":"Booting_ubuntu22.04_riscv64/#1-installing-u-boot","text":"Note: If you plan on installing U-boot from apt or some system repository, install the one which comes with ubuntu 22.04. Older will not work with this process. Also, be sure to checkout a latest Stable version instead of development version. Get source code of u-boot and checkout stable version using commands below. git clone https://github.com/qemu/u-boot.git cd u-boot git checkout v2022.10 Generate configurations for supervisor mode with following command. make qemu-riscv64_smode_defconfig CROSS_COMPILE=riscv64-unknown-linux-gnu- Execute following command to start build process. make CROSS_COMPILE=riscv64-unknown-linux-gnu- This should install u-boot.bin in the source directory. This file will be used later so its path must be kept remember. Here it will be refered to as $UBOOTPATH .","title":"1. Installing U-boot"},{"location":"Booting_ubuntu22.04_riscv64/#2-installing-qemu","text":"Qemu version 7.0 or greater should be installed with networking for ubuntu 22.04 to work. See Installing Qemu for RISC-V for instructions on installing qemu-system-riscv64 .","title":"2. Installing Qemu"},{"location":"Booting_ubuntu22.04_riscv64/#3-getting-ubuntu-2204-pre-build-image-for-risc-v","text":"Ubuntu 22.04 image can be downloaded from https://ubuntu.com/download/risc-v .","title":"3. Getting Ubuntu 22.04 pre-build image for RISC-V"},{"location":"Booting_ubuntu22.04_riscv64/#booting-ubuntu-2204-image-on-qemu","text":"In the directory where ubuntu 22.04 image is present, execute following command to boot into ubuntu 22.04 with qemu-system-riscv64 . If you need more space, you can use following command. qemu-img resize -f raw ubuntu-22.04.1-preinstalled-server-riscv64+unmatched.img +5G This will increase storage size of the image by 5GB. qemu-system-riscv64 \\ -machine virt -nographic -m 2048 -smp 4 \\ -kernel $UBOOTPATH/u-boot.bin \\ -device virtio-net-device,netdev=eth0 -netdev user,id=eth0,hostfwd=::-: \\ -drive file=ubuntu-22.04.1-preinstalled-server-riscv64+unmatched.img,format=raw,if=virtio Here -m is the memory in Megabytes and -smp is number of cores. -nographic means qemu will use same terminal instance instead of opening a new window of its own (which is beneficial while running servers without gui). Whereas hostfwd=::-: will forward traffic going to port to port VM_port . Due to this port will be used to access ssh on qemu machine. This should boot ubuntu 22.04. But it will take a while on first start. On start, credentials will be as follows. Username: ubuntu Password: ubuntu After entering credentials, terminal will prompt for change of password after which ubuntu will be ready to use.","title":"Booting Ubuntu 22.04 Image on qemu"},{"location":"Building_Jenkins_github_repo/","text":"Building Github Repository of Jenkins Linux kernel version, distribution and release at the time of build process Linux Kernel : 5.15.0-46-generic (can be checked using uname -r in ubuntu) Distribution : Ubuntu Release : focal (20.04); also works without issue on ubuntu 22.04 (release can be checked using lsb_release -a in ubuntu) Cloning the github repository First clone the repository using the command below (here it is assumed to be cloned at user's home directory: ~/) git clone https://github.com/jenkinsci/jenkins.git Resolving the dependencies After cloning the repository at ~/, the file CONTRIBUTING.md should be available in ~/jenkins/. This file contains all the information to resolve the dependencies and building the repository. Some notable dependencies are Java Development Kit (JDK), Apache Maven (latest version will be preferable) and git. Running Following command will resolve the mentioned dependencies. sudo apt update && sudo apt install default-jdk default-jre maven git -y Building Jenkins using maven on linux For having the jenkins build up as fast as possible, following command can be used in ~/jenkins/. mvn -am -pl war,bom -Pquick-build clean install Executing Jenkins After the above commands successfully completes execution, jenkins.war should be present in ~/jenkins/war/target and can be executed to run at port 8080 on localhost using following command. java -jar ~/jenkins/war/target/jenkins.war --httpPort=8080 #Considering jenkins repo is cloned at ~/ After this process jenkins UI can be accessed using http://localhost:8080 in a browser and a password will be shown on terminal to login to jenkins first time After this, Jenkins UI will go through a very simple post installation process which one can configure according to his needs.","title":"Building Github Repository of Jenkins"},{"location":"Building_Jenkins_github_repo/#building-github-repository-of-jenkins","text":"","title":"Building Github Repository of Jenkins"},{"location":"Building_Jenkins_github_repo/#linux-kernel-version-distribution-and-release-at-the-time-of-build-process","text":"Linux Kernel : 5.15.0-46-generic (can be checked using uname -r in ubuntu) Distribution : Ubuntu Release : focal (20.04); also works without issue on ubuntu 22.04 (release can be checked using lsb_release -a in ubuntu)","title":"Linux kernel version, distribution and release at the time of build process"},{"location":"Building_Jenkins_github_repo/#cloning-the-github-repository","text":"First clone the repository using the command below (here it is assumed to be cloned at user's home directory: ~/) git clone https://github.com/jenkinsci/jenkins.git","title":"Cloning the github repository"},{"location":"Building_Jenkins_github_repo/#resolving-the-dependencies","text":"After cloning the repository at ~/, the file CONTRIBUTING.md should be available in ~/jenkins/. This file contains all the information to resolve the dependencies and building the repository. Some notable dependencies are Java Development Kit (JDK), Apache Maven (latest version will be preferable) and git. Running Following command will resolve the mentioned dependencies. sudo apt update && sudo apt install default-jdk default-jre maven git -y","title":"Resolving the dependencies"},{"location":"Building_Jenkins_github_repo/#building-jenkins-using-maven-on-linux","text":"For having the jenkins build up as fast as possible, following command can be used in ~/jenkins/. mvn -am -pl war,bom -Pquick-build clean install","title":"Building Jenkins using maven on linux"},{"location":"Building_Jenkins_github_repo/#executing-jenkins","text":"After the above commands successfully completes execution, jenkins.war should be present in ~/jenkins/war/target and can be executed to run at port 8080 on localhost using following command. java -jar ~/jenkins/war/target/jenkins.war --httpPort=8080 #Considering jenkins repo is cloned at ~/ After this process jenkins UI can be accessed using http://localhost:8080 in a browser and a password will be shown on terminal to login to jenkins first time After this, Jenkins UI will go through a very simple post installation process which one can configure according to his needs.","title":"Executing Jenkins"},{"location":"Building_Linux_Kernel/","text":"Building a RISCV Linux kernel and booting it in QEMU inside LXC container This documentation covers how to build a linux kernel with RISCV linux toolchain inside an un-privileged LXC container and then boot it on qemu. Doing this process on privileged lxc container makes life easier, but privileged containers always have security loop holes. For instance, their root id is mapped to root id of host machine. On the other hand un-privileged containers are the safest (see link ). Machine's and LXC Container's Operating System Specifications At the time of creating this documentation, following is the specification of host machine and operating system. Host Machine: Ubuntu focal (20.04) 64-bit. LXC Container: Ubuntu jammy (22.04) 64-bit. LXC Container is unprivileged with non-sudo user. NOTE: Throughout this documentation, name of the lxc container will be qemu_container or qemucontainer with non-sudo user as qemu-user which is running on ubuntu 22.04 and host machine x86. Do not confuse the name with assumption that it is booting on qemu emulator. It is just a naming convention. Pre-requisites Following programs may also have their own pre-requisites. Git: For cloning repositories of following programs. Install it with [sudo] apt install git . TMUX: For convenience of multiple terminals. Install it using [sudo] apt install tmux RISCV GNU toolchain built as linux: For compiling the linux kernel. Busybox: For Generating the binaries for linux kernel boot. QEMU Emulator: For booting the linux kernel Linux Kernel (latest version which is used at point of writing this documentation is 6.0.0 ) The working directory inside lxc container for all of this documentation will be ~/riscv-linux or /home/qemu-user/riscv-linux . NOTE: Busybox will not be built inside the lxc container rather it will be built in (any) host linux machine with sudo privileges. 3. RISCV GNU Toolchain Log in the lxc container to the non-sudo user (here SSH is used to log in). Install the prerequisites for building RISCV GNU TOOLCHAIN inside lxc container with root user using command below. apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev libncurses-dev Clone the GNU toolchain using the command below. git clone https://github.com/riscv-collab/riscv-gnu-toolchain.git Create a directory in which the RISCV GNU toolchain is desired to be installed (here it will be /home/qemu-user/riscv-linux/riscv-gnu-installed ) Execute following command inside cloned repository with --prefix as the absolute directory path to where the RISCV toolchain is to be installed ./configure --prefix=/home/qemu-user/riscv-linux/riscv-gnu-installed Execute following inside cloned repository (execution of this command will take a while to complete) make linux -j$(nproc) # 'nproc' is the command used to determine the number of processors in machine so that 'make' can use parallelism. After the execution of command is complete, add bin directory created inside the riscv installation directory to the $PATH and add the expression to .bashrc . According to this documentation, following expression will be added to .bashrc . PATH=\"/home/qemu-user/riscv-linux/riscv-gnu-installed/bin:$PATH\" Check if the toolchain is installed by executing following commands. exec $SHELL riscv64-unknown-linux-gnu-gcc Expected Output: fatal error: no input files compilation terminated. Now RISCV linux toolchain is ready ! 4. Busybox Busybox is the package for creating linux binutils and set of directories for linux to boot into. Busybox will be installed in host machine instead of lxc container. The reason for this is linux kernel requires block oriented device and character oriented device for it to boot. Those devices can be created using mknod command which can only be created inside a host machine with sudo privileges. Busybox will be used in creating initial ram disk file (in gz format) which is used to boot kernel. It does not matter at which operating system or on which machine this file is created. But the machine on which it is compiled, must also have RISCV GNU toolchain installed above. Clone Busybox using the command below. git clone https://git.busybox.net/busybox Navigate to cloned directory. cd busybox Before building busybox, we need to produce a configuration (.config file) for busybox. It is better to apply default configurations and then change only those which are desired. make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- defconfig After the command is executed, a .config file will be present in the busybox cloned directory. Now, an additional option is to be enabled which enables busybox to build the libraries in the executable instead of separate shared libraries. For this purpose, execute the following command to access the configuration menu. Then go to Settings menu by pressing enter and from there, enable [ ] Build static binary (no shared libs) by pressing space. After the option is enabled, exit by pressing esc twice two times and press yes to the prompt about file saving. make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- menuconfig Now that configuration is complete, build busybox by executing following command. make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- -j$(nproc) Execute following command which will produce all the basic linux utilities in _install directory in busybox repo directory. make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- -j$(nproc) install Navigate to _install directory and create dev directory. cd _install mkdir dev Now, a linux console and a ram devices are to be created inside dev directory. A fact to understand here is that, every device is a file in linux but they are special kind of files. A detail of these devices can be found here . In this documentation mknod command is used to create these devices. sudo mknod dev/console c 5 1 sudo mknod dev/ram b 1 0 After executing above commands, following files with names ram and console will be created as shown in the image below. Now an init file is needed because linux kernel does not boot itself, it rather searches for init file in the directories (read linux kernel messages during build procedure). init file contains commands to mount some directories during boot (more information can be found here ). In busybox/_install , create a file with following contents (be sure to make it executable with chmod +x init ). vim init #!/bin/sh echo \"### INIT SCRIPT ###\" mkdir /proc /sys /tmp mount -t proc none /proc #For processes mount -t sysfs none /sys #For all the devices on the machine mount -t tmpfs none /tmp #For virtual memory echo -e \"\\nThis boot took $(cut -d' ' -f1 /proc/uptime) seconds\\n\" exec /bin/sh Now that all the files are ready for linux to boot into, pack them in cpio format and then to gz format. It is because cpio format is in \"Early userspace support\" in linux kernel (see link ) whereas gz format is needed because it is one of the formats needed by qemu emulator. Following command produces a qemu-compatible initramfs file for linux kernel to boot in. find -print0 | cpio -0oH newc | gzip -9 > ../initramfs.cpio.gz Command Details: find -print0 separates the file names with null character cpio -0oH newc produces an archive file in newc format gzip -9 creates a gz format zip file. -9 represents the best compression level at the slowest speed ../initramfs.cpio.gz represents the output file which is created in parent directory to present working directory. At this point, our work with busybox is done. Copy the produced file into the lxc container (use scp command if it is on ssh). 5. QEMU Emulator Install the pre-requisites of qemu emulator on lxc container with root user with following command (see link ). apt-get install git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build Clone the QEMU Emulator repository using the command below with root user: git clone https://github.com/qemu/qemu.git Build QEMU for RISCV with root user using commands below (see link ). ./configure --target-list=riscv64-softmmu make -j$(nproc) For system-wide installation of QEMU Emulator, run following command with root user. make -j$(nproc) install After execution of this command, work with QEMU Emulator is done and its commands can be accessed anywhere. 6. Linux Kernel Clone the linux kernel from Linus Torvalds' repository using the command below. git clone https://github.com/torvalds/linux.git Navigate to cloned repository. cd linux Building Linux kernel with riscv64-unknown-linux-gnu-gcc Before building linux kernel with RISCV toolchain a configuration file (.config) must be produced in its directory. First, produce a file with default configurations, then change configurations according to needs. make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- defconfig make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- menuconfig Above command will open configuration menu. Enter General setup , scroll down and enable Initial RAM filesystem and RAM disk (initramfs/initrd) support using Space key. Then enter () Initramfs source file(s) and here put the absolute path to initramfs.cpio.gz file which was just created using busybox. For this documentation, it is /home/qemu-user/riscv-linux/initramfs.cpio.gz . Double-press esc and save the file. Now linux kernel is ready to be compiled with riscv64-linux-gnu-gcc toolchain. So execute the command below. make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- -j$(nproc) If the above command successfully executed without any errors, there must be Kernel: arch/riscv/boot/Image.gz is ready printed on terminal. On newer linux kernels, it might be scrolled up a little, use Ctrl-shift-f to find it. Booting into the linux kernel using QEMU emulator Now that everything is ready, execute the following command in linux/arch/riscv/boot/ directory to boot linux on sifive's unleashed . qemu-system-riscv64 -kernel Image -machine sifive_u -nographic Command Details qemu-system-riscv64 is the qemu built for riscv64 -kernel takes the image produced by linux kernel compilation and is present in linux/arch/riscv/boot/ directory. -machine takes one of the machine names as arguments available in qemu-system-riscv64 . Available machines can be listed on terminal using command qemu-system-riscv64 -machine help . -nographic restricts the use of GUI (which is a better option considering lxc container does not support gtk initialization). If everything goes on right, the kernel will boot successfully as shown in the picture below. Reference links https://risc-v-getting-started-guide.readthedocs.io/en/latest/linux-qemu.html https://hackernoon.com/how-to-set-up-the-environment-for-riscv-64-linux-kernel-development-in-ubuntu-2004-si5p35kv","title":"Building a RISCV Linux kernel and booting it in QEMU inside LXC container"},{"location":"Building_Linux_Kernel/#building-a-riscv-linux-kernel-and-booting-it-in-qemu-inside-lxc-container","text":"This documentation covers how to build a linux kernel with RISCV linux toolchain inside an un-privileged LXC container and then boot it on qemu. Doing this process on privileged lxc container makes life easier, but privileged containers always have security loop holes. For instance, their root id is mapped to root id of host machine. On the other hand un-privileged containers are the safest (see link ).","title":"Building a RISCV Linux kernel and booting it in QEMU inside LXC container"},{"location":"Building_Linux_Kernel/#machines-and-lxc-containers-operating-system-specifications","text":"At the time of creating this documentation, following is the specification of host machine and operating system. Host Machine: Ubuntu focal (20.04) 64-bit. LXC Container: Ubuntu jammy (22.04) 64-bit. LXC Container is unprivileged with non-sudo user. NOTE: Throughout this documentation, name of the lxc container will be qemu_container or qemucontainer with non-sudo user as qemu-user which is running on ubuntu 22.04 and host machine x86. Do not confuse the name with assumption that it is booting on qemu emulator. It is just a naming convention.","title":"Machine's and LXC Container's Operating System Specifications"},{"location":"Building_Linux_Kernel/#pre-requisites","text":"Following programs may also have their own pre-requisites. Git: For cloning repositories of following programs. Install it with [sudo] apt install git . TMUX: For convenience of multiple terminals. Install it using [sudo] apt install tmux RISCV GNU toolchain built as linux: For compiling the linux kernel. Busybox: For Generating the binaries for linux kernel boot. QEMU Emulator: For booting the linux kernel Linux Kernel (latest version which is used at point of writing this documentation is 6.0.0 ) The working directory inside lxc container for all of this documentation will be ~/riscv-linux or /home/qemu-user/riscv-linux . NOTE: Busybox will not be built inside the lxc container rather it will be built in (any) host linux machine with sudo privileges.","title":"Pre-requisites"},{"location":"Building_Linux_Kernel/#3-riscv-gnu-toolchain","text":"Log in the lxc container to the non-sudo user (here SSH is used to log in). Install the prerequisites for building RISCV GNU TOOLCHAIN inside lxc container with root user using command below. apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev libncurses-dev Clone the GNU toolchain using the command below. git clone https://github.com/riscv-collab/riscv-gnu-toolchain.git Create a directory in which the RISCV GNU toolchain is desired to be installed (here it will be /home/qemu-user/riscv-linux/riscv-gnu-installed ) Execute following command inside cloned repository with --prefix as the absolute directory path to where the RISCV toolchain is to be installed ./configure --prefix=/home/qemu-user/riscv-linux/riscv-gnu-installed Execute following inside cloned repository (execution of this command will take a while to complete) make linux -j$(nproc) # 'nproc' is the command used to determine the number of processors in machine so that 'make' can use parallelism. After the execution of command is complete, add bin directory created inside the riscv installation directory to the $PATH and add the expression to .bashrc . According to this documentation, following expression will be added to .bashrc . PATH=\"/home/qemu-user/riscv-linux/riscv-gnu-installed/bin:$PATH\" Check if the toolchain is installed by executing following commands. exec $SHELL riscv64-unknown-linux-gnu-gcc Expected Output: fatal error: no input files compilation terminated. Now RISCV linux toolchain is ready !","title":"3. RISCV GNU Toolchain"},{"location":"Building_Linux_Kernel/#4-busybox","text":"Busybox is the package for creating linux binutils and set of directories for linux to boot into. Busybox will be installed in host machine instead of lxc container. The reason for this is linux kernel requires block oriented device and character oriented device for it to boot. Those devices can be created using mknod command which can only be created inside a host machine with sudo privileges. Busybox will be used in creating initial ram disk file (in gz format) which is used to boot kernel. It does not matter at which operating system or on which machine this file is created. But the machine on which it is compiled, must also have RISCV GNU toolchain installed above. Clone Busybox using the command below. git clone https://git.busybox.net/busybox Navigate to cloned directory. cd busybox Before building busybox, we need to produce a configuration (.config file) for busybox. It is better to apply default configurations and then change only those which are desired. make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- defconfig After the command is executed, a .config file will be present in the busybox cloned directory. Now, an additional option is to be enabled which enables busybox to build the libraries in the executable instead of separate shared libraries. For this purpose, execute the following command to access the configuration menu. Then go to Settings menu by pressing enter and from there, enable [ ] Build static binary (no shared libs) by pressing space. After the option is enabled, exit by pressing esc twice two times and press yes to the prompt about file saving. make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- menuconfig Now that configuration is complete, build busybox by executing following command. make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- -j$(nproc) Execute following command which will produce all the basic linux utilities in _install directory in busybox repo directory. make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- -j$(nproc) install Navigate to _install directory and create dev directory. cd _install mkdir dev Now, a linux console and a ram devices are to be created inside dev directory. A fact to understand here is that, every device is a file in linux but they are special kind of files. A detail of these devices can be found here . In this documentation mknod command is used to create these devices. sudo mknod dev/console c 5 1 sudo mknod dev/ram b 1 0 After executing above commands, following files with names ram and console will be created as shown in the image below. Now an init file is needed because linux kernel does not boot itself, it rather searches for init file in the directories (read linux kernel messages during build procedure). init file contains commands to mount some directories during boot (more information can be found here ). In busybox/_install , create a file with following contents (be sure to make it executable with chmod +x init ). vim init #!/bin/sh echo \"### INIT SCRIPT ###\" mkdir /proc /sys /tmp mount -t proc none /proc #For processes mount -t sysfs none /sys #For all the devices on the machine mount -t tmpfs none /tmp #For virtual memory echo -e \"\\nThis boot took $(cut -d' ' -f1 /proc/uptime) seconds\\n\" exec /bin/sh Now that all the files are ready for linux to boot into, pack them in cpio format and then to gz format. It is because cpio format is in \"Early userspace support\" in linux kernel (see link ) whereas gz format is needed because it is one of the formats needed by qemu emulator. Following command produces a qemu-compatible initramfs file for linux kernel to boot in. find -print0 | cpio -0oH newc | gzip -9 > ../initramfs.cpio.gz Command Details: find -print0 separates the file names with null character cpio -0oH newc produces an archive file in newc format gzip -9 creates a gz format zip file. -9 represents the best compression level at the slowest speed ../initramfs.cpio.gz represents the output file which is created in parent directory to present working directory. At this point, our work with busybox is done. Copy the produced file into the lxc container (use scp command if it is on ssh).","title":"4. Busybox"},{"location":"Building_Linux_Kernel/#5-qemu-emulator","text":"Install the pre-requisites of qemu emulator on lxc container with root user with following command (see link ). apt-get install git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build Clone the QEMU Emulator repository using the command below with root user: git clone https://github.com/qemu/qemu.git Build QEMU for RISCV with root user using commands below (see link ). ./configure --target-list=riscv64-softmmu make -j$(nproc) For system-wide installation of QEMU Emulator, run following command with root user. make -j$(nproc) install After execution of this command, work with QEMU Emulator is done and its commands can be accessed anywhere.","title":"5. QEMU Emulator"},{"location":"Building_Linux_Kernel/#6-linux-kernel","text":"Clone the linux kernel from Linus Torvalds' repository using the command below. git clone https://github.com/torvalds/linux.git Navigate to cloned repository. cd linux","title":"6. Linux Kernel"},{"location":"Building_Linux_Kernel/#building-linux-kernel-with-riscv64-unknown-linux-gnu-gcc","text":"Before building linux kernel with RISCV toolchain a configuration file (.config) must be produced in its directory. First, produce a file with default configurations, then change configurations according to needs. make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- defconfig make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- menuconfig Above command will open configuration menu. Enter General setup , scroll down and enable Initial RAM filesystem and RAM disk (initramfs/initrd) support using Space key. Then enter () Initramfs source file(s) and here put the absolute path to initramfs.cpio.gz file which was just created using busybox. For this documentation, it is /home/qemu-user/riscv-linux/initramfs.cpio.gz . Double-press esc and save the file. Now linux kernel is ready to be compiled with riscv64-linux-gnu-gcc toolchain. So execute the command below. make ARCH=riscv CROSS_COMPILE=riscv64-unknown-linux-gnu- -j$(nproc) If the above command successfully executed without any errors, there must be Kernel: arch/riscv/boot/Image.gz is ready printed on terminal. On newer linux kernels, it might be scrolled up a little, use Ctrl-shift-f to find it.","title":"Building Linux kernel with riscv64-unknown-linux-gnu-gcc"},{"location":"Building_Linux_Kernel/#booting-into-the-linux-kernel-using-qemu-emulator","text":"Now that everything is ready, execute the following command in linux/arch/riscv/boot/ directory to boot linux on sifive's unleashed . qemu-system-riscv64 -kernel Image -machine sifive_u -nographic Command Details qemu-system-riscv64 is the qemu built for riscv64 -kernel takes the image produced by linux kernel compilation and is present in linux/arch/riscv/boot/ directory. -machine takes one of the machine names as arguments available in qemu-system-riscv64 . Available machines can be listed on terminal using command qemu-system-riscv64 -machine help . -nographic restricts the use of GUI (which is a better option considering lxc container does not support gtk initialization). If everything goes on right, the kernel will boot successfully as shown in the picture below.","title":"Booting into the linux kernel using QEMU emulator"},{"location":"Building_Linux_Kernel/#reference-links","text":"https://risc-v-getting-started-guide.readthedocs.io/en/latest/linux-qemu.html https://hackernoon.com/how-to-set-up-the-environment-for-riscv-64-linux-kernel-development-in-ubuntu-2004-si5p35kv","title":"Reference links"},{"location":"Building_qemu/","text":"Installing QEMU for emulating riscv64 QEMU is an open-source emulator. It can be used to emulate different architectures on a single machine. In RISC-V CI there are various programs which run on RISC-V architecture. But instead of porting them to a dedicated board of riscv architecture, they can be run readily on qemu emulator. Here two types of QEMU emulators will be used for RISC-V applications: qemu-system-riscv64: It can be used to load a complete linux operating system image. qemu-riscv64: It can be used to execute program's binary directly without need of a complete operating system. Installing Pre-requisites Execute the following command to install the pre-requisites for installing qemu on ubuntu 22.04 (jammy) sudo apt-get install meson git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build qemu-slirp is important for enabling user-level networking with qemu-system-riscv64 qemu-system-riscv64 while loading image of server installation of ubuntu. So it needs to be installed first. Get the source code of qemu-slirp using following command: git clone https://github.com/openSUSE/qemu-slirp.git Then Execute following commands to install slirp in meson, which can later be used by qemu during build. meson build ninja -C build install Note: Make sure you have riscv64-unknown-linux-gnu toolchain installed for compiling program and executing them on qemu later. There are some optional dependencies which one can download, but they are actually not needed for installing qemu and make it work. Installing qemu-system-riscv64 What is qemu-system-riscv64 qemu-system-riscv64 is qemu executable program. It can load a complete linux distribution. It cannot take program's executable binary as argument and run it without a dedicated linux distribution. Installing qemu-system-riscv64 on ubuntu Get source code of qemu from github using the command below git clone https://github.com/qemu/qemu.git Configure qemu for riscv64-softmmu with following command (replace $PREFIX with valid location of installation). ./configure --prefix=$PREFIX --target-list=riscv64-linux-user,riscv64-softmmu --enable-slirp Execute following command to start the build. make Execute following command to install the binaries at $PREFIX location. make install Note: After the installation with slirp following error can be encountered on some systems . qemu-system-riscv64: symbol lookup error: qemu-system-riscv64: undefined symbol: slirp_new, version SLIRP_4.0 Solution: This can be solved by executing following command in source directory of qemu (which is cloned from github). [sudo] ldconfig Testing qemu-system-riscv64 qemu-system-riscv64 can only be tested by booting a linux operating system. See Booting RISC-V Ubuntu 22.04 on qemu-system-riscv64 . Installing qemu-riscv64 What is qemu-riscv64 qemu-riscv64 is qemu executable program. But instead of porting a complete operating system (like qemu-system-riscv64 ), it can readily execute binaries. Throughout cross-compiling section, qemu-riscv64 will be used with linux-user and executable of every program can be tested on qemu (e.g. python, ruby etc.). Installing qemu-riscv64 on ubuntu 22.04 Get source code of qemu using the command below git clone https://github.com/qemu/qemu.git Use following command in the root directory of repository to configure qemu for riscv64-linux-user ./configure --target-list=riscv64-linux-user --prefix=$PREFIX # Replace $PREFIX with a valid location to install at Note: If this is not your architecture/platform, you can see a list of available platform/architecture by executing following command. ./configure --help Use the following command to start the build process make -j$(nproc) After the builld is complete without any error, use the following command to install binaries at $PREFIX location make install Add the $PREFIX/bin to $PATH variable so that it may be recognized as a command. Using this method causes the qemu-riscv64 to have an issue with sysroot. It starts searching for libraries in the root folder of the machine which is based on x86_64-linux-gnu . A simple workaround is to give path of the sysroot/ folder where riscv64-unknown-linux-gnu toolchain is installed. Here that directory will be denoted as $RISCV_SYSROOT Testing qemu-riscv64 Create a C file in your favorite editor or by using the commands below: echo \"#include\" > helloworld.c echo \"int main(){\" >> helloworld.c echo \"printf(\"Hello World !\");\" >> helloworld.c echo '}' >> helloworld.c Execute following command to compile C program with riscv gnu toolchain riscv64-unknown-linux-gnu-gcc helloworld.c -o helloworld Execute following command to execute the compiled binary on qemu-riscv64 qemu-riscv64 -L $RISCV_SYSROOT ./helloworld If everything went right, following output will be shown. Hello World !","title":"Installing `QEMU` for emulating riscv64"},{"location":"Building_qemu/#installing-qemu-for-emulating-riscv64","text":"QEMU is an open-source emulator. It can be used to emulate different architectures on a single machine. In RISC-V CI there are various programs which run on RISC-V architecture. But instead of porting them to a dedicated board of riscv architecture, they can be run readily on qemu emulator. Here two types of QEMU emulators will be used for RISC-V applications: qemu-system-riscv64: It can be used to load a complete linux operating system image. qemu-riscv64: It can be used to execute program's binary directly without need of a complete operating system.","title":"Installing QEMU for emulating riscv64"},{"location":"Building_qemu/#installing-pre-requisites","text":"Execute the following command to install the pre-requisites for installing qemu on ubuntu 22.04 (jammy) sudo apt-get install meson git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev ninja-build qemu-slirp is important for enabling user-level networking with qemu-system-riscv64 qemu-system-riscv64 while loading image of server installation of ubuntu. So it needs to be installed first. Get the source code of qemu-slirp using following command: git clone https://github.com/openSUSE/qemu-slirp.git Then Execute following commands to install slirp in meson, which can later be used by qemu during build. meson build ninja -C build install Note: Make sure you have riscv64-unknown-linux-gnu toolchain installed for compiling program and executing them on qemu later. There are some optional dependencies which one can download, but they are actually not needed for installing qemu and make it work.","title":"Installing Pre-requisites"},{"location":"Building_qemu/#installing-qemu-system-riscv64","text":"","title":"Installing qemu-system-riscv64"},{"location":"Building_qemu/#what-is-qemu-system-riscv64","text":"qemu-system-riscv64 is qemu executable program. It can load a complete linux distribution. It cannot take program's executable binary as argument and run it without a dedicated linux distribution.","title":"What is qemu-system-riscv64"},{"location":"Building_qemu/#installing-qemu-system-riscv64-on-ubuntu","text":"Get source code of qemu from github using the command below git clone https://github.com/qemu/qemu.git Configure qemu for riscv64-softmmu with following command (replace $PREFIX with valid location of installation). ./configure --prefix=$PREFIX --target-list=riscv64-linux-user,riscv64-softmmu --enable-slirp Execute following command to start the build. make Execute following command to install the binaries at $PREFIX location. make install Note: After the installation with slirp following error can be encountered on some systems . qemu-system-riscv64: symbol lookup error: qemu-system-riscv64: undefined symbol: slirp_new, version SLIRP_4.0 Solution: This can be solved by executing following command in source directory of qemu (which is cloned from github). [sudo] ldconfig","title":"Installing qemu-system-riscv64 on ubuntu"},{"location":"Building_qemu/#testing-qemu-system-riscv64","text":"qemu-system-riscv64 can only be tested by booting a linux operating system. See Booting RISC-V Ubuntu 22.04 on qemu-system-riscv64 .","title":"Testing qemu-system-riscv64"},{"location":"Building_qemu/#installing-qemu-riscv64","text":"","title":"Installing qemu-riscv64"},{"location":"Building_qemu/#what-is-qemu-riscv64","text":"qemu-riscv64 is qemu executable program. But instead of porting a complete operating system (like qemu-system-riscv64 ), it can readily execute binaries. Throughout cross-compiling section, qemu-riscv64 will be used with linux-user and executable of every program can be tested on qemu (e.g. python, ruby etc.).","title":"What is qemu-riscv64"},{"location":"Building_qemu/#installing-qemu-riscv64-on-ubuntu-2204","text":"Get source code of qemu using the command below git clone https://github.com/qemu/qemu.git Use following command in the root directory of repository to configure qemu for riscv64-linux-user ./configure --target-list=riscv64-linux-user --prefix=$PREFIX # Replace $PREFIX with a valid location to install at Note: If this is not your architecture/platform, you can see a list of available platform/architecture by executing following command. ./configure --help Use the following command to start the build process make -j$(nproc) After the builld is complete without any error, use the following command to install binaries at $PREFIX location make install Add the $PREFIX/bin to $PATH variable so that it may be recognized as a command. Using this method causes the qemu-riscv64 to have an issue with sysroot. It starts searching for libraries in the root folder of the machine which is based on x86_64-linux-gnu . A simple workaround is to give path of the sysroot/ folder where riscv64-unknown-linux-gnu toolchain is installed. Here that directory will be denoted as $RISCV_SYSROOT","title":"Installing qemu-riscv64 on ubuntu 22.04"},{"location":"Building_qemu/#testing-qemu-riscv64","text":"Create a C file in your favorite editor or by using the commands below: echo \"#include\" > helloworld.c echo \"int main(){\" >> helloworld.c echo \"printf(\"Hello World !\");\" >> helloworld.c echo '}' >> helloworld.c Execute following command to compile C program with riscv gnu toolchain riscv64-unknown-linux-gnu-gcc helloworld.c -o helloworld Execute following command to execute the compiled binary on qemu-riscv64 qemu-riscv64 -L $RISCV_SYSROOT ./helloworld If everything went right, following output will be shown. Hello World !","title":"Testing qemu-riscv64"},{"location":"Creating_CI_CD_pipeline/","text":"Creating a CI/CD pipeline in Jenkins Pre Requisistes For sake of this documentation, jenkins built-in sample script is used to create and execute a cd/cd pipeline in jenkins. In the built-in script maven is used as M3, so one must install Maven plugin inside jenkins and name it M3 . Usually maven is already present inside jenkins and can be configured from Global Configuration Tools . Following steps demonstrate configuring Maven plugin. Go to Jenkins Dashboard and click on Manage Jenkins In Manage Jenkins , under System Configuration section, click on Global Tool Configuration . In Global Tool Configuration , scroll down to Maven section and click on the respective option under the Maven Section (should be Maven installations\u2026 or Add Maven ). Under Maven installations , enter M3 in \u201cname\u201d text box, check Install Automatically and select Version greater than 3, then click Apply and Save . This should install Maven version 3 and configure as M3 . Steps for Jenkins pipeline creation After installing Jenkins and having all the suggested plugins installed, go to Jenkins dashboard and click on Create Job . On the next page, give your pipeline a name, select Pipeline and click OK . A Configuration page for the pipeline will appear. Select Build Triggers options and General options according to need and scroll down to the Pipeline section. Definition section contains configuration for stages and steps of the pipeline. Under Definition section, you can either choose Pipeline script and try writing your own script or try some sample pipeline (like Hello World , Github+Maven etc) or you could select Pipeline script from SCM and give a github repository containing configurations of Pipeline. Press Save and Apply . This should take you to the Pipeline and you can build the pipeline and if no unresolved dependencies are present, the pipeline should build without any error.","title":"Creating a CI/CD pipeline in Jenkins"},{"location":"Creating_CI_CD_pipeline/#creating-a-cicd-pipeline-in-jenkins","text":"","title":"Creating a CI/CD pipeline in Jenkins"},{"location":"Creating_CI_CD_pipeline/#pre-requisistes","text":"For sake of this documentation, jenkins built-in sample script is used to create and execute a cd/cd pipeline in jenkins. In the built-in script maven is used as M3, so one must install Maven plugin inside jenkins and name it M3 . Usually maven is already present inside jenkins and can be configured from Global Configuration Tools . Following steps demonstrate configuring Maven plugin. Go to Jenkins Dashboard and click on Manage Jenkins In Manage Jenkins , under System Configuration section, click on Global Tool Configuration . In Global Tool Configuration , scroll down to Maven section and click on the respective option under the Maven Section (should be Maven installations\u2026 or Add Maven ). Under Maven installations , enter M3 in \u201cname\u201d text box, check Install Automatically and select Version greater than 3, then click Apply and Save . This should install Maven version 3 and configure as M3 .","title":"Pre Requisistes"},{"location":"Creating_CI_CD_pipeline/#steps-for-jenkins-pipeline-creation","text":"After installing Jenkins and having all the suggested plugins installed, go to Jenkins dashboard and click on Create Job . On the next page, give your pipeline a name, select Pipeline and click OK . A Configuration page for the pipeline will appear. Select Build Triggers options and General options according to need and scroll down to the Pipeline section. Definition section contains configuration for stages and steps of the pipeline. Under Definition section, you can either choose Pipeline script and try writing your own script or try some sample pipeline (like Hello World , Github+Maven etc) or you could select Pipeline script from SCM and give a github repository containing configurations of Pipeline. Press Save and Apply . This should take you to the Pipeline and you can build the pipeline and if no unresolved dependencies are present, the pipeline should build without any error.","title":"Steps for Jenkins pipeline creation"},{"location":"Creating_Jenkins_Node_on_LXC/","text":"Creating a Jenkins Node on LXC Container What is a container A container is a virtualization method for isolating the applications (or even operating systems) from each other. Why do we need a container for Jenkins node In Jenkins, node is a location where our jobs run. One user can use one node for all of his processes and multiple users may also use one node for all of their processes. In Jenkins freestyle project, we can use bash shell or windows command shell due to which there is a possibility to navigate anywhere in the server machine. This possibility can lead to various security and integrity issues for server administrators and also for other users using that webserver. So one must isolate each node and allocate each node to each user separately. What is LXC Container LXC stands for Linux Containers. LXC is a package for linux operating systems and provides linux users with containers which may contain a whole linux operating system while also being lightweight than a virtual machine. More information regarding LXC can be found at https://linuxcontainers.org/lxc/introduction/ On ubuntu 20.04 one can install LXC using command [sudo] apt-get install lxc Creating a container with LXC NOTE: Throughout this document, the name of the container will be my-container and the name of the user will be user1 . So wherever my-container is written, one may change the name to whatever one wants to give it. Pre-requisites Before proceeding, it is important to mention that at the point of writing this document following are the specifications for linux kernel and distribution: Linux Kernel : 5.15.0-46-generic (can be checked on ubuntu by command uname -r ) Distribution : Ubuntu focal (20.04) (can be checked on ubuntu by command lsb_release -a ) By default linux users are not allowed to create any network device on the machine. For doing that, one must add uid and gid in the /etc/lxc/lxc-usernet . The uid and gid of the user you want to use can be found in the files /etc/uid and /etc/gid respectively. After getting the gid and uid of the user you want to allow for creating the network devices, one must go to /etc/lxc/lxc-usernet and add the uid and gid in the following format: veth lxcbr0 10 e.g. jenkins veth lxcbr0 10 In above example jenkins is the username, veth is the command used for creating the bridges between virtual network devices and physical network devices (you will be able to see that ethernet device in our container will be lxcbr0 ) and lxbr0 is the network device we want to create. \u201810\u2019 represents the number of devices we want to create using our specified user. According lxc documentation, in ubuntu 20.04 an additional command is required before creating lxc container: export DOWNLOAD_KEYSERVER=\"hkp://keyserver.ubuntu.com\" Creating image After this, one can create container using following command systemd-run --unit=my-unit --user --scope -p \"Delegate=yes\" -- lxc-create -t download -n my-container This runs lxc container with unit name my-unit , container name my-container and delegates a control group (also known as the cgroup ) which is needed for resource allocation for processes in container. This will output the list of available linux distributions in which one may want to run the container and will prompt for Distribution as shown in the following image. After selecting the suitable distribution, release and architecture (which is also mentioned in the table), the container may be created as shown in the image below: Next thing is to start a container which will change its state from STOPPED to RUNNING using the following command. lxc-start -n my-container Above command will have no output if it succeeds. The state of the container can be checked using the following command. lxc-info -n my-container After starting the container, its state will be set as running and is just like turning a linux machine ON. From this point onwards, if one wants to use the machine in the terminal then use the following command and this will switch the terminal to the root of the container. lxc-attach my-container Now the container is ready to be used and is completely isolated from the host machine. Using SSH to access container with username and password The above mentioned method can be used to attach the host machine terminal to the container and this can be used to access the container. But if one wants to access the machine remotely then one possible and well-known method will be to configure and use SSH on the container. As it is an out of the box linux distro and only the root user is present, so first create another user using the following command and then manage its permissions for /home folder . #Considering you remain the root user for execution of all the following #commands useradd user1 cd /home mkdir user1 #Creating home directory for user1 chown user1:user1 user1 #Giving ownership of home directory to new user #For adding the same shell and bashrc configurations for new user, use #following #command, otherwise the shell will be very basic for new user and will be #very inconvenient to use. usermod -s /bin/bash user1 For the sake of simplicity of this document the name used for the new user is user1 here. (You may want to set the password for user1 by executing the passwd command in root.) At this point user1 is not in sudoers. For adding it to the sudoers, it must be added in the sudo group which can be done by using the following command. usermod -a -G sudo user1 Now switch to the user1 using the following command. su - user Now install openssh-server for configuring the ssh on user1. sudo apt install openssh-server After that one must find the ip of the container we are using, for this either run following command while in container with user1, sudo apt-install net-tools #Because ifconfig is part of net-tools which are by default not installed on new #container Ifconfig -a OR open a new terminal in the host machine and execute the following command. lxc-info my-container -iH So, the ip of the container is 10.0.3.127 . The command for establishing an ssh connection to a remote machine is mentioned below and it will ask for the password of the remote machine which is actually the container in our case. ssh user1@10.0.3.127 After entering the password, terminal will switch to the container\u2019s user1 as can be seen in the following image. Using SSH to access Jenkins agents on the container First install some initial dependencies (git, jdk, jre) on the containers for running agents on the container. sudo apt update sudo apt install default-jdk default-jre git maven Now login to jenkins with administrator privileges and create a node in it from Dashboard > Manage Jenkins > Nodes and press + New Node . Enter a name for the node and select the desirable node type. For this documentation, the node will be a permanent type and the name will be temp_node . After this click on Create which will display the configuration page of the node. Write the description of the node as desired. Number of executors means number of threads running at a time (it will be better to set it to the number of processors present on the machine which is running this node). Remote root directory will be the directory where the jobs will run by default on the node. In our case this will be a specified directory inside the container. Labels indicate that this node will run only when a job with specified labels is run, otherwise this node will not be used (also depends on the usage method in the next option). If the purpose is to use the node by default for every job, then leave it empty. Select a desired usage option. In launch methods, select \u201cLaunch agents via SSH\u201d In \u201cHost\u201d enter the ip address of the container which is 10.0.3.127 in our case. In \u201cCredentials\u201d, click Add and this will open another sub dialog for entering credentials information. Select the kind as \u201cUsername wih password\u201d. Leave other options as is and write the username and password of the container user, in our case the username will be user1 and password will be the password which was set for user1. \u201cID\u201d and \u201cDescription\u201d are optional. Click on \u201cAdd\u201d. Now as the credentials are added, click on the dropdown menu and select the username you just added. In our case it is user1 as the username added was user1. After this rest of the options need not to be changed if this node is going to be a default node. Click on \u201cSave\u201d. After complete setup, the configuration for this node will look something like this. If no issue is encountered during this whole setup, jenkins will take us to the log and after sometime (when the ssh connection is established) we can see \u201cAgent successfully connected and online\u201d at the bottom of the log as can be seen in the screenshot below. After this point, node will be able to run jobs from the container directory. Reference Links Documentation for LXC containers can be found at: https://linuxcontainers.org Details regarding Jenkins ssh agents can be found at: https://acloudguru.com/blog/engineering/adding-a-jenkins-agent-node","title":"Creating a Jenkins Node on LXC Container"},{"location":"Creating_Jenkins_Node_on_LXC/#creating-a-jenkins-node-on-lxc-container","text":"","title":"Creating a Jenkins Node on LXC Container"},{"location":"Creating_Jenkins_Node_on_LXC/#what-is-a-container","text":"A container is a virtualization method for isolating the applications (or even operating systems) from each other.","title":"What is a container"},{"location":"Creating_Jenkins_Node_on_LXC/#why-do-we-need-a-container-for-jenkins-node","text":"In Jenkins, node is a location where our jobs run. One user can use one node for all of his processes and multiple users may also use one node for all of their processes. In Jenkins freestyle project, we can use bash shell or windows command shell due to which there is a possibility to navigate anywhere in the server machine. This possibility can lead to various security and integrity issues for server administrators and also for other users using that webserver. So one must isolate each node and allocate each node to each user separately.","title":"Why do we need a container for Jenkins node"},{"location":"Creating_Jenkins_Node_on_LXC/#what-is-lxc-container","text":"LXC stands for Linux Containers. LXC is a package for linux operating systems and provides linux users with containers which may contain a whole linux operating system while also being lightweight than a virtual machine. More information regarding LXC can be found at https://linuxcontainers.org/lxc/introduction/ On ubuntu 20.04 one can install LXC using command [sudo] apt-get install lxc","title":"What is LXC Container"},{"location":"Creating_Jenkins_Node_on_LXC/#creating-a-container-with-lxc","text":"NOTE: Throughout this document, the name of the container will be my-container and the name of the user will be user1 . So wherever my-container is written, one may change the name to whatever one wants to give it.","title":"Creating a container with LXC"},{"location":"Creating_Jenkins_Node_on_LXC/#pre-requisites","text":"Before proceeding, it is important to mention that at the point of writing this document following are the specifications for linux kernel and distribution: Linux Kernel : 5.15.0-46-generic (can be checked on ubuntu by command uname -r ) Distribution : Ubuntu focal (20.04) (can be checked on ubuntu by command lsb_release -a ) By default linux users are not allowed to create any network device on the machine. For doing that, one must add uid and gid in the /etc/lxc/lxc-usernet . The uid and gid of the user you want to use can be found in the files /etc/uid and /etc/gid respectively. After getting the gid and uid of the user you want to allow for creating the network devices, one must go to /etc/lxc/lxc-usernet and add the uid and gid in the following format: veth lxcbr0 10 e.g. jenkins veth lxcbr0 10 In above example jenkins is the username, veth is the command used for creating the bridges between virtual network devices and physical network devices (you will be able to see that ethernet device in our container will be lxcbr0 ) and lxbr0 is the network device we want to create. \u201810\u2019 represents the number of devices we want to create using our specified user. According lxc documentation, in ubuntu 20.04 an additional command is required before creating lxc container: export DOWNLOAD_KEYSERVER=\"hkp://keyserver.ubuntu.com\"","title":"Pre-requisites"},{"location":"Creating_Jenkins_Node_on_LXC/#creating-image","text":"After this, one can create container using following command systemd-run --unit=my-unit --user --scope -p \"Delegate=yes\" -- lxc-create -t download -n my-container This runs lxc container with unit name my-unit , container name my-container and delegates a control group (also known as the cgroup ) which is needed for resource allocation for processes in container. This will output the list of available linux distributions in which one may want to run the container and will prompt for Distribution as shown in the following image. After selecting the suitable distribution, release and architecture (which is also mentioned in the table), the container may be created as shown in the image below: Next thing is to start a container which will change its state from STOPPED to RUNNING using the following command. lxc-start -n my-container Above command will have no output if it succeeds. The state of the container can be checked using the following command. lxc-info -n my-container After starting the container, its state will be set as running and is just like turning a linux machine ON. From this point onwards, if one wants to use the machine in the terminal then use the following command and this will switch the terminal to the root of the container. lxc-attach my-container Now the container is ready to be used and is completely isolated from the host machine.","title":"Creating image"},{"location":"Creating_Jenkins_Node_on_LXC/#using-ssh-to-access-container-with-username-and-password","text":"The above mentioned method can be used to attach the host machine terminal to the container and this can be used to access the container. But if one wants to access the machine remotely then one possible and well-known method will be to configure and use SSH on the container. As it is an out of the box linux distro and only the root user is present, so first create another user using the following command and then manage its permissions for /home folder . #Considering you remain the root user for execution of all the following #commands useradd user1 cd /home mkdir user1 #Creating home directory for user1 chown user1:user1 user1 #Giving ownership of home directory to new user #For adding the same shell and bashrc configurations for new user, use #following #command, otherwise the shell will be very basic for new user and will be #very inconvenient to use. usermod -s /bin/bash user1 For the sake of simplicity of this document the name used for the new user is user1 here. (You may want to set the password for user1 by executing the passwd command in root.) At this point user1 is not in sudoers. For adding it to the sudoers, it must be added in the sudo group which can be done by using the following command. usermod -a -G sudo user1 Now switch to the user1 using the following command. su - user Now install openssh-server for configuring the ssh on user1. sudo apt install openssh-server After that one must find the ip of the container we are using, for this either run following command while in container with user1, sudo apt-install net-tools #Because ifconfig is part of net-tools which are by default not installed on new #container Ifconfig -a OR open a new terminal in the host machine and execute the following command. lxc-info my-container -iH So, the ip of the container is 10.0.3.127 . The command for establishing an ssh connection to a remote machine is mentioned below and it will ask for the password of the remote machine which is actually the container in our case. ssh user1@10.0.3.127 After entering the password, terminal will switch to the container\u2019s user1 as can be seen in the following image.","title":"Using SSH to access container with username and password"},{"location":"Creating_Jenkins_Node_on_LXC/#using-ssh-to-access-jenkins-agents-on-the-container","text":"First install some initial dependencies (git, jdk, jre) on the containers for running agents on the container. sudo apt update sudo apt install default-jdk default-jre git maven Now login to jenkins with administrator privileges and create a node in it from Dashboard > Manage Jenkins > Nodes and press + New Node . Enter a name for the node and select the desirable node type. For this documentation, the node will be a permanent type and the name will be temp_node . After this click on Create which will display the configuration page of the node. Write the description of the node as desired. Number of executors means number of threads running at a time (it will be better to set it to the number of processors present on the machine which is running this node). Remote root directory will be the directory where the jobs will run by default on the node. In our case this will be a specified directory inside the container. Labels indicate that this node will run only when a job with specified labels is run, otherwise this node will not be used (also depends on the usage method in the next option). If the purpose is to use the node by default for every job, then leave it empty. Select a desired usage option. In launch methods, select \u201cLaunch agents via SSH\u201d In \u201cHost\u201d enter the ip address of the container which is 10.0.3.127 in our case. In \u201cCredentials\u201d, click Add and this will open another sub dialog for entering credentials information. Select the kind as \u201cUsername wih password\u201d. Leave other options as is and write the username and password of the container user, in our case the username will be user1 and password will be the password which was set for user1. \u201cID\u201d and \u201cDescription\u201d are optional. Click on \u201cAdd\u201d. Now as the credentials are added, click on the dropdown menu and select the username you just added. In our case it is user1 as the username added was user1. After this rest of the options need not to be changed if this node is going to be a default node. Click on \u201cSave\u201d. After complete setup, the configuration for this node will look something like this. If no issue is encountered during this whole setup, jenkins will take us to the log and after sometime (when the ssh connection is established) we can see \u201cAgent successfully connected and online\u201d at the bottom of the log as can be seen in the screenshot below. After this point, node will be able to run jobs from the container directory.","title":"Using SSH to access Jenkins agents on the container"},{"location":"Creating_Jenkins_Node_on_LXC/#reference-links","text":"Documentation for LXC containers can be found at: https://linuxcontainers.org Details regarding Jenkins ssh agents can be found at: https://acloudguru.com/blog/engineering/adding-a-jenkins-agent-node","title":"Reference Links"},{"location":"Creating_jenkinsfile/","text":"Creating a Cloud-V CI Pipeline file What is a Cloud-V CI Pipeline file A cloud-v-pipeline file is a Continuous Integration (CI) jenkins pipeline script which is written in Groovy. It describes various stages (and possibly steps) which are executed in the defined pattern. These stages can be written in bash or they can be written in Groovy itself. Mainly there can be two types of Cloud-V pipeline files are of two types: Scripted: Only contains stages Declarative: Contains stages as well as steps (more feature-rich and recommended) This documentation will cover how to create a cloud-v-pipeline file with bash script inside it and run it on various compute instances (which are known as Nodes in jenkins). Jenkins Node In jenkins, node represents a compute instance. In simple words, it is the platform on which our job build is going to run. Jenkins Master There is a jenkins Master node which is actually the compute instance on which Jenkins is installed. It is the node which schedules builds on runners. For security reason, no job is allowed to run on this node. Jenkins Slave Jenkins slave nodes are the compute instances on which our job builds run safely. They may be attached with jenkins master via hardware or they may be connected through remote SSH connection. cloud-v-pipeline file written with bash Simple Hello World cloud-v-pipeline file In Cloud-V, all the platforms are running Linux operating system, so the cloud-v-pipeline should be written in bash. Following script is an example of how can we run a bash script in scripted cloud-v-pipeline . node{ stage('*** Phase 1 ***') { //Using bash commands sh '''#!/bin/bash echo \"Hello World !\\n\" ''' } } The keyword sh is used to specify a shell script As there is nothing mentioned with node , so the script will run job build on any available compute instance. cloud-v-pipeline for a Specific Node In previous script, the cloud-v-pipeline would run on any compute instances which are available. But in case if someone wants to run a job build on specific node, then a compute instance name must be specified with keyword node . The following script is an example of running above Hello World program on node named hifive_unleashed . node('hifive_unleashed'){ stage('*** Phase 1 ***') { //Using bash commands sh '''#!/bin/bash echo \"Hello World !\\n\" ''' } } cloud-v-pipeline for Cross-Platform Compilation and Execution Cloud-V supports cross-compilation and execution on emulated RISC-V compute instances. Following tools help in cross compilation and cross-platfrom execution: RISC-V GNU Toolchain QEMU user mode (for running standalone binaries) QEMU System (for running application in Linux) An example pipeline script is given below in scripted pipeline. node('x86_runner2'){ checkout scm //Getting content of this repo stage('*** Compilation Phase ***') { // for display purposes //Compiling helloworld.c using bash commands sh '''#!/bin/bash gcc -g ./helloworld.c -o helloworld.out riscv64-unknown-linux-gnu-gcc ./helloworld.c -o helloworld_riscv_compiled.out //Cross compiling for RISC-V ''' } stage (' *** Running Binaries ***'){ sh '''#!/bin/bash ./helloworld.out qemu-riscv64 -L $RISCV_SYSROOT helloworld_riscv_compiled.out //Running executable on RISC-V emulated platform ''' } } The equivalent declarative pipeline is as follows: pipeline { agent {label \"x86_runner2\"} stages { stage('Clone Repository') { steps('delegate'){ checkout scm //Clones the repository on the local machine } } stage ('Compilation Phase'){ steps{ sh '''#!/bin/bash gcc -g ./helloworld.c -o helloworld.out ''' sh '''#!/bin/bash riscv64-unknown-linux-gnu-gcc ./helloworld.c -o helloworld_riscv_compiled.out ''' } } stage ('Running Binaries'){ steps { sh ''' #!/bin/bash ./helloworld.out ''' sh'''#!/bin/bash qemu-riscv64 -L $RISCV_SYSROOT helloworld_riscv_compiled.out ''' } } } } Reference Links https://www.jenkins.io/doc/book/pipeline/syntax/","title":"Creating a CI pipeline file"},{"location":"Creating_jenkinsfile/#creating-a-cloud-v-ci-pipeline-file","text":"","title":"Creating a Cloud-V CI Pipeline file"},{"location":"Creating_jenkinsfile/#what-is-a-cloud-v-ci-pipeline-file","text":"A cloud-v-pipeline file is a Continuous Integration (CI) jenkins pipeline script which is written in Groovy. It describes various stages (and possibly steps) which are executed in the defined pattern. These stages can be written in bash or they can be written in Groovy itself. Mainly there can be two types of Cloud-V pipeline files are of two types: Scripted: Only contains stages Declarative: Contains stages as well as steps (more feature-rich and recommended) This documentation will cover how to create a cloud-v-pipeline file with bash script inside it and run it on various compute instances (which are known as Nodes in jenkins).","title":"What is a Cloud-V CI Pipeline file"},{"location":"Creating_jenkinsfile/#jenkins-node","text":"In jenkins, node represents a compute instance. In simple words, it is the platform on which our job build is going to run.","title":"Jenkins Node"},{"location":"Creating_jenkinsfile/#jenkins-master","text":"There is a jenkins Master node which is actually the compute instance on which Jenkins is installed. It is the node which schedules builds on runners. For security reason, no job is allowed to run on this node.","title":"Jenkins Master"},{"location":"Creating_jenkinsfile/#jenkins-slave","text":"Jenkins slave nodes are the compute instances on which our job builds run safely. They may be attached with jenkins master via hardware or they may be connected through remote SSH connection.","title":"Jenkins Slave"},{"location":"Creating_jenkinsfile/#cloud-v-pipeline-file-written-with-bash","text":"","title":"cloud-v-pipeline file written with bash"},{"location":"Creating_jenkinsfile/#simple-hello-world-cloud-v-pipeline-file","text":"In Cloud-V, all the platforms are running Linux operating system, so the cloud-v-pipeline should be written in bash. Following script is an example of how can we run a bash script in scripted cloud-v-pipeline . node{ stage('*** Phase 1 ***') { //Using bash commands sh '''#!/bin/bash echo \"Hello World !\\n\" ''' } } The keyword sh is used to specify a shell script As there is nothing mentioned with node , so the script will run job build on any available compute instance.","title":"Simple Hello World cloud-v-pipeline file"},{"location":"Creating_jenkinsfile/#cloud-v-pipeline-for-a-specific-node","text":"In previous script, the cloud-v-pipeline would run on any compute instances which are available. But in case if someone wants to run a job build on specific node, then a compute instance name must be specified with keyword node . The following script is an example of running above Hello World program on node named hifive_unleashed . node('hifive_unleashed'){ stage('*** Phase 1 ***') { //Using bash commands sh '''#!/bin/bash echo \"Hello World !\\n\" ''' } }","title":"cloud-v-pipeline for a Specific Node"},{"location":"Creating_jenkinsfile/#cloud-v-pipeline-for-cross-platform-compilation-and-execution","text":"Cloud-V supports cross-compilation and execution on emulated RISC-V compute instances. Following tools help in cross compilation and cross-platfrom execution: RISC-V GNU Toolchain QEMU user mode (for running standalone binaries) QEMU System (for running application in Linux) An example pipeline script is given below in scripted pipeline. node('x86_runner2'){ checkout scm //Getting content of this repo stage('*** Compilation Phase ***') { // for display purposes //Compiling helloworld.c using bash commands sh '''#!/bin/bash gcc -g ./helloworld.c -o helloworld.out riscv64-unknown-linux-gnu-gcc ./helloworld.c -o helloworld_riscv_compiled.out //Cross compiling for RISC-V ''' } stage (' *** Running Binaries ***'){ sh '''#!/bin/bash ./helloworld.out qemu-riscv64 -L $RISCV_SYSROOT helloworld_riscv_compiled.out //Running executable on RISC-V emulated platform ''' } } The equivalent declarative pipeline is as follows: pipeline { agent {label \"x86_runner2\"} stages { stage('Clone Repository') { steps('delegate'){ checkout scm //Clones the repository on the local machine } } stage ('Compilation Phase'){ steps{ sh '''#!/bin/bash gcc -g ./helloworld.c -o helloworld.out ''' sh '''#!/bin/bash riscv64-unknown-linux-gnu-gcc ./helloworld.c -o helloworld_riscv_compiled.out ''' } } stage ('Running Binaries'){ steps { sh ''' #!/bin/bash ./helloworld.out ''' sh'''#!/bin/bash qemu-riscv64 -L $RISCV_SYSROOT helloworld_riscv_compiled.out ''' } } } }","title":"cloud-v-pipeline for Cross-Platform Compilation and Execution"},{"location":"Creating_jenkinsfile/#reference-links","text":"https://www.jenkins.io/doc/book/pipeline/syntax/","title":"Reference Links"},{"location":"Installing_ssl_certificates_new/","text":"Configure letsencrypt with jenkins SSL certificates allow a website to run on HTTPS protocol which makes sure that data transfer between user and server cannot be intercepted between them. When using HTTPS protocol the data transfer is encrypted between user and server being used. NOTE: Keep the fact in mind that letsencrypt does not generate certificates for bare IP. It needs a domain name. Installing SSL certificates with letsencrypt In unix, letsencrypt package is called certbot . This can be installed using following command: sudo apt install certbot Here standalone mode will be used for generating certificates which authenticates the machine's ownership by hosting a temporary server on port 80. This is because ports less than 1024 are privileged and require root/sudo access. So make sure that port 80 is open in firewall and there is no application already running on it. Also if this process is being done on container, make sure port 80 is forwarded properly. One can also use webroot mode to generate certificates. See this link for more information. Use following command to generate certificate files and keys in /etc/letsencrypt/live/your.domain.name/ certbot certonly --standalone -d your.domain.name This will produce cert.pem , fullchain.pem and privkey.pem . Copy these files to location where .war of jenkins is located. Make sure to change the permission from root to jenkins' user. After that, use following command to convert certificate files to pkcs12 format. openssl pkcs12 -inkey privkey.pem -in fullchain.pem -export -out keys.pkcs12 keytool -importkeystore -srckeystore keys.pkcs12 -srcstoretype pkcs12 -destkeystore keystore This will ask for a password. Here it will be denoted as . Use following command to start jenkins server with generated SSL certificates. java -jar jenkins.war --httpPort=-1 --httpsPort= --httpsKeyStore=keystore --httpsKeyStorePassword= After this, go to browser and type your.domain.name: to start jenkins with https protocol.","title":"Configure `letsencrypt` with jenkins"},{"location":"Installing_ssl_certificates_new/#configure-letsencrypt-with-jenkins","text":"SSL certificates allow a website to run on HTTPS protocol which makes sure that data transfer between user and server cannot be intercepted between them. When using HTTPS protocol the data transfer is encrypted between user and server being used. NOTE: Keep the fact in mind that letsencrypt does not generate certificates for bare IP. It needs a domain name.","title":"Configure letsencrypt with jenkins"},{"location":"Installing_ssl_certificates_new/#installing-ssl-certificates-with-letsencrypt","text":"In unix, letsencrypt package is called certbot . This can be installed using following command: sudo apt install certbot Here standalone mode will be used for generating certificates which authenticates the machine's ownership by hosting a temporary server on port 80. This is because ports less than 1024 are privileged and require root/sudo access. So make sure that port 80 is open in firewall and there is no application already running on it. Also if this process is being done on container, make sure port 80 is forwarded properly. One can also use webroot mode to generate certificates. See this link for more information. Use following command to generate certificate files and keys in /etc/letsencrypt/live/your.domain.name/ certbot certonly --standalone -d your.domain.name This will produce cert.pem , fullchain.pem and privkey.pem . Copy these files to location where .war of jenkins is located. Make sure to change the permission from root to jenkins' user. After that, use following command to convert certificate files to pkcs12 format. openssl pkcs12 -inkey privkey.pem -in fullchain.pem -export -out keys.pkcs12 keytool -importkeystore -srckeystore keys.pkcs12 -srcstoretype pkcs12 -destkeystore keystore This will ask for a password. Here it will be denoted as . Use following command to start jenkins server with generated SSL certificates. java -jar jenkins.war --httpPort=-1 --httpsPort= --httpsKeyStore=keystore --httpsKeyStorePassword= After this, go to browser and type your.domain.name: to start jenkins with https protocol.","title":"Installing SSL certificates with letsencrypt"},{"location":"Multinode_Pipelines/","text":"Multinode Pipelines One can create multinode pipelines in jenkins freestyle pipeline job as well as in jenkins native pipeline job. In such a pipeline, different stages of the pipeline can run on separate nodes. The jenkins native pipeline job can have two types. Scripted Pipeline Declarative pipeline For the sake of this documentation, two nodes are used: container-node and container-node2 Label In jenkins, label specifies where the job or a stage of the job can run. In jenkins, a label can be explicitly added in the node's configuration so that each time that label is mentioned in a jenkins job, that specific node is used for building the job, or the name of the node can also be used as label in case if no label is added in the node. Creating multinode pipelines in Jenkins native pipeline job Scripted Pipeline For creating a multinode pipeline with jenkins native scripted pipeline job, jenkinsfile can be tweaked. The keyword node can be used to specify the node in which the stages are going to run and this keyword can also be used in between stages. Following screenshot indicates a code in which first stage runs on node named container-node . While the second node runs on node named container-node2 . node ('container-node') { stage ('*** Creating a directory in container-node ***'){ sh '''#!/bin/bash mkdir newdir_container-node-$RANDOM ''' } stage ('*** Creating a directory in container-node2'){ node ('container-node2'){ sh'''#!/bin/bash mkdir newdir_container-node2-$RANDOM ''' } } } Declarative pipeline For a declarative pipeline the keyword label can be used in the agent block. This can either be done at the start of the pipeline after the keyword pipeline or it can be used inside the stages. The following code builds two stages each of which is built in separate node. The keyword none with agent means that the agent is not specified globally for each stage and it should be specified inside each stage. pipeline { agent none // Means no agent specified. This means each node will specify its own agent stages { stage('container-node') { agent{ label \"container-node\" //Selecting container-node for this stage } steps { sh '''#!/bin/bash echo 'Hello container-node' mkdir \"newdir-container-node-$RANDOM\" ''' } } stage('container-node2'){ agent{ label \"container-node2\" //Selecting container-node2 for this stage } steps{ sh'''#!/bin/bash echo ''Hello container-node2 mkdir \"newdir-container-node2-$RANDOM\" ''' } } } } Creating multinode pipelines using Jenkins freestyle jobs Jenkins freestyle jobs can be combined together by mentioning post-build jobs in the freestyle job settings. Freestyle jobs are customizable and offer more options than jenkins native pipeline jobs. Each job represents a stage and each stage has separate settings. One can use jenkins freestyle jobs to run on a separate node by selecting the option Restrict where this project can be run in the General section of the job's configuration. In the Label Expression , the node's name can be mentioned in which to run the job. The following image shows the option from job's configuration. This can be done in all the job's configuration for the specified node.","title":"Multinode Pipelines"},{"location":"Multinode_Pipelines/#multinode-pipelines","text":"One can create multinode pipelines in jenkins freestyle pipeline job as well as in jenkins native pipeline job. In such a pipeline, different stages of the pipeline can run on separate nodes. The jenkins native pipeline job can have two types. Scripted Pipeline Declarative pipeline For the sake of this documentation, two nodes are used: container-node and container-node2","title":"Multinode Pipelines"},{"location":"Multinode_Pipelines/#label","text":"In jenkins, label specifies where the job or a stage of the job can run. In jenkins, a label can be explicitly added in the node's configuration so that each time that label is mentioned in a jenkins job, that specific node is used for building the job, or the name of the node can also be used as label in case if no label is added in the node.","title":"Label"},{"location":"Multinode_Pipelines/#creating-multinode-pipelines-in-jenkins-native-pipeline-job","text":"","title":"Creating multinode pipelines in Jenkins native pipeline job"},{"location":"Multinode_Pipelines/#scripted-pipeline","text":"For creating a multinode pipeline with jenkins native scripted pipeline job, jenkinsfile can be tweaked. The keyword node can be used to specify the node in which the stages are going to run and this keyword can also be used in between stages. Following screenshot indicates a code in which first stage runs on node named container-node . While the second node runs on node named container-node2 . node ('container-node') { stage ('*** Creating a directory in container-node ***'){ sh '''#!/bin/bash mkdir newdir_container-node-$RANDOM ''' } stage ('*** Creating a directory in container-node2'){ node ('container-node2'){ sh'''#!/bin/bash mkdir newdir_container-node2-$RANDOM ''' } } }","title":"Scripted Pipeline"},{"location":"Multinode_Pipelines/#declarative-pipeline","text":"For a declarative pipeline the keyword label can be used in the agent block. This can either be done at the start of the pipeline after the keyword pipeline or it can be used inside the stages. The following code builds two stages each of which is built in separate node. The keyword none with agent means that the agent is not specified globally for each stage and it should be specified inside each stage. pipeline { agent none // Means no agent specified. This means each node will specify its own agent stages { stage('container-node') { agent{ label \"container-node\" //Selecting container-node for this stage } steps { sh '''#!/bin/bash echo 'Hello container-node' mkdir \"newdir-container-node-$RANDOM\" ''' } } stage('container-node2'){ agent{ label \"container-node2\" //Selecting container-node2 for this stage } steps{ sh'''#!/bin/bash echo ''Hello container-node2 mkdir \"newdir-container-node2-$RANDOM\" ''' } } } }","title":"Declarative pipeline"},{"location":"Multinode_Pipelines/#creating-multinode-pipelines-using-jenkins-freestyle-jobs","text":"Jenkins freestyle jobs can be combined together by mentioning post-build jobs in the freestyle job settings. Freestyle jobs are customizable and offer more options than jenkins native pipeline jobs. Each job represents a stage and each stage has separate settings. One can use jenkins freestyle jobs to run on a separate node by selecting the option Restrict where this project can be run in the General section of the job's configuration. In the Label Expression , the node's name can be mentioned in which to run the job. The following image shows the option from job's configuration. This can be done in all the job's configuration for the specified node.","title":"Creating multinode pipelines using Jenkins freestyle jobs"},{"location":"Software_Developer_Guide/","text":"Software Developer Guide for RISC-V CI A software developer is the end-user who will develop or build his/her projects on RISC-V CI infrastructure. This guide will cover all the things a software developer needs to create a project based on Cloud-V Continuous Integration (CI). Pre-requisites GitHub account. GitHub project repository with owner rights. Getting an account for Cloud-V Fill out this google form with all the required information for getting an account on Cloud-V. After this we will get back to you with login credentials. Setting up cloud-v-pipeline inside github project repository Cloud-V will need a cloud-v-pipeline written with jenkinsfile pipeline syntax to start execution of tests/checks (see link ). This pipeline will contain all the stages (and may be steps) of a CI/CD pipeline. This pipeline can be scripted pipeline which will only have stages or it can also be declarative pipeline which may also have steps inside stages. A simple scripted Helloworld pipeline in linux is as follows: node{ stage('*** Phase 1 ***') { //Using bash commands sh '''#!/bin/bash echo \"Hello World !\\n\" ''' } } Upon execution of such a pipeline, the console output can be viewed as follows. Note: This cloud-v-pipeline should remain same in all the branches and pull requests. Setting credentials for webhook Cloud-V supports webhooks which can trigger the job from external sources such as GitHub. They work in a way such that, if a specified branch is committed or if a pull request is created, the specified job build starts running depending upon the trigger event which is set in build's configuration in Cloud-V. This process requires access token of the repository CREATED BY OWNER OF REPOSITORY on which the webhook is to be set. These credentials can be safely added to Cloud-V without anyone (even administrator) seeing the passwords as follows. Obtaining github access token for repository Navigate to the dashboard of your github account and click on the your github profile picture on the top-right corner on dashboard. Then click on the \"Settings\" from the list. From the left option bar in Settings scroll down and click on \"Developer settings\". Once there, click on \"Personal access tokens\", then click on \"Fine-grained tokens\" from the dropdown list and after that click on \"Generate new token\". This will open the page for setting up new access token. Follow following steps for creating a token: Give your token a meaningful name under \"Token name\" Set expiration date in \"Expiration\" depending upon how long you would like your repository to be integrated with Cloud-V (think of a meaningful upper bound) The \"Resource owner\" should be the owner of the repository who can access all kinds of settings of the repository Under \"Repository access\", check \"Only select repositories\" and then select the repository for which you would like to create the token Under \"Permissions\" section, expand \"Repository Permissions\" and give the following two permissions: \"Read and write\" access to \"Commit statuses\" (Because after the CI has run, Cloud-V will be able to set the status of the commit accordingly) \"Read-only\" access to \"Webhooks\" Configuring repository webhook In GitHub, Go to repository settings which you want to integrate for Cloud-V. Go to Webhooks Click on Add webhook Add Payload URL as https://dash.cloud-v.co/ghprbhook/ Select content type as application/json Check Enable SSL verification In the section Which events would you like to trigger this webhook? check Let me select individual events and check Pul requests as individual events and dont check any other permission. Webhook settings will look something like this: Configurations inside Cloud-V Note: Currently users are not able to see or modify pipeline build configuration inside Jenkins, that is currently managed by administrator. Users are requested to inform administrator about how they want their pipeline configured. We will provide you with Cloud-V credentials on the provided email. Login with provided credentials. Click on the Credentials in the left menu. This will take you to the credentials page. Scroll down to the Stores scoped to Jenkins and click on the System as shown in the image. Click on Global credentials (unrestricted) . Click on Add Credentials . This will take you to the New Credentials page. Select Kind as Username with password . Select Scope as Global (Jenkins, nodes, items, all child items etc) . Enter your GitHub username in Username Enter Password as GitHub personal authentication token (PAT) which can be acquired from Github account settings. ID is optional but you can enter a unique ID . Description can be left empty. But it is recommended to give a suitable but careful description by which administrator will be able to identify and use these credentials to set up github webhook Select Create This process will look something like this Now credentials will be available in the credentials list and will be shown to you as well as administrator as shown in the image below. This will create an option in configurations for using these credentials in github webhook without changing or viewing them. Note the credentials ID (as shown in the image below) and email it to the same administrator email on which you received the login credentials for Cloud-V. It is important that administrator knows the credentials ID because they will use it in the job build configurations. Note: Please make sure to inform the administrator via email that you have added the credentials in Cloud-V Dashboard. Also, send administrator the ID of credentials via email. Requirements for administrator After the above setup is complete from software developer's side, developer will need to provide the administrator with following information. Dependencies for running the project which can be packages which are needed to install in the RISC-V CI environment by administrator. Events for triggering the job build. URL of GitHub repository. Path and name of cloud-v-pipeline file on the provided GitHub repository. Any additional information which should be given for successful execution of job builds.","title":"Getting Started"},{"location":"Software_Developer_Guide/#software-developer-guide-for-risc-v-ci","text":"A software developer is the end-user who will develop or build his/her projects on RISC-V CI infrastructure. This guide will cover all the things a software developer needs to create a project based on Cloud-V Continuous Integration (CI).","title":"Software Developer Guide for RISC-V CI"},{"location":"Software_Developer_Guide/#pre-requisites","text":"GitHub account. GitHub project repository with owner rights.","title":"Pre-requisites"},{"location":"Software_Developer_Guide/#getting-an-account-for-cloud-v","text":"Fill out this google form with all the required information for getting an account on Cloud-V. After this we will get back to you with login credentials.","title":"Getting an account for Cloud-V"},{"location":"Software_Developer_Guide/#setting-up-cloud-v-pipeline-inside-github-project-repository","text":"Cloud-V will need a cloud-v-pipeline written with jenkinsfile pipeline syntax to start execution of tests/checks (see link ). This pipeline will contain all the stages (and may be steps) of a CI/CD pipeline. This pipeline can be scripted pipeline which will only have stages or it can also be declarative pipeline which may also have steps inside stages. A simple scripted Helloworld pipeline in linux is as follows: node{ stage('*** Phase 1 ***') { //Using bash commands sh '''#!/bin/bash echo \"Hello World !\\n\" ''' } } Upon execution of such a pipeline, the console output can be viewed as follows. Note: This cloud-v-pipeline should remain same in all the branches and pull requests.","title":"Setting up cloud-v-pipeline inside github project repository"},{"location":"Software_Developer_Guide/#setting-credentials-for-webhook","text":"Cloud-V supports webhooks which can trigger the job from external sources such as GitHub. They work in a way such that, if a specified branch is committed or if a pull request is created, the specified job build starts running depending upon the trigger event which is set in build's configuration in Cloud-V. This process requires access token of the repository CREATED BY OWNER OF REPOSITORY on which the webhook is to be set. These credentials can be safely added to Cloud-V without anyone (even administrator) seeing the passwords as follows.","title":"Setting credentials for webhook"},{"location":"Software_Developer_Guide/#obtaining-github-access-token-for-repository","text":"Navigate to the dashboard of your github account and click on the your github profile picture on the top-right corner on dashboard. Then click on the \"Settings\" from the list. From the left option bar in Settings scroll down and click on \"Developer settings\". Once there, click on \"Personal access tokens\", then click on \"Fine-grained tokens\" from the dropdown list and after that click on \"Generate new token\". This will open the page for setting up new access token. Follow following steps for creating a token: Give your token a meaningful name under \"Token name\" Set expiration date in \"Expiration\" depending upon how long you would like your repository to be integrated with Cloud-V (think of a meaningful upper bound) The \"Resource owner\" should be the owner of the repository who can access all kinds of settings of the repository Under \"Repository access\", check \"Only select repositories\" and then select the repository for which you would like to create the token Under \"Permissions\" section, expand \"Repository Permissions\" and give the following two permissions: \"Read and write\" access to \"Commit statuses\" (Because after the CI has run, Cloud-V will be able to set the status of the commit accordingly) \"Read-only\" access to \"Webhooks\"","title":"Obtaining github access token for repository"},{"location":"Software_Developer_Guide/#configuring-repository-webhook","text":"In GitHub, Go to repository settings which you want to integrate for Cloud-V. Go to Webhooks Click on Add webhook Add Payload URL as https://dash.cloud-v.co/ghprbhook/ Select content type as application/json Check Enable SSL verification In the section Which events would you like to trigger this webhook? check Let me select individual events and check Pul requests as individual events and dont check any other permission. Webhook settings will look something like this:","title":"Configuring repository webhook"},{"location":"Software_Developer_Guide/#configurations-inside-cloud-v","text":"Note: Currently users are not able to see or modify pipeline build configuration inside Jenkins, that is currently managed by administrator. Users are requested to inform administrator about how they want their pipeline configured. We will provide you with Cloud-V credentials on the provided email. Login with provided credentials. Click on the Credentials in the left menu. This will take you to the credentials page. Scroll down to the Stores scoped to Jenkins and click on the System as shown in the image. Click on Global credentials (unrestricted) . Click on Add Credentials . This will take you to the New Credentials page. Select Kind as Username with password . Select Scope as Global (Jenkins, nodes, items, all child items etc) . Enter your GitHub username in Username Enter Password as GitHub personal authentication token (PAT) which can be acquired from Github account settings. ID is optional but you can enter a unique ID . Description can be left empty. But it is recommended to give a suitable but careful description by which administrator will be able to identify and use these credentials to set up github webhook Select Create This process will look something like this Now credentials will be available in the credentials list and will be shown to you as well as administrator as shown in the image below. This will create an option in configurations for using these credentials in github webhook without changing or viewing them. Note the credentials ID (as shown in the image below) and email it to the same administrator email on which you received the login credentials for Cloud-V. It is important that administrator knows the credentials ID because they will use it in the job build configurations. Note: Please make sure to inform the administrator via email that you have added the credentials in Cloud-V Dashboard. Also, send administrator the ID of credentials via email.","title":"Configurations inside Cloud-V"},{"location":"Software_Developer_Guide/#requirements-for-administrator","text":"After the above setup is complete from software developer's side, developer will need to provide the administrator with following information. Dependencies for running the project which can be packages which are needed to install in the RISC-V CI environment by administrator. Events for triggering the job build. URL of GitHub repository. Path and name of cloud-v-pipeline file on the provided GitHub repository. Any additional information which should be given for successful execution of job builds.","title":"Requirements for administrator"},{"location":"Tooling/","text":"Tools on Cloud-V Using Environment Modules Users can use environment modules to load different versions of same program. For using environment modules the pattern is as follows: module load Important Note: Be sure to use #!/bin/bash -l instead of #!/bin/bash in CI pipeline file since that is required for environment modules to load For example if you want to load python version 3.9.2 compiled for x86, you will need to use following command: module load python/3.9.2 For packages compiled for RISC-V architecture host, you will need to append _riscv to package name. For example, for python 3.8.15 compiled for RISC-V, following command will be used. module load python_riscv/3.8.15","title":"Using Environment Modules"},{"location":"Tooling/#tools-on-cloud-v","text":"","title":"Tools on Cloud-V"},{"location":"Tooling/#using-environment-modules","text":"Users can use environment modules to load different versions of same program. For using environment modules the pattern is as follows: module load Important Note: Be sure to use #!/bin/bash -l instead of #!/bin/bash in CI pipeline file since that is required for environment modules to load For example if you want to load python version 3.9.2 compiled for x86, you will need to use following command: module load python/3.9.2 For packages compiled for RISC-V architecture host, you will need to append _riscv to package name. For example, for python 3.8.15 compiled for RISC-V, following command will be used. module load python_riscv/3.8.15","title":"Using Environment Modules"},{"location":"jenkins_gitlab_integration/","text":"Integrating GitLab with Jenkins This documentation will cover how to create an integration between jenkins and GitLab. This will allow users to trigger jenkins job when a merge request or a push is detected in GitLab. Pre-requisites GitLab plugin Git plugin GitLab repository with owner's credentials Configuring Jenkins System First jenkins needs to be configured. Go to Dashboard > Manage Jenkins > Configure System Scroll down to Gitlab section Check Enable authentication for '/project' end-point Enter a Connection name . Enter Gitlab host URL as https://gitlab.com/ . In case there is a different domain name, then enter there instead of above url. In Credentials , click on Add then click on Jenkins . In Kind , select GitLab API token . In API token , enter the gitlab personal access token (this will be obtained below while configuring GitLab). Click on Advanced . Click on Test Connection . If everything goes right, it should print success . Configuring GitLab Click on profile avatar in the top right. Click on Edit profile . Click on Access Tokens . Create a new personal access token and copy it (this is the GitLab API token used in above section Configuring Jenkins System ). Go to repository settings. On left-side pane, select Webhooks . Enter GitLab webhook URL (this is explained below in next section). Enter Secret Token (this is explained in the below section). Check desirable trigger options. Click Add webhook . Configuring Jenkins Job Create a jenkins job. On job configuration page, scroll down to Source Code Management . Select Git . In Credentials , add the owner credentials of GitLab repository. This will be Username and Password . Select the appropriate branch (generally it is main ). Scroll down to Build Triggers . Check Build when a change is pushed to GitLab . There will also be a GitLab webhook URL . This is needed in GitLab. This URL will be called as Webhook URL . Click on Advanced in the same option, then scroll down and generate a secret token. This token is also needed. This token will be called as Secret Token . Scroll down to Post-build Actions and select Publish build status to GitLab . Click on Apply and Save . Now whenever there will be a push (or whatever build trigger option is set in jenkins and gitlab webhook), specified jenkins job will be triggered.","title":"Integrating GitLab with Jenkins"},{"location":"jenkins_gitlab_integration/#integrating-gitlab-with-jenkins","text":"This documentation will cover how to create an integration between jenkins and GitLab. This will allow users to trigger jenkins job when a merge request or a push is detected in GitLab.","title":"Integrating GitLab with Jenkins"},{"location":"jenkins_gitlab_integration/#pre-requisites","text":"GitLab plugin Git plugin GitLab repository with owner's credentials","title":"Pre-requisites"},{"location":"jenkins_gitlab_integration/#configuring-jenkins-system","text":"First jenkins needs to be configured. Go to Dashboard > Manage Jenkins > Configure System Scroll down to Gitlab section Check Enable authentication for '/project' end-point Enter a Connection name . Enter Gitlab host URL as https://gitlab.com/ . In case there is a different domain name, then enter there instead of above url. In Credentials , click on Add then click on Jenkins . In Kind , select GitLab API token . In API token , enter the gitlab personal access token (this will be obtained below while configuring GitLab). Click on Advanced . Click on Test Connection . If everything goes right, it should print success .","title":"Configuring Jenkins System"},{"location":"jenkins_gitlab_integration/#configuring-gitlab","text":"Click on profile avatar in the top right. Click on Edit profile . Click on Access Tokens . Create a new personal access token and copy it (this is the GitLab API token used in above section Configuring Jenkins System ). Go to repository settings. On left-side pane, select Webhooks . Enter GitLab webhook URL (this is explained below in next section). Enter Secret Token (this is explained in the below section). Check desirable trigger options. Click Add webhook .","title":"Configuring GitLab"},{"location":"jenkins_gitlab_integration/#configuring-jenkins-job","text":"Create a jenkins job. On job configuration page, scroll down to Source Code Management . Select Git . In Credentials , add the owner credentials of GitLab repository. This will be Username and Password . Select the appropriate branch (generally it is main ). Scroll down to Build Triggers . Check Build when a change is pushed to GitLab . There will also be a GitLab webhook URL . This is needed in GitLab. This URL will be called as Webhook URL . Click on Advanced in the same option, then scroll down and generate a secret token. This token is also needed. This token will be called as Secret Token . Scroll down to Post-build Actions and select Publish build status to GitLab . Click on Apply and Save . Now whenever there will be a push (or whatever build trigger option is set in jenkins and gitlab webhook), specified jenkins job will be triggered.","title":"Configuring Jenkins Job"},{"location":"runner_specs/","text":"Specifications of compute instances in Cloud-V This document contains the specifications of the compute instances available for users to run builds in Cloud-V. The term \"Compute Instance\", can also be safely interchanged with the terms \"Build Executor\" and \"Runner\". Name String Architecture Cores Memory Compute Instance Type J-x86-1 (or) J-QMU-1 x86_64 4 8GiB Hardware with application-level emulator J-TESTVM-1 x86_64 4 8GiB Hardware J-RASP4-1 aarch64 4 4GiB Hardware J-QMS-1 riscv64 2 2GiB QEMU System emulator J-VF1-1 riscv64 2 8GiB Hardware J-VF1-2 riscv64 2 8GiB Hardware J-VF1-3 riscv64 2 8GiB Hardware J-VF2-1 riscv64 4 8GiB Hardware J-VF2-2 riscv64 4 8GiB Hardware J-VF2-3 riscv64 4 8GiB Hardware J-VF2-4 riscv64 4 8GiB Hardware J-VF2-5 riscv64 4 8GiB Hardware J-VF2-6 riscv64 4 8GiB Hardware J-HF-1 riscv64 4 8GiB Hardware Note: The J-QMU-1 and J-x86-1 are one and the same runner. The purpose of creating two separate executors for same hardware is that J-x86-1 is supposed to be specifically for x86 architecture whereas J-QMU-1 is specifically for the users who want to cross compile source code for riscv64 architecture and then use qemu-usermode to execute them. Nevertheless, the tooling available for J-x86-1 can also be used for J-QMU-1","title":"Compute Instance Specifications"},{"location":"runner_specs/#specifications-of-compute-instances-in-cloud-v","text":"This document contains the specifications of the compute instances available for users to run builds in Cloud-V. The term \"Compute Instance\", can also be safely interchanged with the terms \"Build Executor\" and \"Runner\". Name String Architecture Cores Memory Compute Instance Type J-x86-1 (or) J-QMU-1 x86_64 4 8GiB Hardware with application-level emulator J-TESTVM-1 x86_64 4 8GiB Hardware J-RASP4-1 aarch64 4 4GiB Hardware J-QMS-1 riscv64 2 2GiB QEMU System emulator J-VF1-1 riscv64 2 8GiB Hardware J-VF1-2 riscv64 2 8GiB Hardware J-VF1-3 riscv64 2 8GiB Hardware J-VF2-1 riscv64 4 8GiB Hardware J-VF2-2 riscv64 4 8GiB Hardware J-VF2-3 riscv64 4 8GiB Hardware J-VF2-4 riscv64 4 8GiB Hardware J-VF2-5 riscv64 4 8GiB Hardware J-VF2-6 riscv64 4 8GiB Hardware J-HF-1 riscv64 4 8GiB Hardware Note: The J-QMU-1 and J-x86-1 are one and the same runner. The purpose of creating two separate executors for same hardware is that J-x86-1 is supposed to be specifically for x86 architecture whereas J-QMU-1 is specifically for the users who want to cross compile source code for riscv64 architecture and then use qemu-usermode to execute them. Nevertheless, the tooling available for J-x86-1 can also be used for J-QMU-1","title":"Specifications of compute instances in Cloud-V"},{"location":"tooling_J-HF-1/","text":"Tools on J-HF-1 node This compute instance is Sifive's HiFive Unleased board and it has available packages ONLY for RISC-V architecture. Operating System: Ubuntu 20.04.6 (Focal Fossa) Tool Version Installed from Git 2.25.1 apt OpenJDK 11.0.20.1 apt GCC 10.5.0 apt Python3 3.8.10 apt OpenSSL 1.1.1f apt Ruby 2.7.0p0 apt Go 1.14.3 apt rustc 1.41.0 apt Flex 2.6.4 apt Ninja 1.10.0 apt Bison 3.5.1 apt autoconf 2.69 apt gperf 3.1 apt cmake 3.16.3 apt make 4.2.1 apt automake 1.16.1 apt gfortran 9.4.0 apt openssh-server 8.2p1 apt","title":"J-HF-1"},{"location":"tooling_J-HF-1/#tools-on-j-hf-1-node","text":"This compute instance is Sifive's HiFive Unleased board and it has available packages ONLY for RISC-V architecture. Operating System: Ubuntu 20.04.6 (Focal Fossa) Tool Version Installed from Git 2.25.1 apt OpenJDK 11.0.20.1 apt GCC 10.5.0 apt Python3 3.8.10 apt OpenSSL 1.1.1f apt Ruby 2.7.0p0 apt Go 1.14.3 apt rustc 1.41.0 apt Flex 2.6.4 apt Ninja 1.10.0 apt Bison 3.5.1 apt autoconf 2.69 apt gperf 3.1 apt cmake 3.16.3 apt make 4.2.1 apt automake 1.16.1 apt gfortran 9.4.0 apt openssh-server 8.2p1 apt","title":"Tools on J-HF-1 node"},{"location":"tooling_J-QMS-1/","text":"Tools on J-QMS-1 node This is QEMU system compute instance with 64-bit RISC-V Linux and it has all the packages ONLY for RISC-V architecture Operating System: Ubuntu 22.04.4 LTS (Jammy Jellyfish) QEMU Linux Version: 7.2.90 (v9.0.0-rc0-68-g853546f812) Tool Version Installed from pip 22.0.2 apt Git 2.34.1 apt OpenJDK 19.0.1 apt GCC 11.4.0 apt Python3 3.10.12 apt OpenSSL 3.0.2 apt Ruby 3.0.2p107 apt Go 1.18.8 apt rustc 1.75.0 apt Flex 2.6.4 apt Ninja 1.10.1 apt Bison 3.8.2 apt autoconf 2.71 apt gperf 3.1 apt make 4.3 apt cmake 3.22.1 apt","title":"J-QMS-1"},{"location":"tooling_J-QMS-1/#tools-on-j-qms-1-node","text":"This is QEMU system compute instance with 64-bit RISC-V Linux and it has all the packages ONLY for RISC-V architecture Operating System: Ubuntu 22.04.4 LTS (Jammy Jellyfish) QEMU Linux Version: 7.2.90 (v9.0.0-rc0-68-g853546f812) Tool Version Installed from pip 22.0.2 apt Git 2.34.1 apt OpenJDK 19.0.1 apt GCC 11.4.0 apt Python3 3.10.12 apt OpenSSL 3.0.2 apt Ruby 3.0.2p107 apt Go 1.18.8 apt rustc 1.75.0 apt Flex 2.6.4 apt Ninja 1.10.1 apt Bison 3.8.2 apt autoconf 2.71 apt gperf 3.1 apt make 4.3 apt cmake 3.22.1 apt","title":"Tools on J-QMS-1 node"},{"location":"tooling_J-QMU-1J-VM-1/","text":"Tools on J-x86-1 or J-QMU-1 node Tools which are mentioned for x86 architecture are able to run on J-x86-1 . Tools which are mentioned for RISC-V architecture are able to run on J-QMU-1 . The packages which are supported for QEMU User mode can be used by normal commands once they are loaded. Here PACKAGE_NAME is the package which you want to run on QEMU user mode. Operating System: Debian 11 (bullseye) QEMU User Mode Version: Different Versions (see the table below) Tooling available for J-x86-1 The tools available for J-x86-1 is for use on x86 architecture and these tools do not support execution on RISC-V architecture Tool Versions Installed from Host Architecture Environment Modules Support Git 2.3.0.2 source x86 N/A OpenJDK 19.0.1 apt x86 N/A GCC 10.4.0, 12.2.0 apt x86 Yes Python3 3.8.15, 3.9.2 source x86 Yes Go 1.18.8 apt x86 N/A rustc 1.65.0 source x86 N/A Flex 2.6.4 apt x86 N/A Ninja 1.10.1-1 apt x86 N/A Bison 3.7.5 apt x86 N/A autoconf 2.69 apt x86 N/A gperf 2.2.4 apt x86 N/A spike 1.1.1-dev source x86 Yes Verilator 4.038 apt x86 N/A Sail (riscv_sim_RV64, riscv_sim_RV32) 0.5 source x86 Yes cmake 3.18.4 apt x86 N/A make 4.3 apt x86 N/A Tooling available for J-QMU-1 The tools available for J-QMU-1 is for use on RISC-V architecture and these tools do not support execution on x86 architecture Tool Versions Installed from Host Architecture Environment Modules Support Python3 3.8.15 source RISC-V Yes zlib 1.2.13 source RISC-V N/A OpenSSL 1.1.1r source RISC-V Yes Ruby (without IRB) 3.2.0dev source RISC-V Yes rustc 1.65.0 source RISC-V N/A Flex 2.6.4 source RISC-V yes Ninja 1.12.0.git source RISC-V Yes Bison 3.8.2, 2.3 source RISC-V Yes clang 16.0.0 source RISC-V (cross compiler) Yes riscv-pk 1.0.0-91-g573c858 source RISC-V Yes QEMU User mode and RISC-V GNU Cross compilers From now on RISC-V cross-compilers can only be loaded with their respective QEMU User mode on Cloud-V. This is configured so that there is no confusion between toolchain version and qemu user mode being used because both of these will be \"generally\" taken from the latest releases of nightly builds. Loading a certain RISC-V toolchain using environment modules will automatically load the respective qemu usermode version unless otherwise specified. The loading pattern for RISC-V 64-bit GNU Glibc toolchain will be as follows: module load riscv64-gnu-glibc/ And the loading pattern for RISC-V 64-bit GNU Glibc toolchain will be as follows: module load riscv64-gnu-elf/ Following table provides relevant information about version of the toolchain and the respective QEMU User mode version (where the release date is mentioned in pattern MMDDYYYY ). Release date GNU Toolchain version (elf and glibc) QEMU Version 03012024 13.2.0 8.2.1 02022024 13.2.0 8.2.1 02022024 13.2.0 8.1.1 Note: The J-QMU-1 and J-x86-1 are one and the same runner. The purpose of creating two separate executors for same hardware is that J-x86-1 is supposed to be specifically for x86 architecture whereas J-QMU-1 is specifically for the users who want to cross compile source code for riscv64 architecture and then use qemu-usermode to execute them. Nevertheless, the tooling available for J-x86-1 can also be used for J-QMU-1","title":"J-x86-1 or J-QMU-1"},{"location":"tooling_J-QMU-1J-VM-1/#tools-on-j-x86-1-or-j-qmu-1-node","text":"Tools which are mentioned for x86 architecture are able to run on J-x86-1 . Tools which are mentioned for RISC-V architecture are able to run on J-QMU-1 . The packages which are supported for QEMU User mode can be used by normal commands once they are loaded. Here PACKAGE_NAME is the package which you want to run on QEMU user mode. Operating System: Debian 11 (bullseye) QEMU User Mode Version: Different Versions (see the table below)","title":"Tools on J-x86-1 or J-QMU-1 node"},{"location":"tooling_J-QMU-1J-VM-1/#tooling-available-for-j-x86-1","text":"The tools available for J-x86-1 is for use on x86 architecture and these tools do not support execution on RISC-V architecture Tool Versions Installed from Host Architecture Environment Modules Support Git 2.3.0.2 source x86 N/A OpenJDK 19.0.1 apt x86 N/A GCC 10.4.0, 12.2.0 apt x86 Yes Python3 3.8.15, 3.9.2 source x86 Yes Go 1.18.8 apt x86 N/A rustc 1.65.0 source x86 N/A Flex 2.6.4 apt x86 N/A Ninja 1.10.1-1 apt x86 N/A Bison 3.7.5 apt x86 N/A autoconf 2.69 apt x86 N/A gperf 2.2.4 apt x86 N/A spike 1.1.1-dev source x86 Yes Verilator 4.038 apt x86 N/A Sail (riscv_sim_RV64, riscv_sim_RV32) 0.5 source x86 Yes cmake 3.18.4 apt x86 N/A make 4.3 apt x86 N/A","title":"Tooling available for J-x86-1"},{"location":"tooling_J-QMU-1J-VM-1/#tooling-available-for-j-qmu-1","text":"The tools available for J-QMU-1 is for use on RISC-V architecture and these tools do not support execution on x86 architecture Tool Versions Installed from Host Architecture Environment Modules Support Python3 3.8.15 source RISC-V Yes zlib 1.2.13 source RISC-V N/A OpenSSL 1.1.1r source RISC-V Yes Ruby (without IRB) 3.2.0dev source RISC-V Yes rustc 1.65.0 source RISC-V N/A Flex 2.6.4 source RISC-V yes Ninja 1.12.0.git source RISC-V Yes Bison 3.8.2, 2.3 source RISC-V Yes clang 16.0.0 source RISC-V (cross compiler) Yes riscv-pk 1.0.0-91-g573c858 source RISC-V Yes","title":"Tooling available for J-QMU-1"},{"location":"tooling_J-QMU-1J-VM-1/#qemu-user-mode-and-risc-v-gnu-cross-compilers","text":"From now on RISC-V cross-compilers can only be loaded with their respective QEMU User mode on Cloud-V. This is configured so that there is no confusion between toolchain version and qemu user mode being used because both of these will be \"generally\" taken from the latest releases of nightly builds. Loading a certain RISC-V toolchain using environment modules will automatically load the respective qemu usermode version unless otherwise specified. The loading pattern for RISC-V 64-bit GNU Glibc toolchain will be as follows: module load riscv64-gnu-glibc/ And the loading pattern for RISC-V 64-bit GNU Glibc toolchain will be as follows: module load riscv64-gnu-elf/ Following table provides relevant information about version of the toolchain and the respective QEMU User mode version (where the release date is mentioned in pattern MMDDYYYY ). Release date GNU Toolchain version (elf and glibc) QEMU Version 03012024 13.2.0 8.2.1 02022024 13.2.0 8.2.1 02022024 13.2.0 8.1.1 Note: The J-QMU-1 and J-x86-1 are one and the same runner. The purpose of creating two separate executors for same hardware is that J-x86-1 is supposed to be specifically for x86 architecture whereas J-QMU-1 is specifically for the users who want to cross compile source code for riscv64 architecture and then use qemu-usermode to execute them. Nevertheless, the tooling available for J-x86-1 can also be used for J-QMU-1","title":"QEMU User mode and RISC-V GNU Cross compilers"},{"location":"tooling_J-VF1-x/","text":"Tools on J-VF1-1 node This compute instance is Starfive's VisionFive 1 board and it has available packages ONLY for RISC-V architecture. Operating System: Ubuntu 23.04 (Lunar Lobster) Tool Version Installed from Git 2.39.2 apt OpenJDK 21-ea apt GCC 13.1.0 apt Python3 3.11.4 apt OpenSSL 3.0.8 apt Ruby 3.1.2p20 apt Go 1.20.3 apt rustc 1.67.1 apt Flex 2.6.4 apt Ninja 1.11.1 apt Bison 3.8.2 apt autoconf 2.71 apt gperf 3.1 apt cmake 3.25.1 apt make 4.3 apt automake 1.16.5 apt gfortran 13.1.0 apt openssh-server 9.0p1 apt","title":"J-VF1-x"},{"location":"tooling_J-VF1-x/#tools-on-j-vf1-1-node","text":"This compute instance is Starfive's VisionFive 1 board and it has available packages ONLY for RISC-V architecture. Operating System: Ubuntu 23.04 (Lunar Lobster) Tool Version Installed from Git 2.39.2 apt OpenJDK 21-ea apt GCC 13.1.0 apt Python3 3.11.4 apt OpenSSL 3.0.8 apt Ruby 3.1.2p20 apt Go 1.20.3 apt rustc 1.67.1 apt Flex 2.6.4 apt Ninja 1.11.1 apt Bison 3.8.2 apt autoconf 2.71 apt gperf 3.1 apt cmake 3.25.1 apt make 4.3 apt automake 1.16.5 apt gfortran 13.1.0 apt openssh-server 9.0p1 apt","title":"Tools on J-VF1-1 node"},{"location":"tooling_J-VF2-x/","text":"Tools on J-VF2-x node This compute instance is Starfive's VisionFive 2 board and it has available packages ONLY for RISC-V architecture. Operating System: Debian 12 (Bookworm) Tool Version Installed from Git 2.43.0 apt OpenJDK 21.0.2 apt GCC 13.2.0 apt Python3 3.11.7 apt OpenSSL 3.1.5 apt Ruby 3.1.2p20 apt Go 1.22.0 apt rustc 1.70.0 apt Flex 2.6.4 apt Ninja 1.11.1 apt Bison 3.8.2 apt autoconf 2.71 apt gperf 3.1 apt cmake 3.28.3 apt make 4.3 apt automake 1.16.5 apt gfortran 13.2.0 apt openssh-server 9.6p1 apt vim 9.1 apt","title":"J-VF2-x"},{"location":"tooling_J-VF2-x/#tools-on-j-vf2-x-node","text":"This compute instance is Starfive's VisionFive 2 board and it has available packages ONLY for RISC-V architecture. Operating System: Debian 12 (Bookworm) Tool Version Installed from Git 2.43.0 apt OpenJDK 21.0.2 apt GCC 13.2.0 apt Python3 3.11.7 apt OpenSSL 3.1.5 apt Ruby 3.1.2p20 apt Go 1.22.0 apt rustc 1.70.0 apt Flex 2.6.4 apt Ninja 1.11.1 apt Bison 3.8.2 apt autoconf 2.71 apt gperf 3.1 apt cmake 3.28.3 apt make 4.3 apt automake 1.16.5 apt gfortran 13.2.0 apt openssh-server 9.6p1 apt vim 9.1 apt","title":"Tools on J-VF2-x node"},{"location":"Cross_Compiling/Cross_compiling%20python3.8.15/","text":"Cross compiling python3.8.15 for riscv64 This document will include how to build python3.8.15 for riscv64 architecture while using build machine as x86_64. Building Python Get the python source code of python 3.8.15 in form of tarball from this link. Once a tarball is obtained, extract it and use following command in its root folder to configure it. # Here $PREFIX is the directory where the binaries are desired to be installed. ./configure --host=riscv64-unknown-linux-gnu --build=x86_64-linux-gnu --prefix=\"$PREFIX\" --disable-ipv6 ac_cv_file__dev_ptmx=no ac_cv_file__dev_ptc=no After the above command is executed, use following command to start the build. make -j$(nproc) Now to install binaries on the location where PREFIX, use following command. make install This will install binaries for python3.8.15 in the $PREFIX directory and it can be checked using qemu-riscv64 .","title":"Cross compiling python3.8.15 for `riscv64`"},{"location":"Cross_Compiling/Cross_compiling%20python3.8.15/#cross-compiling-python3815-for-riscv64","text":"This document will include how to build python3.8.15 for riscv64 architecture while using build machine as x86_64.","title":"Cross compiling python3.8.15 for riscv64"},{"location":"Cross_Compiling/Cross_compiling%20python3.8.15/#building-python","text":"Get the python source code of python 3.8.15 in form of tarball from this link. Once a tarball is obtained, extract it and use following command in its root folder to configure it. # Here $PREFIX is the directory where the binaries are desired to be installed. ./configure --host=riscv64-unknown-linux-gnu --build=x86_64-linux-gnu --prefix=\"$PREFIX\" --disable-ipv6 ac_cv_file__dev_ptmx=no ac_cv_file__dev_ptc=no After the above command is executed, use following command to start the build. make -j$(nproc) Now to install binaries on the location where PREFIX, use following command. make install This will install binaries for python3.8.15 in the $PREFIX directory and it can be checked using qemu-riscv64 .","title":"Building Python"},{"location":"Cross_Compiling/Cross_compiling_coremark/","text":"Cross-compiling Coremark Coremark is another benchmarking tool. Here coremark will be cross-compiled for riscv64-unknown-linux-gnu and will be run on qemu-riscv64 . The github source code commit at the time of build is eefc986ebd3452d6adde22eafaff3e5c859f29e4 and branch is main . Getting the source code Execute the following command to get the source code of coremark. git clone https://github.com/eembc/coremark.git Tweaking source files for riscv64-unknown-linux-gnu At the time of this documentation, linux is being used for this test. First of all core_portme.mak will be changed. Navigate to linux/ directory in source repository. Open core_portme.mak . Here a single line will be used to include core_portme.mak from posix directory. So, navigate to posix/ directory in source folder Open core_portme.mak in posix/ directory and do the following changes to variables here. Change CC?=cc to CC=riscv64-unknown-linux-gnu-gcc . Scroll down and change EXE=.exe to EXE= (it should be blank). Scroll down and change LD=gcc to LD=riscv64-unknown-linux-gnu-ld . As we are using qemu-riscv64 , so change RUN= to RUN=qemu-riscv64 -L \"$$RISCV_SYSROOT\" Save changes and exit this file. Now open core_portme.h and change #define USE_CLOCK 0 to #define USE_CLOCK 1 and save. Navigate to source directory of repository and execute following command make PORT_DIR=linux/ If everything went right, the output result will be stored in run1.log and run2.log and will be of the form as shown below. 2K validation run parameters for coremark. CoreMark Size : 666 Total ticks : 12368459 Total time (secs): 12.368459 Iterations/Sec : 8893.589735 Iterations : 110000 Compiler version : GCC12.2.0 Compiler flags : -O2 -DPERFORMANCE_RUN=1 -lrt Memory location : Please put data memory location here (e.g. code in flash, data on heap etc) seedcrc : 0x18f2 [0]crclist : 0xe3c1 [0]crcmatrix : 0x0747 [0]crcstate : 0x8d84 [0]crcfinal : 0x0956 Correct operation validated. See README.md for run and reporting rules.","title":"Cross-compiling Coremark"},{"location":"Cross_Compiling/Cross_compiling_coremark/#cross-compiling-coremark","text":"Coremark is another benchmarking tool. Here coremark will be cross-compiled for riscv64-unknown-linux-gnu and will be run on qemu-riscv64 . The github source code commit at the time of build is eefc986ebd3452d6adde22eafaff3e5c859f29e4 and branch is main .","title":"Cross-compiling Coremark"},{"location":"Cross_Compiling/Cross_compiling_coremark/#getting-the-source-code","text":"Execute the following command to get the source code of coremark. git clone https://github.com/eembc/coremark.git","title":"Getting the source code"},{"location":"Cross_Compiling/Cross_compiling_coremark/#tweaking-source-files-for-riscv64-unknown-linux-gnu","text":"At the time of this documentation, linux is being used for this test. First of all core_portme.mak will be changed. Navigate to linux/ directory in source repository. Open core_portme.mak . Here a single line will be used to include core_portme.mak from posix directory. So, navigate to posix/ directory in source folder Open core_portme.mak in posix/ directory and do the following changes to variables here. Change CC?=cc to CC=riscv64-unknown-linux-gnu-gcc . Scroll down and change EXE=.exe to EXE= (it should be blank). Scroll down and change LD=gcc to LD=riscv64-unknown-linux-gnu-ld . As we are using qemu-riscv64 , so change RUN= to RUN=qemu-riscv64 -L \"$$RISCV_SYSROOT\" Save changes and exit this file. Now open core_portme.h and change #define USE_CLOCK 0 to #define USE_CLOCK 1 and save. Navigate to source directory of repository and execute following command make PORT_DIR=linux/ If everything went right, the output result will be stored in run1.log and run2.log and will be of the form as shown below. 2K validation run parameters for coremark. CoreMark Size : 666 Total ticks : 12368459 Total time (secs): 12.368459 Iterations/Sec : 8893.589735 Iterations : 110000 Compiler version : GCC12.2.0 Compiler flags : -O2 -DPERFORMANCE_RUN=1 -lrt Memory location : Please put data memory location here (e.g. code in flash, data on heap etc) seedcrc : 0x18f2 [0]crclist : 0xe3c1 [0]crcmatrix : 0x0747 [0]crcstate : 0x8d84 [0]crcfinal : 0x0956 Correct operation validated. See README.md for run and reporting rules.","title":"Tweaking source files for riscv64-unknown-linux-gnu"},{"location":"Cross_Compiling/Cross_compiling_dhrystone/","text":"Cross-compiling dhrystone Dhrystone is a benchmarking tool. Here dhrystone will be compiled from source and run on qemu-riscv64 . Dhrystone is comparable to VAX 11/780 in a way that VAX 11/780 achieves 1757 dhrystones per second which is also referred to as 1 MIPS of VAX11/780. So number of dhrystones per seconds are obtained and then divided by 1757 to get MIPS. See this link for more details. Cross-compiling for riscv64-unknown-linux-gnu Get the source code of dhrystone using the command below git clone https://github.com/sifive/benchmark-dhrystone.git Navigate to root directory of repository and compile program with riscv64-unknown-linux-gnu-gcc instead of native gcc cd benchmark-dhrystone make CC=riscv64-unknown-linux-gnu-gcc Execute following command to execute dhrystone binary qemu-riscv64 -L $RISCV_SYSROOT ./dhrystone Note: You may want to tweak Makefile and dhry_1.c a little bit to get the correct results.","title":"Cross-compiling `dhrystone`"},{"location":"Cross_Compiling/Cross_compiling_dhrystone/#cross-compiling-dhrystone","text":"Dhrystone is a benchmarking tool. Here dhrystone will be compiled from source and run on qemu-riscv64 . Dhrystone is comparable to VAX 11/780 in a way that VAX 11/780 achieves 1757 dhrystones per second which is also referred to as 1 MIPS of VAX11/780. So number of dhrystones per seconds are obtained and then divided by 1757 to get MIPS. See this link for more details.","title":"Cross-compiling dhrystone"},{"location":"Cross_Compiling/Cross_compiling_dhrystone/#cross-compiling-for-riscv64-unknown-linux-gnu","text":"Get the source code of dhrystone using the command below git clone https://github.com/sifive/benchmark-dhrystone.git Navigate to root directory of repository and compile program with riscv64-unknown-linux-gnu-gcc instead of native gcc cd benchmark-dhrystone make CC=riscv64-unknown-linux-gnu-gcc Execute following command to execute dhrystone binary qemu-riscv64 -L $RISCV_SYSROOT ./dhrystone Note: You may want to tweak Makefile and dhry_1.c a little bit to get the correct results.","title":"Cross-compiling for riscv64-unknown-linux-gnu"},{"location":"Cross_Compiling/Cross_compiling_go/","text":"Cross compiling Go Go currenlty has support for riscv64 architecture. This document will cover how to compile go on x86 for riscv64 architecture. Note: Right now, go can be cross-compiled on x86 but it cannot be executed on x86 with qemu-riscv64 because it needs to execute goroot/pkg/tool/compile and qemu-riscv64 can only execute one binary at a time. Pre Requisites On ubuntu, following pre-requisites should be installed. Snap qemu-riscv64 (linux-user) Go source code is written in go. That means a go toolchain is needed to compile the source code (see link ). As this document cross-compiles the code, first of all install a go language on build machine. Use following command on ubuntu to install a go language compiler. sudo snap install go --classic After this, get the source code of go from following command. git clone https://go.googlesource.com/go goroot Now set the environment variable as follows. export GOROOT_BOOTSTRAP=/snap export GOARCH=riscv64 export GOOS=linux Navigate to goroot/src and execute following command. ./all.bash After this, an executable file will be located in folder goroot/bin/linux_riscv64 .","title":"Cross compiling `Go`"},{"location":"Cross_Compiling/Cross_compiling_go/#cross-compiling-go","text":"Go currenlty has support for riscv64 architecture. This document will cover how to compile go on x86 for riscv64 architecture. Note: Right now, go can be cross-compiled on x86 but it cannot be executed on x86 with qemu-riscv64 because it needs to execute goroot/pkg/tool/compile and qemu-riscv64 can only execute one binary at a time.","title":"Cross compiling Go"},{"location":"Cross_Compiling/Cross_compiling_go/#pre-requisites","text":"On ubuntu, following pre-requisites should be installed. Snap qemu-riscv64 (linux-user) Go source code is written in go. That means a go toolchain is needed to compile the source code (see link ). As this document cross-compiles the code, first of all install a go language on build machine. Use following command on ubuntu to install a go language compiler. sudo snap install go --classic After this, get the source code of go from following command. git clone https://go.googlesource.com/go goroot Now set the environment variable as follows. export GOROOT_BOOTSTRAP=/snap export GOARCH=riscv64 export GOOS=linux Navigate to goroot/src and execute following command. ./all.bash After this, an executable file will be located in folder goroot/bin/linux_riscv64 .","title":"Pre Requisites"},{"location":"Cross_Compiling/Cross_compiling_jdk/","text":"Cross-compiling JDK for riscv64-unknown-linux-gnu JDK is abbreviation of 'Java Development Kit'. It is used for compiling and executing java-based programs and applications. All the information regarding building jdk and relevant dependencies are given at https://github.com/openjdk/jdk/blob/master/doc/building.md Make sure to have riscv64-unknown-linux-gnu toolchain installed on machine. Getting source code The source code of jdk can be obtained using command below git clone https://github.com/openjdk/jdk.git Building the source code for First of all configure the source code using the command below bash configure --host=riscv64-unknown-linux-gnu --build=x86_64-linux-gnu --target=riscv64-unknown-linux-gnu --prefix=/home/ali/custom_installed/RISCV/jdk/967a28c3d85fdde6d5eb48aa0edd8f7597772469 --with-cups=/home/ali/custom_installed/cups --with-fontconfig=/home/ali/custom_installed/fontconfig/e291fda7d42e5d64379555097a066d9c2c4efce3 --x-includes=/usr/include --x-lib=/usr/lib","title":"Cross-compiling JDK for `riscv64-unknown-linux-gnu`"},{"location":"Cross_Compiling/Cross_compiling_jdk/#cross-compiling-jdk-for-riscv64-unknown-linux-gnu","text":"JDK is abbreviation of 'Java Development Kit'. It is used for compiling and executing java-based programs and applications. All the information regarding building jdk and relevant dependencies are given at https://github.com/openjdk/jdk/blob/master/doc/building.md Make sure to have riscv64-unknown-linux-gnu toolchain installed on machine.","title":"Cross-compiling JDK for riscv64-unknown-linux-gnu"},{"location":"Cross_Compiling/Cross_compiling_jdk/#getting-source-code","text":"The source code of jdk can be obtained using command below git clone https://github.com/openjdk/jdk.git","title":"Getting source code"},{"location":"Cross_Compiling/Cross_compiling_jdk/#building-the-source-code-for","text":"First of all configure the source code using the command below bash configure --host=riscv64-unknown-linux-gnu --build=x86_64-linux-gnu --target=riscv64-unknown-linux-gnu --prefix=/home/ali/custom_installed/RISCV/jdk/967a28c3d85fdde6d5eb48aa0edd8f7597772469 --with-cups=/home/ali/custom_installed/cups --with-fontconfig=/home/ali/custom_installed/fontconfig/e291fda7d42e5d64379555097a066d9c2c4efce3 --x-includes=/usr/include --x-lib=/usr/lib","title":"Building the source code for"},{"location":"Cross_Compiling/Cross_compiling_ninja-build/","text":"Cross-compiling ninja-build for RISC-V Ninja is a small build system with a focus on speed. It differs from other build systems in two major respects: it is designed to have its input files generated by a higher-level build system, and it is designed to run builds as fast as possible. This document will cover how to compile ninja to work on 64-bit RISC-V architecture. Getting source code Use following command to get source code of ninja-build and navigate to source directory. git clone git://github.com/ninja-build/ninja.git cd ninja git checkout release Create following cmake file inside the root directory of ninja-build repository. # the name of the target operating system set(CMAKE_SYSTEM_NAME Linux) # which compilers to use for C and C++ set(CMAKE_C_COMPILER riscv64-unknown-linux-gnu-gcc) set(CMAKE_CXX_COMPILER riscv64-unknown-linux-gnu-g++) # where is the target environment located set(CMAKE_FIND_ROOT_PATH /softwares/RISCV/riscv64-unknown-linux-gnu/50c1b734e889e5cbb88bcc7f14975ea9a1d0b936/sysroot ) # adjust the default behavior of the FIND_XXX() commands: # search programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search headers and libraries in the target environment set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)","title":"Cross-compiling ninja-build for RISC-V"},{"location":"Cross_Compiling/Cross_compiling_ninja-build/#cross-compiling-ninja-build-for-risc-v","text":"Ninja is a small build system with a focus on speed. It differs from other build systems in two major respects: it is designed to have its input files generated by a higher-level build system, and it is designed to run builds as fast as possible. This document will cover how to compile ninja to work on 64-bit RISC-V architecture.","title":"Cross-compiling ninja-build for RISC-V"},{"location":"Cross_Compiling/Cross_compiling_ninja-build/#getting-source-code","text":"Use following command to get source code of ninja-build and navigate to source directory. git clone git://github.com/ninja-build/ninja.git cd ninja git checkout release Create following cmake file inside the root directory of ninja-build repository. # the name of the target operating system set(CMAKE_SYSTEM_NAME Linux) # which compilers to use for C and C++ set(CMAKE_C_COMPILER riscv64-unknown-linux-gnu-gcc) set(CMAKE_CXX_COMPILER riscv64-unknown-linux-gnu-g++) # where is the target environment located set(CMAKE_FIND_ROOT_PATH /softwares/RISCV/riscv64-unknown-linux-gnu/50c1b734e889e5cbb88bcc7f14975ea9a1d0b936/sysroot ) # adjust the default behavior of the FIND_XXX() commands: # search programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # search headers and libraries in the target environment set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)","title":"Getting source code"},{"location":"Cross_Compiling/Cross_compiling_openssl/","text":"Cross-compiling openssl What is openssl Openssl is a software library which is used inside many high level languages (e.g. Python, Ruby etc.) and also in linux itself. It is used for security and other cryptography applications. Building openssl v1.0.1 for riscv64 architecture Following are the steps used to build openssl for riscv64 architecture. Get the source code of openssl and navigate inside the cloned repository using the commands below git clone https://github.com/openssl/openssl.git cd openssl Configure openssl for building. In openssl there are some os/compiler choices which one can use to build for his architecture. But in our case there is no support for building with riscv64. As it is written in C language, so it can be compiled whether or not the support is given. Use the following command to generate a Makefile for linux-generic64 ./Configure linux-generic64 --prefix=$PREFIX # Prefix is the directory where you want binaries to be installed at the end After the above command is successfully completed, run the following command to build openssl using riscv64-unknown-linux-gnu-gcc compiler instead of native gcc compiler. make -j$(nproc) CC=riscv64-unknown-linux-gnu-gcc Install the binaries in the specified --prefix using the command below make -j$(nproc) install CC=riscv64-unknown-linux-gnu-gcc The installed binary can be tested on qemu-riscv64 using the command below: qemu-riscv64 -L $RISCV_SYSROOT ./openssl Here $RISCV_SYSROOT is the sysroot/ folder located inside the riscv gnu toolchain installed directory. The above mentioned command will start the openssl console if everything went right. Note: Do not change the directory of openssl or rename it, as it some files inside it are inferred with absolute paths, changing the directory or renaming it will cause other packages to not configure openssl for them when cross-compiling. Building openssl v1.1.1r for riscv64 architecture In openssl v1.1.1r, there is a support for linux64-riscv64 . Following is the procedure for cross-compilation. Checkout the v1.1.1r of openssl by executing following command in the repository directory. git checkout OpenSSL_1_1_1r Execute following command to configure for riscv64 architecture and generate a Makefile . ./Configure linux64-riscv64 --prefix=$PREFIX # Replace $PREFIX with where you want to install binaries Execute following command to cross-compile for riscv64-unknown-linux-gnu . make CROSS_COMPILE=riscv64-unknown-linux-gnu- Then install binaries at $PREFIX with following command. make install Solving post-installation errors On some operating systems, the installed binaries may not run properly and will give following error. ./openssl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory This means that shared libraries cannot be found in the path where the system is looking for them. This can be solved by setting LD_LIBRARY_PATH variable as follows. export LD_LIBRARY_PATH=$PREFIX/lib:$LD_LIBRARY_PATH It will be a good practice to include the above in the bashrc for debian users.","title":"Cross-compiling openssl"},{"location":"Cross_Compiling/Cross_compiling_openssl/#cross-compiling-openssl","text":"","title":"Cross-compiling openssl"},{"location":"Cross_Compiling/Cross_compiling_openssl/#what-is-openssl","text":"Openssl is a software library which is used inside many high level languages (e.g. Python, Ruby etc.) and also in linux itself. It is used for security and other cryptography applications.","title":"What is openssl"},{"location":"Cross_Compiling/Cross_compiling_openssl/#building-openssl-v101-for-riscv64-architecture","text":"Following are the steps used to build openssl for riscv64 architecture. Get the source code of openssl and navigate inside the cloned repository using the commands below git clone https://github.com/openssl/openssl.git cd openssl Configure openssl for building. In openssl there are some os/compiler choices which one can use to build for his architecture. But in our case there is no support for building with riscv64. As it is written in C language, so it can be compiled whether or not the support is given. Use the following command to generate a Makefile for linux-generic64 ./Configure linux-generic64 --prefix=$PREFIX # Prefix is the directory where you want binaries to be installed at the end After the above command is successfully completed, run the following command to build openssl using riscv64-unknown-linux-gnu-gcc compiler instead of native gcc compiler. make -j$(nproc) CC=riscv64-unknown-linux-gnu-gcc Install the binaries in the specified --prefix using the command below make -j$(nproc) install CC=riscv64-unknown-linux-gnu-gcc The installed binary can be tested on qemu-riscv64 using the command below: qemu-riscv64 -L $RISCV_SYSROOT ./openssl Here $RISCV_SYSROOT is the sysroot/ folder located inside the riscv gnu toolchain installed directory. The above mentioned command will start the openssl console if everything went right. Note: Do not change the directory of openssl or rename it, as it some files inside it are inferred with absolute paths, changing the directory or renaming it will cause other packages to not configure openssl for them when cross-compiling.","title":"Building openssl v1.0.1 for riscv64 architecture"},{"location":"Cross_Compiling/Cross_compiling_openssl/#building-openssl-v111r-for-riscv64-architecture","text":"In openssl v1.1.1r, there is a support for linux64-riscv64 . Following is the procedure for cross-compilation. Checkout the v1.1.1r of openssl by executing following command in the repository directory. git checkout OpenSSL_1_1_1r Execute following command to configure for riscv64 architecture and generate a Makefile . ./Configure linux64-riscv64 --prefix=$PREFIX # Replace $PREFIX with where you want to install binaries Execute following command to cross-compile for riscv64-unknown-linux-gnu . make CROSS_COMPILE=riscv64-unknown-linux-gnu- Then install binaries at $PREFIX with following command. make install","title":"Building openssl v1.1.1r for riscv64 architecture"},{"location":"Cross_Compiling/Cross_compiling_openssl/#solving-post-installation-errors","text":"On some operating systems, the installed binaries may not run properly and will give following error. ./openssl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory This means that shared libraries cannot be found in the path where the system is looking for them. This can be solved by setting LD_LIBRARY_PATH variable as follows. export LD_LIBRARY_PATH=$PREFIX/lib:$LD_LIBRARY_PATH It will be a good practice to include the above in the bashrc for debian users.","title":"Solving post-installation errors"},{"location":"Cross_Compiling/Cross_compiling_ruby/","text":"Cross Compilation of Ruby System Specifications Build Architecture: x86_64-linux-gnu Host Architecture: riscv64-unknown-linux-gnu Operating System for Installation Procedure: Ubuntu 20.04 Pre-requisites Pre-requisites for installing ruby from source can be installed using the following command sudo apt-get -y install libc6-dev libssl-dev libmysql++-dev libsqlite3-dev make build-essential libssl-dev libreadline6-dev zlib1g-dev libyaml-dev Other than this, ruby itself is needed for building ruby from source. sudo apt install ruby There is another thing which needs to be taken care of before building ruby from source. If ruby is installed on system itself using apt , then cross compiling ruby will end up in an error as shown in the image below. This error is seen in ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux-gnu] . To tackle this issue, one workaround is to install build ruby for native system, then delete ruby which was installed through apt . This procedure will be added in the Build section. Getting source code Source code of ruby can be obtained from github repository using the command below: git clone https://github.com/ruby/ruby.git Build Installing ruby for native architecture Before cross-compiling, one must install ruby from source on the native machine which will solve the error described in Pre-requisites section above. ( THIS STEP IS STRONGLY RECOMMENDED ! )In the source directory, create a folder with any name in which Makefile will be generated otherwise there will be a lot of files made in the source directory (possibly create copy of repo directory). In the source directory of ruby run following command to generate configure file. ./autogen.sh After this, run the following configure command to generate Makefile . ../configure --prefix=$PREFIX #$PREFIX is where you want to install binary files at the end, so replace it. After the above command is completed, run following command to start the build make -j$(nproc) #-j$(nproc) uses parallelism for make After the above command is complete, run following command to install the binaries on the specified path mentioned in --prefix above make install Now ruby should be available in the $PREFIX path (also in the .bashrc ). Add $PREFIX path to $PATH variable and uninstall the the ruby installed using apt otherwise, the source will keep using that one for building and the error will persist. sudo apt purge ruby Cross-Compiling Ruby for riscv64-unknown-linux-gnu After the ruby installed using apt is uninstalled from the system, clean the working directory with following command. make clean After cleaning the working directory, generate the Makefile again for cross-compiling ruby for riscv64-unknown-linux-gnu target and host using the command below ../../configure --prefix=$PREFIX --build=x86_64-linux-gnu --host=riscv64-unknown-linux-gnu --target=riscv64-unknown-linux-gnu After the above command is successful, start build with following command make -j(nproc) Install the binaries in path mentioned with --prefix above with following command make install After this process, ruby will be installed inside $PREFIX/ directory. Note: Currently, this process (as checked on version 3.1.2) installs ruby without extensions shown in the following image","title":"Cross Compilation of Ruby"},{"location":"Cross_Compiling/Cross_compiling_ruby/#cross-compilation-of-ruby","text":"","title":"Cross Compilation of Ruby"},{"location":"Cross_Compiling/Cross_compiling_ruby/#system-specifications","text":"Build Architecture: x86_64-linux-gnu Host Architecture: riscv64-unknown-linux-gnu Operating System for Installation Procedure: Ubuntu 20.04","title":"System Specifications"},{"location":"Cross_Compiling/Cross_compiling_ruby/#pre-requisites","text":"Pre-requisites for installing ruby from source can be installed using the following command sudo apt-get -y install libc6-dev libssl-dev libmysql++-dev libsqlite3-dev make build-essential libssl-dev libreadline6-dev zlib1g-dev libyaml-dev Other than this, ruby itself is needed for building ruby from source. sudo apt install ruby There is another thing which needs to be taken care of before building ruby from source. If ruby is installed on system itself using apt , then cross compiling ruby will end up in an error as shown in the image below. This error is seen in ruby 2.7.0p0 (2019-12-25 revision 647ee6f091) [x86_64-linux-gnu] . To tackle this issue, one workaround is to install build ruby for native system, then delete ruby which was installed through apt . This procedure will be added in the Build section.","title":"Pre-requisites"},{"location":"Cross_Compiling/Cross_compiling_ruby/#getting-source-code","text":"Source code of ruby can be obtained from github repository using the command below: git clone https://github.com/ruby/ruby.git","title":"Getting source code"},{"location":"Cross_Compiling/Cross_compiling_ruby/#build","text":"","title":"Build"},{"location":"Cross_Compiling/Cross_compiling_ruby/#installing-ruby-for-native-architecture","text":"Before cross-compiling, one must install ruby from source on the native machine which will solve the error described in Pre-requisites section above. ( THIS STEP IS STRONGLY RECOMMENDED ! )In the source directory, create a folder with any name in which Makefile will be generated otherwise there will be a lot of files made in the source directory (possibly create copy of repo directory). In the source directory of ruby run following command to generate configure file. ./autogen.sh After this, run the following configure command to generate Makefile . ../configure --prefix=$PREFIX #$PREFIX is where you want to install binary files at the end, so replace it. After the above command is completed, run following command to start the build make -j$(nproc) #-j$(nproc) uses parallelism for make After the above command is complete, run following command to install the binaries on the specified path mentioned in --prefix above make install Now ruby should be available in the $PREFIX path (also in the .bashrc ). Add $PREFIX path to $PATH variable and uninstall the the ruby installed using apt otherwise, the source will keep using that one for building and the error will persist. sudo apt purge ruby","title":"Installing ruby for native architecture"},{"location":"Cross_Compiling/Cross_compiling_ruby/#cross-compiling-ruby-for-riscv64-unknown-linux-gnu","text":"After the ruby installed using apt is uninstalled from the system, clean the working directory with following command. make clean After cleaning the working directory, generate the Makefile again for cross-compiling ruby for riscv64-unknown-linux-gnu target and host using the command below ../../configure --prefix=$PREFIX --build=x86_64-linux-gnu --host=riscv64-unknown-linux-gnu --target=riscv64-unknown-linux-gnu After the above command is successful, start build with following command make -j(nproc) Install the binaries in path mentioned with --prefix above with following command make install After this process, ruby will be installed inside $PREFIX/ directory. Note: Currently, this process (as checked on version 3.1.2) installs ruby without extensions shown in the following image","title":"Cross-Compiling Ruby for riscv64-unknown-linux-gnu"},{"location":"Cross_Compiling/Cross_compiling_rust/","text":"Cross-compiling rust Rust is a programming language just like C but it focuses on safety of programs. This document describes how one can build rust for x86_64 and then add support to compile code for riscv64 architecture. The executable for RISC-V architecture will be able to run on qemu-riscv64 . Note: Make sure riscv64-unknown-linux-gnu toolchain is installed on the machine. Getting source code Here the code will be taken from rustup GitHub repository. This is because instead of installing cargo , rustup and rustc , just compiling rustup will compile them along with itself. Get the source code using the command below: git clone https://github.com/rust-lang/rustup.git Before starting installation process, if you want to install rust in a specific location, then set CARGO_HOME and RUSTUP_HOME variable in the directory where you want to install rustup. After that, considering you are in the repository directory, start the installation process using the command below: sh rustup-init.sh -y After execution above command, follow the prompts as desired and complete the installation process. Now add riscv64 library support in rust using the command below: rustup target add riscv64gc-unknown-linux-gnu Once this is complete, go to the desired location where a new project is to be created and use following command to create a project's directory structure. cargo new project_name # Use a meaningful project name A directory with name project_name will be created as soon as the above command is executed successfully. This project will contain a main.rs which initially contains a Hello World program. Navigate to the project_name directory and create a folder with name .cargo , this will include a config.toml file inside it, which will tell it cargo during build that what is the target for which the compilation is to be done. The contents of the project_name/.cargo/config.toml will be as follows: [build] target = \"riscv64gc-unknown-linux-gnu\" [target.riscv64gc-unknown-linux-gnu] linker = \"riscv64-unknown-linux-gnu-gcc\" Now the project will be ready to build. Get back to the project_name/ directory and use following command to build the main.rs file: cargo build The output of the above command should as follows: Compiling myproject v0.1.0 (project_name) Finished dev [unoptimized + debuginfo] target(s) in 0.27s After the above command, the executable with the name project_name will be available at following location: project_name/target/riscv64gc-unknown-linux-gnu/debug Now the produced executable can be executed using qemu usermode. Use the following command to execute binary: qemu-riscv64 -L $RISCV_SYSROOT ./project_name","title":"Cross-compiling rust"},{"location":"Cross_Compiling/Cross_compiling_rust/#cross-compiling-rust","text":"Rust is a programming language just like C but it focuses on safety of programs. This document describes how one can build rust for x86_64 and then add support to compile code for riscv64 architecture. The executable for RISC-V architecture will be able to run on qemu-riscv64 . Note: Make sure riscv64-unknown-linux-gnu toolchain is installed on the machine.","title":"Cross-compiling rust"},{"location":"Cross_Compiling/Cross_compiling_rust/#getting-source-code","text":"Here the code will be taken from rustup GitHub repository. This is because instead of installing cargo , rustup and rustc , just compiling rustup will compile them along with itself. Get the source code using the command below: git clone https://github.com/rust-lang/rustup.git Before starting installation process, if you want to install rust in a specific location, then set CARGO_HOME and RUSTUP_HOME variable in the directory where you want to install rustup. After that, considering you are in the repository directory, start the installation process using the command below: sh rustup-init.sh -y After execution above command, follow the prompts as desired and complete the installation process. Now add riscv64 library support in rust using the command below: rustup target add riscv64gc-unknown-linux-gnu Once this is complete, go to the desired location where a new project is to be created and use following command to create a project's directory structure. cargo new project_name # Use a meaningful project name A directory with name project_name will be created as soon as the above command is executed successfully. This project will contain a main.rs which initially contains a Hello World program. Navigate to the project_name directory and create a folder with name .cargo , this will include a config.toml file inside it, which will tell it cargo during build that what is the target for which the compilation is to be done. The contents of the project_name/.cargo/config.toml will be as follows: [build] target = \"riscv64gc-unknown-linux-gnu\" [target.riscv64gc-unknown-linux-gnu] linker = \"riscv64-unknown-linux-gnu-gcc\" Now the project will be ready to build. Get back to the project_name/ directory and use following command to build the main.rs file: cargo build The output of the above command should as follows: Compiling myproject v0.1.0 (project_name) Finished dev [unoptimized + debuginfo] target(s) in 0.27s After the above command, the executable with the name project_name will be available at following location: project_name/target/riscv64gc-unknown-linux-gnu/debug Now the produced executable can be executed using qemu usermode. Use the following command to execute binary: qemu-riscv64 -L $RISCV_SYSROOT ./project_name","title":"Getting source code"},{"location":"Cross_Compiling/Overview/","text":"Cross Compilation Need of Cross Compilation Lets say you have a computer A having processor with architecture a and another computer B having processor with architecture b . Assume computer A has all the necessary tools and softwares whereas computer B does not have any software, tools, compilers and also the dependencies needed to install these tools and softwares. In this scenario, you cannot download the software setups (say tarballs) directly on computer B and have them installed/compiled because they will not be able to get compiled by computer B and will be completely useless. Basic concept The basic workflow in such a condition will be as follows: Install a compiler on computer A such that it runs on computer A and compiles code for architecture a . Using the above installed compiler, install a compiler on computer A such that it runs on computer A but compiles code for architecture b . Such a compiler is called cross compiler. One example of such a cross-compiler is RISC-V GNU TOOLCHAIN . Using the above compiled cross compiler, compile all the programs and also the compiler itself for architecture b . Port all the compiled binaries to the computer B . Such a process is beneficial if you have created a custom architecture and there is no support available for it. Throughout this documentation, the cross compiler used will be RISCV GNU Toolchain mentioned with riscv64-unknown-linux-gcc running on x86_64 and compiling code for riscv64 architecture whereas the native compiler will be gcc running on x86_64 and compiling code for x86_64 unless otherwise specified.","title":"Cross Compilation"},{"location":"Cross_Compiling/Overview/#cross-compilation","text":"","title":"Cross Compilation"},{"location":"Cross_Compiling/Overview/#need-of-cross-compilation","text":"Lets say you have a computer A having processor with architecture a and another computer B having processor with architecture b . Assume computer A has all the necessary tools and softwares whereas computer B does not have any software, tools, compilers and also the dependencies needed to install these tools and softwares. In this scenario, you cannot download the software setups (say tarballs) directly on computer B and have them installed/compiled because they will not be able to get compiled by computer B and will be completely useless.","title":"Need of Cross Compilation"},{"location":"Cross_Compiling/Overview/#basic-concept","text":"The basic workflow in such a condition will be as follows: Install a compiler on computer A such that it runs on computer A and compiles code for architecture a . Using the above installed compiler, install a compiler on computer A such that it runs on computer A but compiles code for architecture b . Such a compiler is called cross compiler. One example of such a cross-compiler is RISC-V GNU TOOLCHAIN . Using the above compiled cross compiler, compile all the programs and also the compiler itself for architecture b . Port all the compiled binaries to the computer B . Such a process is beneficial if you have created a custom architecture and there is no support available for it. Throughout this documentation, the cross compiler used will be RISCV GNU Toolchain mentioned with riscv64-unknown-linux-gcc running on x86_64 and compiling code for riscv64 architecture whereas the native compiler will be gcc running on x86_64 and compiling code for x86_64 unless otherwise specified.","title":"Basic concept"},{"location":"Usage_Monitoring/Integrating_prometheus_grafana/","text":"Integrating Prometheus with Grafana Before starting to integrate Prometheus with Grafana make sure they are set up properly. See this document for setting up Prometheus and Grafana as standalone tools. Configuration in Prometheus Make sure all the node_exporter are running properly and the compute instances are discoverable by prometheus. Use following command for checking if the instances are accessible: telnet COMPUTE_INSTANCE_IP COMPUTE_INSTANCE_PORT If you get following response, then it means there is something wrong with firewall of compute instances as they are not accessible. Name or service not known Configuration in Grafana Enter the grafana IP in browser and login with credentials. Use following steps to integrate Grafana with Prometheus and creating dashbaords in Grafana Go to Grafana settings Go to Data sources tab Click on Add data source In HTTP section, add IP of machine on which Prometheus is running along with the port on which Prometheus is hosted (it is recommended to host Prometheus on the machine where Grafana is hosted, in that case, Prometheus will be accessed using LAN IP). In Type and version section, select Prometheus from drop down menu and choose a version of Prometheus in the next field. Click on Save and test If everything goes right, then it will say Data source is working . Creating a dashboard in Grafana For creating a dashboard, click on Dashboards Click on New and then New Dashboard Then add a panel inside the dashbaord If you know the mathemtical expressions (which are easier and more verbose) then select Code while creating the panels instead of Builder . Note: Be sure to save the dashbaord because otherwise, it will not make changes on its own and dashboard will be lost.","title":"Integrating Prometheus with Grafana"},{"location":"Usage_Monitoring/Integrating_prometheus_grafana/#integrating-prometheus-with-grafana","text":"Before starting to integrate Prometheus with Grafana make sure they are set up properly. See this document for setting up Prometheus and Grafana as standalone tools.","title":"Integrating Prometheus with Grafana"},{"location":"Usage_Monitoring/Integrating_prometheus_grafana/#configuration-in-prometheus","text":"Make sure all the node_exporter are running properly and the compute instances are discoverable by prometheus. Use following command for checking if the instances are accessible: telnet COMPUTE_INSTANCE_IP COMPUTE_INSTANCE_PORT If you get following response, then it means there is something wrong with firewall of compute instances as they are not accessible. Name or service not known","title":"Configuration in Prometheus"},{"location":"Usage_Monitoring/Integrating_prometheus_grafana/#configuration-in-grafana","text":"Enter the grafana IP in browser and login with credentials. Use following steps to integrate Grafana with Prometheus and creating dashbaords in Grafana Go to Grafana settings Go to Data sources tab Click on Add data source In HTTP section, add IP of machine on which Prometheus is running along with the port on which Prometheus is hosted (it is recommended to host Prometheus on the machine where Grafana is hosted, in that case, Prometheus will be accessed using LAN IP). In Type and version section, select Prometheus from drop down menu and choose a version of Prometheus in the next field. Click on Save and test If everything goes right, then it will say Data source is working .","title":"Configuration in Grafana"},{"location":"Usage_Monitoring/Integrating_prometheus_grafana/#creating-a-dashboard-in-grafana","text":"For creating a dashboard, click on Dashboards Click on New and then New Dashboard Then add a panel inside the dashbaord If you know the mathemtical expressions (which are easier and more verbose) then select Code while creating the panels instead of Builder . Note: Be sure to save the dashbaord because otherwise, it will not make changes on its own and dashboard will be lost.","title":"Creating a dashboard in Grafana"},{"location":"Usage_Monitoring/Prometheus_Grafana/","text":"Setting up Promtheus and Grafana What are Prometheus and Grafana Prometheus is a tool for monitoring usage of memory, CPU etc. It takes queries as mathematical expressions (like SQL) and returns the interactive graphical usage stats. It collects data using node_exporter , which is used to get raw data from the compute instances Grafana is used for creating dashboards in which there can be different panels containing the graphical statistics from Prometheus. Grafana dashboards are more interactive and user-friendly than Prometheus. Setting up Node Exporters Node exporters are needed for prometheus to get data from the compute instances. Download pre-compiled tarball of node_exporters from this link and place the tarballs on compute instances. Once node_exporter tarball is downloaded, extract it using following command: tar -xvf node_exporter-x.x.x.linux-amd64.tar.gz Run node_exporter on compute instances using command below (which will run node_exporter on port 9100 by default): ./node_exporter Follow this procedure on every compute instance which is desired to be monitored using Prometheus. Note: Make sure that compute instances can be accessed in the machine in which prometheus is installed. Configuring Prometheus Use this link to get pre-compiled tarball of Prometheus. Once Prometheus is downloaded, extract it using following command: tar -xvf prometheus-x.xx.x.linux-amd.tar.gz Now either configure prometheus.yml file or create another yml file which will include the addresses of node_exporters. Following is an example template for yml file: global: scrape_interval: 15s scrape_configs: - job_name: node static_configs: - targets: ['node_exporter_ip1:node_exporter_port1'] - targets: ['node_exporter_ip2:node_exporter_port2'] Running Prometheus Once prometheus is configured properly, use following command to run prometheus. ./prometheus Note: By default Prometheus looks for prometheus.yml , if you want to use some other file for configuration, you will need to specify explicitly with --config.file option. Running Grafana Once Prometheus is up and running, Grafana can be used to create dashboards with graphical interface in various panels inside dashboards. Use this to get pre-compiled tarball of Grafana After Grafana is ready to be run, use following command to run Grafana: ./grafana-server #By default it will run on port 3000 The default username and password of Grafana will be admin . Once Grafana is installed, a dashboard can be created to with multiple panels which will show data from Prometheus. Reference links https://grafana.com/docs/grafana/latest/getting-started/get-started-grafana-prometheus/","title":"Setting up Promtheus and Grafana"},{"location":"Usage_Monitoring/Prometheus_Grafana/#setting-up-promtheus-and-grafana","text":"","title":"Setting up Promtheus and Grafana"},{"location":"Usage_Monitoring/Prometheus_Grafana/#what-are-prometheus-and-grafana","text":"Prometheus is a tool for monitoring usage of memory, CPU etc. It takes queries as mathematical expressions (like SQL) and returns the interactive graphical usage stats. It collects data using node_exporter , which is used to get raw data from the compute instances Grafana is used for creating dashboards in which there can be different panels containing the graphical statistics from Prometheus. Grafana dashboards are more interactive and user-friendly than Prometheus.","title":"What are Prometheus and Grafana"},{"location":"Usage_Monitoring/Prometheus_Grafana/#setting-up-node-exporters","text":"Node exporters are needed for prometheus to get data from the compute instances. Download pre-compiled tarball of node_exporters from this link and place the tarballs on compute instances. Once node_exporter tarball is downloaded, extract it using following command: tar -xvf node_exporter-x.x.x.linux-amd64.tar.gz Run node_exporter on compute instances using command below (which will run node_exporter on port 9100 by default): ./node_exporter Follow this procedure on every compute instance which is desired to be monitored using Prometheus. Note: Make sure that compute instances can be accessed in the machine in which prometheus is installed.","title":"Setting up Node Exporters"},{"location":"Usage_Monitoring/Prometheus_Grafana/#configuring-prometheus","text":"Use this link to get pre-compiled tarball of Prometheus. Once Prometheus is downloaded, extract it using following command: tar -xvf prometheus-x.xx.x.linux-amd.tar.gz Now either configure prometheus.yml file or create another yml file which will include the addresses of node_exporters. Following is an example template for yml file: global: scrape_interval: 15s scrape_configs: - job_name: node static_configs: - targets: ['node_exporter_ip1:node_exporter_port1'] - targets: ['node_exporter_ip2:node_exporter_port2']","title":"Configuring Prometheus"},{"location":"Usage_Monitoring/Prometheus_Grafana/#running-prometheus","text":"Once prometheus is configured properly, use following command to run prometheus. ./prometheus Note: By default Prometheus looks for prometheus.yml , if you want to use some other file for configuration, you will need to specify explicitly with --config.file option.","title":"Running Prometheus"},{"location":"Usage_Monitoring/Prometheus_Grafana/#running-grafana","text":"Once Prometheus is up and running, Grafana can be used to create dashboards with graphical interface in various panels inside dashboards. Use this to get pre-compiled tarball of Grafana After Grafana is ready to be run, use following command to run Grafana: ./grafana-server #By default it will run on port 3000 The default username and password of Grafana will be admin . Once Grafana is installed, a dashboard can be created to with multiple panels which will show data from Prometheus.","title":"Running Grafana"},{"location":"Usage_Monitoring/Prometheus_Grafana/#reference-links","text":"https://grafana.com/docs/grafana/latest/getting-started/get-started-grafana-prometheus/","title":"Reference links"},{"location":"jenkins_github_integration/Github_PR_webhook_integration/","text":"GitHub Pull Request hook integration with Jenkins Reference Link: https://plugins.jenkins.io/ghprb/ General Guidline If facing an issue, it is better to launch the Jenkins from running the .war file (which is obtained by building the Jenkins github repository) in terminal (which is mostly bash in case of linux) and observing the terminal's output. For example if a webhook is not created, the GUI may not show anything but the terminal will most probably print a message showing the reason for this behavior. GitHub Pull Request Builder Plugin In version control, it is better to check the changes and run tests before the changes are merged into main branch. Sometimes those changes can be enormous to check. So it becomes difficult for requested reviewer of the pull request to check all the changes and run tests on them manually. For that purpose, it is better to automate the process so that whenever a pull request is generated, all the tests are triggered and based on the results, the reviewer decides whether or not to merge the branch with main. This can be achieved using Jenkins' Github Pull Request Builder plugin. Specifications at the time of documentation Operating System: Linux Distribution: Ubuntu Release: Focal (also known as 20.04) Jenkins version: 2.371 (can be seen in config.xml) Github Webhook Builder version: 1.42.2 Pre-Requisites Jenkins. Git Plugin GitHub Plugin Github Pull Request Builder Plugin Github account and repository with permission to generate a pull request to merge the branch. Setting up Jenkins configuration Install the above mentioned plugins from Dashboard > Manage Jenkins > Manage Plugins > Available Plugins . Go to Dashboard > Manage Jenkins > Configure System . Scroll down to Github Pull Request Builder . Leave GitHub Server API URL and Jenkins URL override as it is. In Credentials , click on add and select Jenkins from drop down. Select Kind as Secret text . In Secret , add GitHub Personal authentication token which can be acquired from GitHub account settings. Add some safe description to remind what these credentials are about otherwise jenkins use a lot of credentials and it gets difficult to keep account of them. Leave ID empty. Click on Add . Now select the added credentials from the drop down menu of Credentials . Click on Test Credentials... . Check Test basic connection to GitHub . Click on Connect to API . This will show the message Connected to as . Other settings can be left empty. Click on save. Setting up Jenkins job In this documentation, Pipeline job will be used, but any job is expected to work fine with these settings. For this documentation it is considered that the jenkinsfile for building the pipeline is present in the repository which is to be built. Go to Dashboard and click New Item . Enter a Job name (here it will be github_PR_webhook ). Click OK . It will navigate to the job's configuration page. Add a Description of choice. Scroll down and check GitHub project . Add the URL of GitHub repository. Here the URL of the repository should be added without .git extention. This is important that the person who is creating pull request should be either in admin list or whitelist because otherwise, the webhook will not be created. Scroll down to Build Triggers section. Check GitHub Pull Request Builder . This will open further configurations for this option. Leave GitHub API credentials . Add a GitHub admin's username in the Admin list . This is important becaue otherwise, the checks will not run on generating a pull request. Check Use github hooks for build triggering . Click on Advanced and in Whitelist Target Branches add the branch name for which, when a pull request is generated, the job is supposed to be trigger (here it is main ). Scroll down to Pipeline section. In Definition , select Pipeline script from SCM . Select SCM as Git from drop down. Enter the Repository URL from GitHub. Enter Credentials with access to this repository (This is optional if the repository is public). Under Advanced , enter Refspec as +refs/pull/*:refs/remotes/origin/pr/* [^note]. If the tests are to be run on actual commit in the pull request then, under Branches to build section, in Branch Specifier , enter ${ghprbActualCommit} [^note]. Leave other settings as it is. In Script Path , add the path and name of the jenkinsfile which is present in GitHub repository. Uncheck Lightweight checkout [^note1] Click Apply and then Save . After saving the job, a webhook should be created automatically in GitHub if the credentials provided in the settings are correct. Verifying if the procedure In the GitHub repository, add another branch aside from main . For this, expand main and click on View all branches . Click on New Branch , and insert a name. After a new branch is created, select new branch instead of main in repository page. Add some changings to either of the file (even adding a space is enough). Commit Changes. Create a Pull request. Now after checking the merge conflicts, the checks will run their results will be shown with pull request (as can be seen in the image below). NOTE: The Jenkinfile will run present in the pull request and not in the main branch. Clicking on the Details navigates the user to the Jenkins Job result page where the console output and each stage can be seen. [^note]: This point is taken from the jenkins GitHub Pull Request Builder plugin documentation at https://plugins.jenkins.io/ghprb/ [^note1]: This is an issue mentioned in the documentation of Github Pull Request Builder plugin at https://plugins.jenkins.io/ghprb/ .","title":"GitHub Pull Request hook integration with Jenkins"},{"location":"jenkins_github_integration/Github_PR_webhook_integration/#github-pull-request-hook-integration-with-jenkins","text":"Reference Link: https://plugins.jenkins.io/ghprb/","title":"GitHub Pull Request hook integration with Jenkins"},{"location":"jenkins_github_integration/Github_PR_webhook_integration/#general-guidline","text":"If facing an issue, it is better to launch the Jenkins from running the .war file (which is obtained by building the Jenkins github repository) in terminal (which is mostly bash in case of linux) and observing the terminal's output. For example if a webhook is not created, the GUI may not show anything but the terminal will most probably print a message showing the reason for this behavior.","title":"General Guidline"},{"location":"jenkins_github_integration/Github_PR_webhook_integration/#github-pull-request-builder-plugin","text":"In version control, it is better to check the changes and run tests before the changes are merged into main branch. Sometimes those changes can be enormous to check. So it becomes difficult for requested reviewer of the pull request to check all the changes and run tests on them manually. For that purpose, it is better to automate the process so that whenever a pull request is generated, all the tests are triggered and based on the results, the reviewer decides whether or not to merge the branch with main. This can be achieved using Jenkins' Github Pull Request Builder plugin.","title":"GitHub Pull Request Builder Plugin"},{"location":"jenkins_github_integration/Github_PR_webhook_integration/#specifications-at-the-time-of-documentation","text":"Operating System: Linux Distribution: Ubuntu Release: Focal (also known as 20.04) Jenkins version: 2.371 (can be seen in config.xml) Github Webhook Builder version: 1.42.2","title":"Specifications at the time of documentation"},{"location":"jenkins_github_integration/Github_PR_webhook_integration/#pre-requisites","text":"Jenkins. Git Plugin GitHub Plugin Github Pull Request Builder Plugin Github account and repository with permission to generate a pull request to merge the branch.","title":"Pre-Requisites"},{"location":"jenkins_github_integration/Github_PR_webhook_integration/#setting-up-jenkins-configuration","text":"Install the above mentioned plugins from Dashboard > Manage Jenkins > Manage Plugins > Available Plugins . Go to Dashboard > Manage Jenkins > Configure System . Scroll down to Github Pull Request Builder . Leave GitHub Server API URL and Jenkins URL override as it is. In Credentials , click on add and select Jenkins from drop down. Select Kind as Secret text . In Secret , add GitHub Personal authentication token which can be acquired from GitHub account settings. Add some safe description to remind what these credentials are about otherwise jenkins use a lot of credentials and it gets difficult to keep account of them. Leave ID empty. Click on Add . Now select the added credentials from the drop down menu of Credentials . Click on Test Credentials... . Check Test basic connection to GitHub . Click on Connect to API . This will show the message Connected to as . Other settings can be left empty. Click on save.","title":"Setting up Jenkins configuration"},{"location":"jenkins_github_integration/Github_PR_webhook_integration/#setting-up-jenkins-job","text":"In this documentation, Pipeline job will be used, but any job is expected to work fine with these settings. For this documentation it is considered that the jenkinsfile for building the pipeline is present in the repository which is to be built. Go to Dashboard and click New Item . Enter a Job name (here it will be github_PR_webhook ). Click OK . It will navigate to the job's configuration page. Add a Description of choice. Scroll down and check GitHub project . Add the URL of GitHub repository. Here the URL of the repository should be added without .git extention. This is important that the person who is creating pull request should be either in admin list or whitelist because otherwise, the webhook will not be created. Scroll down to Build Triggers section. Check GitHub Pull Request Builder . This will open further configurations for this option. Leave GitHub API credentials . Add a GitHub admin's username in the Admin list . This is important becaue otherwise, the checks will not run on generating a pull request. Check Use github hooks for build triggering . Click on Advanced and in Whitelist Target Branches add the branch name for which, when a pull request is generated, the job is supposed to be trigger (here it is main ). Scroll down to Pipeline section. In Definition , select Pipeline script from SCM . Select SCM as Git from drop down. Enter the Repository URL from GitHub. Enter Credentials with access to this repository (This is optional if the repository is public). Under Advanced , enter Refspec as +refs/pull/*:refs/remotes/origin/pr/* [^note]. If the tests are to be run on actual commit in the pull request then, under Branches to build section, in Branch Specifier , enter ${ghprbActualCommit} [^note]. Leave other settings as it is. In Script Path , add the path and name of the jenkinsfile which is present in GitHub repository. Uncheck Lightweight checkout [^note1] Click Apply and then Save . After saving the job, a webhook should be created automatically in GitHub if the credentials provided in the settings are correct.","title":"Setting up Jenkins job"},{"location":"jenkins_github_integration/Github_PR_webhook_integration/#verifying-if-the-procedure","text":"In the GitHub repository, add another branch aside from main . For this, expand main and click on View all branches . Click on New Branch , and insert a name. After a new branch is created, select new branch instead of main in repository page. Add some changings to either of the file (even adding a space is enough). Commit Changes. Create a Pull request. Now after checking the merge conflicts, the checks will run their results will be shown with pull request (as can be seen in the image below). NOTE: The Jenkinfile will run present in the pull request and not in the main branch. Clicking on the Details navigates the user to the Jenkins Job result page where the console output and each stage can be seen. [^note]: This point is taken from the jenkins GitHub Pull Request Builder plugin documentation at https://plugins.jenkins.io/ghprb/ [^note1]: This is an issue mentioned in the documentation of Github Pull Request Builder plugin at https://plugins.jenkins.io/ghprb/ .","title":"Verifying if the procedure"},{"location":"jenkins_github_integration/Github_push_webhook/","text":"Github 'Push' webhook integration with Jenkins Purpose of using github webhook integration with jenkins Most of the time, after a push on the upstream repository, one may want to check the result of all the checks on the repository defined by CI/CD pipeline. This tells whether there is some issue with push and whether or not the defined checks/tests have passed. This can be achieved using github push webhook integration with jenkins. Jenkins version and operating system specifications The version of Jenkins and operating system specifications at the time of writing this documentation are mentioned below: Jenkins version: 2.370 Operating System: Linux Distribution: Ubuntu Release: Focal (also called 20.04) Pre-requisites Jenkins ngrok (only if a public IP is not available) Setting up the ngrok The localhost cannot be used for github webhook integration as it cannot be detected by online webservers. For this reason, a public ip must be used. For the sake of this documentation, ngrok is being used, which maps localhost to some public ip which can then be accessed publicly on the internet. Following steps can be used for setting up ngrok on ubuntu: Install ngrok. sudo apt install ngrok For using html content, a sign up is required on ngrok. So sign up on ngrok. Execute the following command to run ngrok which will provide a public ip mapped to localhost. ngrok http This will setup ngrok and provide a public ip for working online. Setting up Jenkins for github webhook Pre-requisites Following plugins should be installed in jenkins: Git Plugin GitHub API Plugin GitHub Plugin Jenkins Configuration in Settings Go to Manage Jenkins > Configure System and scroll down to GitHub section. Click on Add GitHub Server Add a name for the Github server. Leave API URL as is. In Credentials, click on Add . Jenkins will appear in drop down, click on it. Select Kind as Secret text Scroll down to the Secret and here, put down the github personal authentication token (PAT) which can be acquired from github account. Other options can be left unattended. Click on Add . Now the credentials should be added. In the Credentials drop down, select Secret text . Check Manage hooks . Now the connection can be established and can be checked by clicking the Test Connection . Click Save . Jenkins job setup for Github Webhook Create a new jenkins freestyle job and proceed with following settings on the configurations along with desired settings. Check GitHub project in General section and provide GitHub repository URL. In Source Code Management section, select Git . Give Repository URL In Credentials (if the credentials are not created already), click on Add , click on Jenkins from the drop down. Select Kind as Username with password . In Username , enter github username. In Password , enter github personal authentication token (PAT) which can be acquired from github account. Other fields can be left unattended. Click on Add From Credentials drop down, select your added credentials. In Branches to build section, in Branch Specifier field, enter the name of branch of github repository which needs to be built. In Build Triggers section, check GitHub hook trigger for GITScm polling . (Following step is for checking the commit status according to the Jenkins job status, means if Jenkins job fails, commit status is also Failure ) Scroll down to the bottom and Add post-build action . From drop down, select Set GitHub commit status . Leave other settings as is and click on Advanced . Check Handle errors Under drop down Result on failure , select FAILURE Click on Apply and Save By this point, Jenkins is setup for github webhooks. Setting up github repository webhook For the sake of this documentation, I have created a simple repository called jenkins_hello_world_integrated . Go to GitHub repository's settings In Webhooks section, click on Add webhook In Webhooks settings: Add Payload URL as the URL of jenkins and append /github-webhook/ at the end of it. Select Content type application/jason . It is recommended to add Secret which can be generated by jenkins API Token by going to account configuration. It is recommended to Enable SSL verification . Select the events which should trigger the build in jenkins. Check Active . Click on Add Webhook . After this point each time the github repository is commited with a change, jenkins job will start the build and will also denote on the repository if the build has passed or failed (as can be seen in the below screenshot).","title":"Github 'Push' webhook integration with Jenkins"},{"location":"jenkins_github_integration/Github_push_webhook/#github-push-webhook-integration-with-jenkins","text":"","title":"Github 'Push' webhook integration with Jenkins"},{"location":"jenkins_github_integration/Github_push_webhook/#purpose-of-using-github-webhook-integration-with-jenkins","text":"Most of the time, after a push on the upstream repository, one may want to check the result of all the checks on the repository defined by CI/CD pipeline. This tells whether there is some issue with push and whether or not the defined checks/tests have passed. This can be achieved using github push webhook integration with jenkins.","title":"Purpose of using github webhook integration with jenkins"},{"location":"jenkins_github_integration/Github_push_webhook/#jenkins-version-and-operating-system-specifications","text":"The version of Jenkins and operating system specifications at the time of writing this documentation are mentioned below: Jenkins version: 2.370 Operating System: Linux Distribution: Ubuntu Release: Focal (also called 20.04)","title":"Jenkins version and operating system specifications"},{"location":"jenkins_github_integration/Github_push_webhook/#pre-requisites","text":"Jenkins ngrok (only if a public IP is not available)","title":"Pre-requisites"},{"location":"jenkins_github_integration/Github_push_webhook/#setting-up-the-ngrok","text":"The localhost cannot be used for github webhook integration as it cannot be detected by online webservers. For this reason, a public ip must be used. For the sake of this documentation, ngrok is being used, which maps localhost to some public ip which can then be accessed publicly on the internet. Following steps can be used for setting up ngrok on ubuntu: Install ngrok. sudo apt install ngrok For using html content, a sign up is required on ngrok. So sign up on ngrok. Execute the following command to run ngrok which will provide a public ip mapped to localhost. ngrok http This will setup ngrok and provide a public ip for working online.","title":"Setting up the ngrok"},{"location":"jenkins_github_integration/Github_push_webhook/#setting-up-jenkins-for-github-webhook","text":"","title":"Setting up Jenkins for github webhook"},{"location":"jenkins_github_integration/Github_push_webhook/#pre-requisites_1","text":"Following plugins should be installed in jenkins: Git Plugin GitHub API Plugin GitHub Plugin","title":"Pre-requisites"},{"location":"jenkins_github_integration/Github_push_webhook/#jenkins-configuration-in-settings","text":"Go to Manage Jenkins > Configure System and scroll down to GitHub section. Click on Add GitHub Server Add a name for the Github server. Leave API URL as is. In Credentials, click on Add . Jenkins will appear in drop down, click on it. Select Kind as Secret text Scroll down to the Secret and here, put down the github personal authentication token (PAT) which can be acquired from github account. Other options can be left unattended. Click on Add . Now the credentials should be added. In the Credentials drop down, select Secret text . Check Manage hooks . Now the connection can be established and can be checked by clicking the Test Connection . Click Save .","title":"Jenkins Configuration in Settings"},{"location":"jenkins_github_integration/Github_push_webhook/#jenkins-job-setup-for-github-webhook","text":"Create a new jenkins freestyle job and proceed with following settings on the configurations along with desired settings. Check GitHub project in General section and provide GitHub repository URL. In Source Code Management section, select Git . Give Repository URL In Credentials (if the credentials are not created already), click on Add , click on Jenkins from the drop down. Select Kind as Username with password . In Username , enter github username. In Password , enter github personal authentication token (PAT) which can be acquired from github account. Other fields can be left unattended. Click on Add From Credentials drop down, select your added credentials. In Branches to build section, in Branch Specifier field, enter the name of branch of github repository which needs to be built. In Build Triggers section, check GitHub hook trigger for GITScm polling . (Following step is for checking the commit status according to the Jenkins job status, means if Jenkins job fails, commit status is also Failure ) Scroll down to the bottom and Add post-build action . From drop down, select Set GitHub commit status . Leave other settings as is and click on Advanced . Check Handle errors Under drop down Result on failure , select FAILURE Click on Apply and Save By this point, Jenkins is setup for github webhooks.","title":"Jenkins job setup for Github Webhook"},{"location":"jenkins_github_integration/Github_push_webhook/#setting-up-github-repository-webhook","text":"For the sake of this documentation, I have created a simple repository called jenkins_hello_world_integrated . Go to GitHub repository's settings In Webhooks section, click on Add webhook In Webhooks settings: Add Payload URL as the URL of jenkins and append /github-webhook/ at the end of it. Select Content type application/jason . It is recommended to add Secret which can be generated by jenkins API Token by going to account configuration. It is recommended to Enable SSL verification . Select the events which should trigger the build in jenkins. Check Active . Click on Add Webhook . After this point each time the github repository is commited with a change, jenkins job will start the build and will also denote on the repository if the build has passed or failed (as can be seen in the below screenshot).","title":"Setting up github repository webhook"}]} \ No newline at end of file +{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"Cloud-V Documentation This documentation lists the tooling and necessary information to use Cloud-V for RISC-V application development on RISC-V compute instances provided by Cloud-V Overview Slides: link Youtube Channel: youtube.com/@Cloud-V","title":"Home"},{"location":"#cloud-v-documentation","text":"This documentation lists the tooling and necessary information to use Cloud-V for RISC-V application development on RISC-V compute instances provided by Cloud-V Overview Slides: link Youtube Channel: youtube.com/@Cloud-V","title":"Cloud-V Documentation"},{"location":"Creating_CI_CD_pipeline/","text":"Creating a CI/CD pipeline in Jenkins Pre Requisistes For sake of this documentation, jenkins built-in sample script is used to create and execute a cd/cd pipeline in jenkins. In the built-in script maven is used as M3, so one must install Maven plugin inside jenkins and name it M3 . Usually maven is already present inside jenkins and can be configured from Global Configuration Tools . Following steps demonstrate configuring Maven plugin. Go to Jenkins Dashboard and click on Manage Jenkins In Manage Jenkins , under System Configuration section, click on Global Tool Configuration . In Global Tool Configuration , scroll down to Maven section and click on the respective option under the Maven Section (should be Maven installations\u2026 or Add Maven ). Under Maven installations , enter M3 in \u201cname\u201d text box, check Install Automatically and select Version greater than 3, then click Apply and Save . This should install Maven version 3 and configure as M3 . Steps for Jenkins pipeline creation After installing Jenkins and having all the suggested plugins installed, go to Jenkins dashboard and click on Create Job . On the next page, give your pipeline a name, select Pipeline and click OK . A Configuration page for the pipeline will appear. Select Build Triggers options and General options according to need and scroll down to the Pipeline section. Definition section contains configuration for stages and steps of the pipeline. Under Definition section, you can either choose Pipeline script and try writing your own script or try some sample pipeline (like Hello World , Github+Maven etc) or you could select Pipeline script from SCM and give a github repository containing configurations of Pipeline. Press Save and Apply . This should take you to the Pipeline and you can build the pipeline and if no unresolved dependencies are present, the pipeline should build without any error.","title":"Creating a CI/CD pipeline in Jenkins"},{"location":"Creating_CI_CD_pipeline/#creating-a-cicd-pipeline-in-jenkins","text":"","title":"Creating a CI/CD pipeline in Jenkins"},{"location":"Creating_CI_CD_pipeline/#pre-requisistes","text":"For sake of this documentation, jenkins built-in sample script is used to create and execute a cd/cd pipeline in jenkins. In the built-in script maven is used as M3, so one must install Maven plugin inside jenkins and name it M3 . Usually maven is already present inside jenkins and can be configured from Global Configuration Tools . Following steps demonstrate configuring Maven plugin. Go to Jenkins Dashboard and click on Manage Jenkins In Manage Jenkins , under System Configuration section, click on Global Tool Configuration . In Global Tool Configuration , scroll down to Maven section and click on the respective option under the Maven Section (should be Maven installations\u2026 or Add Maven ). Under Maven installations , enter M3 in \u201cname\u201d text box, check Install Automatically and select Version greater than 3, then click Apply and Save . This should install Maven version 3 and configure as M3 .","title":"Pre Requisistes"},{"location":"Creating_CI_CD_pipeline/#steps-for-jenkins-pipeline-creation","text":"After installing Jenkins and having all the suggested plugins installed, go to Jenkins dashboard and click on Create Job . On the next page, give your pipeline a name, select Pipeline and click OK . A Configuration page for the pipeline will appear. Select Build Triggers options and General options according to need and scroll down to the Pipeline section. Definition section contains configuration for stages and steps of the pipeline. Under Definition section, you can either choose Pipeline script and try writing your own script or try some sample pipeline (like Hello World , Github+Maven etc) or you could select Pipeline script from SCM and give a github repository containing configurations of Pipeline. Press Save and Apply . This should take you to the Pipeline and you can build the pipeline and if no unresolved dependencies are present, the pipeline should build without any error.","title":"Steps for Jenkins pipeline creation"},{"location":"Creating_jenkinsfile/","text":"Creating a Cloud-V CI Pipeline file What is a Cloud-V CI Pipeline file A cloud-v-pipeline file is a Continuous Integration (CI) jenkins pipeline script which is written in Groovy. It describes various stages (and possibly steps) which are executed in the defined pattern. These stages can be written in bash or they can be written in Groovy itself. Mainly there can be two types of Cloud-V pipeline files are of two types: Scripted: Only contains stages Declarative: Contains stages as well as steps (more feature-rich and recommended) This documentation will cover how to create a cloud-v-pipeline file with bash script inside it and run it on various compute instances (which are known as Nodes in jenkins). Jenkins Node In jenkins, node represents a compute instance. In simple words, it is the platform on which our job build is going to run. Jenkins Master There is a jenkins Master node which is actually the compute instance on which Jenkins is installed. It is the node which schedules builds on runners. For security reason, no job is allowed to run on this node. Jenkins Slave Jenkins slave nodes are the compute instances on which our job builds run safely. They may be attached with jenkins master via hardware or they may be connected through remote SSH connection. cloud-v-pipeline file written with bash Simple Hello World cloud-v-pipeline file In Cloud-V, all the platforms are running Linux operating system, so the cloud-v-pipeline should be written in bash. Following script is an example of how can we run a bash script in scripted cloud-v-pipeline . node{ stage('*** Phase 1 ***') { //Using bash commands sh '''#!/bin/bash echo \"Hello World !\\n\" ''' } } The keyword sh is used to specify a shell script As there is nothing mentioned with node , so the script will run job build on any available compute instance. cloud-v-pipeline for a Specific Node In previous script, the cloud-v-pipeline would run on any compute instances which are available. But in case if someone wants to run a job build on specific node, then a compute instance name must be specified with keyword node . The following script is an example of running above Hello World program on node named hifive_unleashed . node('hifive_unleashed'){ stage('*** Phase 1 ***') { //Using bash commands sh '''#!/bin/bash echo \"Hello World !\\n\" ''' } } cloud-v-pipeline for Cross-Platform Compilation and Execution Cloud-V supports cross-compilation and execution on emulated RISC-V compute instances. Following tools help in cross compilation and cross-platfrom execution: RISC-V GNU Toolchain QEMU user mode (for running standalone binaries) QEMU System (for running application in Linux) An example pipeline script is given below in scripted pipeline. node('x86_runner2'){ checkout scm //Getting content of this repo stage('*** Compilation Phase ***') { // for display purposes //Compiling helloworld.c using bash commands sh '''#!/bin/bash gcc -g ./helloworld.c -o helloworld.out riscv64-unknown-linux-gnu-gcc ./helloworld.c -o helloworld_riscv_compiled.out //Cross compiling for RISC-V ''' } stage (' *** Running Binaries ***'){ sh '''#!/bin/bash ./helloworld.out qemu-riscv64 -L $RISCV_SYSROOT helloworld_riscv_compiled.out //Running executable on RISC-V emulated platform ''' } } The equivalent declarative pipeline is as follows: pipeline { agent {label \"x86_runner2\"} stages { stage('Clone Repository') { steps('delegate'){ checkout scm //Clones the repository on the local machine } } stage ('Compilation Phase'){ steps{ sh '''#!/bin/bash gcc -g ./helloworld.c -o helloworld.out ''' sh '''#!/bin/bash riscv64-unknown-linux-gnu-gcc ./helloworld.c -o helloworld_riscv_compiled.out ''' } } stage ('Running Binaries'){ steps { sh ''' #!/bin/bash ./helloworld.out ''' sh'''#!/bin/bash qemu-riscv64 -L $RISCV_SYSROOT helloworld_riscv_compiled.out ''' } } } } Reference Links https://www.jenkins.io/doc/book/pipeline/syntax/","title":"Creating a CI pipeline file"},{"location":"Creating_jenkinsfile/#creating-a-cloud-v-ci-pipeline-file","text":"","title":"Creating a Cloud-V CI Pipeline file"},{"location":"Creating_jenkinsfile/#what-is-a-cloud-v-ci-pipeline-file","text":"A cloud-v-pipeline file is a Continuous Integration (CI) jenkins pipeline script which is written in Groovy. It describes various stages (and possibly steps) which are executed in the defined pattern. These stages can be written in bash or they can be written in Groovy itself. Mainly there can be two types of Cloud-V pipeline files are of two types: Scripted: Only contains stages Declarative: Contains stages as well as steps (more feature-rich and recommended) This documentation will cover how to create a cloud-v-pipeline file with bash script inside it and run it on various compute instances (which are known as Nodes in jenkins).","title":"What is a Cloud-V CI Pipeline file"},{"location":"Creating_jenkinsfile/#jenkins-node","text":"In jenkins, node represents a compute instance. In simple words, it is the platform on which our job build is going to run.","title":"Jenkins Node"},{"location":"Creating_jenkinsfile/#jenkins-master","text":"There is a jenkins Master node which is actually the compute instance on which Jenkins is installed. It is the node which schedules builds on runners. For security reason, no job is allowed to run on this node.","title":"Jenkins Master"},{"location":"Creating_jenkinsfile/#jenkins-slave","text":"Jenkins slave nodes are the compute instances on which our job builds run safely. They may be attached with jenkins master via hardware or they may be connected through remote SSH connection.","title":"Jenkins Slave"},{"location":"Creating_jenkinsfile/#cloud-v-pipeline-file-written-with-bash","text":"","title":"cloud-v-pipeline file written with bash"},{"location":"Creating_jenkinsfile/#simple-hello-world-cloud-v-pipeline-file","text":"In Cloud-V, all the platforms are running Linux operating system, so the cloud-v-pipeline should be written in bash. Following script is an example of how can we run a bash script in scripted cloud-v-pipeline . node{ stage('*** Phase 1 ***') { //Using bash commands sh '''#!/bin/bash echo \"Hello World !\\n\" ''' } } The keyword sh is used to specify a shell script As there is nothing mentioned with node , so the script will run job build on any available compute instance.","title":"Simple Hello World cloud-v-pipeline file"},{"location":"Creating_jenkinsfile/#cloud-v-pipeline-for-a-specific-node","text":"In previous script, the cloud-v-pipeline would run on any compute instances which are available. But in case if someone wants to run a job build on specific node, then a compute instance name must be specified with keyword node . The following script is an example of running above Hello World program on node named hifive_unleashed . node('hifive_unleashed'){ stage('*** Phase 1 ***') { //Using bash commands sh '''#!/bin/bash echo \"Hello World !\\n\" ''' } }","title":"cloud-v-pipeline for a Specific Node"},{"location":"Creating_jenkinsfile/#cloud-v-pipeline-for-cross-platform-compilation-and-execution","text":"Cloud-V supports cross-compilation and execution on emulated RISC-V compute instances. Following tools help in cross compilation and cross-platfrom execution: RISC-V GNU Toolchain QEMU user mode (for running standalone binaries) QEMU System (for running application in Linux) An example pipeline script is given below in scripted pipeline. node('x86_runner2'){ checkout scm //Getting content of this repo stage('*** Compilation Phase ***') { // for display purposes //Compiling helloworld.c using bash commands sh '''#!/bin/bash gcc -g ./helloworld.c -o helloworld.out riscv64-unknown-linux-gnu-gcc ./helloworld.c -o helloworld_riscv_compiled.out //Cross compiling for RISC-V ''' } stage (' *** Running Binaries ***'){ sh '''#!/bin/bash ./helloworld.out qemu-riscv64 -L $RISCV_SYSROOT helloworld_riscv_compiled.out //Running executable on RISC-V emulated platform ''' } } The equivalent declarative pipeline is as follows: pipeline { agent {label \"x86_runner2\"} stages { stage('Clone Repository') { steps('delegate'){ checkout scm //Clones the repository on the local machine } } stage ('Compilation Phase'){ steps{ sh '''#!/bin/bash gcc -g ./helloworld.c -o helloworld.out ''' sh '''#!/bin/bash riscv64-unknown-linux-gnu-gcc ./helloworld.c -o helloworld_riscv_compiled.out ''' } } stage ('Running Binaries'){ steps { sh ''' #!/bin/bash ./helloworld.out ''' sh'''#!/bin/bash qemu-riscv64 -L $RISCV_SYSROOT helloworld_riscv_compiled.out ''' } } } }","title":"cloud-v-pipeline for Cross-Platform Compilation and Execution"},{"location":"Creating_jenkinsfile/#reference-links","text":"https://www.jenkins.io/doc/book/pipeline/syntax/","title":"Reference Links"},{"location":"Multinode_Pipelines/","text":"Multinode Pipelines One can create multinode pipelines in jenkins freestyle pipeline job as well as in jenkins native pipeline job. In such a pipeline, different stages of the pipeline can run on separate nodes. The jenkins native pipeline job can have two types. Scripted Pipeline Declarative pipeline For the sake of this documentation, two nodes are used: container-node and container-node2 Label In jenkins, label specifies where the job or a stage of the job can run. In jenkins, a label can be explicitly added in the node's configuration so that each time that label is mentioned in a jenkins job, that specific node is used for building the job, or the name of the node can also be used as label in case if no label is added in the node. Creating multinode pipelines in Jenkins native pipeline job Scripted Pipeline For creating a multinode pipeline with jenkins native scripted pipeline job, jenkinsfile can be tweaked. The keyword node can be used to specify the node in which the stages are going to run and this keyword can also be used in between stages. Following screenshot indicates a code in which first stage runs on node named container-node . While the second node runs on node named container-node2 . node ('container-node') { stage ('*** Creating a directory in container-node ***'){ sh '''#!/bin/bash mkdir newdir_container-node-$RANDOM ''' } stage ('*** Creating a directory in container-node2'){ node ('container-node2'){ sh'''#!/bin/bash mkdir newdir_container-node2-$RANDOM ''' } } } Declarative pipeline For a declarative pipeline the keyword label can be used in the agent block. This can either be done at the start of the pipeline after the keyword pipeline or it can be used inside the stages. The following code builds two stages each of which is built in separate node. The keyword none with agent means that the agent is not specified globally for each stage and it should be specified inside each stage. pipeline { agent none // Means no agent specified. This means each node will specify its own agent stages { stage('container-node') { agent{ label \"container-node\" //Selecting container-node for this stage } steps { sh '''#!/bin/bash echo 'Hello container-node' mkdir \"newdir-container-node-$RANDOM\" ''' } } stage('container-node2'){ agent{ label \"container-node2\" //Selecting container-node2 for this stage } steps{ sh'''#!/bin/bash echo ''Hello container-node2 mkdir \"newdir-container-node2-$RANDOM\" ''' } } } } Creating multinode pipelines using Jenkins freestyle jobs Jenkins freestyle jobs can be combined together by mentioning post-build jobs in the freestyle job settings. Freestyle jobs are customizable and offer more options than jenkins native pipeline jobs. Each job represents a stage and each stage has separate settings. One can use jenkins freestyle jobs to run on a separate node by selecting the option Restrict where this project can be run in the General section of the job's configuration. In the Label Expression , the node's name can be mentioned in which to run the job. The following image shows the option from job's configuration. This can be done in all the job's configuration for the specified node.","title":"Multinode Pipelines"},{"location":"Multinode_Pipelines/#multinode-pipelines","text":"One can create multinode pipelines in jenkins freestyle pipeline job as well as in jenkins native pipeline job. In such a pipeline, different stages of the pipeline can run on separate nodes. The jenkins native pipeline job can have two types. Scripted Pipeline Declarative pipeline For the sake of this documentation, two nodes are used: container-node and container-node2","title":"Multinode Pipelines"},{"location":"Multinode_Pipelines/#label","text":"In jenkins, label specifies where the job or a stage of the job can run. In jenkins, a label can be explicitly added in the node's configuration so that each time that label is mentioned in a jenkins job, that specific node is used for building the job, or the name of the node can also be used as label in case if no label is added in the node.","title":"Label"},{"location":"Multinode_Pipelines/#creating-multinode-pipelines-in-jenkins-native-pipeline-job","text":"","title":"Creating multinode pipelines in Jenkins native pipeline job"},{"location":"Multinode_Pipelines/#scripted-pipeline","text":"For creating a multinode pipeline with jenkins native scripted pipeline job, jenkinsfile can be tweaked. The keyword node can be used to specify the node in which the stages are going to run and this keyword can also be used in between stages. Following screenshot indicates a code in which first stage runs on node named container-node . While the second node runs on node named container-node2 . node ('container-node') { stage ('*** Creating a directory in container-node ***'){ sh '''#!/bin/bash mkdir newdir_container-node-$RANDOM ''' } stage ('*** Creating a directory in container-node2'){ node ('container-node2'){ sh'''#!/bin/bash mkdir newdir_container-node2-$RANDOM ''' } } }","title":"Scripted Pipeline"},{"location":"Multinode_Pipelines/#declarative-pipeline","text":"For a declarative pipeline the keyword label can be used in the agent block. This can either be done at the start of the pipeline after the keyword pipeline or it can be used inside the stages. The following code builds two stages each of which is built in separate node. The keyword none with agent means that the agent is not specified globally for each stage and it should be specified inside each stage. pipeline { agent none // Means no agent specified. This means each node will specify its own agent stages { stage('container-node') { agent{ label \"container-node\" //Selecting container-node for this stage } steps { sh '''#!/bin/bash echo 'Hello container-node' mkdir \"newdir-container-node-$RANDOM\" ''' } } stage('container-node2'){ agent{ label \"container-node2\" //Selecting container-node2 for this stage } steps{ sh'''#!/bin/bash echo ''Hello container-node2 mkdir \"newdir-container-node2-$RANDOM\" ''' } } } }","title":"Declarative pipeline"},{"location":"Multinode_Pipelines/#creating-multinode-pipelines-using-jenkins-freestyle-jobs","text":"Jenkins freestyle jobs can be combined together by mentioning post-build jobs in the freestyle job settings. Freestyle jobs are customizable and offer more options than jenkins native pipeline jobs. Each job represents a stage and each stage has separate settings. One can use jenkins freestyle jobs to run on a separate node by selecting the option Restrict where this project can be run in the General section of the job's configuration. In the Label Expression , the node's name can be mentioned in which to run the job. The following image shows the option from job's configuration. This can be done in all the job's configuration for the specified node.","title":"Creating multinode pipelines using Jenkins freestyle jobs"},{"location":"Software_Developer_Guide/","text":"Software Developer Guide for RISC-V CI A software developer is the end-user who will develop or build his/her projects on RISC-V CI infrastructure. This guide will cover all the things a software developer needs to create a project based on Cloud-V Continuous Integration (CI). Pre-requisites GitHub account. GitHub project repository with owner rights. Getting an account for Cloud-V Fill out this google form with all the required information for getting an account on Cloud-V. After this we will get back to you with login credentials. Setting up cloud-v-pipeline inside github project repository Cloud-V will need a cloud-v-pipeline written with jenkinsfile pipeline syntax to start execution of tests/checks (see link ). This pipeline will contain all the stages (and may be steps) of a CI/CD pipeline. This pipeline can be scripted pipeline which will only have stages or it can also be declarative pipeline which may also have steps inside stages. A simple scripted Helloworld pipeline in linux is as follows: node{ stage('*** Phase 1 ***') { //Using bash commands sh '''#!/bin/bash echo \"Hello World !\\n\" ''' } } Upon execution of such a pipeline, the console output can be viewed as follows. Note: This cloud-v-pipeline should remain same in all the branches and pull requests. Setting credentials for webhook Cloud-V supports webhooks which can trigger the job from external sources such as GitHub. They work in a way such that, if a specified branch is committed or if a pull request is created, the specified job build starts running depending upon the trigger event which is set in build's configuration in Cloud-V. This process requires access token of the repository CREATED BY OWNER OF REPOSITORY on which the webhook is to be set. These credentials can be safely added to Cloud-V without anyone (even administrator) seeing the passwords as follows. Obtaining github access token for repository Navigate to the dashboard of your github account and click on the your github profile picture on the top-right corner on dashboard. Then click on the \"Settings\" from the list. From the left option bar in Settings scroll down and click on \"Developer settings\". Once there, click on \"Personal access tokens\", then click on \"Fine-grained tokens\" from the dropdown list and after that click on \"Generate new token\". This will open the page for setting up new access token. Follow following steps for creating a token: Give your token a meaningful name under \"Token name\" Set expiration date in \"Expiration\" depending upon how long you would like your repository to be integrated with Cloud-V (think of a meaningful upper bound) The \"Resource owner\" should be the owner of the repository who can access all kinds of settings of the repository Under \"Repository access\", check \"Only select repositories\" and then select the repository for which you would like to create the token Under \"Permissions\" section, expand \"Repository Permissions\" and give the following two permissions: \"Read and write\" access to \"Commit statuses\" (Because after the CI has run, Cloud-V will be able to set the status of the commit accordingly) \"Read-only\" access to \"Webhooks\" Configuring repository webhook In GitHub, Go to repository settings which you want to integrate for Cloud-V. Go to Webhooks Click on Add webhook Add Payload URL as https://dash.cloud-v.co/ghprbhook/ Select content type as application/json Check Enable SSL verification In the section Which events would you like to trigger this webhook? check Let me select individual events and check Pul requests as individual events and dont check any other permission. Webhook settings will look something like this: Configurations inside Cloud-V Note: Currently users are not able to see or modify pipeline build configuration inside Jenkins, that is currently managed by administrator. Users are requested to inform administrator about how they want their pipeline configured. We will provide you with Cloud-V credentials on the provided email. Login with provided credentials. Click on the Credentials in the left menu. This will take you to the credentials page. Scroll down to the Stores scoped to Jenkins and click on the System as shown in the image. Click on Global credentials (unrestricted) . Click on Add Credentials . This will take you to the New Credentials page. Select Kind as Username with password . Select Scope as Global (Jenkins, nodes, items, all child items etc) . Enter your GitHub username in Username Enter Password as GitHub personal authentication token (PAT) which can be acquired from Github account settings. ID is optional but you can enter a unique ID . Description can be left empty. But it is recommended to give a suitable but careful description by which administrator will be able to identify and use these credentials to set up github webhook Select Create This process will look something like this Now credentials will be available in the credentials list and will be shown to you as well as administrator as shown in the image below. This will create an option in configurations for using these credentials in github webhook without changing or viewing them. Note the credentials ID (as shown in the image below) and email it to the same administrator email on which you received the login credentials for Cloud-V. It is important that administrator knows the credentials ID because they will use it in the job build configurations. Note: Please make sure to inform the administrator via email that you have added the credentials in Cloud-V Dashboard. Also, send administrator the ID of credentials via email. Requirements for administrator After the above setup is complete from software developer's side, developer will need to provide the administrator with following information. Dependencies for running the project which can be packages which are needed to install in the RISC-V CI environment by administrator. Events for triggering the job build. URL of GitHub repository. Path and name of cloud-v-pipeline file on the provided GitHub repository. Any additional information which should be given for successful execution of job builds.","title":"Getting Started"},{"location":"Software_Developer_Guide/#software-developer-guide-for-risc-v-ci","text":"A software developer is the end-user who will develop or build his/her projects on RISC-V CI infrastructure. This guide will cover all the things a software developer needs to create a project based on Cloud-V Continuous Integration (CI).","title":"Software Developer Guide for RISC-V CI"},{"location":"Software_Developer_Guide/#pre-requisites","text":"GitHub account. GitHub project repository with owner rights.","title":"Pre-requisites"},{"location":"Software_Developer_Guide/#getting-an-account-for-cloud-v","text":"Fill out this google form with all the required information for getting an account on Cloud-V. After this we will get back to you with login credentials.","title":"Getting an account for Cloud-V"},{"location":"Software_Developer_Guide/#setting-up-cloud-v-pipeline-inside-github-project-repository","text":"Cloud-V will need a cloud-v-pipeline written with jenkinsfile pipeline syntax to start execution of tests/checks (see link ). This pipeline will contain all the stages (and may be steps) of a CI/CD pipeline. This pipeline can be scripted pipeline which will only have stages or it can also be declarative pipeline which may also have steps inside stages. A simple scripted Helloworld pipeline in linux is as follows: node{ stage('*** Phase 1 ***') { //Using bash commands sh '''#!/bin/bash echo \"Hello World !\\n\" ''' } } Upon execution of such a pipeline, the console output can be viewed as follows. Note: This cloud-v-pipeline should remain same in all the branches and pull requests.","title":"Setting up cloud-v-pipeline inside github project repository"},{"location":"Software_Developer_Guide/#setting-credentials-for-webhook","text":"Cloud-V supports webhooks which can trigger the job from external sources such as GitHub. They work in a way such that, if a specified branch is committed or if a pull request is created, the specified job build starts running depending upon the trigger event which is set in build's configuration in Cloud-V. This process requires access token of the repository CREATED BY OWNER OF REPOSITORY on which the webhook is to be set. These credentials can be safely added to Cloud-V without anyone (even administrator) seeing the passwords as follows.","title":"Setting credentials for webhook"},{"location":"Software_Developer_Guide/#obtaining-github-access-token-for-repository","text":"Navigate to the dashboard of your github account and click on the your github profile picture on the top-right corner on dashboard. Then click on the \"Settings\" from the list. From the left option bar in Settings scroll down and click on \"Developer settings\". Once there, click on \"Personal access tokens\", then click on \"Fine-grained tokens\" from the dropdown list and after that click on \"Generate new token\". This will open the page for setting up new access token. Follow following steps for creating a token: Give your token a meaningful name under \"Token name\" Set expiration date in \"Expiration\" depending upon how long you would like your repository to be integrated with Cloud-V (think of a meaningful upper bound) The \"Resource owner\" should be the owner of the repository who can access all kinds of settings of the repository Under \"Repository access\", check \"Only select repositories\" and then select the repository for which you would like to create the token Under \"Permissions\" section, expand \"Repository Permissions\" and give the following two permissions: \"Read and write\" access to \"Commit statuses\" (Because after the CI has run, Cloud-V will be able to set the status of the commit accordingly) \"Read-only\" access to \"Webhooks\"","title":"Obtaining github access token for repository"},{"location":"Software_Developer_Guide/#configuring-repository-webhook","text":"In GitHub, Go to repository settings which you want to integrate for Cloud-V. Go to Webhooks Click on Add webhook Add Payload URL as https://dash.cloud-v.co/ghprbhook/ Select content type as application/json Check Enable SSL verification In the section Which events would you like to trigger this webhook? check Let me select individual events and check Pul requests as individual events and dont check any other permission. Webhook settings will look something like this:","title":"Configuring repository webhook"},{"location":"Software_Developer_Guide/#configurations-inside-cloud-v","text":"Note: Currently users are not able to see or modify pipeline build configuration inside Jenkins, that is currently managed by administrator. Users are requested to inform administrator about how they want their pipeline configured. We will provide you with Cloud-V credentials on the provided email. Login with provided credentials. Click on the Credentials in the left menu. This will take you to the credentials page. Scroll down to the Stores scoped to Jenkins and click on the System as shown in the image. Click on Global credentials (unrestricted) . Click on Add Credentials . This will take you to the New Credentials page. Select Kind as Username with password . Select Scope as Global (Jenkins, nodes, items, all child items etc) . Enter your GitHub username in Username Enter Password as GitHub personal authentication token (PAT) which can be acquired from Github account settings. ID is optional but you can enter a unique ID . Description can be left empty. But it is recommended to give a suitable but careful description by which administrator will be able to identify and use these credentials to set up github webhook Select Create This process will look something like this Now credentials will be available in the credentials list and will be shown to you as well as administrator as shown in the image below. This will create an option in configurations for using these credentials in github webhook without changing or viewing them. Note the credentials ID (as shown in the image below) and email it to the same administrator email on which you received the login credentials for Cloud-V. It is important that administrator knows the credentials ID because they will use it in the job build configurations. Note: Please make sure to inform the administrator via email that you have added the credentials in Cloud-V Dashboard. Also, send administrator the ID of credentials via email.","title":"Configurations inside Cloud-V"},{"location":"Software_Developer_Guide/#requirements-for-administrator","text":"After the above setup is complete from software developer's side, developer will need to provide the administrator with following information. Dependencies for running the project which can be packages which are needed to install in the RISC-V CI environment by administrator. Events for triggering the job build. URL of GitHub repository. Path and name of cloud-v-pipeline file on the provided GitHub repository. Any additional information which should be given for successful execution of job builds.","title":"Requirements for administrator"},{"location":"Tooling/","text":"Tools on Cloud-V Using Environment Modules Users can use environment modules to load different versions of same program. For using environment modules the pattern is as follows: module load Important Note: Be sure to use #!/bin/bash -l instead of #!/bin/bash in CI pipeline file since that is required for environment modules to load For example if you want to load python version 3.9.2 compiled for x86, you will need to use following command: module load python/3.9.2 For packages compiled for RISC-V architecture host, you will need to append _riscv to package name. For example, for python 3.8.15 compiled for RISC-V, following command will be used. module load python_riscv/3.8.15","title":"Using Environment Modules"},{"location":"Tooling/#tools-on-cloud-v","text":"","title":"Tools on Cloud-V"},{"location":"Tooling/#using-environment-modules","text":"Users can use environment modules to load different versions of same program. For using environment modules the pattern is as follows: module load Important Note: Be sure to use #!/bin/bash -l instead of #!/bin/bash in CI pipeline file since that is required for environment modules to load For example if you want to load python version 3.9.2 compiled for x86, you will need to use following command: module load python/3.9.2 For packages compiled for RISC-V architecture host, you will need to append _riscv to package name. For example, for python 3.8.15 compiled for RISC-V, following command will be used. module load python_riscv/3.8.15","title":"Using Environment Modules"},{"location":"jenkins_gitlab_integration/","text":"Integrating GitLab with Jenkins This documentation will cover how to create an integration between jenkins and GitLab. This will allow users to trigger jenkins job when a merge request or a push is detected in GitLab. Pre-requisites GitLab plugin Git plugin GitLab repository with owner's credentials Configuring Jenkins System First jenkins needs to be configured. Go to Dashboard > Manage Jenkins > Configure System Scroll down to Gitlab section Check Enable authentication for '/project' end-point Enter a Connection name . Enter Gitlab host URL as https://gitlab.com/ . In case there is a different domain name, then enter there instead of above url. In Credentials , click on Add then click on Jenkins . In Kind , select GitLab API token . In API token , enter the gitlab personal access token (this will be obtained below while configuring GitLab). Click on Advanced . Click on Test Connection . If everything goes right, it should print success . Configuring GitLab Click on profile avatar in the top right. Click on Edit profile . Click on Access Tokens . Create a new personal access token and copy it (this is the GitLab API token used in above section Configuring Jenkins System ). Go to repository settings. On left-side pane, select Webhooks . Enter GitLab webhook URL (this is explained below in next section). Enter Secret Token (this is explained in the below section). Check desirable trigger options. Click Add webhook . Configuring Jenkins Job Create a jenkins job. On job configuration page, scroll down to Source Code Management . Select Git . In Credentials , add the owner credentials of GitLab repository. This will be Username and Password . Select the appropriate branch (generally it is main ). Scroll down to Build Triggers . Check Build when a change is pushed to GitLab . There will also be a GitLab webhook URL . This is needed in GitLab. This URL will be called as Webhook URL . Click on Advanced in the same option, then scroll down and generate a secret token. This token is also needed. This token will be called as Secret Token . Scroll down to Post-build Actions and select Publish build status to GitLab . Click on Apply and Save . Now whenever there will be a push (or whatever build trigger option is set in jenkins and gitlab webhook), specified jenkins job will be triggered.","title":"Integrating GitLab with Jenkins"},{"location":"jenkins_gitlab_integration/#integrating-gitlab-with-jenkins","text":"This documentation will cover how to create an integration between jenkins and GitLab. This will allow users to trigger jenkins job when a merge request or a push is detected in GitLab.","title":"Integrating GitLab with Jenkins"},{"location":"jenkins_gitlab_integration/#pre-requisites","text":"GitLab plugin Git plugin GitLab repository with owner's credentials","title":"Pre-requisites"},{"location":"jenkins_gitlab_integration/#configuring-jenkins-system","text":"First jenkins needs to be configured. Go to Dashboard > Manage Jenkins > Configure System Scroll down to Gitlab section Check Enable authentication for '/project' end-point Enter a Connection name . Enter Gitlab host URL as https://gitlab.com/ . In case there is a different domain name, then enter there instead of above url. In Credentials , click on Add then click on Jenkins . In Kind , select GitLab API token . In API token , enter the gitlab personal access token (this will be obtained below while configuring GitLab). Click on Advanced . Click on Test Connection . If everything goes right, it should print success .","title":"Configuring Jenkins System"},{"location":"jenkins_gitlab_integration/#configuring-gitlab","text":"Click on profile avatar in the top right. Click on Edit profile . Click on Access Tokens . Create a new personal access token and copy it (this is the GitLab API token used in above section Configuring Jenkins System ). Go to repository settings. On left-side pane, select Webhooks . Enter GitLab webhook URL (this is explained below in next section). Enter Secret Token (this is explained in the below section). Check desirable trigger options. Click Add webhook .","title":"Configuring GitLab"},{"location":"jenkins_gitlab_integration/#configuring-jenkins-job","text":"Create a jenkins job. On job configuration page, scroll down to Source Code Management . Select Git . In Credentials , add the owner credentials of GitLab repository. This will be Username and Password . Select the appropriate branch (generally it is main ). Scroll down to Build Triggers . Check Build when a change is pushed to GitLab . There will also be a GitLab webhook URL . This is needed in GitLab. This URL will be called as Webhook URL . Click on Advanced in the same option, then scroll down and generate a secret token. This token is also needed. This token will be called as Secret Token . Scroll down to Post-build Actions and select Publish build status to GitLab . Click on Apply and Save . Now whenever there will be a push (or whatever build trigger option is set in jenkins and gitlab webhook), specified jenkins job will be triggered.","title":"Configuring Jenkins Job"},{"location":"runner_specs/","text":"Specifications of compute instances in Cloud-V This document contains the specifications of the compute instances available for users to run builds in Cloud-V. The term \"Compute Instance\", can also be safely interchanged with the terms \"Build Executor\" and \"Runner\". Name String Architecture Cores Memory Compute Instance Type J-x86-1 (or) J-QMU-1 x86_64 4 8GiB Hardware with application-level emulator J-TESTVM-1 x86_64 4 8GiB Hardware J-RASP4-1 aarch64 4 4GiB Hardware J-QMS-1 riscv64 2 2GiB QEMU System emulator J-VF1-1 riscv64 2 8GiB Hardware J-VF1-2 riscv64 2 8GiB Hardware J-VF1-3 riscv64 2 8GiB Hardware J-VF2-1 riscv64 4 8GiB Hardware J-VF2-2 riscv64 4 8GiB Hardware J-VF2-3 riscv64 4 8GiB Hardware J-VF2-4 riscv64 4 8GiB Hardware J-VF2-5 riscv64 4 8GiB Hardware J-VF2-6 riscv64 4 8GiB Hardware J-HF-1 riscv64 4 8GiB Hardware Note: The J-QMU-1 and J-x86-1 are one and the same runner. The purpose of creating two separate executors for same hardware is that J-x86-1 is supposed to be specifically for x86 architecture whereas J-QMU-1 is specifically for the users who want to cross compile source code for riscv64 architecture and then use qemu-usermode to execute them. Nevertheless, the tooling available for J-x86-1 can also be used for J-QMU-1","title":"Compute Instance Specifications"},{"location":"runner_specs/#specifications-of-compute-instances-in-cloud-v","text":"This document contains the specifications of the compute instances available for users to run builds in Cloud-V. The term \"Compute Instance\", can also be safely interchanged with the terms \"Build Executor\" and \"Runner\". Name String Architecture Cores Memory Compute Instance Type J-x86-1 (or) J-QMU-1 x86_64 4 8GiB Hardware with application-level emulator J-TESTVM-1 x86_64 4 8GiB Hardware J-RASP4-1 aarch64 4 4GiB Hardware J-QMS-1 riscv64 2 2GiB QEMU System emulator J-VF1-1 riscv64 2 8GiB Hardware J-VF1-2 riscv64 2 8GiB Hardware J-VF1-3 riscv64 2 8GiB Hardware J-VF2-1 riscv64 4 8GiB Hardware J-VF2-2 riscv64 4 8GiB Hardware J-VF2-3 riscv64 4 8GiB Hardware J-VF2-4 riscv64 4 8GiB Hardware J-VF2-5 riscv64 4 8GiB Hardware J-VF2-6 riscv64 4 8GiB Hardware J-HF-1 riscv64 4 8GiB Hardware Note: The J-QMU-1 and J-x86-1 are one and the same runner. The purpose of creating two separate executors for same hardware is that J-x86-1 is supposed to be specifically for x86 architecture whereas J-QMU-1 is specifically for the users who want to cross compile source code for riscv64 architecture and then use qemu-usermode to execute them. Nevertheless, the tooling available for J-x86-1 can also be used for J-QMU-1","title":"Specifications of compute instances in Cloud-V"},{"location":"tooling_J-HF-1/","text":"Tools on J-HF-1 node This compute instance is Sifive's HiFive Unleased board and it has available packages ONLY for RISC-V architecture. Operating System: Ubuntu 20.04.6 (Focal Fossa) Tool Version Installed from Git 2.25.1 apt OpenJDK 11.0.20.1 apt GCC 10.5.0 apt Python3 3.8.10 apt OpenSSL 1.1.1f apt Ruby 2.7.0p0 apt Go 1.14.3 apt rustc 1.41.0 apt Flex 2.6.4 apt Ninja 1.10.0 apt Bison 3.5.1 apt autoconf 2.69 apt gperf 3.1 apt cmake 3.16.3 apt make 4.2.1 apt automake 1.16.1 apt gfortran 9.4.0 apt openssh-server 8.2p1 apt","title":"J-HF-1"},{"location":"tooling_J-HF-1/#tools-on-j-hf-1-node","text":"This compute instance is Sifive's HiFive Unleased board and it has available packages ONLY for RISC-V architecture. Operating System: Ubuntu 20.04.6 (Focal Fossa) Tool Version Installed from Git 2.25.1 apt OpenJDK 11.0.20.1 apt GCC 10.5.0 apt Python3 3.8.10 apt OpenSSL 1.1.1f apt Ruby 2.7.0p0 apt Go 1.14.3 apt rustc 1.41.0 apt Flex 2.6.4 apt Ninja 1.10.0 apt Bison 3.5.1 apt autoconf 2.69 apt gperf 3.1 apt cmake 3.16.3 apt make 4.2.1 apt automake 1.16.1 apt gfortran 9.4.0 apt openssh-server 8.2p1 apt","title":"Tools on J-HF-1 node"},{"location":"tooling_J-QMS-1/","text":"Tools on J-QMS-1 node This is QEMU system compute instance with 64-bit RISC-V Linux and it has all the packages ONLY for RISC-V architecture Operating System: Ubuntu 22.04.4 LTS (Jammy Jellyfish) QEMU Linux Version: 7.2.90 (v9.0.0-rc0-68-g853546f812) Tool Version Installed from pip 22.0.2 apt Git 2.34.1 apt OpenJDK 19.0.1 apt GCC 11.4.0 apt Python3 3.10.12 apt OpenSSL 3.0.2 apt Ruby 3.0.2p107 apt Go 1.18.8 apt rustc 1.75.0 apt Flex 2.6.4 apt Ninja 1.10.1 apt Bison 3.8.2 apt autoconf 2.71 apt gperf 3.1 apt make 4.3 apt cmake 3.22.1 apt","title":"J-QMS-1"},{"location":"tooling_J-QMS-1/#tools-on-j-qms-1-node","text":"This is QEMU system compute instance with 64-bit RISC-V Linux and it has all the packages ONLY for RISC-V architecture Operating System: Ubuntu 22.04.4 LTS (Jammy Jellyfish) QEMU Linux Version: 7.2.90 (v9.0.0-rc0-68-g853546f812) Tool Version Installed from pip 22.0.2 apt Git 2.34.1 apt OpenJDK 19.0.1 apt GCC 11.4.0 apt Python3 3.10.12 apt OpenSSL 3.0.2 apt Ruby 3.0.2p107 apt Go 1.18.8 apt rustc 1.75.0 apt Flex 2.6.4 apt Ninja 1.10.1 apt Bison 3.8.2 apt autoconf 2.71 apt gperf 3.1 apt make 4.3 apt cmake 3.22.1 apt","title":"Tools on J-QMS-1 node"},{"location":"tooling_J-QMU-1J-VM-1/","text":"Tools on J-x86-1 or J-QMU-1 node Tools which are mentioned for x86 architecture are able to run on J-x86-1 . Tools which are mentioned for RISC-V architecture are able to run on J-QMU-1 . The packages which are supported for QEMU User mode can be used by normal commands once they are loaded. Here PACKAGE_NAME is the package which you want to run on QEMU user mode. Operating System: Debian 11 (bullseye) QEMU User Mode Version: Different Versions (see the table below) Tooling available for J-x86-1 The tools available for J-x86-1 is for use on x86 architecture and these tools do not support execution on RISC-V architecture Tool Versions Installed from Host Architecture Environment Modules Support Git 2.3.0.2 source x86 N/A OpenJDK 19.0.1 apt x86 N/A GCC 10.4.0, 12.2.0 apt x86 Yes Python3 3.8.15, 3.9.2 source x86 Yes Go 1.18.8 apt x86 N/A rustc 1.65.0 source x86 N/A Flex 2.6.4 apt x86 N/A Ninja 1.10.1-1 apt x86 N/A Bison 3.7.5 apt x86 N/A autoconf 2.69 apt x86 N/A gperf 2.2.4 apt x86 N/A spike 1.1.1-dev source x86 Yes Verilator 4.038 apt x86 N/A Sail (riscv_sim_RV64, riscv_sim_RV32) 0.5 source x86 Yes cmake 3.18.4 apt x86 N/A make 4.3 apt x86 N/A ARM EABI GNU toolchain 13.2.Rel1 source x86 Yes qemu-system-arm 8.2.2 source x86 Yes SCons 4.7.0 source x86 Yes Tooling available for J-QMU-1 The tools available for J-QMU-1 is for use on RISC-V architecture and these tools do not support execution on x86 architecture Tool Versions Installed from Host Architecture Environment Modules Support Python3 3.8.15 source RISC-V Yes zlib 1.2.13 source RISC-V N/A OpenSSL 1.1.1r source RISC-V Yes Ruby (without IRB) 3.2.0dev source RISC-V Yes rustc 1.65.0 source RISC-V N/A Flex 2.6.4 source RISC-V yes Ninja 1.12.0.git source RISC-V Yes Bison 3.8.2, 2.3 source RISC-V Yes clang 16.0.0 source RISC-V (cross compiler) Yes riscv-pk 1.0.0-91-g573c858 source RISC-V Yes QEMU User mode and RISC-V GNU Cross compilers From now on RISC-V cross-compilers can only be loaded with their respective QEMU User mode on Cloud-V. This is configured so that there is no confusion between toolchain version and qemu user mode being used because both of these will be \"generally\" taken from the latest releases of nightly builds. Loading a certain RISC-V toolchain using environment modules will automatically load the respective qemu usermode version unless otherwise specified. The loading pattern for RISC-V 64-bit GNU Glibc toolchain will be as follows: module load riscv64-gnu-glibc/ And the loading pattern for RISC-V 64-bit GNU Glibc toolchain will be as follows: module load riscv64-gnu-elf/ Following table provides relevant information about version of the toolchain and the respective QEMU User mode version (where the release date is mentioned in pattern MMDDYYYY ). Release date GNU Toolchain version (elf and glibc) QEMU Version 03012024 13.2.0 8.2.1 02022024 13.2.0 8.2.1 02022024 13.2.0 8.1.1 Note: The J-QMU-1 and J-x86-1 are one and the same runner. The purpose of creating two separate executors for same hardware is that J-x86-1 is supposed to be specifically for x86 architecture whereas J-QMU-1 is specifically for the users who want to cross compile source code for riscv64 architecture and then use qemu-usermode to execute them. Nevertheless, the tooling available for J-x86-1 can also be used for J-QMU-1","title":"J-x86-1 or J-QMU-1"},{"location":"tooling_J-QMU-1J-VM-1/#tools-on-j-x86-1-or-j-qmu-1-node","text":"Tools which are mentioned for x86 architecture are able to run on J-x86-1 . Tools which are mentioned for RISC-V architecture are able to run on J-QMU-1 . The packages which are supported for QEMU User mode can be used by normal commands once they are loaded. Here PACKAGE_NAME is the package which you want to run on QEMU user mode. Operating System: Debian 11 (bullseye) QEMU User Mode Version: Different Versions (see the table below)","title":"Tools on J-x86-1 or J-QMU-1 node"},{"location":"tooling_J-QMU-1J-VM-1/#tooling-available-for-j-x86-1","text":"The tools available for J-x86-1 is for use on x86 architecture and these tools do not support execution on RISC-V architecture Tool Versions Installed from Host Architecture Environment Modules Support Git 2.3.0.2 source x86 N/A OpenJDK 19.0.1 apt x86 N/A GCC 10.4.0, 12.2.0 apt x86 Yes Python3 3.8.15, 3.9.2 source x86 Yes Go 1.18.8 apt x86 N/A rustc 1.65.0 source x86 N/A Flex 2.6.4 apt x86 N/A Ninja 1.10.1-1 apt x86 N/A Bison 3.7.5 apt x86 N/A autoconf 2.69 apt x86 N/A gperf 2.2.4 apt x86 N/A spike 1.1.1-dev source x86 Yes Verilator 4.038 apt x86 N/A Sail (riscv_sim_RV64, riscv_sim_RV32) 0.5 source x86 Yes cmake 3.18.4 apt x86 N/A make 4.3 apt x86 N/A ARM EABI GNU toolchain 13.2.Rel1 source x86 Yes qemu-system-arm 8.2.2 source x86 Yes SCons 4.7.0 source x86 Yes","title":"Tooling available for J-x86-1"},{"location":"tooling_J-QMU-1J-VM-1/#tooling-available-for-j-qmu-1","text":"The tools available for J-QMU-1 is for use on RISC-V architecture and these tools do not support execution on x86 architecture Tool Versions Installed from Host Architecture Environment Modules Support Python3 3.8.15 source RISC-V Yes zlib 1.2.13 source RISC-V N/A OpenSSL 1.1.1r source RISC-V Yes Ruby (without IRB) 3.2.0dev source RISC-V Yes rustc 1.65.0 source RISC-V N/A Flex 2.6.4 source RISC-V yes Ninja 1.12.0.git source RISC-V Yes Bison 3.8.2, 2.3 source RISC-V Yes clang 16.0.0 source RISC-V (cross compiler) Yes riscv-pk 1.0.0-91-g573c858 source RISC-V Yes","title":"Tooling available for J-QMU-1"},{"location":"tooling_J-QMU-1J-VM-1/#qemu-user-mode-and-risc-v-gnu-cross-compilers","text":"From now on RISC-V cross-compilers can only be loaded with their respective QEMU User mode on Cloud-V. This is configured so that there is no confusion between toolchain version and qemu user mode being used because both of these will be \"generally\" taken from the latest releases of nightly builds. Loading a certain RISC-V toolchain using environment modules will automatically load the respective qemu usermode version unless otherwise specified. The loading pattern for RISC-V 64-bit GNU Glibc toolchain will be as follows: module load riscv64-gnu-glibc/ And the loading pattern for RISC-V 64-bit GNU Glibc toolchain will be as follows: module load riscv64-gnu-elf/ Following table provides relevant information about version of the toolchain and the respective QEMU User mode version (where the release date is mentioned in pattern MMDDYYYY ). Release date GNU Toolchain version (elf and glibc) QEMU Version 03012024 13.2.0 8.2.1 02022024 13.2.0 8.2.1 02022024 13.2.0 8.1.1 Note: The J-QMU-1 and J-x86-1 are one and the same runner. The purpose of creating two separate executors for same hardware is that J-x86-1 is supposed to be specifically for x86 architecture whereas J-QMU-1 is specifically for the users who want to cross compile source code for riscv64 architecture and then use qemu-usermode to execute them. Nevertheless, the tooling available for J-x86-1 can also be used for J-QMU-1","title":"QEMU User mode and RISC-V GNU Cross compilers"},{"location":"tooling_J-VF1-x/","text":"Tools on J-VF1-x node This compute instance is Starfive's VisionFive 1 board and it has available packages ONLY for RISC-V architecture. Operating System: Ubuntu 23.04 (Lunar Lobster) Tool Version Installed from Git 2.39.2 apt OpenJDK 21-ea apt GCC 13.1.0 apt Python3 3.11.4 apt OpenSSL 3.0.8 apt Ruby 3.1.2p20 apt Go 1.20.3 apt rustc 1.67.1 apt Flex 2.6.4 apt Ninja 1.11.1 apt Bison 3.8.2 apt autoconf 2.71 apt gperf 3.1 apt cmake 3.25.1 apt make 4.3 apt automake 1.16.5 apt gfortran 13.1.0 apt openssh-server 9.0p1 apt","title":"J-VF1-x"},{"location":"tooling_J-VF1-x/#tools-on-j-vf1-x-node","text":"This compute instance is Starfive's VisionFive 1 board and it has available packages ONLY for RISC-V architecture. Operating System: Ubuntu 23.04 (Lunar Lobster) Tool Version Installed from Git 2.39.2 apt OpenJDK 21-ea apt GCC 13.1.0 apt Python3 3.11.4 apt OpenSSL 3.0.8 apt Ruby 3.1.2p20 apt Go 1.20.3 apt rustc 1.67.1 apt Flex 2.6.4 apt Ninja 1.11.1 apt Bison 3.8.2 apt autoconf 2.71 apt gperf 3.1 apt cmake 3.25.1 apt make 4.3 apt automake 1.16.5 apt gfortran 13.1.0 apt openssh-server 9.0p1 apt","title":"Tools on J-VF1-x node"},{"location":"tooling_J-VF2-x/","text":"Tools on J-VF2-x node This compute instance is Starfive's VisionFive 2 board and it has available packages ONLY for RISC-V architecture. Operating System: Debian 12 (Bookworm) Tool Version Installed from Git 2.43.0 apt OpenJDK 21.0.2 apt GCC 13.2.0 apt Python3 3.11.7 apt OpenSSL 3.1.5 apt Ruby 3.1.2p20 apt Go 1.22.0 apt rustc 1.70.0 apt Flex 2.6.4 apt Ninja 1.11.1 apt Bison 3.8.2 apt autoconf 2.71 apt gperf 3.1 apt cmake 3.28.3 apt make 4.3 apt automake 1.16.5 apt gfortran 13.2.0 apt openssh-server 9.6p1 apt vim 9.1 apt","title":"J-VF2-x"},{"location":"tooling_J-VF2-x/#tools-on-j-vf2-x-node","text":"This compute instance is Starfive's VisionFive 2 board and it has available packages ONLY for RISC-V architecture. Operating System: Debian 12 (Bookworm) Tool Version Installed from Git 2.43.0 apt OpenJDK 21.0.2 apt GCC 13.2.0 apt Python3 3.11.7 apt OpenSSL 3.1.5 apt Ruby 3.1.2p20 apt Go 1.22.0 apt rustc 1.70.0 apt Flex 2.6.4 apt Ninja 1.11.1 apt Bison 3.8.2 apt autoconf 2.71 apt gperf 3.1 apt cmake 3.28.3 apt make 4.3 apt automake 1.16.5 apt gfortran 13.2.0 apt openssh-server 9.6p1 apt vim 9.1 apt","title":"Tools on J-VF2-x node"}]} \ No newline at end of file diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 2a9d2eb..0f8724e 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -1,173 +1,3 @@ - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - - - None - 2024-03-27 - daily - \ No newline at end of file diff --git a/docs/sitemap.xml.gz b/docs/sitemap.xml.gz index 191fd80918f03205400aa5ec277f5b384278bdb6..d734161fa1f5b193a8977226d5b21eaa49dc17ea 100644 GIT binary patch literal 127 zcmV-_0D%7=iwFqTcOPZ~|8r?{Wo=<_E_iKh04<9_3V)_WXo8&M?ytk3HC}0~zlG)Vub#FEDJzc{lbH8-(9uOc^x;q6&(zC#KEY!7PvFK);`nDt0`%Db3dmzV{* zbU9mZIj-Kmef^Ak2WRpgJ}+++i-(eGVdRJ42EWM)m5BlG97 z%0627MnS!l<89}qeeZ(}9L+biUMUx44doYK;O!AvrJ~f;E@?kwd*+U>UNL(v&*{7U z%h4&LM$>58TcK^foBjqwZVL6idMWhRy_fA8OE=29B;RTAs6)9Ah4^o1C%d5e O2NS2Wi2=JH0|Nj6(PEYW diff --git a/docs/tooling_J-HF-1/index.html b/docs/tooling_J-HF-1/index.html index 6d64908..79e8143 100644 --- a/docs/tooling_J-HF-1/index.html +++ b/docs/tooling_J-HF-1/index.html @@ -8,7 +8,7 @@ J-HF-1 - Cloud-V Docs - + - - - + + @@ -34,7 +33,7 @@ Cloud-V Docs
- +
@@ -86,9 +85,9 @@
    -
  • »
  • -
  • Tooling on Compute Instances »
  • -
  • J-HF-1
  • +
  • + +
@@ -233,14 +232,15 @@

Tools on J-HF-1 node

- - - - - + + + + + diff --git a/docs/tooling_J-QMS-1/index.html b/docs/tooling_J-QMS-1/index.html index 80d30a2..82bc65a 100644 --- a/docs/tooling_J-QMS-1/index.html +++ b/docs/tooling_J-QMS-1/index.html @@ -8,7 +8,7 @@ J-QMS-1 - Cloud-V Docs - + - - - + + @@ -34,7 +33,7 @@ Cloud-V Docs
- +
@@ -86,9 +85,9 @@
    -
  • »
  • -
  • Tooling on Compute Instances »
  • -
  • J-QMS-1
  • +
  • + +
@@ -227,14 +226,15 @@

Tools on J-QMS-1 node

- - - - - + + + + + diff --git a/docs/tooling_J-QMU-1J-VM-1/index.html b/docs/tooling_J-QMU-1J-VM-1/index.html index 0c2ba7e..e9c4076 100644 --- a/docs/tooling_J-QMU-1J-VM-1/index.html +++ b/docs/tooling_J-QMU-1J-VM-1/index.html @@ -8,7 +8,7 @@ J-x86-1 or J-QMU-1 - Cloud-V Docs - + - - - + + @@ -34,7 +33,7 @@ Cloud-V Docs
- +
@@ -92,9 +91,9 @@
    -
  • »
  • -
  • Tooling on Compute Instances »
  • -
  • J-x86-1 or J-QMU-1
  • +
  • + +
@@ -234,6 +233,27 @@

Tooling available for J-x86-1x86 N/A + +ARM EABI GNU toolchain +13.2.Rel1 +source +x86 +Yes + + +qemu-system-arm +8.2.2 +source +x86 +Yes + + +SCons +4.7.0 +source +x86 +Yes +

Tooling available for J-QMU-1

@@ -392,14 +412,15 @@

QEMU User mode and RISC-V

- - - - - + + + + + diff --git a/docs/tooling_J-VF1-x/index.html b/docs/tooling_J-VF1-x/index.html index 8e4cb12..467e4e6 100644 --- a/docs/tooling_J-VF1-x/index.html +++ b/docs/tooling_J-VF1-x/index.html @@ -8,7 +8,7 @@ J-VF1-x - Cloud-V Docs - + - - - + + @@ -34,7 +33,7 @@ Cloud-V Docs
- +
@@ -86,9 +85,9 @@
    -
  • »
  • -
  • Tooling on Compute Instances »
  • -
  • J-VF1-x
  • +
  • + +
@@ -97,7 +96,7 @@
-

Tools on J-VF1-1 node

+

Tools on J-VF1-x node

This compute instance is Starfive's VisionFive 1 board and it has available packages ONLY for RISC-V architecture.

Operating System: Ubuntu 23.04 (Lunar Lobster)

@@ -236,14 +235,15 @@

Tools on J-VF1-1 node

- - - - - + + + + + diff --git a/docs/tooling_J-VF2-x/index.html b/docs/tooling_J-VF2-x/index.html index cdb4e00..1f43448 100644 --- a/docs/tooling_J-VF2-x/index.html +++ b/docs/tooling_J-VF2-x/index.html @@ -8,7 +8,7 @@ J-VF2-x - Cloud-V Docs - + - - - + + @@ -34,7 +33,7 @@ Cloud-V Docs
- +
@@ -86,9 +85,9 @@
    -
  • »
  • -
  • Tooling on Compute Instances »
  • -
  • J-VF2-x
  • +
  • + +
@@ -241,14 +240,15 @@

Tools on J-VF2-x node

- - - - - + + + + + diff --git a/mkdocs_src/docs/tooling_J-QMU-1J-VM-1.md b/mkdocs_src/docs/tooling_J-QMU-1J-VM-1.md index 097fd64..bf149bb 100644 --- a/mkdocs_src/docs/tooling_J-QMU-1J-VM-1.md +++ b/mkdocs_src/docs/tooling_J-QMU-1J-VM-1.md @@ -31,6 +31,9 @@ The tools available for `J-x86-1` is for use on x86 architecture and these tools | Sail (riscv_sim_RV64, riscv_sim_RV32) | 0.5 | source | x86 | Yes | | cmake | 3.18.4 | apt | x86 | N/A | | make | 4.3 | apt | x86 | N/A | +| ARM EABI GNU toolchain | 13.2.Rel1 | source | x86 | Yes | +| qemu-system-arm | 8.2.2 | source | x86 | Yes | +| SCons | 4.7.0 | source | x86 | Yes | ## Tooling available for `J-QMU-1`