makefile에 주어진 의존성을 트리로 표시하는 방법은 무엇입니까?


18

문제

makefile의 하나 이상의 대상에 대한 종속성을보고 싶습니다. 그래서 makefile을 구문 분석 할 수있는 프로그램을 찾고 트리와 같은 형식 (들여 쓰기, 아트 아트, ...) 또는 그래프 (점, ...)로 종속성을 나타냅니다.

비슷한

다른 상황에서이를 수행하는 프로그램이 있습니다.

  • pactree 또는 빚은 ascii 형식 또는 dot그래프 와 같은 트리의 각 형식으로 소프트웨어 패키지에 대한 종속성을 표시 할 수 있습니다 .
  • gcc -M source_file.c C 소스 파일의 종속성을 작성 규칙으로 표시합니다.
  • pstree 는 프로세스 트리의 ASCII 표현을 표시합니다.

진행

웹을 검색하면 도움이 거의 없습니다 . 그게 나를 시도하게

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

그러나 이것을 멋진 트리 / 그래프로 표현하기 위해 펄이나 파이썬에서 더 많은 파싱 코드를 해킹 해야하는 것처럼 보입니다. 그리고 나는이 방법으로 완전하고 정확한 그래프를 얻을 수 있는지 아직 모른다.

요구 사항

그래프를 어떤 방식 으로든 제한하는 것이 좋을 것입니다 (내장 규칙, 주어진 대상, 깊이 만). 대부분의 경우, 나는 "합리적"인 인간의 의존성을 줄 도구를 찾고 있습니다. -시청 가능한 형식 (예 : "유사한"의 프로그램).

질문

  • 이를 수행 할 수있는 프로그램이 있습니까?
  • 전체 정보와 정확한 정보를 얻을 수 make -dnq ...있습니까?
  • 이 정보를 얻는 더 좋은 방법이 있습니까?
  • 이 정보를 파싱하려는 스크립트 / 시도가 이미 존재합니까?

1
여기서 이해해야 할 것은 다음과 같습니다. 종속성은 트리를 형성하지 않습니다. 그것들은 DAG 라고도하는 방향성있는 (비정상적으로!) 비순환 그래프를 형성합니다 . 다음에 대한 종속성 그래프를 스케치 해보십시오. A는 B에 의존합니다. A는 또한 C에 의존합니다; B는 D에 의존한다; C는 D에 의존합니다.
— 와일드 카드

@Wildcard 알고 있지만 내 목적으로는 종속성을 트리로 나타내는 것으로 충분합니다 . 나는 서브 그래프를 복제하고 (원을 자르는) 나무로 만들기에 좋습니다. 명시 적이 지 않아서 죄송합니다. 예를 들어의 출력으로 괜찮을 것입니다 printf 'A\n B\n D\n C\n D\n'. (누가 댓글에 줄 바꿈을 넣을 수 없다고 말했습니까? :)
— Lucas

"A는 B에 의존하고; B는 D에 의존하고; D는 C에 의존하고; A는 D에 의존한다"와 어떻게 구별 되는가? 모든 DAG에 전체 주문을 적용 할 수 있지만 (DAG도 부분 주문을 나타내므로) DAG를 트리로 바꿀 수는 없습니다. 이것이 기본 그래프 이론입니다. DAG의 트리 표현을 생성하여 표시 할 수있는 알고리즘을 알고 싶습니다. 이러한 기본 알고리즘이 없으면 종속성을 트리로 표시하려는 모든 도구는 매우 해킹되고 오류가 발생하기 쉽습니다.
— 와일드 카드

어쩌면 나는 다시 명시 적으로 충분하지 않았지만 비슷한 항목 에서 제시 한 예가 명확 하다고 생각 했습니다. 나는 그래프 이론에 관심이 없다 (적어도이 질문에서). 내가 원하는 것은 나무와 비슷하게 보이는 시각적 표현입니다 (특히 dot순서 그래프가 잘 표시되도록 터미널에 표시 해야하는 경우 ). 명확하게하기 위해 질문을 조금 업데이트합니다.
— Lucas

2
RANT : 솔직히 말해서 make가이 기본 제공품과 같은 것을 제공하지 않는 것에 대해 약간 실망했습니다. Make는 세계에서 가장 널리 사용되는 빌드 시스템 중 하나이며,이 기능은 너무나도 유용 할 것이므로, 그 기능을 추가 한 사람은 아무도 없었습니다. 이 정보를 명확하게 정의 된 텍스트 형식으로 출력하면 충분합니다. make는 오픈 소스이며 언제든지이 기능을 직접 추가 할 수 있습니다. 그리고 make가 기본적으로 블랙 박스가 아니었다면, 믿습니다! RANT 이상.
— antred

답변:


10

같은 저자의 makefile2graph 를 사용해보십시오 . 대신 비슷한 도구 MakeGraphDependencies가 작성되었습니다 .javac

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

그런 다음 벡터 그래픽 편집기를 사용하여 필요한 연결을 강조 표시하십시오.


1
나는 그 도구를 시도했다. 심지어 작동하지 않습니다 (적어도 내가 시도한 화신에 대해서는 아닙니다). 대부분의 경우 메모리 액세스 위반이 발생합니다.
— antred

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_GRAPH1로 설정 하면 다음 과 같이 출력됩니다.

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하지 않는 경우에만 작동한다는 것 입니다. 최신으로 간주되는 대상의 빌드 레시피를 실행하지 않기 때문입니다.


추가 ;후 target $@작품에 터치 명령
— mug896의

두 번째 문제의 경우 make -B무조건 모든 대상을 만드는 옵션을 사용하십시오 .
— mug896

2

I 사용 --profile 개작 (드롭에 대한 대체 make), 그것은 callgrind 형식의 종속성 트리를 생성.

그러면 gprof2dot 는 대상 트리의 이미지를 생성 할 수 있습니다.


설명서를 잘못 이해했거나 remake --profile실행하는 대상에 대한 종속성 그래프 만 출력합니까? 아니면 어떻게 든 모든 대상에 대한 그래프를 출력 할 수 있습니까?
— 루카스

그것이 실행되는 것만 두려워요. 하지만 당신은 건성 운영하는 모든 실행할 수 있습니다
— 빅터 Sergienko

오 예, remake --targets -r | grep -v %| grep -v '\t*\.'|xargs remake -n --profile -B유망한 것 같습니다 .
— 루카스
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.