Среда Разработки

Система сборки не предъявляет специальных требований к среде. Стандартная среда Linux практически всегда предоставляет все необходимые средства. Однако в условиях, когда сообщество предлагает широкий выбор дистрибутивов Linux, ориентированных на различные задачи, полезно описать минимальный набор программных и аппаратных средств, необходимых для работы. А также, дать некоторые советы по организации сетевого окружения.

Вообще, понятие среда разработки программ, является обширной темой, включающей в себя не только компиляторы различных языков программирования и системы версионного контроля. Среда, – это прежде всего сетевая инфраструктура, обеспечивающая работу коллектива программистов или целой организации, занимающейся производством программного и аппаратного обеспечения.

System Requirements

Изначально, система сборки создавалась для работы в условиях промышленного производства программного обеспечения линеек аппаратных платформ, имеющих различную архитектуру и назначение. Однако здесь, мы не будем рассматривать все вопросы, касающиеся построения полнофункциональной среды предприятия, а сосредоточимся на минимально необходимых аппаратных и программных средствах, достаточных для пользователя системы сборки.

Build System

Система сборки предназначена для работы на персональных 64-разрядных Intel машинах с установленной операционной системой Linux. Разумеется в среде должны быть установлены coreutils, tar, bash, sed, awk, bison, perl, утилиты файловых систем Ext4, FAT32, а также компилятор GNU GCC и средства autoconf, automake.

Компилятор должен быть собран таким образом, чтобы он предоставлял возможность создания не только 64-битного объектного кода, но и 32-битного. Это подразумевает наличие в системе минимального набора 32-битных системных библиотек.

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

Platform

Платформа Radix.Linux насчитывает сотни пакетов и, естественно, данный набор позволяет составить начальный список требований к среде разработки со стороны множества программ разных производителей. Однако и здесь нет ничего свехъестественого с точки зрения большинства дистрибутивов Linux.

Следующий список пакетов показывает основной набор средств, на которые прежде всего надо обратить внимание после инсталляции системы.


common utils and libraries:

            bash-4.2.045
       coreutils-8.21
      util-linux-2.29.2
            curl-7.31.0
          dialog-1.2_20130523
         ncurses-5.9
       diffutils-3.3
            file-5.14
       findutils-4.4.2
       sharutils-4.14
            flex-2.6.4
            gawk-4.1.0
             sed-4.2.2
          shtool-2.0.8

        bdftopcf-1.0.4
         gettext-0.18.2.1
   gettext-tools-0.18.2.1
     ghostscript-9.07
           gperf-3.1
            db48-4.8.30
         mariadb-5.5.32
      postgresql-9.4.1
          sqlite-3.7.17
            pcre-8.33
       libdatrie-0.2.8
             pth-2.0.7
           boost-1.54.0

            cpio-2.11
           bzip2-1.0.6
            gzip-1.6
             lha-114i
           lrzip-0.616
          libzip-0.10.1
            lzip-1.16
             lzo-2.03
            lzop-1.03
            zlib-1.2.8
              xz-5.0.5
            rzip-2.1
             tar-1.26
            wget-1.14
             vim-7.4.050
         minicom-2.6.2

Source Control Management:

             git-1.8.4
       mercurial-2.7.2
      subversion-1.7.13
          bazaar-2.6.0

File System Tools:

       e2fsprogs-1.42.8
      dosfstools-3.0.22
          mtools-4.0.18

compilers & libraries:

        binutils-2.23.52.0.1
             gcc-4.8.2-multilib
         gcc-g++-4.8.2-multilib
        gcc-objc-4.8.2-multilib
           bison-2.7
              bc-1.06.95
      erlang-otp-17.5
            llvm-3.3
             lua-5.1.5
            yasm-1.2.0
            perl-5.18.1
             php-5.4.20

           glibc-2.17-multilib

build process:

          ccache-3.1.9

