Як відобразити залежності, задані в makefile як дерево?


18

Проблема

Я хочу побачити залежності для однієї або декількох цілей makefile. Тому я шукаю програму, яка зможе проаналізувати makefiles, а потім представлятиме залежності в якомусь дерев’яному форматі (відступ, ascii-art, ...) або у вигляді графіка (крапка, ...).

Подібні

Є програми, які роблять це для інших ситуацій:

  • pactree або борговий кредит може відображати залежності для програмних пакетів у відповідному форматі у дереві, як формат ascii або у вигляді dotграфіка,
  • gcc -M source_file.c відображає залежності вихідного файлу С як правило формування,
  • pstree відображає ascii подання дерева процесу.

Прогрес

У пошуку в Інтернеті я знайшов незначну допомогу . Це привело мене до спробу

make --always-make --silent --dry-run some_target | \
  grep --extended-regexp 'Considering target file|Trying rule prerequisite'

але схоже, що я маю зламати ще якийсь код розбору в perl або python, щоб представити це як гарне дерево / графік. І я ще не знаю, чи дійсно отримаю повний і правильний графік таким чином.

Вимоги

Було б непогано обмежити графік якимось чином (ніяке вбудоване правило, лише задана ціль, лише деяка глибина), але здебільшого я просто шукаю інструмент, який дасть мені залежність у якомусь "розумному", людському -видимий формат (як програми у розділі "Подібні" робити).

Запитання

  • Чи є програми, які можуть це зробити?
  • Чи отримаю я повну та правильну інформацію make -dnq ...?
  • Чи є кращий спосіб отримати цю інформацію?
  • Чи існують сценарії / спроби розбору цієї інформації?

1
Тут важливо зрозуміти: Залежності НЕ утворюють дерево. Вони утворюють спрямований і (сподіваюся!) Ациклічний графік - також відомий як DAG . Спробуйте накреслити графік залежності для наступного, і ви побачите його: A залежить від B; A також залежить від C; B залежить від D; C залежить від D.
Wildcard

@Wildcard Я знаю, але для моєї мети достатньо представити залежності як дерево. Я чудово копіюю підграграфи (і вирізаючи по колах), щоб зробити його деревом. Вибачте, що явно не вказали. Для вас прикладу, я б добре з виходом printf 'A\n B\n D\n C\n D\n'. (Хто сказав, що я не можу ставити нові рядки в коментарі? :)
Лукас

Як це можна відрізнити від "A залежить від B; B залежить від D; D залежить від C; A залежить від D"? Ви можете накласти повне замовлення на будь-який DAG (оскільки будь-який DAG також являє собою часткове впорядкування), але ви не можете перетворити DAG у дерево. Це основна теорія графів. Мені було б цікаво побачити ваш алгоритм створення дерев яного представлення DAG, яке потім може відображатися. Без такого базового алгоритму будь-який інструмент, який прагнув відображати залежності як дерево, був би надзвичайно хитким та схильним до помилок.
Wildcard

Можливо, я знову не був достатньо явним, але я подумав, що приклади, які я наводжу в розділі " Подібні", це зрозуміли. Мене не цікавить теорія графів (принаймні в цьому питанні). Все, що я хочу для цього, - це візуальне зображення, схоже на дерево (особливо, якщо воно повинно відображатися на терміналі, оскільки dotграфіки замовлень, очевидно, добре). Я трохи оновлю питання, щоб зробити його більш зрозумілим (сподіваюся).
Лукас

2
РАНТ: Я, чесно кажучи, трохи розчарований, що змусити не запропонувати щось подібне нестандартно. Make є однією з найпоширеніших систем побудови в світі, і ця особливість була б настільки надзвичайно корисною, що важко зрозуміти, що за час бога відомо, скільки десятиліть, які складаються, ніхто не додав такої функції. Виведення цієї інформації у чітко визначеному текстовому форматі було б цілком достатньо. Я розумію, що make є відкритим кодом, і я завжди міг сам додати цю функцію. І повірте, якби make в принципі не була для мене чорною скринькою, я б! ОРАНТАЙТЕ над.
antred

Відповіді:


10

Спробуйте makefile2graph від того ж автора, є аналогічний інструмент MakeGraphDependitions, записаний javaзамість c.

make -Bnd | make2graph | dot -Tsvg -o out.svg

Потім використовуйте деякий редактор векторної графіки, щоб виділити потрібні з'єднання.


