4 декабря 2015 в 10:05

Кросс-компиляция и сборка пакета под Synology DSM

C++*
На новом месте работы мне поставили задачу запустить продукт на NAS от производителей Synology и QNAP. Продукт написан на C++ с применением C++11, Boost и Qt5. За неимением свободного веб разработчика, интерфейс был написан наWt, который в свою очередь для сборки использует CMake. Под катом будет сборка этого зоопарка и создания простого пакета.


Основной источник информации официальное руководство DSM Developer Guide,
описывающий в общих чертах работу с toolchain(установка, компиляция open source проектов, пакетирование). Т.к. был куплен бюджетный вариант DS 114, который имеет под капотом Marvell Armada 370 и версию прошивки DSM 5.2, то все будет собираться под arm.

Для подготовки окружения буду использовать package toolkit, который можно скачать со страницы проекта Synology Open Source Project. Это немного удобней, потому что устройства в разных ценовых категориях поставляются с разными процессорами, что требует скачивания нескольких наборов инструментов.
Подробней можно посмотреть на странице What kind of CPU does my NAS have.

распаковываем package toolkit
$ mkdir -p ~/synology/toolkit
$ tar xvf pkgscripts.tgz -C ~/synology/toolkit


выкачиваем окружение и инструменты
$ cd ~/synology/toolkit/pkgscripts/
$ sudo ./EnvDeploy -v 5.2 -p armada370


Boost


Boost на удивление собирается довольно просто. В фай ~/user-config.jam прописываем
using gcc : arm : arm-marvell-linux-gnueabi-g++ ;

и собираем:
$ ./bootstrap.sh --prefix=/home/dmitry/synology/toolkit/build_env/ds.armada370-5.2/usr/local/arm-marvell-linux-gnueabi/arm-marvell-linux-gnueabi/libc
$ export PATH=~/synology/toolkit/build_env/ds.armada370-5.2/usr/local/arm-marvell-linux-gnueabi/bin:$PATH
$ ./b2 toolset=gcc-arm link=static threading=multi install

Webtoolkit


Для настройки CMake использую toolchain-файл toolchain-arm-marvell.cmake
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_SYSTEM_VERSION 1)

SET(CMAKE_C_COMPILER   /home/dmitry/synology/toolkit/build_env/ds.armada370-5.2/usr/local/arm-marvell-linux-gnueabi/bin/arm-marvell-linux-gnueabi-gcc)
SET(CMAKE_CXX_COMPILER /home/dmitry/synology/toolkit/build_env/ds.armada370-5.2/usr/local/arm-marvell-linux-gnueabi/bin/arm-marvell-linux-gnueabi-g++)
SET(CMAKE_LINKER /home/dmitry/synology/toolkit/build_env/ds.armada370-5.2/usr/local/arm-marvell-linux-gnueabi/bin/arm-marvell-linux-gnueabi-ld.gold)

SET(CMAKE_FIND_ROOT_PATH /home/dmitry/synology/toolkit/build_env/ds.armada370-5.2/usr/local/arm-marvell-linux-gnueabi/arm-marvell-linux-gnueabi/libc)

SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

Дальше:
$ tar xvf wt-3.3.4.tar.gz
$ cd wt-3.3.4
$ mkdir build
$ cd build
$ cmake -DCMAKE_TOOLCHAIN_FILE=~/toolchain-arm-marvell.cmake \
		-DCMAKE_BUILD_TYPE=Release \
		-DSHARED_LIBS=OFF \
		-DCMAKE_INSTALL_PREFIX=/home/dmitry/synology/toolkit/build_env/ds.armada370-5.2/usr/local/arm-marvell-linux-gnueabi/arm-marvell-linux-gnueabi/libc \
		..
$ make 
$ make install

Собираю пример, который буду пакетировать:
$ cd examples/composer
$ make

Проверяю полученный файл:
$ file Home.wt
Home.wt: ELF 32-bit LSB  executable, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.16, BuildID[sha1]=228a30c3dab0572993e41468aa0862fc93e11487, not stripped

Qt5


