ยุติการนำ Swift มาใช้ – ปิดประเด็นปัญหาการรองรับ Swift 6.0 ของเบราว์เซอร์ Ladybird
(github.com/LadybirdBrowser)- โปรเจกต์เบราว์เซอร์ Ladybird ได้สรุปรายการ ปัญหาที่เกิดขึ้นระหว่างการเปลี่ยนการรองรับ Swift 6.0 จากขั้นทดลองไปเป็นทางการ แต่ภายหลังได้ตัดสินใจว่าจะไม่เดินหน้าการนำ Swift มาใช้อีกต่อไป
- อุปสรรคหลักคือปัญหาที่เกี่ยวข้องกับ การทำงานร่วมกันระหว่าง Swift และ C++ (Interop) เช่น ABI ไม่ตรงกัน, การพึ่งพากันแบบวนลูปของเฮดเดอร์, การไม่สามารถคืนค่าบางชนิดได้ โดยหลายรายการได้รับการแก้ไขหลัง Swift 6.0.0
- ใน ระบบบิลด์ CMake ก็มีรายงานปัญหา เช่น target สำหรับ deploy ไม่ตรงกันในสภาพแวดล้อม Swift + Ninja, ข้อผิดพลาดในการจัดการ
install_name, และออปชันคอมไพล์ที่ไม่เข้ากัน - ภายในโค้ดของ Ladybird เองก็พบความไม่เสถียรในการบิลด์หลายจุด เช่น การตั้งค่า modulemap ของโมดูล AK และ LibGfx, การแครชของ Swift frontend, และการชนกันของ namespace ของชนิดข้อมูล
- จากข้อจำกัดทางเทคนิคที่สะสมเหล่านี้ จึงมีการยุติการรวม Swift เข้ากับระบบ และนำไปสู่ การตัดสินใจคงแนวทางพัฒนาโดยยึด C++ เป็นหลัก
ปัญหาที่เกี่ยวข้องกับ Swift
- มี บั๊กระดับภาษาและ ABI จำนวนมากที่ต้องแก้ไขเพื่อให้การรองรับ Swift 6.0 พ้นจากขั้นทดลอง
- เกิด assertion failure ระหว่างบิลด์ Swift แบบโอเพนซอร์สจากความไม่ตรงกันของเวอร์ชัน LLVM
- ปัญหา ABI ไม่ตรงกันระหว่างคอมไพเลอร์กับ bridging header เมื่อคืนค่า
Optional<CxxValueType> - ในสภาพแวดล้อม Ubuntu 22.04 เมื่อ include เฮดเดอร์
<execution>จะเกิด การพึ่งพาแบบวนลูปของโมดูล libstdc++ - รวมถึง ปัญหาความเข้ากันได้กับ C++23 เช่น ไม่สามารถคืนค่า
swift::Optional<swift::String>ได้ และไม่สามารถโหลดเฮดเดอร์<chrono>
- ปัญหาบางส่วนได้รับการแก้ไขในรีลีสหลัง Swift 6.0.0 แต่บางส่วน แก้เฉพาะบนสาขา main และยังไม่ถูกรวมในเวอร์ชันเสถียร
- หลายรายการมีการเสนอ “วิธีแก้ชั่วคราว (workaround สำหรับการบิลด์)” แต่ไม่ใช่คำตอบที่แก้ปัญหาได้สมบูรณ์
ปัญหาที่เกี่ยวข้องกับ CMake
- เมื่อใช้ Swift ร่วมกับ Ninja build จะมีคำเตือนจำนวนมากจากการที่
CMAKE_OSX_DEPLOYMENT_TARGETไม่ถูกนำไปใช้- จำเป็นต้องตั้งค่า
CMAKE_Swift_COMPILER_TARGETด้วยตนเอง
- จำเป็นต้องตั้งค่า
- เมื่อเปิดใช้นโยบาย CMP0157 การตั้งค่าไดเรกทอรี
install_nameจะ ถูกมองข้าม ทำให้ต้องแก้ไขเอง- การแก้ไขที่เกี่ยวข้องมีกำหนด backport ไปยัง CMake 3.29 และ 3.30
- มีปัญหาที่ ออปชันลิงก์ซึ่ง Swift compiler ไม่เข้าใจ ถูกส่งมาจาก dependency ภายนอก
ปัญหาภายในโปรเจกต์ Ladybird
- ระหว่างการตั้งค่า clang module map ของโมดูล AK และ LibGfx เกิดการชนกับ system header
- เมื่อ include
<math.h>จะเกิดข้อผิดพลาดด้านการรู้จักโมดูลและทำให้บิลด์ล้มเหลว
- เมื่อ include
- Swift frontend แครชใน debug build ระหว่างการทดสอบคอนเทนเนอร์ AK
- หลีกเลี่ยงได้ด้วยการบิลด์ในโหมด release เท่านั้น
- การชนกันของ namespace ของชนิด
Stringทำให้ Swift frontend ปิดตัวผิดปกติ- ต้องระบุให้ชัดเจนเป็น
AK.StringหรือSwift.String
- ต้องระบุให้ชัดเจนเป็น
- เมื่อใช้โมดูล Swift Testing จะมี การแครชของ compiler frontend และยังมีปัญหาที่
AK::StringViewไม่ถูกมองว่าเป็นCxxSequenceType
รายการปรับปรุงเพิ่มเติม
- ใน Swift เมื่อฟังก์ชัน C++ คืนค่า
Optional<CxxType>จะเกิด แอปพลิเคชันแครช- วิธีแก้ชั่วคราวคือคืนค่าเป็นอาร์เรย์ขนาด 0 หรือ 1 แทน
- SourceKit-LSP และ vscode-swift ต้องการ
compile_commands.jsonที่ระดับรากของโปรเจกต์- แก้ได้ด้วยการสร้าง symbolic link
- บน Linux มีความไม่สะดวกที่ต้อง เพิ่มพาธ
<swift/bridging>ด้วยตนเอง
คำถามที่ยังไม่คลี่คลาย
- ยังไม่ชัดเจนว่าใน Swift จะ ส่งผ่าน view type หรือ byte slice ของ C++ โดยไม่ต้องคัดลอกข้อมูล ได้อย่างไร
- Swift ยัง ไม่สามารถมองชนิดภายในอย่าง AK::Optional, AK::HashMap ว่าเทียบเท่ากับชนิดของ
std:: - รวมถึง วิธีผสาน garbage collector ของ Swift เข้ากับระบบจัดการหน่วยความจำของ Ladybird ก็ยังไม่ถูกกำหนด
ประเด็นนี้เดิมเป็นเอกสารที่บันทึกอุปสรรคทางเทคนิคสำหรับการรวม Swift 6.0 อย่างเป็นระบบ แต่ภายหลังเมื่อทีม Ladybird ยุติการนำ Swift มาใช้ ประเด็น “Swift 6.0 Blockers” ก็ถูกปิดลง
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
คอมมิตที่ลบ Swift มีคำอธิบายเพิ่มเติมเล็กน้อย
มีข้อความว่า “เนื่องจากไม่มีความคืบหน้ามาเป็นเวลานาน เราจึงยกเลิกการนำ Swift มาใช้และลบออกจากโค้ดเบส”
ดูคอมมิตที่เกี่ยวข้องได้ที่นี่
ฉันลองใช้ Swift ครั้งแรกในปี 2021 แล้วก็แปลกใจ หลังจากทำ C#/.NET มานานกว่า 10 ปี
ฉันคิดว่า C# ก็ซับซ้อนแล้ว แต่ Swift เป็นภาษาที่ซับซ้อนกว่ามาก
โดยเฉพาะเวลาสร้าง backend API หรือ data access layer แทบไม่มีข้อมูลอ้างอิงให้ดูเลย
ความรู้เกี่ยวกับ Swift ส่วนใหญ่สะสมอยู่บนแพลตฟอร์มของ Apple ดังนั้นนอกเหนือจากนั้นก็ให้ความรู้สึกเหมือนต้องเป็นผู้บุกเบิกเองแทบทั้งหมด
อย่างที่ Larry Wall เคยพูดไว้ ความซับซ้อนของเครื่องมือควรสอดคล้องกับความซับซ้อนของปัญหา (กล่าวถึง Raku)
แต่กฎอย่าง “struct ส่งต่อแบบค่า ส่วน class ส่งต่อแบบอ้างอิง” ไปขัดกับหลักการ “รักษาแหล่งข้อมูลจริงเพียงหนึ่งเดียว” ทำให้ประสบการณ์พัฒนาน่าเบื่อและช้าลง
ฉันแทบไม่คืบหน้าเพราะ best practice ของ Swift ที่ขัดแย้งกันเอง และสุดท้ายก็พบว่าคำแนะนำจำนวนมากเชื่อถือไม่ได้
มี syntactic sugar มากเกินไป และมีวิธีทำสิ่งเดียวกันได้เป็นสิบแบบ จนต้องเปิดดูlanguage referenceอยู่ตลอด
ไม่ว่าภาษาจะเป็นอะไร ก็หวังว่า Ladybird จะไปโฟกัสกับการทำ JavaScript implementation ที่เป็นมิตรกับผู้ใช้ในอนาคต
การที่ JS ถูกใช้เพื่อติดตามกิจกรรมผู้ใช้ บล็อกการวางข้อความ หรือเก็บข้อมูลอุปกรณ์มากเกินไปเป็นปัญหา
ถ้ารายงานค่า spoof แบบทำให้เป็นมาตรฐานเดียวกันระหว่างผู้ใช้เหมือน Tor ได้ ก็น่าจะช่วยเรื่องความเป็นส่วนตัว
ถ้าทำเป็นตัวเลือกแบบสลับเปิดปิดก็น่าจะโอเค แต่ถ้าตั้งเป็นค่าเริ่มต้นคงยากต่อการยอมรับ
การลบ Swift น่าสนใจดี เหตุผลยังไม่ได้อธิบายชัดเจนเลยอยากรู้
ถ้ามันรันบน Linux ได้เมื่อไร ฉันตั้งใจว่าจะลองทดสอบดู
เป็นปัญหาที่ Swift ไม่สามารถ import ไลบรารี C++ หลายเวอร์ชันพร้อมกันได้ หรือเกิดการชนกันของเวอร์ชัน operator
Swift เป็นภาษาที่ดี แต่คงซับซ้อนเกินไปหากจะเพิ่มเข้าไปทีหลังในโปรเจกต์ขนาดใหญ่ที่มีอยู่แล้ว
สงสัยว่าเหตุใด Ladybird ถึงลองใช้ Swift ฉันคิดว่า Rust น่าจะมี**การทำงานร่วมกับ C++**ที่ดีกว่าไม่ใช่หรือ
GC ของ Swift ก็ดูน่าจะเสียเปรียบต่อประสิทธิภาพของเบราว์เซอร์ด้วย
ลิงก์1, ลิงก์2
ถึงจะมีทางเลี่ยง แต่ประสิทธิภาพการทำงานก็ลดลง
เพียงแต่สำหรับ Ladybird ดูเหมือนว่ายังไม่เพียงพอ
ก่อนหน้านี้เขาเคยสร้างภาษา Jakt ใน SerenityOS แต่ดูเหมือนสุดท้ายก็กลับไปใช้ C++
มีการพูดคุยเก่าเกี่ยวกับเรื่องนี้ในโพสต์นี้
Swift เป็นภาษาที่พึ่งพา Apple มากเกินไปอยู่แล้ว จึงไม่ได้น่าแปลกใจ
แค่ใช้ส่วนที่ปลอดภัยของ C++ ให้ดีก็พอ และจริงๆ เบราว์เซอร์ส่วนใหญ่ก็เขียนด้วย C++
Chromium และ Firefox กำลังค่อยๆ แทนที่ด้วยภาษาที่ปลอดภัยกว่า การเขียนเบราว์เซอร์ใหม่ด้วย C++ อีกครั้งจึงเหมือนทำผิดซ้ำแบบเดิม
การใช้ C++ เป็นมรดกตกค้างมาตั้งแต่ยุค KHTML ในปี 1998
รวมฟีเจอร์ STL สมัยใหม่อย่าง string_view ด้วยไหม? ถึงอย่างนั้นก็ยังห่างไกลจาก memory safety แบบสมบูรณ์อยู่ดี
นอกจาก benchmark บางตัวแล้ว ในโปรแกรมจริงแทบจะช้ากว่าเกือบตลอด
เสียดายที่ลบ Swift ถ้าอย่างนั้นภาษา Jakt ของตัวเองจะกลับมาเป็นตัวเลือกอีกไหม
ฉันมองว่าโอกาสจะนำภาษาใหม่เข้ามาอีกค่อนข้างต่ำ
ถ้าเป็นโปรเจกต์ที่ดำเนินงานด้วยการสนับสนุนจากภายนอกแล้วเป็นแบบนี้ ก็คงยากจะยั่งยืนในระยะยาว
ฉันคิดว่า Swift สุดท้ายก็เป็นแค่ภาษาเล่นของ Appleเท่านั้น
Apple จะไม่ปล่อยให้มันเติบโตไปได้ไกลกว่านั้น
Mac UI ของ Ladybird เป็นเลเยอร์บางๆ ที่วางอยู่บน AppKit
เขียนด้วย Objective-C++ ไม่ใช่ Swift
ดูได้ที่ซอร์สโค้ด
มันถูกสร้างขึ้นตั้งแต่สมัย SerenityOS นานก่อนจะมีการนำ Swift มาใช้ ดังนั้นที่ใช้ Objective-C++ ก็เพียงเพราะมันเป็นภาษาที่คุ้นเคย
ตอนที่เคยประกาศว่าจะย้ายไป Swift ฉันก็วิจารณ์ไว้แล้ว
ฉันมองว่า Swift ออกแบบมาไม่ค่อยดี และความเร็วในการคอมไพล์ก็ช้า รวมถึงมีโอกาสน้อยที่จะเติบโตเป็น system language ได้
อีกทั้งก็ไม่มีผู้เชี่ยวชาญด้วย ดังนั้นฉันคิดว่าการตัดสินใจครั้งนี้ถูกต้องแล้ว
ฟีเจอร์อย่าง Concurrency หรือ Swift Testing ก็เป็นตัวอย่างของสิ่งที่ถูกผลักดันตามความต้องการของ Apple
งานข้ามแพลตฟอร์มส่วนใหญ่กำลังถูกทำแยกโดยทีมขนาดเล็ก
ต่อให้ไม่นับ Chris Lattner เหล่า lead ของ Swift ก็ยังเป็นบุคคลที่ได้รับการยอมรับในชุมชน C++
คงดีถ้าฝั่ง Rust รองรับ Swift ABI ใน FFI ควบคู่กับ C ด้วย