1
Я спробував цей інструмент. Він навіть не починає працювати (принаймні, не для будь-якого з втілень, з якими я намагався). Здебільшого він просто вискакує з деяким порушенням доступу до пам'яті.
antred

3

Я знайшов свого роду хак, щоб принаймні вивести чітко структуровану інформацію про те, яка ціль залежить від того, які передумови. Мінус - досить настирливий. Іншими словами, вам потрібно змінити свій файл файлів, щоб перетворити рецепти збірки всіх ваших цілей у трохи умовну функцію. Я опублікую короткий приклад:

getRecipe = $(if $(DEPENDENCY_GRAPH),@echo Target $@ depends on prerequisites "$^",$(1))


VARIABLE_TARGET_NAME = foobar.txt

all : TopLevelTarget

TopLevelTarget : Target_A Target_D
    $(call getRecipe,\
        @echo Building target $@)

Target_A : Target_B
    $(call getRecipe,\
        @echo Building target $@)

Target_D : Target_C
    $(call getRecipe,\
        @echo Building target $@)

Target_B : $(VARIABLE_TARGET_NAME)
    $(call getRecipe,\
        @echo Building target $@)

Target_C :
    $(call getRecipe,\
        @echo Building target $@)

$(VARIABLE_TARGET_NAME) :
    $(call getRecipe,\
        @echo Building target $@)

У цьому прикладі я використовую ручну прокручену функцію getRecipe, щоб обгортати рецепт кожної окремої цілі, а потім вирішувати, чи реально запускати цей рецепт або просто виводити, яка мета будується і від яких передумов залежить. Останнє відбувається лише за умови встановлення змінної DEPENDENCY_GRAPH(наприклад, як змінної середовища). У прикладі рецепт збірки - це не що інше, як відлуння, що говорить про те, що мета будується, але ви, очевидно, можете замінити це командою на ваш вибір.

Якщо DEPENDENCY_GRAPHвстановлено 1, це призводить до виводу:

Target foobar.txt depends on prerequisites ""
Target Target_B depends on prerequisites "foobar.txt"
Target Target_A depends on prerequisites "Target_B"
Target Target_C depends on prerequisites ""
Target Target_D depends on prerequisites "Target_C"
Target TopLevelTarget depends on prerequisites "Target_A Target_D"

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

Якщо DEPENDENCY_GRAPHне встановлено взагалі або встановлено 0, вихід:

Building target foobar.txt
Building target Target_B
Building target Target_A
Building target Target_C
Building target Target_D
Building target TopLevelTarget

або, іншими словами, замість цього використовується звичайний рецепт збірки. Я ще не перевіряв, чи надійно це працює зі складними рецептами. Однією з проблем, з якою я вже стикався, є те, що вона зовсім не працює з багаторядковими рецептами.

Наприклад, в останньому рецепті збирання цілі, якщо крім того, що сказано, що ціль будується, я насправді хотів touchу файл:

$(VARIABLE_TARGET_NAME) :
    $(call getRecipe,\
        @echo Building target $@\
        touch $@)

makeначебто здається, що touch $@частина є лише частиною відлуння в попередньому рядку:

Building target foobar.txt touch foobar.txt

Якщо я відмовлюся від зворотної косої риски в попередньому рядку, makeскаржиться на *** unterminated call to functionдзвінок ': відсутнє )'. Stop.Якщо у когось є ідея, як змусити makeграти добре, я всі вуха. :)

EDIT: Інша проблема такого підходу полягає в тому, що це буде працювати лише тоді, коли результатів збірки вже не існує, оскільки, makeочевидно, не виконується рецептура збірки цілі, яку вона вважає актуальною.


додати ;після target $@роботи сенсорної команди
mug896

для другої проблеми використовуйте make -Bваріант, який беззастережно робить усі цілі.
mug896

2

Я використав римейк --profile (заміна спаду для make), він генерував дерево залежності у форматі callgrind.

Тоді gprof2dot може генерувати зображення цільового дерева.


Я розумію документацію неправильно чи видає remake --profileграфік залежності лише для цілі, яку вона виконує? Або може якимось чином вивести графік для всіх цілей?
Лукас

Боюсь лише той, яким він керує. Але ви можете запустити їх усіх із сушитися
Віктор Сергієнко,

О так, щось схоже remake --targets -r | grep -v %| grep -v '\t*\.'|xargs remake -n --profile -Bвиглядає багатообіцяюче.
Лукас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.