Как обрабатывать правило сборки с неизвестными целями в OMake при построении генератора списка целей

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

У меня есть несколько файлов определений и инструмент, который может использовать эти файлы определений и создавать файлы GraphViz. Однако есть две проблемы:

  • Каждый файл определения может создавать несколько графиков, и список графиков, которые он может создавать, закодирован в файле. В моем инструменте дампа есть опция -list, в которой перечислены все графики, которые создаст файл определения.
  • Этот инструмент дампа встроен в исходное дерево.
  • Я хочу, чтобы этот список был доступен в OMakefile, чтобы я мог использовать другие правила для преобразования файлов DOT в SVG и иметь фальшивую цель, зависящую от всех SVG (цель: единая команда сборки, которая строит SVG-описания всех моих графиков).

Если бы у меня была только первая проблема, это было бы легко — я бы запустил инструмент для создания списка, а затем использовал этот список для создания цели, которая вызывает дампер для вывода файлов GraphViz. Тем не менее, я скорее застрял на принудительной сборке инструмента дампа до того, как он понадобится.

Если бы это был make, я бы просто рекурсивно запустил make, чтобы построить инструмент дампа. Однако OMake не допускает рекурсивного вызова, а функцию build можно использовать только из osh.

Любые предложения для хорошего решения этой проблемы?


person Michael Ekstrand    schedule 26.03.2010    source источник


Ответы (1)


Хорошо, вот мое предложение. Во-первых, вот быстрый генератор, сделанный в bash, который может принимать аргумент «--list», который создает переменную omake, содержащую список вещей, которые нужно сделать. Генератор называется «generator.txt», так как мы собираемся «сделать» его, переименовав в .sh.

#!/bin/bash

if [ "$1" = "--list" ]; then
    echo -e 'FILES[] = \n\ta\n\tb\n\tc'
else
    echo 1 > a.dot
    echo 2 > b.dot
    echo 3 > c.dot
fi

Затем сам OMakefile:

.INCLUDE: rules : generator.txt
    cp generator.txt generator.sh
    chmod 755 generator.sh  
    ./generator.sh
    ./generator.sh --list > rules

DOTS[] =
    $(addsuffix .dot, $(FILES))

SVGS[] =
    $(addsuffix .svg, $(FILES))

# rule to turn a .dot into a .svg
%.svg: %.dot
    cp $*.dot $*.svg

.DEFAULT: $(SVGS)

.PHONY: clean
clean:
    rm -f generator.sh a.* b.* c.* rules

Хитрость здесь заключается в том, чтобы сгенерировать файл «правил» из генератора.txt, который будет включен в OMakefile. Всякий раз, когда генератор.txt (исходник для нашего генератора) изменяется, мы заново создаем (собираем) генератор, запускаем его (создавая файлы a.dot, b.dot, c.dot) и, наконец, запускаем его с --list для создания нашего Переменная FILE[], содержащая список файлов для генерации.

Затем становится тривиальным создание переменных DOTS и SVGS, а также правила, которое превращает точку в svg. Цель по умолчанию зависит от списка svgs, который будет строить все по порядку.

Проблема с этим подходом заключается в том, что сборка генератора довольно грубая, поскольку мы должны иметь список зависимостей «INCLUDE», являющийся реальными файлами. Тем не менее, это должно по крайней мере выполнять операции в правильном порядке.

Обратите внимание, как изменение генератора.txt (например, добавление другого .dot для создания или изменение того, как будет генерироваться содержимое .dot) правильно приводит к повторному созданию генератора.sh, а затем любого сгенерированного файла, который был бы был изменен.

РЕДАКТИРОВАТЬ

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

Я полагаю, что есть способы обойти это:

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

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

  • Третий, который был бы моим любимым, — иметь двухэтапную систему сборки. В подкаталоге у вас есть OMakefile, который генерирует генератор и выводит файлы. В другом подкаталоге у вас есть еще один OMakefile, который считывает содержимое первого каталога для создания списка файлов для обработки, а затем запускает преобразование. Затем в основном каталоге bash-скрипт вызывает omake в первом каталоге, затем во втором. Надеюсь, это должно означать, что вы можете сгенерировать все с помощью одной команды, но также и то, что перестроение будет минимальным: первый omake будет регенерировать файлы только в том случае, если входные данные изменились, а второй omake преобразует только измененные или новые файлы.

person small_duck    schedule 13.04.2010
comment
Спасибо. Я пробовал аналогичное решение с INCLUDE. Однако моя программа-генератор сама по себе является нетривиальной программой OCaml. Я не понимал, что INCLUDE deps должны быть настоящими файлами, и пытался использовать свою программу как зависимость; это не сработало (не удалось построить программу). Из-за отсутствия в OMake поддержки рекурсивных сборок я не вижу простого способа использовать это решение. Есть предложения в этом духе? - person Michael Ekstrand; 14.04.2010