В каталоге исходников Qt идем в qtbase/mkspecs/devices.
Создаем каталог armada370, с содержимым
qmake.conf
include(../common/linux_device_pre.conf)

QMAKE_INCDIR         += $$[QT_SYSROOT]/usr/include 

QMAKE_LIBDIR          += $$[QT_SYSROOT]/lib  

QMAKE_CC                = $${CROSS_COMPILE}gcc
QMAKE_CXX              = $${CROSS_COMPILE}g++
QMAKE_LINK             = $${CROSS_COMPILE}g++
QMAKE_LINK_SHLIB = $${CROSS_COMPILE}g++

QMAKE_AR                = $${CROSS_COMPILE}ar cqs
QMAKE_OBJCOPY    = $${CROSS_COMPILE}objcopy
QMAKE_NM               = $${CROSS_COMPILE}nm -P
QMAKE_STRIP          = $${CROSS_COMPILE}strip

QMAKE_CFLAGS      += -march=armv7-a -mfpu=vfpv3-d16 
QMAKE_CXXFLAGS += $$QMAKE_CFLAGS 


DISTRO_OPTS += hard-float

QT_QPA_DEFAULT_PLATFORM = eglfs

include(../common/linux_arm_device_post.conf)
load(qt_config)

-mfpu=vfpv3-d16 — это оптимизация fpu, а DISTRO_OPTS отвечает за hard-float/soft-float.
qplatformdefs.h взял стандартным из конфигурации для других ARM.
При вызове configure необходимо передать:
  • -device armada370
  • -device-option CROSS_COMPILE=arm-marvell-linux-gnueabi-
  • -sysroot .../arm-marvell-linux-gnueabi/arm-marvell-linux-gnueabi/libc

Собирал в chroot'е
conf.sh:
#!/bin/bash

CFG=''
CFG+=' -opensource'          
CFG+=' -confirm-license'     
CFG+=' -v'                   
CFG+=' -static'              
CFG+=' -device armada370'
CFG+=' -make libs'
CFG+=' -device-option CROSS_COMPILE=/usr/local/arm-marvell-linux-gnueabi/bin/arm-marvell-linux-gnueabi- ' 
CFG+=' -sysroot /usr/local/arm-marvell-linux-gnueabi/arm-marvell-linux-gnueabi/libc'
CFG+=' -release'             
CFG+=' -nomake tools'        
CFG+=' -nomake examples'     
CFG+=' -no-compile-examples' 
CFG+=' -no-dbus'
CFG+=' -no-gui'
CFG+=' -no-widgets'
CFG+=' -qt-sql-sqlite'

CFG+=' -D QT_NO_GRAPHICSVIEW'
CFG+=' -D QT_NO_GRAPHICSEFFECT'
CFG+=' -D QT_NO_STYLESHEET'
CFG+=' -D QT_NO_STYLE_CDE'
CFG+=' -D QT_NO_STYLE_CLEANLOOKS'
CFG+=' -D QT_NO_STYLE_MOTIF'
CFG+=' -D QT_NO_STYLE_PLASTIQUE'
CFG+=' -no-qml-debug'


CFG+=' -no-alsa'
CFG+=' -no-cups'
CFG+=' -no-dbus'
CFG+=' -no-directfb'
CFG+=' -no-evdev'
CFG+=' -no-gtkstyle'
CFG+=' -no-kms'
CFG+=' -no-libudev'
CFG+=' -no-linuxfb'
CFG+=' -no-mtdev'
CFG+=' -no-nis'
CFG+=' -no-pulseaudio'
CFG+=' -no-sm'
CFG+=' -no-xcb'
CFG+=' -no-xcb-xlib'
CFG+=' -no-xinerama'
CFG+=' -no-xinput2'
CFG+=' -no-xkb'
CFG+=' -no-xrender'
CFG+=' -no-icu'
CFG+=' -no-use-gold-linker'
CFG+=' -no-eglfs'
CFG+=' -no-cups'
CFG+=' -no-fontconfig'
CFG+=' -no-sse2'
CFG+=' -no-sse3'
CFG+=' -no-sse4.1'
CFG+=' -no-avx'
CFG+=' -no-opengl'

