Theppitak's blog

My personal blog.

28 มิถุนายน 2554

scim-thai 0.1.2

scim-thai 0.1.2 ออกไปแล้วเมื่อวานนี้ ก็คงเป็นตัวสุดท้ายในการปรับรุ่นแพกเกจต่าง ๆ ใน linux.thai.net ระลอกนี้ (แต่ไม่ใช่หมดแค่นี้ อาจมีการออกรุ่นตัวอื่นที่ได้ปรับรุ่นไปแล้วอีกถ้าจำเป็น)

สำหรับ scim-thai รุ่นนี้ ถือเป็น maintenance release คือไม่ได้มีการเพิ่มความสามารถใหม่อะไร แต่เป็นการแก้ปัญหาเล็ก ๆ น้อย ๆ เกี่ยวกับระบบ build ที่ตรวจพบในช่วง 3 ปีที่ผ่านมา กล่าวคือ

  • ปรับการ config การแปลข้อความด้วย gettext จาก gettextize ให้มาใช้ autopoint แทน ซึ่งทำให้ปรับข้อมูล PO ได้แนบเนียนไร้ร่องรอยมากขึ้น
  • แก้ปัญหาการคอมไพล์ในกรณีที่ libthai ไม่ได้ติดตั้งไว้ในพาธมาตรฐาน เป็นปัญหาที่พบในระหว่างพัฒนา libthai ซึ่งต้องติดตั้งแยกต่างหากจาก libthai ของระบบ แล้วทำให้พบว่า make rule ของ scim-thai ยังติดปัญหาการคอมไพล์กับ libthai ที่แยกติดตั้งต่างหากนี้อยู่ กลายเป็นกรณีตัวอย่างให้อุดรูรั่ว
  • แก้ปัญหาเรื่องการกำหนด LDFLAGS ซึ่งพบระหว่างที่จะ build แพกเกจ Debian รุ่นใหม่โดยปรับการ build ให้ใช้แฟล็ก "-Wl,--as-needed" แล้วพบว่าแฟล็กนี้ไม่มีผล ตรวจสอบแล้วพบว่าเป็นปัญหาการใช้ target *_LDFLAGS ใน Makefile.am ในการเพิ่มไลบรารีให้กับมอดูล ซึ่งพอสคริปต์ configure กำหนด LDFLAGS=-Wl,--as-needed แล้ว แฟล็กนี้มันจะไปต่อท้ายค่าใน target *_LDFLAGS อีกที ซึ่งผมดันไปลิสต์ไลบรารีในนั้นเสียแล้ว ค่า LDFLAGS จากการ configure ก็เลยไปต่อท้ายอยู่หลังรายชื่อไลบรารี จึงไม่มีผลกับไลบรารี ที่ถูกแล้ว ต้องใช้ target *_LIBADD ในการเพิ่มไลบรารีแทน ชื่อไลบรารีจึงจะมาอยู่หลัง LDFLAGS ในคำสั่งคอมไพล์ เป็นปัญหาที่มาดูทีหลังก็งง ว่าตอนนั้นผมทำแบบนั้นไปได้อย่างไร ทำให้ต้องมางมอยู่นานกว่าจะเจอ

สำหรับผู้ที่สนใจเรื่องการใช้แฟล็ก --as-needed ของลิงเกอร์ ก็ขออธิบายสักหน่อย

แฟล็ก --as-needed ใช้เพื่อให้ object file ที่ได้นั้น ลิงก์เฉพาะกับไลบรารีที่มีการใช้ symbol โดยตรงเท่านั้น (ตรวจสอบการลิงก์ได้ด้วยคำสั่ง objdump -p {so/exe-file} แล้วดูที่บรรทัด NEEDED ทั้งหลายใน Dynamic Section)

กล่าวคือ สมมติว่า object file ของเรามีการเรียกใช้ libA และ libB โดย libA ไปลิงก์กับ libP, libQ อีกที เวลาลิงก์จะต้องใส่ไลบรารีทั้งหมดที่ใช้ คือเป็น "-lA -lB -lP -lQ" และลิงเกอร์ก็จะลิงก์ทุกไลบรารีเข้ามาใน object file ของเรา นี่คือกรณีปกติ

