รวมรวมวิธีการคอมไพล์ GNOME ใช้เอง
จัดให้ตามคำขอครับ สำหรับผู้สนใจใช้ GNOME แบบ bleeding edge ซึ่งมีหลายวิธี ตามดีกรีความเป็น geek ของคุณ:
บทความนี้จะอธิบายวิธีที่ใช้ JHBuild นะครับ
การติดตั้ง GNOME จาก SVN snapshot ไว้ใช้งาน อาจจะอันตรายเกินกว่าจะเอางานในชีวิตประจำวันเข้าไปเสี่ยงด้วย จึงควรพิจารณาแยกรุ่น โดยใช้ GNOME ที่เสถียรจาก distro ทำงาน แต่แยก GNOME จาก SVN ไว้ทดสอบต่างหาก โดยขอแนะนำว่าอย่าใช้ root account หรือ sudo คอมไพล์และติดตั้ง เพราะความผิดพลาดในการ configure เพียงเล็กน้อย อาจทำให้ระบบคุณมั่วได้ ทางที่ดี ควรสร้างไดเรกทอรีสำหรับ user ธรรมดาไว้รองรับ และ build ในฐานะ user ธรรมดาเท่านั้น ซึ่งก็มีทางเลือกต่าง ๆ เช่น:
$HOME/gnome-svn (ตั้งชื่อกันเอาเองนะครับ ถ้าไม่ชอบชื่อ gnome-svn) แล้วใช้ jhbuild shell เรียกโปรแกรมเป็นรายตัวไป วิธีนี้ใช้ในกรณีที่คุณสนใจโปรแกรมเป็นตัว ๆ ไป ไม่ได้อยากดูหน้าตาเดสก์ท็อปทั้งหมด แต่ระวังว่ามีบางโปรแกรม เช่น gedit, epiphany ที่จะตรวจหา instance ที่มีอยู่ก่อนเรียก instance ใหม่ ซึ่งถ้ามี instance เดิมอยู่ คุณจะได้หน้าต่างของโปรแกรมรุ่นของ distro ไม่ใช่รุ่นของ SVN $HOME/gnome-svn แล้วใช้ X session เรียก GNOME รุ่น SVN เอาขณะล็อกอิน วิธีนี้ก็เป็นไปได้ แต่ไม่ขอแนะนำ เพราะหลายครั้งที่โปรแกรมรุ่นใหม่มีการเปลี่ยนแปลงวิธี config ถ้าคุณใช้วิธีนี้ ข้อมูล gconf ของคุณจะถูกใช้ร่วมกันระหว่าง GNOME จาก distro กับ GNOME รุ่น SVN และอาจตีกันเองได้บ่อย ๆ $HOME เช่น /opt/gnome-svn หรือ /home/gnome-svn (ผมใช้อย่างหลัง เพราะได้แบ่งพาร์ทิชันสำหรับ /home ไว้ แต่ไม่ได้เตรียมเนื้อที่สำหรับ /opt ไว้) โดย chown ให้เป็นของ user ที่สั่ง build จากนั้น สร้าง user account ต่างหากเพื่อใช้เรียก GNOME จาก svn โดยเฉพาะ วิธีนี้มีข้อดีคือ คุณสามารถละเลงทุกอย่างในเดสก์ท็อปของคุณได้ระหว่างทดสอบ พังก็ลบทิ้งสร้างใหม่ได้ โดยไม่รบกวนงานปกติของคุณ เอาล่ะ อ่านแล้วเลือกวิธีที่คุณชอบละกัน ตามความเห็นของผม คิดว่าวิธีสุดท้ายนี่แหละ ที่มีปัญหาน้อยที่สุด จากประสบการณ์ที่ผ่านมา โดยมีเกร็ดอีกอย่างหนึ่งคือ คุณไม่จำเป็นต้อง logout เพื่อเข้าไปทดสอบในอีก account หนึ่ง แต่สามารถสลับผู้ใช้โดยเลือก switch user ที่ logout dialog หรือใช้แอพเพล็ตสลับผู้ใช้ (fast-user-switch-applet) เพื่อล็อกอินในอีกดิสเพลย์หนึ่งได้ หรือจะเรียกใช้ gdm ในหน้าต่างซ้อน (Xnest/Xephr) เลยก็ได้ ซึ่งสำหรับกรณีหลัง ก็เพียงแต่เรียกเมนู Applications > System Tools > New Login in a Window หรือสั่งจาก command line:
$ gdmflexiserver --Xnest
ประเด็นหนึ่งที่คุณจะพบก็คือ เรื่องของ dbus กล่าวคือ โดยปกติ JHBuild จะ build dbus, hal, avahi จาก source ให้ ซึ่งอาจเป็นคนละรุ่นกับ distro แต่ปัญหาก็คือ distro จะเปิด dbus, hal, avahi daemon เอาไว้อยู่แล้ว และบ่อยครั้งที่โปรแกรมที่ config ไว้ให้คอมไพล์กับคนละรุ่นจะทำงานกับ daemon เหล่านี้ไม่ได้ ผลคือเรียกโปรแกรมไม่ขึ้น หรือโปรแกรม crash ไปเฉย ๆ เรื่องแบบนี้ report bug ก็ไม่ได้ด้วย เพราะเป็นความผิดของเราเอง วิธีแก้คือ config JHBuild ให้ไปใช้ dbus ของระบบเสีย ไม่ต้อง build เอง รายละเอียดจะกล่าวต่อไป
ตอนหน้ามาลงมือกันครับ
ตอนที่แล้ว วางแผนกันแล้ว คราวนี้มาเริ่มติดตั้ง JHBuild กัน
JHBuild รุ่นล่าสุดสำหรับ GNOME สามารถ check out ได้จาก GNOME SVN:
$ svn co http://svn.gnome.org/svn/jhbuild/trunk jhbuild
คุณสามารถใช้โพรโทคอล svn:// ก็ได้ ถ้า http:// ใช้ไม่ได้ในเครือข่ายของคุณ:
$ svn co svn://svn.gnome.org/svn/jhbuild/trunk jhbuild
(สำหรับคนที่มี svn account กับ GNOME ก็ใช้ svn+ssh:// นะครับ)
เมื่อ check out มาแล้ว สำรวจดูจะเห็น autogen.sh และ configure.ac ดูเหมือนต้องใช้ autotools แต่ไม่ต้องครับ กรณีนั้นใช้กับการ build พวกเอกสารเท่านั้น ถ้าคุณเพียงแต่จะใช้ build โปรแกรมอย่างเดียว ก็นี่เลย:
$ make -f Makefile.plain install
จะติดตั้ง jhbuild ไว้ที่ $HOME/bin ของคุณ แถมติดตั้งเมนูเรียก jhbuild แบบ GUI ไว้ที่เมนู Applications > Programming อีกต่างหาก.. แต่เอาเข้าจริง ผมไม่ได้ใช้ GUI หรอก เพราะส่วนมากจะสั่ง build แบบ background มากกว่า ดังจะกล่าวต่อไป
ค่า config ของ jhbuild กำหนดที่ ~/.jhbuildrc เป็นแฟ้มภาษา python โดยจะมีตัวอย่างของแฟ้มนี้อยู่ในแฟ้ม sample.jhbuildrc ใน source tree ของ jhbuild คัดลอกไปแก้ได้เลย ค่าสำคัญที่น่าสนใจได้แก่:
svnroots['svn.gnome.org'] svn+ssh://... URL จะได้ commit ได้ด้วย แต่สำหรับ anonymous user ก็ไม่จำเป็นต้องตั้งค่านี้ ยกเว้นกรณีที่ค่าปริยายใช้ไม่ได้ในเครือข่ายของคุณ moduleset 'gnome-2.20' คุณสามารถตรวจดู moduleset ทั้งหมดที่มีอยู่ได้จากไดเรกทอรี modulesets/ ใน jhbuild source tree modules 'meta-gnome-desktop' ซึ่งจะไปดึงเอา official GNOME package ทั้งหมดมา ถ้าคุณสนใจ module อื่นนอกเหนือ official GNOME ก็เลือกเพิ่มได้ เช่น 'meta-gnome-proposed' สำหรับ module ที่เสนอเพิ่มในรุ่นถัดไป, 'epiphany-extensions' สำหรับ extention ทั้งหลายของ epiphany ซึ่ง module นี้ยังไม่อยู่ใน official GNOME ฯลฯ skip checkoutroot prefix /home/gnome-svn ก็กำหนดที่นี่ ที่เหลือก็มีคำอธิบายใน comment ของแฟ้มตัวอย่างนะครับ หรือจะอ่านจาก manual ของ JHBuild ก็ได้
และเพื่อความสะดวกในการเรียก คุณอาจเพิ่ม $HOME/bin ในตัวแปรสภาพแวดล้อม $PATH ของคุณด้วย
ก่อนจะเริ่มใช้ JHBuild คุณควรตรวจสอบเสียหน่อย ว่าขาดแพกเกจจำเป็นอะไรหรือเปล่า โดยสั่ง:
$ jhbuild sanitycheck
ขาดอะไรก็ติดตั้งเพิ่มให้เขานะครับ ที่สำคัญคือ jhbuild ใช้ python ขาดไม่ได้เป็นอันขาด ส่วนเครื่องมือพื้นฐานอย่าง autoconf, automake ฯลฯ พวกนี้ คุณอาจใช้ของระบบก็ได้ หรือจะ build เองด้วยคำสั่งนี้ก็ได้:
$ jhbuild bootstrap
แต่จากประสบการณ์ ผมแนะนำว่าใช้ของระบบดีกว่า เพราะเอาเข้าจริง คุณก็จะสั่ง bootstrap แค่ครั้งเดียวนี่แหละ ในขณะที่ถ้าใช้ของระบบ จะมีการอัปเกรดตามปกติของ distro อยู่ตลอด ทำให้เครื่องมือของคุณไม่เก่า ฉะนั้น พอเริ่มใช้ JHBuild ในเครื่องหลัง ๆ ของผม ผมไม่ใช้ bootstrap เลย แต่พยายามติดตั้งแพกเกจที่จำเป็นให้ครบในระบบ คือ:
เรียบร้อยละ ตอนหน้ามา build กัน
ติดตั้ง JHBuild พร้อม config ไปแล้วก็ลงมือ build กัน
วิธีที่จะสั่ง build แพกเกจทั้งหมดที่ config ไว้ โดยเริ่มตั้งแต่ check out, configure, make, install ก็คือ:
$ jhbuild build
JHBuild จะตรวจสอบ dependency ของ module ที่กำหนด แล้วไล่ build ตั้งแต่ปลายสุดขึ้นมาตามลำดับ
แต่คุณก็เลือก build เฉพาะสิ่งที่ต้องการ แทนที่จะ build GNOME desktop ทั้งตัวได้เหมือนกัน:
$ jhbuild build gtk+
จะ build สิ่งที่ gtk+ ต้องการตามลำดับขึ้นมาจนถึงตัว gtk+ เอง
ในกรณีที่ build ไม่ผ่านที่บาง module จะมีตัวเลือกขึ้นมาถาม เช่น:
*** error during stage build of ORBit2: ########## Error running make *** [1/1] [1] rerun stage build [2] ignore error and continue to install [3] give up on module [4] start shell [5] go to stage force_checkout [6] go to stage configure choice: _
คุณสามารถเลือกตัวเลือกต่าง ๆ ได้ ตามปกติถ้าไม่มีเวลาดู ผมก็อาจจะเลือกข้อ 2 เพื่อฝืนให้มันทำต่อไป แล้ว module ต่อ ๆ ไปก็จะใช้รุ่นเก่าที่ผม build ไว้ครั้งก่อน แต่ถ้าเป็นการ build ครั้งแรก คุณคงเลือกข้อ 3 จะดีกว่า แพกเกจไหนที่ต้องใช้แพกเกจนี้ก็จะไม่ถูก build
ถ้าคิดอยากจะลองแก้บั๊กด้วยตัวเอง ก็เลือกข้อ 4 เพื่อเข้าเชลล์ไปตรวจสอบและแก้บั๊ก แล้ว exit กลับออกมาที่ prompt เดิมนี้ แล้วเลือกข้อ 1 ให้มันพยายาม build ใหม่
คำตอบสำหรับคำถามนี้ คงไม่มีหลักตายตัว อาศัย programming sense ของคุณละกัน :-)
มีวิธี build แบบ non-interactive ด้วย เช่น คุณอาจจะไปสั่ง build แบบ remote ที่เครื่องอื่นในแบบ daemon หรือ cron job ก็ได้ โดยสั่ง:
$ jhbuild tinderbox -o output-dir
โดยมันจะเก็บ build log ในรูป HTML page ลงใน output-dir (ตัวอย่าง) และเลือกตัวเลือก "give up on module" โดยอัตโนมัติสำหรับ module ที่ไม่ผ่าน
ผมชอบใช้แบบ tinderbox มาก เพราะประหยัดเวลาดี ผมสามารถสั่งให้มัน build แบบ background ไว้ แล้วก็ไปทำงานอื่นได้ สักพักก็กลับมาเช็กว่ามี error ที่ module ไหนบ้าง แล้วก็ตามซ่อมเป็นตัว ๆ ไป
การสั่ง build เพียง module เดียวเท่านั้น โดยไม่ต้อง build dependency ของมัน (เช่น ในกรณีที่จะกลับมาซ่อม module ที่ build ไม่ผ่าน) ก็ใช้คำสั่ง:
$ jhbuild buildone module
การใช้งานอีกลักษณะหนึ่งที่หลายคนอาจสนใจ คือการแยกขั้นตอน check out กับการ build ออกจากกัน อาจจะดีสำหรับคนที่ build ในเครื่องที่ไม่ได้ต่อเน็ตตลอดเวลา (คนหิ้วโน้ตบุ๊กอาจจะนึกออก) ก็อาจจะ check out ให้เสร็จทีเดียว แล้วค่อย build แบบ off-line ทีหลัง
สั่ง check out source ทั้งหมดโดยไม่ build ได้โดย:
$ jhbuild update
และ build แบบ off-line ได้โดยเพิ่มตัวเลือก -n หลังคำสั่งของ JHBuild เช่น:
$ jhbuild tinderbox -n -o output-dir
build กันไปก่อนนะครับ คราวหน้ามาดูวิธีเรียกโปรแกรมแบบแบ่งภาคกัน
build กันเสร็จแล้ว ก็มาเริ่มใช้โปรแกรมที่ build กันนะครับ
ก่อนจะเริ่มใช้ มีประเด็นเรื่อง DBus ที่เราวางแผนไว้ว่าจะใช้ของระบบ ปัญหาก็คือ โดยปกติ DBus จะรู้จัก service เฉพาะของระบบเท่านั้น ถ้าบังเอิญ GNOME รุ่นใหม่ที่เรา build มีการสร้าง service ใหม่โดยไม่ได้ register กับ DBus โปรแกรมบางโปรแกรมที่เรา build ก็จะเรียกไม่ขึ้น หรือไม่ก็ crash ไปดื้อ ๆ
เราทำให้ DBus รู้จัก service ของเราได้โดยเพิ่มแฟ้ม /etc/dbus-1/session-local.conf และ /etc/dbus-1/system-local.conf โดยมีเนื้อหาดังนี้:
/etc/dbus-1/session-local.conf:
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> <busconfig> <!-- Include jhbuild gnome session services --> <servicedir>/home/gnome-svn/share/dbus-1/services</servicedir> </busconfig>
/etc/dbus-1/system-local.conf:
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> <busconfig> <!-- Our well-known bus type, do not change this --> <type>system</type> <!-- Include jhbuild gnome system services --> <includedir>/home/gnome-svn/etc/dbus-1/system.d</includedir> </busconfig>
(ตรงชื่อไดเรกทอรี ผมทำตัวเอนไว้ เพื่อให้แก้เป็นชื่อไดเรกทอรีที่คุณใช้ได้สะดวกนะครับ)
ถ้าสงสัยว่าผมได้สองแฟ้มนี้มายังไง ก็ลองอ่าน /etc/dbus-1/session.conf กับ /etc/dbus-1/system.conf ดูละกันครับ แฟ้ม *-local.conf นี้ ควรจะถูก include มาจากสองแฟ้มนั้น ส่วน syntax ก็ดัดแปลงโค้ด XML เท่านั้นเอง
restart DBus เพื่อให้การแก้ไขมีผล:
# /etc/init.d/dbus restart
ต่อไปนี้ก็พร้อมเรียกโปรแกรมละ
ตระเตรียมทุกอย่างเสร็จแล้ว จะทดสอบโปรแกรมที่ build ก็อาจเรียกเป็นรายโปรแกรม หรือเข้า GNOME session ไปเลย
เนื่องจากคุณมี environment สองแบบ คือของ distro และจาก JHBuild การเรียกโปรแกรมที่ build จึงต้องมีการกำหนด environment ต่างหาก ซึ่ง JHBuild ช่วยคุณได้ โดยสั่ง:
$ jhbuild run command-line
จะเรียก command-line ภายใต้ environment ที่กำหนด $PATH ให้ไปชี้ที่ bin และ $LD_LIBRARY_PATH ไปที่ lib ที่ติดตั้งโดย JHBuild รวมถึง environment อื่นที่เกี่ยวข้องด้วย
หรือสั่งอีกแบบ:
$ jhbuild shell
จะสร้าง shell ที่กำหนด environment เหล่านี้ให้เสร็จ จากนั้น command line ที่คุณเรียก ก็จะไปหาโปรแกรมและไลบรารีในแหล่งที่ติดตั้งโดย JHBuild ก่อน
คุณใช้หลักการเดียวกันนี้ในการเข้า GNOME session ทั้ง session จากแหล่งที่ติดตั้งโดย JHBuild ได้ โดยกำหนดใน ~/.xsession ของ user account ที่ใช้ทดสอบ:
#!/bin/sh exec /home/thep/bin/jhbuild run gnome-session
(ในที่นี้ สมมุติว่าใช้ account "thep" ในการ build ซึ่ง jhbuild จะติดตั้งไว้ที่ $HOME/bin ของ account "thep")
อย่าลืม chmod ให้สคริปต์ executable ด้วยนะครับ
จากนั้น ก็ล็อกอินเป็น user account ที่ใช้ทดสอบนั้น (โดย switch user ที่ logout dialog แทนที่จะ logout หรือใช้ gdm ใน nested window ตามที่กล่าวไปแล้ว) โดยเลือกวาระ (session) เป็น X session (จากปกติที่เป็น GNOME session ซึ่งจะเป็น GNOME ของระบบ)
จบแล้ว ไม่ยากเกินไปใช่ไหมครับ เห็นยาว ๆ นี่ เป็นเกร็ดเล็กเกร็ดน้อยซะเยอะ