GCC และ g ++ bootstrapped เป็นอย่างไร


186

สิ่งนี้ได้ดักฟังฉันมาระยะหนึ่งแล้ว GCC และ g ++ รวบรวมตัวเองอย่างไร

ฉันเดาว่าการแก้ไขทุกครั้งจะได้รับการคอมไพล์ด้วยการแก้ไขที่สร้างไว้ก่อนหน้านี้ มันเป็นเรื่องจริงเหรอ? และถ้าเป็นเช่นนั้นหมายความว่ารุ่นเก่าที่สุดของ g ++ และ GCC ถูกเขียนไว้ในชุดประกอบหรือไม่?


13
ในที่สุดการแก้ไขแต่ละครั้งก็สามารถรวบรวมได้ด้วยตัวเอง :)
Martin Hennings

4
นี่เป็นเรื่องที่น่าสนใจหากคุณต้องการดูว่าคอมไพเลอร์ตัวแรกเกิดขึ้นได้อย่างไร
parkovski

1
@parkovski ลิงค์นี้ตายหรือเปล่า?
Nubcake

ลิงก์เห็นครั้งสุดท้ายเมื่อวันที่ 04 มิ.ย. 2016: web.archive.org/web/20160604035203/homepage.ntlworld.com/…
akraf

คำตอบ:


175

GCC รุ่นที่เก่าแก่ที่สุดได้รับการคอมไพล์โดยใช้คอมไพเลอร์ C ตัวอื่นเนื่องจากมีเวอร์ชั่นอื่นเมื่อเขียน คอมไพเลอร์ C ตัวแรกที่เคยใช้ (แคลิฟอร์เนียในปี 1973, IIRC) ถูกนำมาใช้เช่นกัน PDP-11หรือในภาษาโปรแกรม B ซึ่งนำหน้ามันในทำนองเดียวกันคอมไพเลอร์ C ++ ตัวแรก (CPre / Cfront , 1979-1983) อาจถูกนำมาใช้ครั้งแรกใน C จากนั้นเขียนใหม่ใน C ++

เมื่อคุณคอมไพล์ GCC หรือคอมไพเลอร์โฮสติ้งด้วยตนเองอื่น ๆ ลำดับเต็มของสิ่งปลูกสร้างคือ:

  1. สร้าง GCC เวอร์ชันใหม่ด้วยคอมไพเลอร์ C ที่มีอยู่
  2. สร้าง GCC เวอร์ชันใหม่ขึ้นมาใหม่ด้วยรุ่นที่คุณเพิ่งสร้างขึ้น
  3. (ไม่บังคับ) ทำซ้ำขั้นตอนที่ 2 เพื่อจุดประสงค์ในการตรวจสอบ

กระบวนการนี้เรียกว่าการบูตสแตรป มันทดสอบความสามารถของคอมไพเลอร์ในการคอมไพล์ตัวเองและตรวจสอบให้แน่ใจว่าคอมไพเลอร์ที่ได้นั้นถูกสร้างขึ้นด้วยการปรับแต่งทั้งหมดที่ตัวมันใช้เอง

แก้ไข : Drew Dormann, ในความคิดเห็นที่จุดไปยังบัญชี Bjarne Stroustrup ของการดำเนินงานที่เก่าแก่ที่สุดของ C มันถูกนำมาใช้ใน C ++ แต่แปลโดยสิ่งที่ Stroustrup เรียกว่า "preprocessor" จาก C ++ ถึง C; ไม่ใช่คอมไพเลอร์เต็มตามคำจำกัดความของเขา แต่ C + + ก็ยังถูก bootstrapped ใน C


19
กระบวนการสร้าง bootstrap เวอร์ชัน 3 ขั้นตอนมีไว้สำหรับการตรวจสอบความถูกต้องตัวคอมไพเลอร์เองถูกใช้เป็นกรณีทดสอบของตัวเอง GCC ที่คอมไพล์ด้วย [อื่น ๆ ] ควรให้ผลลัพธ์ที่เหมือนกัน (ไบนารีที่เหมือนกันมาโครลดราคาแบบที่ชอบ__DATE__และ__TIME__แตกต่างกันระหว่างการเรียกใช้คอมไพเลอร์เดียวกัน ) ขณะที่ GCC ที่คอมไพล์ด้วย [GCC ที่คอมไพล์ด้วย [อื่น ๆ ]] - ถ้าไม่ใช่นั่นเป็นข้อผิดพลาด bootstrap บิลด์ 3 ขั้นตอนได้รับการออกแบบมาเพื่อรองรับ
pmdj

