Использование Возможностей Git В Модульной Системе Сборки Проекта

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

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

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



Использование возможностей git в модульной системе сборки проекта

Несколько слов о примерах Изначально предполагалось предоставить данной публикации фрагменты системы сборки в том виде, в котором она реализована в ЛИНТЕР , однако в этом проекте мы не используем нативные модули git и используем собственную утилиту make. Поэтому, чтобы не пострадала практическая ценность материала для читателей, все примеры адаптирован для использования совместно с подмодулями git и gnu make, что привело к определённым трудностям, которые будут указаны ниже.

Описание демо-версии Для простоты рассмотрим интеграцию системы сборки с git на примере условного продукта под названием project, который состоит из следующих функциональных модулей: приложения – само приложение; демо – демонстрационные примеры; libfoo и libbar — это библиотеки, от которых зависят приложения.

Граф зависимостей проекта будет следующим:

Использование возможностей git в модульной системе сборки проекта

Рисунок 1. График зависимости проекта.

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

Этот метод организации имеет ряд преимуществ по сравнению с монорепозиторием:

  • каждый субмодуль имеет отдельную историю редактирования;
  • возможность клонировать только часть проекта;
  • каждый репозиторий может иметь индивидуальные правила и политики доступа;
  • возможность извлечения проекта в произвольную структуру рабочей копии.

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

При этом корневой make-файл проекта должен не только «знать» положение модулей внутри проекта, но и обеспечивать вызов дочерних процессов make на целевых объектах в необходимой последовательности: от ветвей дерева зависимостей к корни.

Для этого нужно явно описать эти межмодульные зависимости; в нашем примере это сделано следующим образом :

  
  
  
  
  
   

MODS = project application libfoo libbar demo submodule.project.deps = application demo submodule.demo.deps = application submodule.application.deps = libfoo libbar submodule.libfoo.deps = submodule.libbar.deps =

Корректного обхода этого дерева можно добиться с помощью инструментов make, создав динамические цели с явным указанием зависимостей, для чего объявим функцию gen-dep следующего вида:

define gen-dep $(1):$(foreach dep,$(submodule.$(1).

deps),$(dep)) ; endef

Теперь если в теле корневого Makefile вызвать gen-dep для всех модулей

$(foreach mod,$(MODS),$(eval $(call gen-dep,$(mod))))

тогда это создаст следующие динамические цели во время выполнения (вы можете проверить это, запустив make с ключом -p)

project: application demo demo: application application: libfoo libbar libbar: libfoo:

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

В то же время, если имя цели совпадает с существующим файлом или каталогом, то это может привести к сбою выполнения, так как make «не знает», что эти наши цели — действия, а не файлы, во избежание этого укажем явно:

$(eval .

PHONY: $(foreach mod,$(MODS), $(mod)))

Допустим, перед разработчиком стоит задача внесения изменений в приложение, для чего ему необходимо получить только подмодули application, libbar, libfoo. Для этого система сборки должна на основе заявленных выше зависимостей сформировать описание модулей и их размещение для последующего использования git, что, как известно , описывает зарегистрированные подмодули в файле с именем .

gitmodules, расположенном в корне клонированного репозитория.

Мы принесем это следующие изменения в нашем примере, чтобы обеспечить генерацию .

gitmodules минимально необходимого состава:

… MODURLPREFIX ?= [email protected]/ MODFILE ?= .

gitmodules … define tmpl.module "[submodule \"$(1)\"]" endef define tmpl.path "\tpath = $(1)" endef define tmpl.url "\turl = $(1)" endef … define submodule-set submodule.$(1).

name := $(2) submodule.$(1).

path := $(3) submodule.$(1).

url := $(4) endef define set-default $(call submodule-set,$(1),$(1),$(1),$(MODURLPREFIX)$(1).

git) endef define gen-dep $(1):$(foreach dep,$(submodule.$(1).

deps),$(dep))

Теги: #git #make #Системы контроля версий #linter #разработка #инструменты разработчика #Разработка веб-сайтов #git #Системы контроля версий

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.