make & autotools:

        autoconf-2.69
        automake-1.11.5
              m4-1.4.17
            make-3.82
           cmake-2.8.12.2
           ninja-1.6.0
            re2c-0.14.3
      pkg-config-0.25

documentation:

         texinfo-4.13a
           c2man-2.0.42
        help2man-1.43.3
        xmltoman-0.4
         gtk-doc-1.20
     NaturalDocs-1.52
             gts-0.7.6
        graphviz-2.38.0

Версии пакетов здесь характеризуют текущее состояние среды, в которой на данный момент собирается trunk репозитория platform.

Кроме того необходимо позаботиться о модулях интерпретатора языка Python. Если в среде разработки установлен Python версии 2.7, то обязательно должен быть инсталлирован пакет setuptools. Сделать это можно с помощью команды,

# wget https://bootstrap.pypa.io/ez_setup.py -O - | python

которую следует выполнять от имени привилегированного пользователя. Более подробные инструкции по инсталляции можно найти на странице setuptools репозитория пакетов языка Python.

Поскольку все пакеты для целевой системы собираются в собственном cross-окружении, список требований не велик. Однако данный список позволяет не только использовать систему сборки, но также работать над созданием собственных toolchain-ов и, кроме того, поддерживать репозиторий сторонних пакетов в собственной подсети для ускорения загрузки исходных архивов перед началом сборки. В разделе, посвященном получению продуктов Radix.Linux, мы говорили кратко об увеличении скорости загрузки и сборки сторонних пакетов.

Hardware

Для создания работоспособной среды Linux необходимо собирать большое число пакетов. Здесь, прежде всего, важны объем дискового пространства и скорость обращения к дискам. Кроме того, важно иметь достаточный запас оперативной памяти.

На данный момент состояние репозитория таково, что в качестве рекомендуемой машины, наверное, стоит указать машину, построенную на базе процессора Intel Core i7 (не ниже третьего поколения) с оперативной памятью не менее 16GiB.

Рекомендуемый объем диска, легко установить исходя из того, что после полной сборки ветки репозитория на 10 целевых устройств, ее объем составляет более 500 GiB. Таким образом, для работы с несколькими целевыми устройствами на 2-х – 3-х локальных ветках, разработчику потребуется диск объемом не менее 1 ТiB. Ну а далее, все будет зависеть от задач, стоящих перед разработчиком.

Working Example

Наш опыт показал, что создание устойчивого окружения для сборки легче всего осуществляется на базе дистрибутива Slackware. Если воспользоваться текущей сборкой оригинального дистрибутива и дополнить ее небольшим количеством пакетов, то можно в течение нескольких лет не заботиться об обновлении системы.

Разумеется, можно просто инсталлировать стабильную версию дистрибутива с одного из зеркал, список которых приведен на странице mirrorlist. Однако лучше всего создать инсталляционный диск самостоятельно, что даст возможность выбрать наиболее свежую и достаточно стабильную версию дистрибутива, удовлетворяющую текущим задачам.

Для создания загрузочного диска Slackware необходимо полностью загрузить каталог, содержащий исходный дистрибутив, например, ftp://mirror.yandex.ru/slackware/slackware64-current, на свою машину. Перейти в этот каталог и выполнить следующий скрипт:

#!/bin/sh

mkisofs -o /tmp/slackware64-dvd.iso \
  -R -J -A "Slackware Install" \
  -hide-rr-moved \
  -v -d -N \
  -no-emul-boot -boot-load-size 4 -boot-info-table \
  -sort isolinux/iso.sort \
  -b isolinux/isolinux.bin \
  -c isolinux/isolinux.boot \
  -eltorito-alt-boot -no-emul-boot -eltorito-platform 0xEF \
  -eltorito-boot isolinux/efiboot.img \
  -m 'source' \
  -V "SlackDVD" .

isohybrid -u /tmp/slackware64-dvd.iso

