วิธีแสดงการขึ้นต่อกันที่กำหนดใน makefile เป็นแผนผัง


18

ปัญหา

ฉันต้องการดูการอ้างอิงสำหรับหนึ่งหรือมากกว่าหนึ่งเป้าหมายของ makefile ดังนั้นฉันกำลังมองหาโปรแกรมที่สามารถแยกวิเคราะห์ makefiles แล้วจะแสดงการอ้างอิงในรูปแบบต้นไม้บางอย่าง (เยื้อง, ascii-art, ... ) หรือเป็นกราฟ (dot, ... )

คล้ายคลึงกัน

มีโปรแกรมที่ทำสิ่งนี้สำหรับสถานการณ์อื่น ๆ :

  • pactreeหรือcashreeสามารถแสดงการขึ้นต่อกันของชุดซอฟต์แวร์ในรูปแบบตามลำดับในแผนผังเช่นรูปแบบ 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'

แต่ดูเหมือนว่าฉันจะต้องแฮกรหัสการแยกวิเคราะห์เพิ่มเติมใน Perl หรือ Python เพื่อแสดงสิ่งนี้ว่าเป็นต้นไม้ / กราฟที่ดี และฉันยังไม่รู้ว่าฉันจะได้กราฟที่สมบูรณ์และถูกต้องหรือไม่

ความต้องการ

มันจะดีที่จะ จำกัด กราฟในบางวิธี (ไม่มีกฎบิวด์อิน, เฉพาะเป้าหมายที่กำหนด, เพียงบางส่วนเท่านั้น) แต่ส่วนใหญ่ฉันแค่มองหาเครื่องมือที่จะให้การพึ่งพาฉันใน "เหตุผล" มนุษย์ รูปแบบที่ดูได้ (เช่นโปรแกรมภายใต้ "Similar" do)

คำถาม

  • มีโปรแกรมใดบ้างที่สามารถทำได้
  • ฉันจะได้รับข้อมูลที่ครบถ้วนและถูกต้องmake -dnq ...หรือไม่
  • มีวิธีที่ดีกว่าในการรับข้อมูลนี้หรือไม่?
  • สคริปต์ / ความพยายามแยกวิเคราะห์ข้อมูลนี้มีอยู่แล้วหรือไม่?

1
สิ่งสำคัญที่ต้องทำความเข้าใจที่นี่คือ: การพึ่งพาไม่ได้สร้างต้นไม้ พวกเขาฟอร์มกำกับและ (หวังว่า) วัฏจักรกราฟยังเป็นที่รู้จักDAG ลองร่างกราฟการพึ่งพาสำหรับสิ่งต่อไปนี้แล้วคุณจะเห็น: A ขึ้นอยู่กับ B; A ขึ้นอยู่กับ C; B ขึ้นอยู่กับ D; C ขึ้นอยู่กับ D.
Wildcard

@ Wildcard ฉันรู้ แต่สำหรับจุดประสงค์ของฉันมันก็เพียงพอที่จะเป็นตัวแทนการพึ่งพาเป็นต้นไม้ ฉันสบายดีกับการทำซ้ำกราฟย่อย (และตัดเป็นวงกลม) เพื่อทำให้เป็นต้นไม้ ขออภัยที่ไม่เปิดเผย printf 'A\n B\n D\n C\n D\n'สำหรับคุณเช่นฉันจะดีกับการส่งออกของ (ใครบอกว่าผมไม่สามารถใส่บรรทัดใหม่ในความคิดเห็น :)?
ลูคัส

