Làm thế nào để hiển thị các phụ thuộc được đưa ra trong một tệp thực hiện dưới dạng cây?


18

Vấn đề

Tôi muốn xem các phụ thuộc cho một hoặc nhiều mục tiêu của tệp thực hiện. Vì vậy, tôi đang tìm kiếm một chương trình có thể phân tích các tệp tạo tệp và sau đó sẽ biểu diễn các phụ thuộc theo một số định dạng giống như cây (thụt, ascii-art, ...) hoặc dưới dạng biểu đồ (dấu chấm, ...).

Giống

Có những chương trình làm điều này cho các tình huống khác:

  • pactree hoặc owree có thể hiển thị các phụ thuộc cho các gói phần mềm ở định dạng tương ứng trong một cây như định dạng ascii hoặc dưới dạng dotbiểu đồ,
  • gcc -M source_file.c hiển thị các phụ thuộc của tệp nguồn C dưới dạng quy tắc,
  • pstree hiển thị một đại diện ascii của cây quy trình.

Phát triển

Tìm kiếm trên web tôi tìm thấy rất ít sự giúp đỡ . Điều đó dẫn tôi đến thử

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

nhưng có vẻ như tôi phải hack thêm một số mã phân tích cú pháp trong perl hoặc python để thể hiện điều này như một cây / biểu đồ đẹp. Và tôi vẫn chưa biết liệu tôi có thực sự có được biểu đồ đầy đủ và chính xác theo cách này không.

Yêu cầu

Sẽ rất tốt nếu giới hạn đồ thị theo một số cách (không có quy tắc dựng sẵn, chỉ một mục tiêu nhất định, chỉ một số độ sâu) nhưng đối với hầu hết tôi chỉ tìm kiếm một công cụ sẽ cung cấp cho tôi các phụ thuộc trong một số "hợp lý", con người định dạng có thể xem được (như các chương trình trong "Tương tự" làm).

Câu hỏi

  • Có chương trình nào có thể làm điều này?
  • Tôi sẽ nhận được thông tin đầy đủ và chính xác từ make -dnq ...?
  • Có cách nào tốt hơn để có được thông tin này?
  • Các kịch bản / nỗ lực để phân tích thông tin này đã tồn tại?

1
Điều cốt yếu cần hiểu ở đây là: Phụ thuộc KHÔNG tạo thành cây. Chúng tạo thành một đồ thị chu kỳ có hướng và (hy vọng!), Còn được gọi là DAG . Hãy thử phác thảo biểu đồ phụ thuộc cho các mục sau và bạn sẽ thấy: A phụ thuộc vào B; A cũng phụ thuộc vào C; B phụ thuộc vào D; C phụ thuộc vào D.
Wildcard

@Wildcard Tôi biết nhưng với mục đích của tôi, nó đủ để thể hiện sự phụ thuộc như một cái cây. Tôi ổn với việc nhân đôi các sơ đồ con (và cắt theo vòng tròn) để biến nó thành một cái cây. Xin lỗi vì đã không rõ ràng. Ví dụ với bạn, tôi sẽ ổn với đầu ra của printf 'A\n B\n D\n C\n D\n'. (Ai nói tôi không thể đưa dòng mới vào bình luận? :)
Lucas

Làm thế nào mà phân biệt được với "A phụ thuộc vào B; B phụ thuộc vào D; D phụ thuộc vào C; A phụ thuộc vào D"? Bạn có thể áp đặt tổng số đơn đặt hàng cho bất kỳ DAG nào (vì bất kỳ DAG nào cũng đại diện cho một thứ tự một phần), nhưng bạn không thể biến DAG thành cây. Đây là lý thuyết đồ thị cơ bản. Tôi sẽ thấy thú vị khi thấy thuật toán của bạn để tạo một cây đại diện cho một DAG mà sau đó có thể được hiển thị. Nếu không có một thuật toán cơ bản như vậy, bất kỳ công cụ nào tìm cách hiển thị các phụ thuộc dưới dạng cây sẽ rất cần thiết và rất dễ bị lỗi.
tự đại diện

Có thể tôi không đủ rõ ràng một lần nữa nhưng tôi nghĩ những ví dụ tôi đưa ra dưới Tương tự đã làm cho nó rõ ràng. Tôi không quan tâm đến lý thuyết đồ thị (ít nhất là trong câu hỏi này). Tất cả những gì tôi muốn cho điều này là một biểu diễn trực quan trông giống như một cái cây (đặc biệt là nếu nó sẽ được hiển thị trên một thiết bị đầu cuối, vì dotđồ thị đơn hàng rõ ràng là tốt.) Tôi sẽ cập nhật câu hỏi một chút để làm cho nó rõ ràng hơn (tôi hy vọng).
Lucas

