Continuous Cross Compilation for Raspberry PI
I wanted to deploy a continuous integration system that cross-compiles a CMake project written in c ++ with OpenGL on Raspberry PI. At the same time, I wanted to see if there were convenient automatic assembly servers that did not contain python and did not consume hundreds of megabytes of ram in idle time. One of the goals of this article is to find out if I have passed a better or simpler solution :)
TLDR: drone is cool, allows you to add a simple file to the root of the repository on github / bitbucket - and get automatic builds / tests / deploy. Just like in Travis, but self-hosted.
Going to Google, I found out that there are only two servers that meet my simple requirements:
- drone.io
- concourse.ci
I settled on drone.io. I chose according to the description, I can not objectively compare.
Drone has two versions, 0.4 and 0.5. 0.5 is beta, it looks a bit prettier, but I haven’t found any fundamentally new features. The only bug in 0.4 fixed in 0.5 that I came across is that you can accidentally deprive yourself of the Administrator checkbox through the UI.
Documentation at http://readme.drone.io/ - version 0.4. For 0.5 - http://readme.drone.io/0.5/ .
Of the unobvious nuances - drone works with one of the repository providers, such as github, bitbucket, gogs. Moreover, one drone instance can work with only one source. This is corrected by the launch of several independent drone servers, fortunately they do not spend extra resources in idle time.
In my case - one drone looks in bitbucket, one - in gogs running on the same server.
I ran drone through the docker image, it looks like this:
Launch:
docker run -d \ -e REMOTE_DRIVER=bitbucket \ -e "REMOTE_CONFIG=https://bitbucket.org?client_id=***&client_secret=***" \ -e DRONE_DATABASE_DRIVER=sqlite3 \ -e DRONE_DATABASE_CONFIG=/var/lib/drone/drone.sqlite \ -v /var/lib/drone_bitbucket:/var/lib/drone \ -v /var/run/docker.sock:/var/run/docker.sock \ -p 81:8000 \ --restart=always \ --name=drone_bitbucket \ drone/drone:0.4And that’s it :)
This is what drone looks like after installation on the server:
By clicking on the drone button, go for permissions in bitbucket, and if successful, will show all the repositories available to the account:
Initially, the Active tab will be empty, all repositories will be in Available. Here is such a power button for each bitpack of the repository:

Now for the fun part, the build process itself :)
The build process in drone is extremely simple to configure. The root of the active repository should have a .drone.yml file that describes how to assemble and deploy the contents of the repository. The tag docker of the image is set, in which the assembly and commands for the assembly will take place. The whole .drone.yml for raspberry looks like this:
build:
image: notfl3/cross_raspberry_pi
commands:
- cmake -D CMAKE_BUILD_TYPE=Debug -D CMAKE_TOOLCHAIN_FILE=/Toolchain-RaspberryPi.cmake .
- make
publish:
sftp:
host:
port: 22
username: ...
password: ...
destination_path: ...
files:
- ...The most difficult place for me was to create a docker image that could be cross-compiled for Raspberry. There are a lot of ready-made ones on the Internet, but I made mine (basically to see what kind of docker this is). It looks something like this:
FROM debian:sid
RUN apt-getupdate
RUN apt-get install -y git
RUN apt-get install -y cmake
ENV CROSS_TRIPLE arm-linux-gnueabihf
RUN mkdir -p /rpi/tools && cd /rpi/tools && git init && git remote add -f origin https://github.com/raspberrypi/tools && \
git config core.sparseCheckout true && echo "arm-bcm2708/gcc-linaro-${CROSS_TRIPLE}-raspbian-x64" >> .git/info/sparse-checkout && \
git pull --depth=1 origin master
RUN mkdir -p /rpi/rootfs/opt
COPY lib/ /rpi/rootfs/lib/
COPY usr/ /rpi/rootfs/usr/
COPY opt/vc/ /rpi/rootfs/opt/vc/
COPY Toolchain-RaspberryPi.cmake /Toolchain-RaspberryPi.cmake
RUN mkdir -p /build
WORKDIR /buildThis is the contents of my Dockerfile, in order to create a full-fledged image used for assembly - you need to put it in one directory to / usr, / lib, / opt taken from this Raspbian'a and the Toolchain-RaspberryPi.cmake file after the docker build . -t notfl3/cross_raspberry_pidrone command launched on the same server will be able to use this image and collect our builds.
Cross-compilation itself occurs according to the rules of CMake , the only caveat - I registered my Toolchain.cmake file for gcc from raspberry-tools, it looks like this:
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)
# Whereis the target environment
SET(CMAKE_FIND_ROOT_PATH /rpi/rootfs)
# Specify the cross compiler
SET(CMAKE_C_COMPILER /rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc "--sysroot=${CMAKE_FIND_ROOT_PATH}")
SET(CMAKE_CXX_COMPILER /rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-g++ "--sysroot=${CMAKE_FIND_ROOT_PATH}")
# Searchfor programs onlyin the build host directories
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# Searchfor libraries and headers onlyin the target directories
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
INCLUDE_DIRECTORIES(${CMAKE_FIND_ROOT_PATH}/usr/include/arm-linux-gnueabihf)
INCLUDE_DIRECTORIES(${CMAKE_FIND_ROOT_PATH}/usr/include/)
With these simple manipulations, I was able to get a working build with a glfw window for raspberry, which quickly assembled on an external dedicated server.
Going, amazing!