สิ่งนั้นจะแตกต่างจาก "A ขึ้นอยู่กับ B; B ขึ้นอยู่กับ D; D ขึ้นอยู่กับ C; A ขึ้นอยู่กับ D" คุณสามารถกำหนดการสั่งซื้อทั้งหมดใน DAG ใด ๆ (เนื่องจาก DAG ใด ๆ ยังแสดงถึงการสั่งซื้อบางส่วน) แต่คุณไม่สามารถเปลี่ยน DAG ให้กลายเป็นต้นไม้ นี่คือทฤษฎีกราฟพื้นฐาน ฉันสนใจที่จะเห็นอัลกอริทึมของคุณในการสร้างทรีของ DAG ซึ่งสามารถแสดงได้ หากไม่มีอัลกอริธึมพื้นฐานเครื่องมือใด ๆ ที่พยายามแสดงการพึ่งพาเป็นต้นไม้จะมีความจำเป็นอย่างยิ่งต่อการแฮ็กและเกิดข้อผิดพลาดได้ง่าย
Wildcard

บางทีฉันอาจจะไม่ชัดเจนเพียงพออีกครั้ง แต่ฉันคิดว่าตัวอย่างที่ฉันให้ไว้ในSimilarทำให้ชัดเจน ฉันไม่สนใจทฤษฎีกราฟ (ในคำถามนี้อย่างน้อย) ทั้งหมดที่ฉันต้องการคือการแสดงภาพที่มีลักษณะคล้ายกับต้นไม้ (โดยเฉพาะถ้ามันควรจะแสดงบนเทอร์มินัลสำหรับdotกราฟการสั่งซื้อที่เห็นได้ชัด) ฉันจะอัปเดตคำถามเล็กน้อยเพื่อให้ชัดเจนขึ้น (ฉันหวังว่า)
ลูคัส

2
พูดจาโผงผาง: ฉันผิดหวังเล็กน้อยที่ทำให้ไม่ได้เสนออะไรแบบนี้ออกมาทันที Make เป็นหนึ่งในระบบสร้างที่กว้างขวางที่สุดในโลกและคุณลักษณะนี้จะมีประโยชน์อย่างมากจนยากที่จะเข้าใจว่าในช่วงที่พระเจ้าทรงทราบว่ามีกี่ทศวรรษที่ผ่านมาไม่มีใครเพิ่มคุณลักษณะดังกล่าว การส่งออกข้อมูลนี้ในรูปแบบข้อความที่กำหนดไว้อย่างชัดเจนจะเพียงพอโดยสิ้นเชิง ฉันเข้าใจว่าการทำนั้นเป็นโอเพ่นซอร์สและฉันสามารถเพิ่มคุณสมบัตินี้ด้วยตัวเองได้เสมอ และเชื่อฉันเถอะถ้าการทำไม่ได้เป็นกล่องดำสำหรับฉัน RANT มากกว่า
antred

คำตอบ:


10

ลองmakefile2graphจากนักเขียนคนเดียวกันมี AA เครื่องมือที่คล้ายกัน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_GRAPHตั้งค่าเป็น 1 ผลลัพธ์นี้ในผลลัพธ์:

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 $@คำสั่ง touch ในการทำงาน
mug896

สำหรับปัญหาที่สองให้ใช้make -Bตัวเลือกที่สร้างเป้าหมายทั้งหมดโดยไม่มีเงื่อนไข
mug896

2

ฉันใช้remake --profile (การแทนที่แบบดรอปอินmake) มันสร้างแผนผังการพึ่งพาในรูปแบบ callgrind

จากนั้นgprof2dotสามารถสร้างภาพต้นไม้เป้าหมาย


ฉันเข้าใจว่าเอกสารไม่ถูกต้องหรือremake --profileส่งกราฟอ้างอิงสำหรับเป้าหมายที่ดำเนินการเท่านั้น หรือมันสามารถออกกราฟสำหรับเป้าหมายทั้งหมดได้หรือไม่?
ลูคัส

มีเพียงคนเดียวเท่านั้นที่ฉันกลัว แต่คุณสามารถวิ่งได้ทั้งหมดด้วย - วิ่งหนี
Victor Sergienko

โอ้ใช่แล้วบางสิ่งที่remake --targets -r | grep -v %| grep -v '\t*\.'|xargs remake -n --profile -Bดูเหมือนว่าจะเป็นไปได้
ลูคัส
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.