2
RANT: Tôi thực sự có một chút thất vọng khi không cung cấp thứ gì đó giống như thế này. Make là một trong những hệ thống xây dựng có phạm vi rộng nhất trên thế giới và tính năng này sẽ vô cùng hữu ích đến nỗi khó có thể nắm bắt được rằng trong suốt thời gian Thiên Chúa biết có bao nhiêu thập kỷ tồn tại không ai thêm tính năng này. Xuất thông tin này trong một định dạng văn bản được xác định rõ ràng sẽ là hoàn toàn đủ. Tôi hiểu rằng make là nguồn mở và tôi luôn có thể tự thêm tính năng này. Và tin tôi đi, nếu cơ bản không phải là một hộp đen đối với tôi, tôi sẽ làm thế! RANT hơn.
antred

Câu trả lời:


10

Hãy thử makefile2graph từ cùng một tác giả, có một công cụ tương tự MakeGraphDependencies được viết javathay vì c.

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

Sau đó sử dụng một số trình soạn thảo đồ họa vector để làm nổi bật các kết nối bạn cần.


1
Tôi đã thử công cụ đó. Thậm chí không bắt đầu hoạt động (ít nhất là không cho bất kỳ hóa thân nào tôi đã thử với nó). Hầu hết thời gian nó chỉ xuất hiện với một số vi phạm truy cập bộ nhớ.
antred

3

Tôi đã tìm thấy một loại hack để ít nhất xuất ra thông tin có cấu trúc rõ ràng về mục tiêu nào phụ thuộc vào điều kiện tiên quyết nào. Nhược điểm là, nó khá xâm phạm. Nói cách khác, bạn cần thay đổi tệp tạo tệp của mình để bọc các công thức xây dựng của tất cả các mục tiêu của bạn thành một hàm có điều kiện nhỏ. Tôi sẽ đăng một ví dụ ngắn gọn:

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

Trong ví dụ này, tôi đang sử dụng hàm getRecipe được cuộn bằng tay để bọc công thức của từng mục tiêu riêng lẻ và sau đó quyết định có thực sự chạy công thức đó hay đơn giản là đầu ra mục tiêu nào đang được xây dựng và điều kiện tiên quyết phụ thuộc vào. Cái sau chỉ xảy ra nếu biến DEPENDENCY_GRAPHđược đặt (ví dụ như biến môi trường). Trong ví dụ, công thức xây dựng không có gì khác hơn là tiếng vang nói rằng mục tiêu đang được xây dựng, nhưng rõ ràng bạn có thể thay thế điều này bằng một lệnh bạn chọn.

Với DEPENDENCY_GRAPHđặt thành 1, điều này dẫn đến kết quả đầu ra:

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"

cần đủ dễ phân tích cú pháp và sau đó chuyển thành biểu đồ dấu chấm.

Với hoàn toàn DEPENDENCY_GRAPHkhông được đặt hoặc được đặt thành 0, đầu ra là:

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

hoặc, nói cách khác, công thức xây dựng bình thường được sử dụng thay thế. Tôi chưa thử liệu điều này có hiệu quả với các công thức phức tạp không. Một vấn đề tôi đã gặp phải là nó hoàn toàn không hoạt động với các công thức nấu ăn đa dòng.

Chẳng hạn, trong công thức xây dựng của mục tiêu cuối cùng, nếu ngoài việc nói rằng mục tiêu đang được xây dựng, tôi thực sự muốn vào touchtệp:

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

makedường như nghĩ rằng touch $@phần đó chỉ là một phần của tiếng vang trong dòng trước:

Building target foobar.txt touch foobar.txt

Nếu tôi bỏ dấu gạch chéo ngược ở dòng trước, hãy makephàn nàn *** unterminated call to functioncuộc gọi ': mất tích )'. Stop.Nếu có ai có ý tưởng làm thế nào makeđể chơi đẹp, tôi là tất cả. :)

EDIT: Vấn đề khác với cách tiếp cận này là nó sẽ chỉ hoạt động nếu không có kết quả xây dựng nào, vì makerõ ràng là không thực thi công thức xây dựng của mục tiêu mà nó xem là cập nhật.


thêm ;sau target $@lệnh cảm ứng để hoạt động
Mug896

cho vấn đề thứ hai, sử dụng make -Btùy chọn vô điều kiện thực hiện tất cả các mục tiêu.
cốc896

2

Tôi đã sử dụng remake --profile (một thay thế thả vào make), nó tạo ra một cây phụ thuộc theo định dạng callgrind.

Sau đó gprof2dot có thể tạo ra một hình ảnh của cây mục tiêu.


Tôi có hiểu tài liệu sai hay remake --profilechỉ xuất ra biểu đồ phụ thuộc cho mục tiêu mà nó thực hiện? Hoặc bằng cách nào đó nó có thể xuất đồ thị cho tất cả các mục tiêu?
Lucas

Chỉ có một cái nó chạy, tôi sợ. Nhưng bạn có thể chạy tất cả chúng với Tiếtdry-run
Victor Sergienko

Ồ phải, một cái gì đó remake --targets -r | grep -v %| grep -v '\t*\.'|xargs remake -n --profile -Btrông có vẻ đầy hứa hẹn.
Lucas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.