Пишем на D для Raspberry Pi

в 12:16, , рубрики: D, dlang, dub, GDC, Raspberry Pi, кросскомпиляция, Разработка для интернета вещей, системное программирование

Пишем на D для Raspberry Pi - 1
Dlang, или просто D — молодой язык программирования с многолетней историей. Не смотря на то, что язык с таким названием появился очень давно, то, что сейчас называется D2 или просто D, появилось недавно и слабо напоминает предшественника. Писать на D очень удобно, а произодительность не уступает C++, поэтому не удивительно, что он добрался до ARM и его мобильных представителей Android и iOS. Кроме того растёт интерес к интернету вещей и просто портативным устройствам.
В статье рассмотрена задача кросскомпиляции кода на dlang для Raspberry Pi. В этом нет ничего сложного, да и подводных камней не замечено. Данная публикация — простой мануал для начала использования D на разных устройствах в целом и Raspberry Pi в частности.

Hello, World

Нам понадобится:

  • Компьютер с линуксом (в моём случае Ubuntu 14.04 на виртуалке)
  • Raspberry Pi с ssh доступом (использована Raspberry Pi B+)

Не смотря на то, что можно собирать исходники прямо на Raspberry Pi, лучше это делать на отдельном более мощном компьютере. На самой малине слишком мало памяти, а кросскомпиляция под Raspberry Pi – дело несложное. Для начала нам нужен компилятор dlang для Raspberry Pi. Тут два варианта: LDC (LLVM based D Compiler) и GDC (GNU D Compiler). Проще оказалось найти подходящую версию GDC. LDC под ARM есть и его тоже можно использовать, просто так сложилось, что я использую GDC.
Идём на сайт GDC в раздел downloads.
Скачиваем x86_64 сборку для целевой платформы arm-linux-gnueabihf (тут по-внимательнее, сам GDC будет запускаться на x86, а таргет armhf; не путать с GDC для arm, который запускается на устройстве).

Скачиваем, распаковываем из консоли.

wget http://gdcproject.org/downloads/binaries/5.2.0/x86_64-linux-gnu/gdc-5.2.0-arm-linux-gnueabihf+2.066.1.tar.xz

Распаковываем

tar -xf gdc-5.2.0-arm-linux-gnueabihf+2.066.1.tar.xz

для удобства я ещё переименовал папку

mv arm-unknown-linux-gnueabihf gdc-arm

Для постоянного использования я скопировал папку с gdc в /usr/bin и сделал алиас gdc-arm, но для примера к статье будем всё делать локально в папке. И так создаём ссылку-шорткат:

ln -s gdc-arm/bin/arm-linux-gnueabihf-gdc gdc

Вообще говоря, этого уже достаточно чтобы собирать D код под Raspberry PI. Проверим на примере Hello, world. Итак пишем исходник:

import std.stdio;
void main() {
    writeln("Hello, World!");
}

И сохраняем в hello.d. Компилируем:

./gdc hello.d -o hello

Теперь копируем на девайс идём на него и проверяем. У меня это выглядело так:

scp hello pi@192.168.1.85/~/dlang/hello

А на девайсе:

pi@raspberrypi:~/dlang $ ./hello 
Hello, World!

Усложняем задачу – линковка библиотек

Всё, описанное выше, тривиально и работает из коробки. Теперь соберём что-то посложнее. Например, «Hello, vibe.d», то есть примитивное приложение на web фреймвёрке vibe.d. Отличие от обычного HelloWorld одно – нужно линковать библиотеки. Кросскомпиляция dlang в этом вопросе ничем не отличается от C, C++ и других компилируемых языков. Поэтому можно использовать любой удобный подход к кросскомпиляции на Raspberry Pi.
Библиотеки нужны для конкретной архитектуры и их лучший источник – репозиторий, установленного на Raspberry дистрибутива. Обычно это https://www.raspbian.org/RaspbianRepository. Проще всего использовать библиотеки прямо с самого устройства. Только не собирать на нём (очень плохая идея, очень медленно и вечно в свопе), а просто использовать файлы. Хорошей идеей будет использовать sshfs (подсмотрено здесь: wiki.dlang.org/GDC/Cross_Compiler/Existing_Sysroot). Основное преимущество данного подхода – абсолютная универсальность и стабильность. Не важно какой дистрибутив установлен, будут взяты идеально подходящие библиотеки. Нет никаких конфликтов и несоответствия версий дистрибутива или библиотек.

Почему бы не подцепить Raspbian как источник пакетов на самой билд-машине

К сожалению все попытки подключить этот источник и использовать библиотеки не увенчались успехом. После долгих мучений, очень похожих на эти: answers.launchpad.net/ubuntu/+source/build-essential/+question/250970 затея была заброшена.

Почему бы не взять репозиторий ubuntu для arm

Есть небольшие проблемы с подключением. Хотя позже всё же получилось подключить и даже собрать, я получил Illegal Instruction при запуске. Архитектура armhf имеет ещё кучу разновидностей и флагов и надо ещё разобраться и найти те репозитории, которые подойдут Raspberry Pi.

