- PVSM.RU - https://www.pvsm.ru -
Большинство разработчиков давно привыкли использовать ту или иную IDE [1] и не задумываются о том, как их исходный код превращается в исполняемый модуль. Современные средства разработки содержат UI [2] и автоматизацию сборки для огромного числа типов проектов на все случаи жизни. И это очень здорово, так как позволят не задумываться над вещами, не имеющими непосредственного отношения к решаемой задаче. Но иногда задача бывает настолько сложной, что уже не получается использовать стандартные типы проектов. И тут появляется "Система сборки проектов".
Ярким примером такого типа проектов является .NET Micro Framework [3] — реализация платформы Microsoft .NET для микроконтроллеров. В этой статье будет сделан обзор его системы сборки и особенности ее реализации.
Прежде чем говорить о том, как устроен проект и как происходит его сборка, нужно понять, какие перед проектом стоят цели и какие из этого следуют требования.
Идея .Net Micro Framewok заключается в том, чтобы разрабатывать приложения на .Net для самых маленьких устройств, управляемых микроконтроллерами. Такие устройства обладают несколькими сотнями килобайт Flash и несколькими десятками килобайт RAM. Из-за ограниченности ресурсов на них нельзя использовать полноценные операционные системы, включая IoT редакции.
Обычно разработка для таких устройств ведется на CC++ со вставками на ассемблере и тесно связана с конкретным микроконтроллером. Все управление "железом" происходит через запись и чтение множества регистров. При этом используются компиляторы и линковщики из специализированного набора для платформы — Toolchain [4].
Раньше на рынке было представлено множество архитектур
микроконтроллеров. Каждый производитель имел несколько семейств устройств и у любого из них могла быть своя схема регистров. Кроме того, существовало множество разных toolchain. Поэтому выбор микроконтроллера являлся крайне важной вехой проекта, так как потом перейти на другое устройство было очень сложно.
Сейчас миром микроконтроллеров правит ARM [5]. Многие производители отказались от собственных ядер и перешли на эту архитектуру. Это значительно унифицировало разработку и облегчило миграцию с одного устройства на другое. Кроме того, огромными темпами развивается CMSIS [6] — не зависящий от конкретного производителя набор стандартных программных интерфейсов для работы с ARM микроконтроллерами. Каждый организация поставляет реализацию CMSIS для своих устройств, что позволяет, теоретически, абстрагироваться от особенностей реализации того или иного микроконтроллера.
Но тем не мене на рынке еще существует достаточно большое количество устройств как с отличной от ARM архитектурой, так и не имеющих реализации CMSIS.
.Net Micro Framework — это попытка поднять разработку для микроконтроллеров на более высокий уровень абстракции. Если CMSIS унифицирует устройства с ARM архитектурой, то .NetMF пытается унифицировать работу с микроконтроллерами в принципе. И заодно позволяет использовать мощь управляемого кода и удобство Visual Studio при разработке для встраиваемых систем. При этом никто не ограничивает использование .NetMF только микроконтроллерами. Например, существует его реализация для Windows, которая используется в эмуляторе [7].
Таким образом, основным требованием к .NetMF является возможность запуска на любом микроконтроллере, имеющем достаточное количество памяти (в документации указаны минимальные требования 256KB RAM и 512K Flash/ROM). Исходя из этого, компиляция должна выполняться разными toolchain, в зависимости от выбранного устройства. Архитектура системы должна учитывать то, что работа на низком уровне, с "железом" может вестись как по средствам одной из реализаций CMSIS, так и любой другой библиотеки или операционной системы (как в случае эмулятора для Windows).
Другие требования, связанные с реализацией .Net, системы безопасности, отладки и т.д., я не буду рассматривать, так как они не влияют на систему сборки проекта.
Итак, к системе предъявляются три основных требования:
Причем пункты 2 и 3 являются следствием первого пункта.
.Net Micro Framework имеет следующую архитектуру:
Система разделена на несколько слоев:
Два верхних слоя (приложения пользователя и системные библиотеки) написаны на управляем коде. Это то, что мы видим в Visual Studio. Слой аппаратного обеспечения — это и есть само «железо», на котором запущен .NetMF. Слой TinyCLR — это среда исполнения кода.
TinyCLR разделена на 3 части:
Разделение на PAL и HAL выполняет требование номер три (возможность использования как API операционной системы, так и широкий набор библиотек для работы с "железом").
Абстракция HAL представляет собой набор интерфейсов, с которыми работает PAL, и более высокие уровни. Это позволяет делать множество реализаций для разных платформ и использовать любые библиотеки или API.
Таким образом, разработчики разделяют код на следующие слои:
Часть, обозначенная на схеме как Native Code, написана на C/C++. Managed Code написан на C#. Соответственно, разные части репозитория компилируются разными компиляторами.
Чтобы реализовать возможность компиляции разными toolchain и при этом сохранить целостность проекта, нужна мощная система сборки, которая позволяет производить гибкую настройку всего процесса. Система сборки первых версий .NetMF была основана на MAKEFILE [8]. Затем произошел переход на MSBuild [9]. Причем на тот момент, сборка Visual C++ проектов в Visual Studio не использовала MSBuild (а большая часть NetMF написана на CC++), поэтому пришлось делать "нестандартный" проект. В результате получилась преобразованная в формат MSBuild копия системы сборки, основанной на MAKEFILE.
В итоге, это позволило выполнить все требования, связанные с мультиплатформенностью .NetMF.
Недавно была опубликована статья [10] о системе сборки .NetMF. Автор описывает проблемы, с которыми сталкивается проект.
Имеется несколько сценариев работы:
Прежде чем рассмотреть каждый сценарий, нужно еще раз напомнить, что .Net Micro Framework является "архитектурно нейтральной" и включает как как big-endian, так и little-endian системы. Поэтому для сборки может быть использовано множество разных toolchain. Для этого применяется сложный скрипт для MSBuild. Причем при создании этого скрипта разработчики исходили из очень интересной интерпретации требования номер два: возможность использовать разные toolchain. Для них важно было, во-первых, иметь возможность добавлять новые toolchain, не "сломав" существующее решение. А, во-вторых, дать пользователю возможность выбора toolchain. Например, сейчас компиляцию можно делать как с помощью GCC ARM [11], так и с помощью MDK [12].
На этом этапе из исходных кодов собираются расширения, использующиеся MSBuild при сборке остальной части репозитория. Причины, по которым этот сценарий отделен от остальных, заключаются в особенности реализации MSBuild. Дело в том, что перед началом процесса сборки MSBuild сразу загружает все необходимые компоненты. Это значит, что они должны уже существовать к этому моменту. Кроме того, у MSBuild есть система кэширования, из-за которой собранные компоненты могут быть недоступны, если попытаться собрать остальную часть репозитория сразу после сборки предварительных компонентов.
Поэтому нужно сначала собрать расширения, затем полностью выгрузить MSBuild и уже только потом собирать остальной репозиторий.
В процессе сборки .NetMF участвует множество утилит. Одни из них занимаются подписыванием модулей, другие сжатием, третьи преобразованием форматов и т.д. Эти утилиты в основном представляют собой консольные приложения Windows. Они участвуют как в сборке "портов" для устройств, так и в сборке SDK. Поэтому они должны быть собраны заранее. В MSBuild они используются с помощью скриптов-оберток(wrappers).
Процесс создания инфраструктуры для разработки приложения для .NetMF включает в себя множество шагов:
Стоит отметить, что пакеты требуется пописывать несколько раз на разных этапах. И тут так же проявляется проблема, описанная выше (предварительная сборка). В SDK включены asseblies, которые требуются для сборки SDK. Это решается выполнением первого пункта.
Прошивка для конкретного устройства тоже появляется в результате выполнения большого количества шагов:
Все это выполняется с помощью скриптов для MSBuild.
Этот пункт следует из требования об использовании широкого набора библиотек для работы с "железом".
Любой проект так или иначе сталкивается с зависимостями между его составными частями. Это могут быть как ссылки между файлами, так и ссылки между программными модулями, такими, как .exe и .dll. В общем случае существует два типа зависимостей, которые нужно разрешать:
В .NetMF есть как жесткие, так и мягкие зависимости. И если жесткие зависимости разрешаются автоматически, то проблема мягких зависимостей является одной из самых сложных. Сейчас она решается путем указания определенных значений в переменных окружения и указания ссылок на реализации в скриптах MSBuild. Это не лучшее решение, хотя оно и работает. Скрипты настолько сложны и полны ссылок друг на друга, что понять, где именно нужно поменять ссылки, очень сложно.
Подводя итог, можно сказать, что .NetMF из-за своей "архитектурной нейтральности" имеет весьма сложную структуру. Следствием этого является очень непростая система сборки проекта. Мы рассмотрели основные задачи, их общие решения и некоторые особенности системы сборки .NetMF. В следующей статья я расскажу о деталях реализации этой системы с помощью скриптов для MSBuild.
Автор: AlexandrSurkov
Источник [14]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/117581
Ссылки в тексте:
[1] IDE: https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D0%B3%D1%80%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%B0%D1%8F_%D1%81%D1%80%D0%B5%D0%B4%D0%B0_%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B8
[2] UI: https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D1%82%D0%B5%D1%80%D1%84%D0%B5%D0%B9%D1%81_%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8F
[3] .NET Micro Framework: https://ru.wikipedia.org/wiki/.NET_Micro_Framework
[4] Toolchain: https://en.wikipedia.org/wiki/Toolchain
[5] ARM: https://ru.wikipedia.org/wiki/ARM_%28%D0%B0%D1%80%D1%85%D0%B8%D1%82%D0%B5%D0%BA%D1%82%D1%83%D1%80%D0%B0%29
[6] CMSIS: http://www.arm.com/products/processors/cortex-m/cortex-microcontroller-software-interface-standard.php
[7] эмуляторе: https://geektimes.ru/post/265986/
[8] MAKEFILE: https://habrahabr.ru/post/155201/
[9] MSBuild: https://ru.wikipedia.org/wiki/MSBuild
[10] статья: https://github.com/NETMF/netmf-interpreter/wiki/BuildSystemRequirements
[11] GCC ARM: https://launchpad.net/gcc-arm-embedded
[12] MDK: http://www2.keil.com/mdk5/
[13] XIP: https://ru.wikipedia.org/wiki/Execute_in_place
[14] Источник: https://geektimes.ru/post/274094/
Нажмите здесь для печати.