Bir dosyada verilen bağımlılıklar ağaç olarak nasıl görüntülenir?


18

Sorun

Bir makefile'ın bir veya daha fazla hedefi için bağımlılıkları görmek istiyorum. Bu yüzden makefiles ayrıştırabilir ve daha sonra bazı ağaç gibi bir format (girinti, ascii-art, ...) veya bir grafik (nokta, ...) olarak bağımlılıkları temsil edecek bir program arıyorum.

Benzer

Diğer durumlar için bunu yapan programlar vardır:

  • pakt veya borç , yazılım paketlerinin bağımlılıklarını ascii biçiminde veya dotgrafik olarak ilgili biçimde görüntüleyebilir ,
  • gcc -M source_file.c C kaynak dosyasının bağımlılıklarını bir make kuralı olarak görüntüler,
  • pstree süreç ağacının ascii temsilini görüntüler.

İlerleme

Web'de arama yaparken çok az yardım buldum . Bu beni denemeye yönlendirdi

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

ama güzel bir ağaç / grafik olarak göstermek için perl veya python biraz daha ayrıştırma kodu kesmek zorunda gibi görünüyor. Tam ve doğru grafiği bu şekilde elde edip edemeyeceğimi henüz bilmiyorum.

Gereksinimler

Grafiği bazı şekillerde sınırlamak güzel olurdu (yerleşik bir kural yok, sadece belirli bir hedef, sadece biraz derinlik) ama çoğunlukla sadece bana bazı "makul", insandaki bağımlılıkları verecek bir araç arıyorum görüntülenebilir biçimi ("Benzer" altındaki programlar gibi).

Sorular

  • Bunu yapabilen programlar var mı?
  • Tam ve doğru bilgileri nereden alacağım make -dnq ...?
  • Bu bilgiyi almanın daha iyi bir yolu var mı?
  • Bu bilgileri ayrıştırma komut dosyaları / girişimleri zaten var mı?

1
Burada anlaşılması gereken önemli nokta şudur: Bağımlılıklar bir ağaç oluşturmaz. DAG olarak da bilinen yönlendirilmiş ve (umarım!) Asiklik bir grafik oluştururlar . Aşağıdakiler için bağımlılık grafiğini çizmeyi deneyin ve göreceksiniz: A, B'ye bağlıdır; A ayrıca C'ye bağlıdır; B, D'ye bağlıdır; C
Wildcard,

@Wildcard biliyorum ama amacım için bir ağaç olarak bağımlılıkları temsil etmek yeterli . Alt ağacı çoğaltmak (ve daireler çizmek) ile iyiyim. Açık olmadığım için üzgünüm. Örneğin, ben çıktı ile iyi olurdu printf 'A\n B\n D\n C\n D\n'. (Kim yorumlara yeni satırlar koyamayacağımı kim söyledi? :)
Lucas

Bunun "A B'ye; B D'ye; D C'ye; A D'ye bağlıdır" dan nasıl ayırt edilebilir? Herhangi bir DAG'a toplam sipariş verebilirsiniz (herhangi bir DAG ayrıca kısmi bir siparişi temsil ettiğinden), ancak bir DAG'ı ağaca dönüştüremezsiniz. Bu temel grafik teorisidir. Daha sonra görüntülenebilen bir DAG'ın ağaç temsilini oluşturmak için algoritmanızı görmek isterim. Böyle bir altta yatan algoritma olmadan, bir ağaç gibi bağımlılıkları sergilemeye çalışan herhangi bir araç zorunlu olarak aşırı derecede haksız ve hataya açık olacaktır.
Joker karakter

Belki de yine değil açık yeterliydi ama altında ben vermek örnekler düşünce Benzer onu temizlemek yaptı. Grafik teorisiyle ilgilenmiyorum (en azından bu soruda). Bunun için tek istediğim, bir ağaca benzeyen görsel bir sunum (özellikle bir terminalde görüntülenmesi gerekiyorsa, dotsipariş grafikleri gayet iyi.) Soruyu daha açık hale getirmek için biraz güncelleyeceğim (umarım).
Lucas

