Як відобразити залежності, задані в 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.