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

maketouch $@부분은 이전 줄의 에코 의 일부일 뿐이라고 생각합니다 .

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.