โพสต์บล็อกนั้นค่อนข้างไม่ถูกต้อง
เท่าที่ฉันทราบได้มีการนำการเปลี่ยนแปลง C ++ ABI มาใช้กับ GCC ทุกรุ่นที่สำคัญ (เช่นการเปลี่ยนแปลงที่มีส่วนประกอบหมายเลขเวอร์ชันแรกหรือเวอร์ชันที่สองต่างกัน)
ไม่จริง. การเปลี่ยนแปลง C ++ ABI เพียงอย่างเดียวที่นำมาใช้ตั้งแต่ GCC 3.4 สามารถใช้งานร่วมกันได้ซึ่งหมายความว่า C ++ ABI มีความเสถียรมาเกือบเก้าปี
เพื่อให้เรื่องแย่ลงการกระจาย Linux ที่สำคัญส่วนใหญ่ใช้สแน็ปช็อต GCC และ / หรือแพตช์เวอร์ชัน GCC ทำให้แทบจะเป็นไปไม่ได้เลยที่จะทราบว่า GCC เวอร์ชันใดที่คุณอาจจัดการเมื่อคุณแจกจ่ายไบนารี
ความแตกต่างระหว่าง GCC เวอร์ชันแพตช์ของดิสทริบิวชันนั้นมีเพียงเล็กน้อยและไม่มีการเปลี่ยนแปลง ABI เช่น 4.6.3 20120306 (Red Hat 4.6.3-2) ของ Fedora คือ ABI เข้ากันได้กับรุ่นอัปสตรีม FSF 4.6.x และเกือบจะแน่นอนกับ 4.6 ใด ๆ x จาก distro อื่น ๆ
บนไลบรารีรันไทม์ของ GNU / Linux GCC ใช้การกำหนดเวอร์ชันสัญลักษณ์ ELF ดังนั้นจึงง่ายต่อการตรวจสอบเวอร์ชันสัญลักษณ์ที่ต้องการโดยอ็อบเจ็กต์และไลบรารีและหากคุณมีlibstdc++.so
สัญลักษณ์ที่ให้สัญลักษณ์เหล่านั้นก็จะใช้งานได้ไม่สำคัญว่าจะเป็นเวอร์ชันที่ได้รับการแก้ไขที่แตกต่างกันเล็กน้อย จาก distro เวอร์ชันอื่นของคุณ
แต่ไม่มีรหัส C ++ (หรือรหัสใด ๆ ที่ใช้การสนับสนุนรันไทม์ C ++) อาจเชื่อมโยงแบบไดนามิกหากใช้งานได้
นี่ไม่เป็นความจริงเช่นกัน
ที่กล่าวว่าการลิงก์แบบคงที่libstdc++.a
เป็นทางเลือกหนึ่งสำหรับคุณ
สาเหตุที่อาจใช้ไม่ได้หากคุณโหลดไลบรารี (โดยใช้dlopen
) แบบไดนามิกคือสัญลักษณ์ libstdc ++ ซึ่งขึ้นอยู่กับว่าแอปพลิเคชันของคุณอาจไม่ต้องการเมื่อคุณเชื่อมโยง (แบบคงที่) ดังนั้นสัญลักษณ์เหล่านั้นจะไม่ปรากฏในไฟล์ปฏิบัติการของคุณ ซึ่งสามารถแก้ไขได้โดยการเชื่อมโยงไลบรารีที่แบ่งใช้แบบไดนามิกเข้ากับlibstdc++.so
(ซึ่งเป็นสิ่งที่ถูกต้องที่จะทำต่อไปหากขึ้นอยู่กับมัน) การคั่นด้วยสัญลักษณ์ ELF หมายถึงสัญลักษณ์ที่มีอยู่ในไฟล์ปฏิบัติการของคุณจะถูกใช้โดยไลบรารีที่แบ่งใช้ แต่อื่น ๆ ไม่ใช้ ที่มีอยู่ในไฟล์ปฏิบัติการของคุณจะพบได้ในสิ่งที่libstdc++.so
เชื่อมโยงไปยัง หากแอปพลิเคชันของคุณไม่ได้ใช้งานdlopen
คุณไม่จำเป็นต้องสนใจเรื่องนั้น
อีกทางเลือกหนึ่ง (และทางเลือกหนึ่งที่ฉันชอบ) คือการปรับใช้เวอร์ชันใหม่libstdc++.so
ควบคู่ไปกับแอปพลิเคชันของคุณและตรวจสอบให้แน่ใจว่าพบก่อนระบบเริ่มต้นlibstdc++.so
ซึ่งสามารถทำได้โดยบังคับให้ตัวเชื่อมโยงแบบไดนามิกดูในตำแหน่งที่ถูกต้องไม่ว่าจะใช้$LD_LIBRARY_PATH
ตัวแปรสภาพแวดล้อมที่รัน - เวลาหรือโดยการตั้งค่าRPATH
ในปฏิบัติการในเวลาลิงค์ ฉันชอบใช้RPATH
เพราะมันไม่ได้ขึ้นอยู่กับสภาพแวดล้อมที่ตั้งไว้อย่างถูกต้องเพื่อให้แอปพลิเคชันทำงาน หากคุณเชื่อมโยงแอพลิเคชันของคุณด้วย'-Wl,-rpath,$ORIGIN'
(หมายเหตุราคาเดียวเพื่อป้องกันไม่ให้เปลือกพยายามที่จะขยาย$ORIGIN
) แล้วปฏิบัติการจะมีRPATH
ของ$ORIGIN
ที่บอกลิงเกอร์แบบไดนามิกที่จะมองหาห้องสมุดสาธารณะในไดเรกทอรีเดียวกันเป็นปฏิบัติการของตัวเอง ถ้าใส่ใหม่กว่าlibstdc++.so
ในไดเร็กทอรีเดียวกันกับไฟล์ปฏิบัติการซึ่งจะพบได้ในขณะรันไทม์แก้ไขปัญหาได้ (อีกทางเลือกหนึ่งคือการใส่ไฟล์ปฏิบัติการลงใน/some/path/bin/
libstdc ++ ที่ใหม่กว่าดังนั้นใน/some/path/lib/
และเชื่อมโยงกับ'-Wl,-rpath,$ORIGIN/../lib'
หรือตำแหน่งคงที่อื่น ๆ ที่สัมพันธ์กับไฟล์ปฏิบัติการและตั้งค่า RPATH ให้สัมพันธ์กับ$ORIGIN
)
-static-libstdc++
เลือกใด ๆ คุณก็แค่ใช้-static