Как отобразить зависимости, заданные в make-файле в виде дерева?

18

проблема

Я хочу увидеть зависимости для одной или нескольких целей make-файла. Поэтому я ищу программу, которая может анализировать make-файлы и затем представлять зависимости в некотором древовидном формате (отступ, ascii-art, ...) или в виде графика (точка, ...).

Аналогичный

Есть программы, которые делают это для других ситуаций:

  • pactree или debtree могут отображать зависимости для пакетов программного обеспечения в соответствующем формате в виде дерева, такого как формат ascii или в виде dotграфика,
  • gcc -M source_file.c отображает зависимости исходного файла C как правило make,
  • 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; А также зависит от С; 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»? Вы можете наложить полное упорядочение на любую группу обеспечения доступности баз данных (поскольку любая группа обеспечения доступности баз данных также представляет частичное упорядочение), но вы не можете превратить группу обеспечения доступности баз данных в дерево. Это основная теория графов. Мне было бы интересно увидеть ваш алгоритм создания древовидного представления группы доступности базы данных, которая затем может быть отображена. Без такого базового алгоритма любой инструмент, который стремился бы отображать зависимости в виде дерева, по необходимости был бы чрезвычайно хакерским и подверженным ошибкам.
Wildcard
Может быть, я не был достаточно ясен, но я подумал, что примеры, которые я привожу в « Похожем», прояснили. Я не интересуюсь теорией графов (по крайней мере, в этом вопросе). Все, что я хочу для этого, - это визуальное представление, которое выглядит подобно дереву (особенно, если оно должно отображаться на терминале, поскольку dotграфики заказов явно хороши.) Я немного обновлю вопрос, чтобы прояснить его (я надеюсь).
Лукас
2
RANT: Я, честно говоря, немного расстроен тем, что make не предлагает что-то подобное из коробки. Make - одна из самых распространенных систем сборки в мире, и эта функция была бы настолько полезна, что трудно понять, что во времена, когда Бог знает, сколько десятилетий этой сборки не было, никто не добавил такую ​​функцию. Вывод этой информации в четко определенном текстовом формате будет вполне достаточным. Я понимаю, что make является открытым исходным кодом, и я всегда мог добавить эту функцию сам. И поверьте мне, если бы make не был для меня черным ящиком, я бы! RANT окончен.
antred

Ответы:

10

Попробуйте makefile2graph от того же автора, где вместо этого написан похожий инструмент MakeGraphDependencies .javac

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

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

XAE
источник
1
Я попробовал этот инструмент. Даже не начинает работать (по крайней мере, ни для одного из воплощений make, с которыми я пробовал). Большую часть времени он просто выходит из строя с некоторым нарушением доступа к памяти.
antred
3

Я нашел способ взломать, по крайней мере, выводить четко структурированную информацию о том, какая цель зависит от каких предпосылок. Недостатком является то, что это довольно навязчиво. Другими словами, вам нужно изменить свой make-файл, чтобы обернуть рецепты сборки всех ваших целей в небольшую условную функцию. Я выложу краткий пример:

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играть хорошо, я весь в ушах. :)

РЕДАКТИРОВАТЬ: Другая проблема с этим подходом заключается в том, что он будет работать только в том случае, если результаты компиляции уже не существуют, поскольку, makeочевидно, не выполняет рецепт компоновки целевого объекта, который он считает актуальным.

antred
источник
добавить ;после target $@сенсорной команды к работам
mug896
для второй проблемы используйте make -Bопцию, которая безоговорочно ставит все цели.
mug896
2

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

Затем gprof2dot может сгенерировать изображение целевого дерева.

Виктор Сергиенко
источник
Я неправильно понимаю документацию или remake --profileвыводит граф зависимостей только для цели, которую он выполняет? Или это может как-то вывести график для всех целей?
Лукас
Боюсь, только тот, на котором он работает. Но вы можете запустить их все с -dry перспективе
Виктор Сергиенко
Ах да, что-то вроде remake --targets -r | grep -v %| grep -v '\t*\.'|xargs remake -n --profile -Bвыглядит многообещающе.
Лукас