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

    На новом месте работы мне поставили задачу запустить продукт на 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 оказался древним и пришлось идти в обход, но это другая история.
    Поделиться публикацией
    Похожие публикации
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 0

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