cd qtbase
./configure $CFG "$@"


$ sudo chroot ~/synology/toolkit/build_env/ds.armada370-5.2/
$ cd /root/qt-everywhere-opensource-src-5.5.0/
$ ./conf.sh
$ cd qtbase
$ make
$ make install



Пакетирование



Пакет имеет расширение spk, представляет из файловый архив. Структура минимального пакета имеет вид:

INFO — текстовый файл с описанием пакета:
scripts — скрипты выполняемые на разных этапах установки/удаления пакета, и скрипт запуска демона;
package.tgz — сжатый архив содержащий исполняемые файлы, библиотеки, ресурсы и т. д.

Собранный пакет composer.skp имеет структуру:

composer.wt, composer.xml, composer.css и paperclip.png взяты из примера Wt и интереса не вызывают.

INFO

package="composer"
displayname="Mail composer"
version="1.0.0" 
arch="armada370"
description="This example implements a GMail-like mail composer and shows among other things how to upload files asynchronously, showing a cross-browser upload progress bar and with support for multiple files."
maintainer="Wt"
dsmuidir=ui

dsmuidir опциональная переменная, необходимая для автоматической создания ссылки с /volumeX/@appstore/[packge name]/[dsmuidir] на /usr/syno/synoman/webman/3rdparty/[package name]. /volumeX/@appstore/[packge name], где X=1,2..N — путь по которому будет находится установленное приложение. /usr/syno/synoman/webman/3rdparty/[package name] путь для интеграции в UI DSM.

config

Для интеграции в UI DSM нужно создать каталог /usr/syno/synoman/webman/3rdparty/[package name] и поместить туда файл config примерного содержания:
{
	".url": {
		"eu.webtoolkit.composer": {
			"type": "url",
			"allUsers": true,
			"title": "Mail composer",
			"desc":"This example implements a GMail-like mail composer and shows among other things how to upload files asynchronously, showing a cross-browser upload progress bar and with support for multiple files.",
			"icon":"composer_{0}.png",
			"url": "3rdparty/composer/index.cgi"
		}
	}
}

composer_{0}.png — плейсхолдер заменяется на composer_48.png/composer_64.png/composer_72.png/composer_256.png.
url — путь к html/cgi который будет открываться в новом окне, при нажатии на приложение. В /usr/syno/synoman/webman/3rdparty/[package name] допускается html, js, css, cgi, изображения. А вот подсунуть php не получилось.

index.cgi

#!/bin/sh

if [ `ifconfig | grep bond0 | awk '{print $1}'` ]
then
IP_ADDR=`ifconfig bond0 | grep "inet addr" | awk '{print $2}' | awk -F: '{print $2}'`
else
IP_ADDR=`ifconfig eth0 | grep "inet addr" | awk '{print $2}' | awk -F: '{print $2}'`
fi
echo Location: http://$IP_ADDR:8585
echo ""
exit 

Простой cgi скрипт перенаправляющий на приложение написанный на Wt.

start-stop-status

#!/bin/sh

case $1 in
	start)
		${SYNOPKG_PKGDEST}/composer.wt --docroot=${SYNOPKG_PKGDEST} --approot=${SYNOPKG_PKGDEST} --http-address=0.0.0.0 --http-port=8585 &
		exit 0
	;;
	stop)

		pkill composer.wt
		exit 0
	;;
	restart)
		exit 0;
	;;
	status)
		if [ "$?" = "0" ]; then 
			exit 0
		else
			exit 1
		fi		
	;;
	log)
		exit 0
	;;
esac

Запуск остановка приложения.

Выводы



В случае с Synology использование toolchain имеет свои плюсы и минусы.
Возможные плюсы:
  • не надо собирать и класть необходимые системные библиотеки;
  • можно включить дополнительные оптимизации по cpu.

Возможные минусы:
  • возможно придется делать сборки под каждый toolchain.


У QNAP toolchain оказался древним и пришлось идти в обход, но это другая история.
Dmitry @RPG18
карма
31,2
рейтинг 0,3
C++/Golang
Самое читаемое Разработка

Комментарии (0)

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.