Основная идея Mxx_ru заключается в том, что каждый проект определяет target (цель), которая должна быть построена. Каждая цель описывается экземпляром класса, производного от Mxx_ru::Abstract_target. Каждая цель описывается в одном проектном файле. Каждая цель должна иметь уникальный псевдоним (prj_alias). В Mxx_ru псевдонимом цели является имя проектного файла, в котором описывается цель.
Задачей проектного файла является создание экземпляра объекта-цели и передача этого объекта в Mxx_ru с помощью функции Mxx_ru::setup_target. Поэтому проекты в Mxx_ru, как правило, имеют вид:
Класс Mxx_ru::Abstract_target является базовым классом для всех целей. Он определяет два самых важных метода: build для построения цели и clean для очистки цели. В самом классе Mxx_ru::Abstract_target эти методы считаются абстрактными (чистыми виртуальными, в терминологии C++), т.е. должны быть переопределены в производных классах. Но, поскольку в Ruby нет понятия чистого виртуального метода, то попытка вызова методов build, clean из класса Mxx_ru::Abstract_target приведет к порождению исключения Mxx_ru::Abstract_method_ex.
Получить псевдоним цели можно с помощью метода prj_alias.
Как правило, цель определяется для того, чтобы получить один результирующий файл. Например, исполнимый файл для C++ проектов, DVI-файл для LaTeX проектов или jar-файл для Java проектов. Но, в общем случае, цель может приводить к построению нескольких файлов — это зависит от типа проекта.
Сколько бы файлов не производила цель, все их полные имена должны быть переданы в базовый класс Mxx_ru::Abstract_target посредством метода mxx_add_full_target_name. Получить имена всех производимых целью файлов можно с помощью метода mxx_full_target_names.
Важно, чтобы в имена производимых файлов не включались имена промежуточных результатов построения цели. Например, для C/C++ проектов такими промежуточными результатами являются объектные файлы. Их имена не должны быть доступны через mxx_full_target_names.
Часто бывает, что цель нуждается в файлах, производимых другой целью из другого проектного файла. Например, для линкования exe-файла могут потребоваться lib-файлы, создаваемые другими подпроектами. В этих случая проект (цель) нуждается в подпроектах (подчиненных проектах, подчиненных целях).
Подпроектом должен быть проектный Mxx_ru-файл, созданный по обычным правилам формирования проектных Mxx_ru-файлов. Подпроекты указываются при помощи метода required_prj:
Метод required_prj не только сохраняет в описании проекта имя его подпроекта — в нем происходит загрузка и обработка файла подпроекта.
Получить имена всех подпроектов можно с помощью метода mxx_required_prjs.
Обработка подпроектов может зависить от типа проекта, но исходя из здравого смысла, можно ожидать, что в методе build сначала вызываются методы build для всех подпроектов. Например, в C++ проектах так и происходит.
В некоторых случаях требуется из файлов определенного типа при помощи специальных инструментов сгенерировать исходные файлы. Например, из .y-файлов с помощью yacc генерируется исходный код синтаксических анализаторов.
Различные генераторы работают с разными файлами, получают различные наборы параметров и производят разное количество различных исходных файлов. Например, инструмент uic из Qt может производить как заголовочные, так и файлы реализации.
Поэтому в Mxx_ru используется обобщенное понятие генератора. Есть базовый класс Mxx_ru::Abstract_generator, который определяет два метода: build и clean. Все генераторы должны быть производными от этого класса.
Поскольку различные генераторы требуют различных способов работы с ними, то Mxx_ru никак не специфицирует других интерфейсов генераторов. Единственное требование: генераторы должны быть переданы в Mxx_ru::Abstract_target с помощью метода generator.
За запуск генераторов отвечает конкретный класс, производный от Mxx_ru::Abstract_target. Например, классы целей для C++ проектов запускают генераторы после того, как обработают все подпроекты и перед тем, как начнется компиляция самого проекта.
Т.к. Mxx_ru не определяет интерфейса, с помощью которого любому генератору можно дать указания по генерации, то обычно использование конкретного генератора выглядит следующим образом:
Например:
Либо, учитывая, что метод generator возвращает переданный ему объект-генератор, можно вызывать методы генератора не сохраняя ссылку на него в отдельной переменной:
Получить список всех установленных генераторов можно с помощью метода mxx_generators.
Еще один способ применения генераторов описан в 6.6 на стр. 80
Mxx_ru поддерживает карту целей — псевдонимам (т.е. именам проектных файлов) сопоставлены объекты-цели. Функция Mxx_ru::setup_target предназначена для занесения очередной цели в эту карту.
Кроме того, функция Mxx_ru::setup_target автоматически запускает построение или очистку проекта, если переданная в Mxx_ru::setup_target цель является самой верхней (т.е. цель создается в проектном файле, имя которого передано интерпретатору Ruby)1.
При обработке самой верхней цели Функция Mxx_ru::setup_target проверяет наличие аргумента --mxx-clean. Если этот аргумент указан, то у цели вызывается метод clean. В противном случае у цели вызывается метод build.