Основные принципы Mono, инструменты, создание простейшего приложения
Серия контента:
Этот контент является частью # из серии # статей: Работаем с Mono. Часть 1
Этот контент является частью серии: Работаем с Mono. Часть 1
Следите за выходом новых статей этой серии.
Mono — программная платформа, позволяющая разработчикам достаточно просто создавать развитые кроссплатформенные приложения. Технология Mono разрабатывается в виде open source реализации технологии .NET Framework от Microsoft и поддерживает стандарты ECMA-334 (стандарт языка C#) и ECMA-335 (стандарт среды исполнения (Common Language Runtime, CLI). Открытость указанных стандартов позволяет уменьшить проблемы создания кроссплатформенных приложений.
В базовом варианте Mono состоит из нескольких компонентов:
- Компилятор языка C# — компилятор с полной поддержкой версий 1.0 и 2.0 языка C#. Кроме того в последних версиях поддерживаются практически все возможности версии C# 3.0, а начиная с версии Mono 2.6 включена поддержка возможностей версии C# 4.0 (пока только как опция, полноценная поддержка заявлена в версии 2.8).
- Среда исполнения Mono — состоит из среды исполнения (CLI) непосредственно, компилятора среды исполнения (Just-In-Time, JIT), генератора машинного кода (Ahead-Of-Time, AOT), загрузчика сборок, сборщика мусора, подсистемы управления многопоточностью и компонентов поддержки взаимодействия между сборками и COM (или аналогами в Linux, например XCOM).
- Базовая библиотека классов — набор стандартных классов, совместимых с классами Microsoft .NET Framework.
- Библиотека классов Mono — набор классов, поддерживающих дополнительные функции для разработки Linux-приложений. Например, классы для поддержки Zip, OpenGL, Cairo, Gtk+.
Совместимость Mono и Microsoft .NET Framework
В текущей версии Mono поддерживаются следующие версии и возможности Microsoft .NET Framework:
- поддержка версии .NET 1.1:
- язык C# 1.0;
- базовые библиотеки версии 1.1: mscorlib, System, System.Xml;
- ASP .NET 1.1 (разработка веб-приложений);
- ADO .NET 1.1 (модель доступа к данным);
- Winforms/System.Drawing 1.1 (пользовательский интерфейс Microsoft Windows);
- базовые классы пространств имен System.Management (информация о системе, работа с устройствами) и System.EnterpriseServices (разработка масштабируемых бизнес-приложений, преимущественно на базе COM+ технологии) не поддерживаются в связи с отсутствием близких по идеологии технологий в Linux.
- поддержка версии .NET 2.0:
- язык C# 2.0 (поддержка дженериков (шаблонов, generics);
- базовые библиотеки версии 2.0: mscorlib, System, System.Xml;
- ASP .NET 2.0 (кроме WebParts);
- ADO .NET 2.0;
- Winforms/System.Drawing 2.0 (не поддерживаются языки с письмом справа налево);
- поддержка версий .NET 3.0 и 3.5:
- C# 3.0;
- System.Core (базовая библиотека классов);
- LINQ (Language Integrated Query, интегрированный язык запросов);
- ASP .NET 3.5;
- ASP .NET MVC (создание веб-приложений с поддержкой шаблона “модель-представление-поведение”);
- LINQ to SQL — поддержка большинства (но не полного комплекта) функций;
- WCF (Windows Communication Foundation) — частичная поддержка на уровне библиотек Silverlight 2.0;
- WPF (Windows Presentation Foundation) — не поддерживается и пока поддержка не планируется;
- WF (Workflow Foundation) — не поддерживается, планируется поддержка с версии WF4;
- поддержка версии .NET 4.0, реализованная в версии Mono в SVN:
- C# 4.0;
- ASP .NET 4.0 (пока частичная поддержка);
- LINQ 4.0.
Описание основных компонентов и возможностей Mono
Компилятор Mono C# поддерживает версии языков C# 1.0, 2.0 и 3.0. Для создания кода можно использовать один из нескольких вариантов компилятора, в зависимости от потребностей:
- mcs — компилятор, поддерживающий версию 1.1 среды исполнения. Компилирует код на языках C# 1.0 и C#3.0 (без поддержки дженериков и всего, что с ними связано). Данный компилятор планируется исключить в версии Mono 2.8, как устаревший.
- gmcs — компилятор, поддерживающий версии от 2.0 до 3.5 среды исполнения и обладающий полной поддержкой C# 3.0.
- smcs — опциональный компилятор для создания Moonlight (аналог Microsoft Silverlight) приложений.
- dmcs — опциональный компилятор, реализованный в тестовом варианте в версии Mono 2.6 и планируемый к включению в версию 2.8. Поддерживает среду исполнения версии 4.0 и язык C# 4.0.
Начиная с версии Mono 2.2 реализована поддержка классов компилятора Mono.CSharp.Evaluator (сборка Mono.Sharp.dll) для создания собственных сервисов компиляции.
Среда исполнения Mono поддерживает инфраструктуру промежуточного языка CLI (Common Language Infrastructure), соответствующую стандарту ECMA-335. Виртуальная машина среды исполнения допускает возможность запуска приложений и сборок, скомпилированных в других системах (например, возможно запускать в Linux без перекомпиляции приложения, созданные при помощи Microsoft Visual Studio для исполнения в Microsoft Windows).
Также, вместо использования виртуальной машины, среда исполнения может быть интегрирована в приложение с целью создания встраиваемой системы, не требующей установки Mono для запуска и обладающей высоким быстродействием. При этом, в приложение включаются только необходимые компоненты среды исполнения.
В среде Mono реализован Ahead-Of-Time (AOT) компилятор промежуточного языка. Цель этого компилятора в том, чтобы уменьшить время запуска программы и оптимизировать ее код, путем компиляции промежуточного языка CLI в машинный код. Аналогом в Microsoft .NET Framework является утилита Ngen. Для запуска приложения в этом режиме можно воспользоваться опцией —aot среды исполнения (также можно включить полную оптимизацию кода при помощи опцее -O=all). Например:
В качестве сборщика мусора в данный момент используется Boehm’s GC, однако в текущей разрабатываемой ветке SVN присутствует совершенно новый сборщик мусора, разработанный специально для Mono.
Установка Mono
Mono входит в репозитории огромного количества дистрибутивов, поэтому проблем с установкой из репозитория возникнуть не должно. Другой вопрос, какие версии располагаются в репозиториях. На данный момент на сайте проекта Mono предлагается скачать бинарные файлы версии 2.4.x. Эти же версии лежат в репозиториях современных дистрибутивов. Последней стабильной версией Mono считается 2.6.3, которая имеется только в виде исходных текстов.
Если есть желание установить Mono 2.6.3, то придется заняться самостоятельной сборкой версии из исходных текстов.
В качестве подопытной системы выберем недавно вышедшую Ubuntu 10.04. Тем не менее пользователям других версий и дистрибутивов это не должно особенно огорчать, потому что разница будет только в менеджерах пакетов и именах пакетов.
Для чистоты эксперимента, чтобы определить все пакеты, которые нужны, возьмем систему Ubuntu 10.04 установленную с нуля и обновленную (при помощи Synaptic или aptitude) до текущего состояния.
Первым делом создадим каталог для исходных текстов и сборки проектов:
Для работы с пространством имен System.Windows.Forms (на классах которого построен графический интерфейс операционных систем семейства Microsoft Windows) необходимо установить библиотеку libgdiplus, которая реализует функции Microsoft GDI+ для Mono. Взять исходные тексты этой библиотеки можно с сайта проекта Mono:
Распакуем исходные тексты и перейдем в каталог проекта:
При базовой установке Ubuntu устанавливается минимальный набор инструментов для разработчика, поэтому необходимо проследить, чтобы нужные инструменты присутствовали в системе. Для установки и работы потребуются компилятор g++, парсер Bison, интерпретатор макроязыка M4, библиотека Glib 2.0, GetText для поддержки интернационализации. Для работы с Mono требуется также Pkg-config. При отсутствии в системе эти пакеты (и их зависимости) нужно будет установить. Для Ubuntu это делается командой:
Для работы библиотеки libgdiplus нужна библиотека libcairo2 версии не ниже 1.6.4. Эта библиотека входит в состав исходных текстов libgdiplus и может быть скомпилирована совместно с ней, однако при наличии более свежей версии рекомендуется пользоваться именно ей. В репозиториях Ubuntu 10.04 лежит libcairo2 версии 1.8.10. Установим ее из репозитория:
Остается только сконфигурировать и собрать libgdiplus. По умолчанию установка производится в каталог /usr/local/bin для библиотеки и /usr/local/include для заголовочных файлов, что не всегда удобно, так как в будущем понадобится настройка переменных окружения LD_LIBRARY_PATH и LD_RUN_PATH. Удобнее, если библиотеки и заголовочные файлы будут расположены в /usr/bin и /usr/include соответственно.
Скачиваем mono runtime:
Рассмотрим наиболее интересные параметры конфигурации исходных текстов:
Этот параметр установлен в yes по умолчанию. При этом mono оптимизмруется для работы под средствами виртуализации Xen. В реальной среде производительность несколько ниже. Мы в нашем случае будем использовать no.
Возможность выделения приложением больших объемов памяти (свыше 3 Гб). По умолчанию no.
Включение поддержки Moonlight — свободного аналога Microsoft Silverlight.
Местоположение библиотеки libgdiplus для поддержки классов System.Windows.Forms. Значение installed означает, что библиотека установлена в системе (как в нашем случае), sibling — исходные тексты библиотеки лежат в каталоге с текстами mono,
— библиотека установлена по указанному пути (используется, если библиотека установлена в нестандартный каталог или установлено несколько разных версий в разных каталогах).
Включение поддержки больших массивов, у которых индекс выходит за пределы Int32.MaxValue. По умолчанию такие массивы не поддерживаются даже в 64-битных системах (в том числе и в Microsoft Windows для архитектуры x64).
Включение многопоточного сборщика мусора при наличии нескольких процессоров. По умолчанию сборщик мусора однопоточный. Следует заметить, что разработчики Mono предупреждают, что возможность является экспериментальной и не протестирована тщательно.
Конфигурируем и устанавливаем Mono:
В моем случае изначально сборка закончилась неудачно в связи с тем, что make почему-то не хватило прав, хотя собиралось все в домашнем каталоге пользователя. Если вдруг такое произошло, помогает sudo make вместо make.
Mono Runtime готов к работе.
Создание первого приложения
С целью протестировать работоспособность Mono создадим традиционное приложение Hello World с выводом в терминал и вариант с созданием окна.
Для вывода в терминал воспользуемся методом WriteLine класса Console.
Скомпилируем программу с поддержкой .NET версии 1.1:
Или с поддержкой .NET версии 2.0:
Компиляция должна пройти без ошибок и запуск:
приводит к выводу в консоль сообщения “Hello World! This is our first Mono program”
Сделаем ознакомительное приложение с использованием графического интерфейса. В среде Linux уместнее всего было бы использовать библиотеки Gtk#, однако в данный момент эта библиотека не установлена и это будет темой одной из будущих статей. Воспользуемся библиотекой Winforms, которая входит в состав Mono по умолчанию. Работа с этой библиотекой также будет описана в будущих статьях, поэтому код дается без комментариев.
Скомпилируем программу с поддержкой .NET версии 1.1:
Или с поддержкой .NET версии 2.0:
Не забываем указать ключ -pkg:dotnet, подключающий библиотеки, содержащие пространство имен System.Windows.Forms.
на экране появится пустое окно с заголовком “Hello World! This is our first Mono program” и кнопками сворачивания, разворачивания и закрытия.
MoMA — анализатор “чужих” сборок
Как было сказано выше, Mono совместим с .NET Framework на уровне исполняемых файлов и сборок. Однако, как это часто бывает, запуск скомпилированных, например, в Microsoft Visual Studio программ заканчивается ошибочно. В этом случае не помешает определить, стало ли причиной ошибки отсутствие какой-либо библиотеки в среде Mono в Linux (и решить проблему установкой этой библиотеки) или проблема связана с тем, что та или иная возможность не поддерживается в Mono.
В этом поможет инструмент Mono Migration Analyzer (MoMA), который можно скачать с сайта проекта Mono.
Для запуска MoMA его нужно распаковать в отдельный каталог и запустить сборку MoMA.exe:
Тестирование сборок на совместимость состоит из пяти шагов и интуитивно понятно, более того реальный шаг всего один — выбор сборок для тестирования, остальные шаги содержат справочную информацию, итоги тестирования и форму для сбора информации о том, как улучшить данный инструмент.
Следует отметить, что MoMA — инструмен достаточно простой, поэтому возможны варианты, что какие-то проблемы в коде найдены не будут, а также возможно нахождение проблемы, которая, тем не менее, не помешает исполнению кода.
Все проблемы, которые находит MoMA можно свести к четырем видам.
- Missing Methods — отсутствующие методы.
В сборке присутствует вызов методов, которые не имеют никакой реализации (в том числе даже заглушки) в Mono. Если такое приложение попытаться скомпилировать в Mono, это приведет к ошибке вида:
Если же данный код скомпилировать, например, в Visual Studio, а затем запустить в среде Mono, это приведет к исключению System.MissingMethodException при вызове отсутствующего метода.
Бороться с этой проблемой можно двумя способами. Первый состоит в том, чтобы заменить отсутствующий метод другими методами, реализующими ту же задачу. Второй состоит в том, чтобы реализовать отсутствующий метод и, по возможности, предложить его для включения в новую версию Mono.
MonoTodo — вызов методов, реализованных частично.
Вызов подобных методов может привести к проблеме, а может и не привести. Как правило атрибутом [MonoTodo] помечаются методы, в которых либо нереализована какая-то небольшая часть функциональности, либо метод нуждается в чистке и оптимизации. При использовании данных методов проблем, скорей всего не будет, хотя часть функциональности может оказаться недоступной.
Если проблема возникает, можно обойти использование данного метода, дождаться его более полной реализации в будущих версиях Mono или реализовать самостоятельно и включить в будущие версии.
NotImplementedException — исключение “метод не реализован”.
Проблема очень похожа на предыдущую с той разницей, что при каких-то обстоятельствах метод может вернуть исключение NotImplementedException. Проявится проблема или нет можно понять только после тестирования приложения в среде Mono. Если проблема проявляется, то пути для ее решения будут такими же, как и в предыдущем случае.
P/Invokes (Platform Invokes) — вызов функций, написанных на неуправляемых языках.
Проблема может возникнуть, если, например, используется вызов методов COM-объектов в среде Microsoft Windows. Само собой разумеется, что эти объекты не имеют реализации в Linux. Решить проблему можно реализовав схожую функциональность в управляемом коде или создав необходимую библиотеку для Linux.
Если же вызов происходит из COM-объектов, написанных самостоятельно, то должна быть обеспечена их кроссплатформенность, тогда ошибок при исполнении кода не будет. В противном случае лучше изменить реализацию так, чтобы вызовы из COM-объектов не использовались.
Работа с MoMA из командной строки
В случае, если использование графического интерфейса не нужно или невозможно, можно использовать MoMA из командной строки.
При этом указывается параметр —nogui, может быть указан параметр —out с указанием месторасположения отчета об анализе, а затем указывается одна или несколько анализируемых сборок. Например:
Заключение
Мы рассмотрели основные возможности среды исполнения Mono. К сожалению, большинство подробностей о внутренней работе среды исполнения и библиотеках (в том числе и более подробное рассмотрение кода простых приложений этой статьи) остались не охваченными, однако многие из пробелов будут рассмотрены в будущих статьях. Кроме того, большая часть информации о функционировании .NET Framework актуальна и для Mono. Так, например, рекомендуется ознакомиться с обзором .NET Framework.