Проблема

Проблема

Проблема

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

Похожий

Существуют программы, которые делают это и в других ситуациях:

  • пактриилидолгдеревоможет отображать зависимости для пакетов программного обеспечения в соответствующем формате в виде дерева, например, формата 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

Пытатьсяmakefile2graphот того же автора есть похожий инструментMakeGraphDependenciesнаписано javaвместо c.

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

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

решение2

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

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

решение3

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

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сообщение: missing )'. Stop.Если у кого-то есть идеи, как makeиграть по-хорошему, я весь внимание. :)

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

решение4

Если вам просто нужно вывести список зависимостей для конкретной цели, вы можете использовать следующую команду:

make -dn MAKE=: you_target | sed -rn "s/^ *Considering target file '(.*)'\.$/\1/p"

MAKE=:для не бегущего ребенкаделает.

К сожалению, включены также Makefiles. Вы можетеотфильтровать ихиспользуя следующий скрипт оболочки ( list-deps):

#!/bin/sh -e

dbg="`make -dn "$@"`"
all="`echo -n "$dbg" | sed -rn "s/^ *Considering target file '(.+)'\.$/\1/p"`"
mks="`echo -n "$dbg" | sed -rn "s/^ *Reading makefile '([^']+)'.*$/\1/p"`"
echo -n "$all" | grep -vxF "$mks"

Теперь вы можете вывести список всех зависимостей для цели с помощью этой команды:

list-deps MAKE=: your_target

Если вам нужно перечислить только те зависимости, которые необходимо переделать, см.этот ответ.

Редактировать: Для тех, кто найдет этот ответ - вы можете сохранить отступы, используя

make -dn MAKE=: you_target | sed -rn "s/^(\s+)Considering target file '(.*)'\.$/\1\2/p"

Вы также можете сделать это целью в Makefile:

.PHONY: graph 
graph: 
    make -dn MAKE=: all | sed -rn "s/^(\s+)Considering target file '(.*)'\.$/\1\2/p" 

Связанный контент