Como exibir dependências dadas em um makefile como uma árvore?

14

Problema

Eu quero ver as dependências de um ou mais destinos de um makefile. Então, eu estou procurando por um programa que possa analisar makefiles e então representar as dependências em algum formato de árvore (recuo, ascii-art, ...) ou como um grafo (ponto, ...).

Similar

Existem programas que fazem isso para outras situações:

  • pactree ou debtree pode exibir as dependências para pacotes de software no respectivo formato em uma árvore como formato ascii ou como dot graph,
  • gcc -M source_file.c exibe as dependências do arquivo de origem C como uma regra de criação,
  • O pstree exibe uma representação ASCII da árvore de processos.

Progresso

Pesquisando na web eu encontrei pouca ajuda . Isso me levou a tentar

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

mas parece que tenho que hackear mais algum código de análise em perl ou python para representar isso como uma boa árvore / gráfico. E eu ainda não sei se vou realmente obter o gráfico completo e correto dessa maneira.

Requisitos

Seria bom limitar o gráfico de algumas maneiras (sem regra interna, apenas um determinado alvo, apenas alguma profundidade), mas na maior parte eu estou apenas procurando por uma ferramenta que me dará as dependências em alguns "razoável ", formato de visualização humana (como os programas em" Similar ").

Perguntas

  • Existem programas que podem fazer isso?
  • Receberei as informações completas e corretas de make -dnq ... ?
  • Existe uma maneira melhor de obter essas informações?
  • Os scripts / tentativas de análise dessas informações já existem?
por Lucas 16.05.2016 / 18:51

2 respostas

6

Tente makefile2graph do mesmo autor, há uma ferramenta semelhante MakeGraphDependencies escrito em java em vez de c .

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

Em seguida, use um editor de gráficos vetoriais para destacar as conexões de que você precisa.

    
por 16.05.2016 / 20:56
1

Eu encontrei uma espécie de hack para, pelo menos, gerar informações claramente estruturadas sobre qual alvo depende de quais pré-requisitos. A desvantagem é que é bastante intrusiva. Em outras palavras, você precisa alterar seu makefile para agrupar as receitas de compilação de todos os seus alvos em uma pequena função condicional. Vou postar um breve exemplo:

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

Neste exemplo, estou usando a função getRecipe enrolada à mão para agrupar a receita de cada destino individual e, em seguida, decidir se a receita realmente será executada ou se simplesmente a saída está sendo criada e quais pré-requisitos ela depende. O último acontece apenas se a variável DEPENDENCY_GRAPH estiver definida (por exemplo, como uma variável de ambiente). No exemplo, a receita de construção nada mais é do que um eco dizendo que o alvo está sendo construído, mas você poderia obviamente substituir isso por um comando de sua escolha.

Com DEPENDENCY_GRAPH definido como 1, isso resulta na saída:

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 deve ser fácil o suficiente para analisar e depois converter em um gráfico de pontos.

Com DEPENDENCY_GRAPH não definido ou definido como 0, a saída é:

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

ou, em outras palavras, a receita de compilação normal é usada em seu lugar. Eu ainda não testei se isso funciona de forma confiável com receitas complicadas. Um problema que já enfrentei é que ele não funciona com receitas de várias linhas.

Por exemplo, na receita de compilação do último destino, se além de dizer que o alvo está sendo construído, eu realmente queria touch o arquivo:

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

make parece achar que a parte touch $@ é meramente parte do eco da linha anterior:

Building target foobar.txt touch foobar.txt

Se eu deixar a barra invertida na linha anterior, make reclama *** unterminated call to function call ': falta )'. Stop. Se alguém tiver uma ideia de como fazer com que make seja legal, sou todo ouvidos. :)

EDIT: O outro problema com essa abordagem é que isso só funcionará se nenhum resultado de compilação já existir, já que make obviamente não executa a receita de compilação de um destino que considera atualizado.

    
por 27.07.2017 / 14:54