Problema

Problema

Problema

Quiero ver las dependencias de uno o más objetivos de un archivo MAKE. Así que estoy buscando un programa que pueda analizar archivos MAKE y luego representar las dependencias en algún formato similar a un árbol (sangría, arte ascii,...) o como un gráfico (punto,...).

Similar

Hay programas que hacen esto para otras situaciones:

  • pactreeodeudorpuede mostrar las dependencias de los paquetes de software en el formato respectivo en un árbol como formato ascii o como un dotgráfico,
  • gcc -M source_file.cmuestra las dependencias del archivo fuente C como una regla de creación,
  • ptreemuestra una representación ascii del árbol de procesos.

Progreso

Buscando en la web encontréun poco de ayuda. Eso me llevó a intentarlo

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

pero parece que tengo que hackear más código de análisis en Perl o Python para poder representar esto como un bonito árbol/gráfico. Y todavía no sé si realmente conseguiré el gráfico completo y correcto de esta manera.

Requisitos

Sería bueno limitar el gráfico de alguna manera (sin reglas incorporadas, solo un objetivo determinado, solo algo de profundidad), pero en su mayor parte solo estoy buscando una herramienta que me brinde las dependencias en algunos aspectos humanos "razonables". -formato visible (como lo hacen los programas bajo "Similar").

Preguntas

  • ¿Existe algún programa que pueda hacer esto?
  • ¿Recibiré la información completa y correcta de make -dnq ...?
  • ¿Existe una mejor manera de obtener esta información?
  • ¿Existen ya scripts/intentos de analizar esta información?

Respuesta1

Intentarmakefile2graphdel mismo autor hay una herramienta similarHacer dependencias de gráficosescrito en javalugar de c.

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

Luego use algún editor de gráficos vectoriales para resaltar las conexiones que necesita.

Respuesta2

solíarehacer --perfil(un reemplazo directo de make), generó un árbol de dependencia en formato callgrind.

Entoncesgprof2dotpuede generar una imagen del árbol de destino.

Respuesta3

He encontrado una especie de truco para al menos generar información claramente estructurada sobre qué objetivo depende de qué requisitos previos. La desventaja es que es bastante intrusivo. En otras palabras, necesita cambiar su archivo MAKE para envolver las recetas de compilación de todos sus objetivos en una pequeña función condicional. Publicaré un breve ejemplo:

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 $@)

En este ejemplo, estoy usando la función getRecipe desarrollada manualmente para envolver la receta de cada objetivo individual y luego decidir si realmente ejecutar esa receta o simplemente generar qué objetivo se está construyendo y de qué requisitos previos depende. Esto último ocurre sólo si la variable DEPENDENCY_GRAPHestá configurada (por ejemplo, como variable de entorno). En el ejemplo, la receta de construcción no es más que un eco que dice que el objetivo se está construyendo, pero obviamente puedes reemplazar esto con un comando de tu elección.

Si DEPENDENCY_GRAPHse establece en 1, esto da como resultado el resultado:

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"

que debería ser bastante fácil de analizar y luego convertir en un gráfico de puntos.

Sin DEPENDENCY_GRAPHconfigurar nada o configurarlo en 0, la salida es:

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

o, en otras palabras, se utiliza la receta de construcción normal. Aún no he probado si esto funciona de manera confiable con recetas complicadas. Un problema con el que ya me he encontrado es que no funciona en absoluto con recetas de varias líneas.

Por ejemplo, en la receta de compilación del último objetivo, si además de decir que el objetivo se está construyendo, en realidad quería touchel archivo:

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

makeParece pensar que la touch $@parte es simplemente parte del eco de la línea anterior:

Building target foobar.txt touch foobar.txt

Si dejo fuera la barra invertida al final de la línea anterior, makese queja *** unterminated call to functionllamada': falta )'. Stop.Si alguien tiene una idea de cómo makejugar bien, soy todo oídos. :)

EDITAR: El otro problema con este enfoque es que solo funcionará si no existen resultados de compilación, ya que makeobviamente no ejecuta la receta de compilación de un objetivo que considera actualizado.

Respuesta4

Si solo necesita enumerar las dependencias para el objetivo específico, puede usar el siguiente comando:

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

MAKE=:es para no correr niñomarcas.

Desafortunadamente, los Makefiles incluidos también se enumeran. Puedefiltrarlosusando el siguiente script de shell ( 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"

Ahora puedes enumerar todas las dependencias del objetivo usando este comando:

list-deps MAKE=: your_target

Si necesita enumerar solo las dependencias que deben rehacerse, consulteesta respuesta.

Editar: para otras personas que encuentren esta respuesta, pueden conservar la sangría utilizando

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

También puedes convertirlo en un objetivo en el Makefile:

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

información relacionada