2
RANT: Dürüst olmak gerekirse, markanın kutudan çıktığı gibi bir şey sunmadığı için biraz sinirliyim. Make, dünyadaki en yaygın yapı sistemlerinden biridir ve bu özellik o kadar büyük ölçüde yararlı olacaktır ki, Tanrı boyunca kaç yıldır bu tür bir özellik bulunmadığını kimsenin böyle bir özellik eklemediğini bilmesi zordur. Bu bilgilerin açık bir şekilde tanımlanmış bir metin biçiminde çıkarılması tamamen yeterli olacaktır. Make'in açık kaynak olduğunu anlıyorum ve bu özelliği her zaman kendim ekleyebilirim. Ve inan bana, eğer marka benim için temelde bir kara kutu olmasaydı, isterdim! RANT bitti.
antred

Yanıtlar:


10

Aynı yazardan makefile2graph'ı deneyin . MakeGraphDependenciesjava yerine yazılmış benzer bir araç var c.

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

Ardından, ihtiyacınız olan bağlantıları vurgulamak için bazı vektör grafik düzenleyicilerini kullanın.


1
Bu aracı denedim. Çalışmaya bile başlamıyor (en azından denediğim enkarnasyonların hiçbiri için değil). Çoğu zaman bellek erişim ihlali ile kendini gösterir.
antred

3

En azından hangi hedefin hangi önkoşullara bağlı olduğu hakkında net bir şekilde yapılandırılmış bilgiler elde etmek için bir tür saldırı buldum. Olumsuz, oldukça müdahaleci. Başka bir deyişle, tüm hedeflerinizin inşa tariflerini küçük bir koşullu işleve sarmak için makefile'ınızı değiştirmeniz gerekir. Kısa bir örnek göndereceğim:

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

Bu örnekte, her bir hedefin tarifini sarmak için elle haddelenmiş getRecipe işlevini kullanıyorum ve daha sonra bu tarifi çalıştırıp çalıştırmayacağınıza veya hangi hedefin inşa edildiğini ve hangi önkoşullara bağlı olduğuna karar veriyorum. İkincisi, yalnızca değişken DEPENDENCY_GRAPHayarlandığında (örn. Ortam değişkeni olarak) gerçekleşir. Örnekte, yapı tarifi, hedefin inşa edildiğini söyleyen bir yankıdan başka bir şey değildir, ancak bunu istediğiniz bir komutla değiştirebilirsiniz.

İle DEPENDENCY_GRAPH1 olarak ayarlandığında, çıktıda bu sonuçları:

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"

ayrıştırmak ve daha sonra bir nokta grafiğe dönüştürmek için yeterince kolay olmalıdır.

İle DEPENDENCY_GRAPHtüm ayarlanır veya 0 olarak ayarlanmamış, çıkışı:

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

veya başka bir deyişle, bunun yerine normal yapı tarifi kullanılır. Bunun karmaşık tariflerle güvenilir bir şekilde çalışıp çalışmadığını henüz test etmedim. Zaten karşılaştığım bir sorun, çok satırlı tariflerle hiç çalışmadığı.

Örneğin, son hedefin derleme tarifinde, hedefin inşa edildiğini söylemeye ek olarak, aslında touchdosyaya istedim :

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

maketouch $@parçanın önceki satırdaki yankının yalnızca bir parçası olduğunu düşünüyor gibi görünüyor :

Building target foobar.txt touch foobar.txt

Ben önceki çizgide sondaki ters eğik çizgi dışı bırakırsanız, makeşikayet *** unterminated call to function'çağrısı: Eksik )'. Stop.herkes nasıl bir fikir varsa makegüzel oynamak için, dinliyorum. :)

DÜZENLEME: Bu yaklaşımla ilgili diğer sorun, bunun yalnızca henüz bir sonuç oluşturmadıysa işe yarayacağıdır make;


eklemek ;sonra target $@çalışmalara dokunmatik komutu
mug896

ikinci sorun için, make -Bkoşulsuz olarak tüm hedefleri yapan seçeneği kullanın .
mug896

2

Kullandığım --profile yeniden çevrimi (drop-in için yerine make), bir callgrind formatında bir bağımlılık ağacı oluşturulur.

Daha sonra gprof2dot hedef ağacın bir görüntüsünü oluşturabilir.


Belgeleri yanlış anlıyor muyum veya remake --profileyalnızca yürüttüğü hedefin bağımlılık grafiğini çıkarıyor mu? Veya bir şekilde tüm hedefler için grafik çıktısı alabilir mi?
Lucas

Sadece koştuğunda, korkarım. Ama hepsini
Victor Sergienko

Oh evet, remake --targets -r | grep -v %| grep -v '\t*\.'|xargs remake -n --profile -Bumut verici görünüyor.
Lucas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.