Первого декабря 2016 года мы проделали эти действия и загрузили готовый образ на наш FTP-сервер. В каталоге additional-packages можно найти все необходимые пакеты программ, которые надо инсталлировать поверх slackware64-current (от 1 декабря 2016 года) для того, чтобы иметь возможность собирать дистрибутив Radix.Linux.

Инсталлировать дополнительные пакеты просто. Для этого достаточно воспользоваться скриптами _install.sh, расположенными в соответствующих подкаталогах папки additional-packages, от имени пользователя root.

Важно отметить, что новая версия дистрибутива содержит свежий Bourne again shell и, для обеспечения совместимости скриптов, написанных для старых версий bash, необходимо экспортировать переменную BASH_COMPAT

# /etc/profile: This file contains system-wide defaults used by
# all Bourne (and related) shells.

export BASH_COMPAT=42

# Set the values for some environment variables:

  .  .  .

в начале файла /etc/profile Slackware-машины.

Sources

В разделе Download, посвященном получению продуктов Radix.Linux, мы уже говорили о необходимости сокращения времени сборки и о том, как можно организовать зеркалирование сторонних продуктов в собственной сети.

Здесь же, мы рассмотрим два принципа, которых, на наш взгляд, следует придерживаться неукоснительно.

Первый принцип касается версий сторонних продуктов, используемых в целевых сборках, и заключается в том, что никогда в своей работе нельзя использовать "безымянные" или "плавающие" срезы сторонних репозиториев.

Если рассмотреть, в качестве примера, следующие строки Make-файла из репозитория sources:

.
.
.

# Revisions from 'ci20-v2013.10' branch. Supports MIPS Creator CI20.
#
#                                              hash | date
#           ----------------------------------------+--------
revisions  = 6cfaf802b580f2f7e92a5dec705ff9c196c637b4-20150826

.
.
.

$(tarballs): $(git_repo)
       @for revision in $(revisions) ; do \
         hash=`echo $$revision | cut -f 1 -d '-'` ; \
         date=`echo $$revision | cut -f 2 -d '-'` ; \
         if [ ! -f u-boot-ci20-2013.10-$$date.tar.bz2 ] ; then \
           echo -e "\n======= Creating 'u-boot-ci20-2013.10-$$date.tar.bz2' snapshot =======" ; \
           ( cd $(repo_name) && \
             git archive --format=tar --prefix=u-boot-ci20-2013.10-$$date/ $$hash | \
             bzip2 >../u-boot-ci20-2013.10-$$date.tar.bz2 ) ; \
         fi ; \
       done

.
.
.

можно видеть, что мы делаем вполне осознанный выбор, а не снимаем "плавающий" HEAD.

Вдальнейшем, такой подход нам позволит, в случае обнаружения ошибок, апеллировать к автору с вполне четкими претензиями и что, наиболее важно, с точным местоположением найденой ошибки. Если бы мы не позаботились об этом ранее, и снимали безымянные срезы чужого репозитория, то нам наверное не удалось бы поговорить с автором предметно.

Второй принцип касается собственных изменений сторонних продуктов, и состоит в следующем.

Мы не храним готовые patch-файлы в репозиториях, а приготавливаем их непосредственно после загрузки исходных архивов. Примером тому может служить множество Make-файлов каталога sources. Такой подход, позволяет нам, во-первых, избавиться от возможных ошибок, связанных с наложением patch-файлов несоответствующих версий, и, во-вторых, что является наиболее важным, сохранить нашу работу в таком виде, который нам позволит не просто единожды исправить какую-либо ошибку, а обеспечить возможность наиболее быстрой адаптации к новым версиям продуктов и сохранения опыта в коллективе разработчиков.

