aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Nazaryev <sergey@nazaryev.ru>2016-06-05 03:01:51 +0000
committerSergey Nazaryev <sergey@nazaryev.ru>2016-06-05 03:01:51 +0000
commit877cfec696e38b2af326d86009fbe3fd450ad727 (patch)
treef33f4d0f6c23cf1f9b470dde3faa278d3b3266eb
downloaditiviti-aptitude-test-877cfec696e38b2af326d86009fbe3fd450ad727.zip
itiviti-aptitude-test-877cfec696e38b2af326d86009fbe3fd450ad727.tar.gz
itiviti-aptitude-test-877cfec696e38b2af326d86009fbe3fd450ad727.tar.bz2
Initial release
-rw-r--r--Makefile.inc20
-rw-r--r--PROBLEM70
-rw-r--r--README48
-rw-r--r--README.md5
-rwxr-xr-xbuild-system-shell11
-rw-r--r--src/libraries/storage/Makefile4
-rw-r--r--src/libraries/transport/Makefile5
-rw-r--r--src/libraries/util/Makefile5
-rw-r--r--src/servers/Makefile3
-rw-r--r--src/servers/trading/fix/Makefile5
10 files changed, 176 insertions, 0 deletions
diff --git a/Makefile.inc b/Makefile.inc
new file mode 100644
index 0000000..5e8ac8e
--- /dev/null
+++ b/Makefile.inc
@@ -0,0 +1,20 @@
+# TODO: MAKEFILE_LIST может хранить больше, чем один (наш) Makefile, в
+# зависимости от переменной окружения MAKEFILES
+buildsysdir = $(strip $(dir $(firstword $(MAKEFILE_LIST))))
+projectdir = $(CURDIR:$(buildsysdir)%=%)
+
+build:
+ @[ "$(DRIVER)" == "subdir" ] && echo "Building $(DRIVER) $(projectdir)";
+ @builtlist="$(BUILTLIST)"; \
+ deps=''; \
+ for i in $(DEPENDS) $(SUBDIRS); do \
+ if [[ ":$$builtlist:" != *":$$i:"* ]]; then \
+ deps=$$(make BUILTLIST="$$builtlist" -C "$(buildsysdir)$$i" 3>&1 1>&2); \
+ builtlist="$$builtlist:$$deps"; \
+ echo "$$i" >&3; \
+ fi \
+ done;
+ @[ "$(DRIVER)" == "executable" || "$(DRIVER)" == "dynamic-library" ] && echo "Building $(DRIVER) $(projectdir)" >&2
+ @echo "$(projectdir)" >&3
+
+# vim: set ft=make:
diff --git a/PROBLEM b/PROBLEM
new file mode 100644
index 0000000..5ce5976
--- /dev/null
+++ b/PROBLEM
@@ -0,0 +1,70 @@
+Тестовое задание Itiviti
+========================
+
+Реализовать рекурсивный обход дерева проектов на GNU make.
+
+Есть иерархически организованное дерево проектов:
+
+src/
+ libraries/
+ storage/
+ transport/
+ util/
+ servers/
+ trading/
+ fix/
+ market_data/
+ fix/
+
+В каждой директории есть Makefile, описывающий сборку данного проекта, например
+
+src/servers/trading/fix/Makefile:
+-------
+NAME = trading_fix
+DRIVER = executable
+DEPENDS = src/libraries/storage src/libraries/transport
+-------
+
+или
+
+src/libraries/transport/Makefile:
+------
+NAME = transport
+DRIVER = dynamic-library
+DEPENDS = src/libraries/util
+-------
+
+или
+
+src/servers/Makefile:
+------
+NAME = servers
+DRIVER = subdir
+SUBDIRS = trading market_data
+------
+
+Т.е. указывается имя собираемого проекта (NAME), как его собирать (DRIVER) и список зависимостей (DEPENDS).
+Для DRIVER=subdir в переменной SUBDIRS перечисляются подпроекты.
+
+"Рекурсивная" сборка включает в себя сборку всех зависимостей проекта (подпроектов для DRIVER=subdir).
+
+Например, сборка src/servers/trading/fix вызовет сборку следующих проектов:
+src/libraries/util
+src/libraries/transport
+src/libraries/storage
+src/servers/trading/fix
+
+Задача: написать рекурсивный обход дерева проектов на языке GNU make.
+
+Т.е. запуск
+
+$ make -C src/servers/trading/fix
+
+должен вывести нечто вроде
+
+Building dynamic-library src/libraries/util
+Building dynamic-library src/libraries/transport
+Building dynamic-library src/libraries/storage
+Building executable src/servers/trading/fix
+
+Каждый проект при этом должен собираться не более одного раза.
diff --git a/README b/README
new file mode 100644
index 0000000..35593e6
--- /dev/null
+++ b/README
@@ -0,0 +1,48 @@
+Тестовая система сборки
+=======================
+
+Эта система сборки позволяет рекурсивно обходить дерево зависимостей,
+описанного с помощью файловой системы и метаинформации в Makefile'ах.
+Формат метаинформации и более подробную информацию см. в задании (файл
+`PROBLEM`).
+
+Требования к работе системы сборки
+----------------------------------
+
+ * GNU Make
+ * bash (используется башизм)
+
+Как использовать
+----------------
+
+$ ./build-system-shell # войти в shell для сборки
+$ make -C src/servers/trading/fix # собрать `src/servers/trading/fix`
+$ exit # выйти из shell для сборки
+
+Как работает
+------------
+
+Для корректной работы системы необходимо войти в специальный shell.
+На самом деле это bash с небольшими изменениями:
+ * 3 файловый дескриптор проброшен в /dev/null
+ * во все Makefile'ы, собираемые в этом shell'е, будет
+ инджектиться Makefile.inc, который предоставляет основной механизм сборки
+ (переменная `MAKEFILES`).
+ * отключается лишний verbose от GNU Make (переменная `MAKEFLAGS`)
+
+После вызова `make -C %проект%` происходит следующее:
+ * начинает выполняться цель `build` (от неё зависит цель `all` в каждом из `Makefile`)
+ * перед началом сборки мы проходимся по списку зависимостей и вызываем для
+ каждой зависимости её Makefile
+ * после того, как n-ая зависимость собралась, в 3 файловый дескриптор
+ пишется весь список собранных в процессе её сборки сущностей, который
+ потом попадает в переменную builtlist
+ * перед сборкой n-ой зависимости мы смотрим, нет ли уже в переменной
+ builtlist этой зависимости; если есть -- значит, она уже была собрана в
+ процессе данной сборки, иначе собираем её.
+ * в момент каждого дочернего вызова make передаётся переменная BUILTLIST,
+ содержащая список того, что было собрано родительским и дочерними make'ами
+ до этого
+
+*Примечание*: 3 файловый дескриптор нужен для того, чтобы передавать информацию из дочерних
+процессов так, чтобы эта информация не перемешивалась с stdout'ом и stderr'ом.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..16328df
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+Тестовая система сборки
+=======================
+
+ # . build-system.sh
+ # make -C src/servers/trading/fix
diff --git a/build-system-shell b/build-system-shell
new file mode 100755
index 0000000..fd906c0
--- /dev/null
+++ b/build-system-shell
@@ -0,0 +1,11 @@
+#!/bin/bash -efu
+
+# Переменная DIR содержит путь до директории, которая хранит выполняемый
+# скрипт (т.е. этот shell)
+# Это нужно для того, чтобы войти в шелл можно было из любой директории и путь
+# до Makefile.inc оказался правильным.
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+export MAKEFILES="$DIR/Makefile.inc"
+export MAKEFLAGS="--no-print-directory"
+exec /bin/bash 3>/dev/null
diff --git a/src/libraries/storage/Makefile b/src/libraries/storage/Makefile
new file mode 100644
index 0000000..3864c1d
--- /dev/null
+++ b/src/libraries/storage/Makefile
@@ -0,0 +1,4 @@
+NAME = storage
+DRIVER = dynamic-library
+
+all: build
diff --git a/src/libraries/transport/Makefile b/src/libraries/transport/Makefile
new file mode 100644
index 0000000..78c4519
--- /dev/null
+++ b/src/libraries/transport/Makefile
@@ -0,0 +1,5 @@
+NAME = transport
+DRIVER = dynamic-library
+DEPENDS = src/libraries/util
+
+all: build
diff --git a/src/libraries/util/Makefile b/src/libraries/util/Makefile
new file mode 100644
index 0000000..46c466c
--- /dev/null
+++ b/src/libraries/util/Makefile
@@ -0,0 +1,5 @@
+NAME = util
+DRIVER = dynamic-library
+DEPENDS = src/libraries/storage
+
+all: build
diff --git a/src/servers/Makefile b/src/servers/Makefile
new file mode 100644
index 0000000..b81b286
--- /dev/null
+++ b/src/servers/Makefile
@@ -0,0 +1,3 @@
+NAME = servers
+DRIVER = subdir
+SUBDIRS = trading market_data
diff --git a/src/servers/trading/fix/Makefile b/src/servers/trading/fix/Makefile
new file mode 100644
index 0000000..9baf9b0
--- /dev/null
+++ b/src/servers/trading/fix/Makefile
@@ -0,0 +1,5 @@
+NAME = trading_fix
+DRIVER = executable
+DEPENDS = src/libraries/storage src/libraries/transport
+
+all: build