การลิงก์ดังกล่าวมีปัญหาในทางปฏิบัติ เพราะไลบรารีต่าง ๆ มีการต่อยอดกันเป็นทอด ๆ หลายชั้น เช่น เฉพาะ GTK+ ก็มีไลบรารีลูกต่อพ่วงมาอีกถึง 44 ตัว:

$ ldd /usr/lib/libgtk-3.so.0.0.10 | wc -l
44

ในนี้ก็มีตั้งแต่ pango, glib, ati, cairo, freetype, libxcb และพรรคพวกอีกมากมาย และการลิงก์เฉพาะ GTK+ เข้ามาในโปรแกรมของเรา ก็จะต้องลิงก์ไลบรารีเหล่านี้เข้ามาทั้งหมด ทั้งที่ไม่มีการเรียกใช้ฟังก์ชันโดยตรงเลยก็ตาม

ความจริง ตอน run-time ก็จะต้องโหลดไลบรารีเหล่านี้เข้ามาทั้งหมดอยู่แล้ว ไม่งั้น GTK+ ก็ทำงานไม่ได้ อ้าว แล้วถ้างั้นมีปัญหาอะไร?

ปัญหาก็คือ การลิงก์ตรงกับไลบรารีใด ๆ จะหมายถึงการเกิด dependency ระหว่างแพกเกจของไลบรารีที่ลิงก์กันนั้น ทำให้ระบบแพกเกจโดยรวมมี dependency จำนวนมโหฬารเกินความจำเป็น และจะเป็นอุปสรรคต่อการขยับไลบรารีหนึ่ง ๆ ขึ้นสู่ major version ใหม่ (ซึ่งอาจไม่ ABI compatible กับรุ่นเก่า) เพราะจะต้องตามไป rebuild แพกเกจทั้งหมดที่ลิงก์ตรงกับมันอยู่ กลายเป็นปริมาณงานที่มากเกินจำเป็น ในเมื่อโปรแกรมคุณแค่ใช้ฟังก์ชันของ GTK+ เท่านั้น ทำไมจะต้องไป rebuild เมื่อมีการปรับ major version ของ cairo หรือ freetype ด้วย? สู้ให้เรื่องพวกนี้มัน encapsulate อยู่ในแพกเกจ GTK+ เท่านั้นไม่ดีหรือ?

นี่จึงเป็นที่มาของการใช้แฟล็ก --as-needed ในการ build แพกเกจของ distro ต่าง ๆ เพื่อให้มีการลิงก์เฉพาะกับไลบรารีที่มีการใช้ symbol โดยตรงเท่านั้น แล้วเวลาโหลดหรือติดตั้ง มันก็จะทำงานเป็นทอด ๆ ตามลำดับ dependency เอง ถ้ามีการปรับ major version ก็จะ rebuild เฉพาะแพกเกจที่มีการเรียกใช้ symbol โดยตรงเท่านั้น

บางคนอาจถามว่า แล้วทำไมไม่แค่ลิงก์แบบ "-lgtk-3-0" กับแพกเกจที่ใช้ GTK+ ก็พอล่ะ? ไม่ต้องแถมพ่วงพวก pango, glib ฯลฯ มาด้วยก็ได้ คำตอบคือการลิงก์แบบนี้ไม่ portable ครับ ลิงเกอร์ของ GNU อาจทำได้ แต่ยูนิกซ์ทั่วไปทำไม่ได้ ต้องใส่ library ที่ต้องการตามลำดับให้ครบด้วยจึงจะลิงก์ผ่าน (เข้าใจว่ามาจากวิธีลิงก์แบบ static ที่ต้องมีไลบรารีครบ) ดังนั้น พวก link flags ที่ได้จาก pkg-config จึงมีไลบรารีที่ต้องใช้แถมพ่วงมาทั้งหมดเสมอ แล้วลิงเกอร์ของ GNU สามารถมาคัดออกอีกทีด้วยตัวเลือก --as-needed ได้

ป้ายกำกับ: ,

0 ความเห็น:

แสดงความเห็น (มีการกลั่นกรองสำหรับ blog ที่เก่ากว่า 14 วัน)

<< กลับหน้าแรก

hacker emblem