Таким образом, для того, чтобы добавить новый пакет к целевой сборке, разработчику необходимо:

  1. Добавить алгоритм загрузки стороннего пакета в ветку репозитория sources, служащего для заполнения собственного FTP-хранилища.
  2. Создать, по образу и подобию других Make-файлов, алгоритм загрузки и, если необходимо, приготовления patch-файлов в каталоге 'sources/...' собственной ветки продуктового репозитория (например, такой, как описан в каталоге, где хранится Make-файл загрузки aalib) и, после этого;
  3. Приступить к непосредственной сборке пакета.

Дополнительную информацию по вопросу приготовления patch-файлов можно получить в разделе, посвященном определению зависимостей целевого пакета, а также во множестве файлов репозитория https://csvn.radix.pro/platform платформы Radix.Linux .

Разумеется, для одного человека, которому необходимо получить быстрый и никому более не нужный результат, данная процедура может показаться сложной и вовсе не обязательной. Однако мы основываемся на том, что работа целого коллектива разработчиков должна быть обеспечена не только средствами разработки, но и способами сохранения результатов труда, быстрого перехода на новые версии сторонних продуктов и, что не маловажно, обмена опытом между инженерами.

Toolchains

Мы уже неоднократно упоминали о том, что основным принципом платформы Radix.Linux является то, что вся разработка осуществляется исключительно cross-средствами.

Во-первых, это позволяет действительно правильно и однозначно определять зависимости пакетов друг от друга. Ведь при наличии постоянно пополняющегося, во время сбоки, окружения, пакет, который не обнаружит необходимых вещей в этом окружении, просто не соберется. Если подобная разработка идет в обычной рабочей среде, то будет необходимо приложить дополнительные усилия для того, чтобы определить зависимости. Например, просмотреть все полученые библиотеки и исполняемые файлы утилитой ldd на предмет зависимости от сторонних библиотек. Однако и этого может быть недостаточно поскольку в целевом окружении может не оказаться необходимых компонентов, которые присутствуют на машине разработчика.

Во-вторых, вся сборка конечного продукта будет являться действительно монолитной, то есть такой, когда все пакеты будут работать, на целевой машине, именно в том окружении, в котором происходила их сборка. Например, при таком подходе, не окажется, что исходные тексты пакета конфигурировались для работы с одним интерфейсом прикладного программирования (API), какого-либо набора программ и библиотек, а в реальных условиях целевой среды, пакет окажется в совершенно других условиях своего "существования".

И, наконец, в-третьих, целевые программы и библиотеки могут быть собраны так, что все ресурсы процессора и периферийного оборудования целевого устройства будут использованы с максимальной эффективностью. Тут, разумеется, не все может быть так гладко и, бывают ситуации, когда вы просто не сможете настроить компилятор на новый процессор, для которого еще нет необходимой поддержки со стороны разработчиков компилятора, однако, вы всегда сможете найти компромисс, поскольку вы полностью владеете всем процессом, начиная с построения cross-компилятора и заканчивая сборкой системы в целом.

Итак, toolchains.

Для хранения процедур сборки cross-компиляторов предусмотрен отдельный репозиторий https://csvn.radix.pro/toolchains. В отличие от остальных продуктов, система сборки встроена напрямую, поскольку является достаточно простой и не требует специальной поддержки.

Прежде чем начинать сборку какого-либо cross-компилятора, необходимо подготовить целевой каталог, в который во время сборки будут инсталлироваться готовые компоненты. По умолчанию, это каталог '/opt/toolchain'. И, в общем случае, достаточно создать этот каталог, отдав права на него группе разработчиков, так как это описано в разделе Build System in Practice.

Собрать необходимый cross-компилятор можно выполнив следующие действия.

Выбрать необходимую ветку или тег репозитория https://csvn.radix.pro/toolchains, например:

svn co https://csvn.radix.pro/toolchains/trunk toolchains

Перейти в каталог сборки, например:

cd toolchains/products/JZ47XX-glibc/1.0.9/

И выполнить команду:

make