Создаём папку, в которую смонтируем всю файловую систему Raspberry Pi и записываем её в переменную окружения:

mkdir rpi
echo $RPIROOT

export RPIROOT=~/test_pi/rpi/
echo $RPIROOT
/home/user/test_pi/rpi/

Монтируем через sshfs:

sshfs -o idmap=user,follow_symlinks pi@192.168.1.85:/ $RPIROOT

Так как нам нужно указывать архитектуру и пути поиска либ, для сокращения записи создадим ещё один шорткат. Создадим файлик gdc-rpi и запишем туда скрипт для запуска GDC с нужными флагами.

#!/bin/bash
~/test_pi/gdc -march=armv6j -mfpu=vfp -mfloat-abi=hard --sysroot=$RPIROOT -B$RPIROOT/usr/lib/arm-linux-gnueabihf "$@"

Тут немного подробнее: -march=armv6j -mfpu=vfp -mfloat-abi=hard – это флаги архитектуры процессора Raspberry Pi. sysroot — рут девайса, -B – место поиска либ, у нас оно на самом же девайсе в usr/lib
Добавляем прав на запуск и проверяем:

user@ubuntu:~/test_pi$ chmod 777 gdc-rpi 
user@ubuntu:~/test_pi$ ./gdc-rpi
gdc: fatal error: no input files
compilation terminated.

Всё работает, теперь нам на билд-машине нужен DUB (это билд-система и за одно менеджер зависимостей). Качаем и ставим его любым удобным способом, описанным здесь.
Создаём простой проект vibe.d:

dub init -tvibe.d test_vibe_pi

DUB создаст папку с минимальным проектом внутри. Теперь собираем:

cd test_vibe_pi/
dub build --compiler=../gdc-rpi

На выходе имеем файлик test_vibe_pi. Если нет чего-то вроде libcurl, то идём на девайс и apt-get'ом ставим всё необходимое. У меня уже всё было после прошлых экспериментов.
Копируем его на девайс и проверяем:

cp test_vibe_pi $RPIROOT/home/pi/dlang

На Raspberry Pi:

pi@raspberrypi:~/dlang $ ./test_vibe_pi
Listening for requests on http://[::1]:8080/
Listening for requests on http://127.0.0.1:8080/
Please open http://127.0.0.1:8080/ in your browser.

Всё, минимальный сайтик, отдающий «Hello, World!» на любой запрос на 127.0.0.1:8080/, готов.

Для тех, кто хочет собирать свои проекты прямо на устройстве

Собирать код на столь слабом устройстве — плохая идея, но иногда удобнее выкатывать проект на девайс в виде исходников. GDC для Raspberry есть готовый, можно идти в раздел ARM gdcproject.org/downloads и качать armhf версию. Для сборки скорее всего понадобится DUB и вот его придётся собирать, потому что готовый бинарь с сайта не запускается на Raspberry Pi B+.
Качаем исходники с сайта https://code.dlang.org/download (можно с гитхаба, это уж как хочется). Распаковываем, складываем в папку с удобным называнием

user@ubuntu:~/test_pi$ wget https://github.com/rejectedsoftware/dub/archive/v0.9.24.tar.gz
user@ubuntu:~/test_pi$ tar -xf v0.9.24.tar.gz 
user@ubuntu:~/test_pi$ mv dub-0.9.24/ dub
user@ubuntu:~/test_pi$ cd dub

Для сборки под линуксом с использованием GDC есть отдельный скрипт: build-gdc.sh. Он ожидает, что gdc есть в системе, либо задана переменная окружения GDC. Используем переменную. Просто указываем путь до нашего скрипта-шортката и запускаем:

GDC=../gdc-rpi ./build-gdc.sh

Generating version file...
./build-gdc.sh: 15: ./build-gdc.sh: git: not found
Running ../gdc-rpi...
DUB has been built as bin/dub.

You may want to run
sudo ln -s /home/user/test_pi/dub/bin/dub /usr/local/bin
now.

Если получен этот вывод и никаких ошибок линковки, то теперь есть рабочий DUB для Raspberry Pi. Копируем на девайс и проверяем.

user@ubuntu:~/test_pi/dub$ cd ..
user@ubuntu:~/test_pi$ cp dub/bin/dub rpi/home/pi/dlang/dub-test/dub

На устройстве:

pi@raspberrypi:~/dlang/dub-test $ ./dub

Neither a package description file, nor source/app.d was found in
/home/pi/dlang/dub-test
Please run DUB from the root directory of an existing package, or run
"dub init --help" to get information on creating a new package.

Failed to find a package named ''.

DUB запустился и справедливо заметил отсутствие проекта в папке. Проекта у нас действительно нет, а главная цель достигнута – DUB работает на Raspberry Pi.

Вот и всё, мы можем собирать любые проекты на D под Rapberry Pi. Например, можно запустить сервер для умного дома. Есть поддержка MQTT в виде плагина к vibe.d, а так же возможность использовать любую существующую C библиотеку.

Автор: bfDeveloper

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js