질문

질문

질문

makefile의 하나 이상의 대상에 대한 종속성을 보고 싶습니다. 그래서 저는 makefile을 구문 분석한 다음 일부 트리 형식(들여쓰기, ascii-art 등) 또는 그래픽(점, ...)으로 종속성을 표현할 수 있는 프로그램을 찾고 있습니다.

비슷한

다른 상황에서도 이를 수행할 수 있는 프로그램이 있습니다:

  • 파크 트리또는부채 나무dot해당 형식의 소프트웨어 패키지의 종속성을 트리 형식(예: ASCII 형식) 또는 그래픽으로 표시할 수 있습니다 .
  • gcc -M source_file.cC 소스 파일의 종속성을 make 규칙으로 표시합니다.
  • 나무프로세스 트리의 ASCII 표현을 표시합니다.

진전

내가 찾은 웹 검색 중별로 도움이 안됨. 이것이 나에게 시도를 하게 만들었다

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

하지만 이것을 멋진 트리/그래프로 표현하려면 Perl이나 Python에서 구문 분석 코드를 좀 더 해독해야 할 것 같습니다. 이런 식으로 실제로 완전하고 정확한 다이어그램을 얻을 수 있는지 아직 모르겠습니다.

필요하다

어떤 방식으로든 차트를 제한하면 좋겠지만(기본 제공 규칙 없음, 주어진 목표만, 특정 깊이만) 대부분의 경우 "합리적인" 것을 제공하는 도구를 찾고 있습니다. 종속성 - 볼 수 있는 형식입니다("유사" 아래의 프로그램과 동일).

질문

  • 이것을 할 수 있는 프로그램이 있나요?
  • 로부터 완전하고 정확한 정보를 얻을 수 있습니까 make -dnq ...?
  • 이 정보를 얻을 수 있는 더 좋은 방법이 있나요?
  • 이 정보를 구문 분석하려는 스크립트/시도가 이미 존재합니까?

답변1

노력하다makefile2graph같은 작성자의 유사한 도구가 있습니다.MakeGraph 종속성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변수가 설정된 경우에만 발생합니다(예: 환경 변수로). 예제에서 빌드 레시피는 대상이 빌드되고 있음을 나타내는 에코에 불과하지만 이를 원하는 명령으로 대체할 수 있습니다.

1 로 설정 하면 DEPENDENCY_GRAPH출력 결과는 다음과 같습니다.

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_GRAPH0으로 설정하면 출력은 다음과 같습니다.

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

maketouch $@이 부분은 이전 줄의 에코의 일부인 것 같습니다 .

Building target foobar.txt touch foobar.txt

이전 줄에서 후행 백슬래시를 생략하면 ':missing' 호출 make에 대해 불평합니다 . 이 문제를 해결하는 방법을 아는 사람이 있으면 귀담아듣겠습니다. :)*** unterminated call to function)'. Stop.make

편집: 이 접근 방식의 또 다른 문제는 빌드 결과가 없는 경우에만 작동한다는 것입니다. make분명히 최신이라고 생각하는 대상에 대한 빌드 레시피가 실행되지 않기 때문입니다.

답변4

특정 대상에 대한 종속성만 나열해야 하는 경우 다음 명령을 사용할 수 있습니다.

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

MAKE=:아이들이 도망가지 못하게 하기 위함이에요만들다.

불행하게도 포함된 Makefile도 나열되어 있습니다. 당신은 할 수그들을 필터링다음 쉘 스크립트( 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" 

관련 정보