Поскольку мы ориентируемся на сборку всех компиляторов, входящих в набор GCC, сначала будет собран "родной", для машины разработчика компилятор, используемый вдальнейшем для сборки компилятора языка ADA. Помещен он будет в каталог 'build-system/gnattools/...', так как является временным средством и предназначен лишь для работы на этапе создания cross-компиляторов.

По окончании сборки, готовый cross-компилятор, дополнительно, будет архивирован и помещен в каталог 'dist', для отчуждения.

Если во время сборки, не определена переменная TOOLCHAIN_VERSION, то, по умолчанию, в качестве версии готового toolchain-а будет принята величина '1.0.0'. Сделано это для того, чтобы вновь разрабатываемые сборки или отладочные версии не влияли на основные, используемые в работе, версии toolchain-ов, инсталлированных в каталог '/opt/toolchain'. Только после того, как сборка отлажена и протестирована, ей назначается новая версия и осуществляется ее распространение среди разработчиков. Решение о том, какую именно версию toolchain-а надо использовать, будет приниматься уже на этапе настройки той или иной версии системы сборки платформы.

Вообще, создание cross-компиляторов представляется довольно тривиальной задачей. Здесь необходимо только представлять особенности архитектуры целевого устройства и иметь навыки настройки исходных текстов программ с помощью утилит autoconf, automake. Пользователи среды Radix.Linux, рассмотрев структуру любой из веток репозитория https://csvn.radix.pro/toolchains, а также изучив раздел New Toolchain Connection, могут вполне самостоятельно делать собственные сборки компиляторов и подключать их к системе сборки платформы.

Важно заметить, что мы не случайно используем отчуждаемые cross-компиляторы, а не строим их непосредственно перед сборкой платформы. Во-первых, такой подход позволяет существенно сократить время сборки целевых систем, а во-вторых, разработка cross-компиляторов как отдельных продуктов, позволяет обеспечить более полное тестирование, так как команда, отвечающая за cross-компиляторы, может получать информацию о их работе от большого количества пользователей и тем самым накапливать и распространять опыт, который в условиях разрозненной работы, может быть просто утерян.

Network Resources

В заключение, позволим себе дать несколько советов по организации внутренней сети, но только в рамках, касающихся зеркалирования сторонних архивов и, может быть, средств обмена актуальной информацией между разработчиками.

FTP Server

Если посмотреть на содержимое каталога sources нашего FTP-сервера, можно заметить, что фактически это локальная копия master-ветки репозитория sources.

После изменения или добавления Make-файлов, отвечающих за загрузку пакетов из оригинальных источников, данные файлы обновляются на сервере, посредством команды,

$ git pull

и готовы к обновлению содержимого сервера. Разумеется, обновления делаются только в тех каталогах, где это необходимо.

Пользователи системы сборки вполне могут организовать подобное ведение истории в собственной локальной сети, сохраняя тем самым, не только сторонние архивы, но и сведения о том, где данные архивы были получены.

Последнее обстоятельство довольно важно, поскольку иногда бывает трудно найти в глобальной сети действительно оригинальный источник. Более того, некоторые пакеты, со временем, лишаются поддержки и, в лучшем случае, остаются на таких сетевых ресурсах, как ibiblio.org .

Mirrors

Как правило, производители оборудования ведут собственные репозитории ядра Linux и необходимых драйверов устройств. Размеры этих репозиториев довольно велики и, для их клонирования может потребоваться много времени.

Организовав, в собственной сети, зеркала, наиболее важных репозиториев и, отдав процедуру их обновления cron-демону, можно существенно снизить временные затраты на получение срезов этих репозиториев для FTP-хранилища.

Media Wiki

Еще одним полезным ресурсом локальной сети может быть сервер, например Media Wiki, для обмена полезной информацией между разработчиками. Информация, которая содержится на подобных ресурсах, позволяет ускорить обучение персонала, а иногда, дать простые средства взаимодействия.

Например, в условиях небольшого коллектива разработчиков, и соответствующей CM-политике, можно легко организовать очередь обновления транка.