19
@ pmjordan: "ถ้าไม่ใช่นั่นเป็นข้อผิดพลาด" หรือมีโอกาสน้อยกว่าที่จะเป็นแบ็คดอร์ผู้คดเคี้ยวในกระบวนการของการเปิดตัว ("Reflections on Trusting Trust")
Steve Jessop

12
@sleske: นั่นไม่เป็นความจริง เอาต์พุตไบนารีของขั้นตอนที่ 2 จะต้องเหมือนกันกับเอาต์พุตไบนารีของขั้นตอนที่ 3 มิฉะนั้นจะมีจุดบกพร่องอยู่ที่ใดที่หนึ่ง เหตุผลก็คือ pmjordan พูดว่า: NewCompiler1 และ NewCompiler2 เป็นโปรแกรมที่มีแหล่งเดียวกัน (ของ NewCompiler) พวกเขาจะได้รับการป้อนข้อมูลที่เหมือนกัน (แหล่งที่มาสำหรับ NewCompiler) ดังนั้นพวกเขาจะสร้างผลลัพธ์ที่เหมือนกันไม่ว่าคอมไพเลอร์ที่พวกเขารวบรวม (ในกรณีนี้ NewCompiler1 ถูกคอมไพล์ด้วย OldCompiler และ NewCompiler2 ถูกคอมไพล์ด้วย NewCompiler1) นั่นคือ NewCompiler2 และ NewCompiler3 เป็นเลขฐานสองที่เหมือนกัน
Steve Jessop

12
ฉันเคยสงสัย: ถ้าเราสูญเสียไบนารีคอมไพเลอร์ C ทั้งหมด? และต้องเริ่มต้นจากศูนย์? นี่คือวิธีที่ฉันจะไปเกี่ยวกับมัน: มี Tiny C Compiler (ซึ่งจริง ๆ แล้วสามารถรวบรวมเคอร์เนล Linux, ดังนั้นมันค่อนข้างสมบูรณ์คุณสมบัติ) ไฟล์ต้นฉบับของ C ทั้งหมดสร้างโค้ด 30k บรรทัดรวมถึงความคิดเห็น แม้ว่าจะเป็นความพยายามบางอย่าง แต่บางคนที่เข้าใจ C สามารถเรียนรู้จากแหล่งข้อมูลได้วิธีสร้างไบนารีเอาต์พุตและ "รวบรวม" แหล่งข้อมูล TCC จากมือ จากนั้นคอมไพล์ TCC อีกครั้งด้วยและใช้มันเพื่อบู๊ต GCC หรือคล้ายกัน
datenwolf

11
@datenwolf: อย่างนั้นใช่ หากเราสามารถสันนิษฐานได้ว่าเราได้สูญเสียไบนารีคอมไพเลอร์ C ทั้งหมด แต่เรายังมีแอสเซมเบลอร์อยู่เราอาจเขียนโปรแกรมแอสเซมเบลอร์ TinyTinyC มันจะเป็นคอมไพเลอร์ C ที่มีคุณสมบัติครบถ้วนน้อยกว่า TinyC: เราไม่ต้องการให้สามารถคอมไพล์ GCC หรือเคอร์เนลลินุกซ์ได้เราแค่ต้องการให้สามารถรวบรวม TinyC ได้ จากนั้นเรียกใช้จากแหล่งที่มาของ TinyC ซึ่งทำให้คอมไพเลอร์ C สามารถรวบรวม Linux (และหวังว่า glibc และ GCC) และเราอยู่ในธุรกิจ ถ้าเราไม่มีแอสเซมเบลอร์เราก็จะบูตสแตรปอันใดอันหนึ่งได้ง่ายกว่าคอมไพเลอร์ C
Steve Jessop
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.