พื้นฐานการคอมไพล์โปรแกรมบนลินุกส์

 

ตัวเองเริ่มหัดใช้ลินุกส์ใหม่ๆ คงเหมือนหลายท่าน มึนงงในทุกๆเรื่อง ส่วนมากจะเอาประสบการณ์เดิม (DOS/Windows) มาเปรียบเทียบ จะเกิดคำถามในหัวมาก "ทำไม" "เพราะอะไร" "เพื่ออะไร" เยอะแยะตาแป๊ะขายไก่ ภาษาอังกฤษก็แค่ถูๆไถๆ หาหนังสือภาษาไทยมาอ่าน (ซึ่งส่วนมากจะเน้นเรื่อง Server หรือ Admin) อ่านซ้ำแล้วซ้ำอีก ก็ยังง๊งงง พูดตรงๆอ่านไม่ค่อยจะรู้เรื่อง ไม่ค่อยมีที่มาที่ไป ใครว่าลินุกส์เรียนรู้ง่าย ตัวเองเถียงใจขาดดิ้น "ยากจริงๆ" กว่าจะเก็บเกี่ยวประสบการณ์ได้ขนาดนี้ใช้เวลาไม่ต่ำกว่า 3 ปี ซึ่งก็ยังคิดว่าตัวเองไม่รู้เรื่องอะไรเท่าไหร่ จริงๆก็เกือบจะถอดใจไปแล้ว ...

ถ้าไม่มาเจอคุณหมอมดแดง(DrRider) กับคุณวิทยา(wd) ความรู้ทั้งนั้น เราเองก็รับรู้ ได้บ้าง ไม่ได้บ้าง แต่ทำให้ลินุกส์เป็นเรื่องสนุกสำหรับตัวเองไป สองท่านกล่าวมานี้ตัวเองมักจะขึ้นต้น "อาจารย์" เสมอ โดยให้เกียรติเพราะถือว่าได้ให้ความรู้ด้านลินุกส์กับตัวเองจริงๆ จากที่เคยมีความรู้แบบเทาๆ ก็ชัดเจนขึ้นมาก ทำให้พัฒนาการด้านลินุกส์ช่วงหลังๆไปได้เร็วขึ้น ก็ถือโอกาสขอบคุณมา ณ ที่นี้ด้วย ...

ที่มาของบล็อกไตเติ้ลนี้ เนื่องจากไม่สามารถเข้าถึงเว็บ "ไทยลินุกส์คาเฟ่" รอมานานมาก จนอดใจหายว่าจะปิดตัวจริงๆ เสียดายบทความดีๆในเว็บแห่งนี้ ซึ่งตัวเองมักใช้เป็นลิงค์อ้างอิงเสมอๆ บทความแปลชิ้นนี้ตัวเองชอบมาก เพราะทำให้เข้าใจหลักการทำงานลินุกส์ดีขึ้น โชคดีที่ได้คัดลอกเก็บเอาไว้อ่านส่วนตัว พอมาเริ่มเขียนบทความให้เว็บของอาจารย์ wd ก็รู้สึกเกร็งๆการเขียนจริงๆ เพราะมีแต่ผู้รู้ทั้งนั้น (กลัวปล่อยไก่) ในเมื่อยังไม่รู้จะเขียนอะไร ก็ถือโอกาสนี้นำบทความดังกล่าวมาเผยแพร่ (ขัดตาทัพไปก่อน) ...

บทความนี้นำมาจากกระทู้ในเว็บบอร์ด "ไทยลินุกส์คาเฟ่" เป็นเรื่องพื้นฐานการคอมไพล์โปรแกรม มีทั้งหมด 3 ตอน แต่ตัวเองนำมายุบรวมกันเป็นเรื่องเดียว ผู้เขียนบทความนี้ก็คือ คุณ ETO เคยเป็นผู้เชี่ยวชาญเกี่ยวกับลินุกส์ประจำบอร์ดดังกล่าวในรุ่นแรกๆ แล้วอยู่ๆแกก็หายจากวงการนี้ไปสัก 4 ปีให้หลัง ทราบว่าคงมีความจำเป็นบางปราการในเรื่องหน้าที่การงาน แต่ก็ขอขอบคุณที่ได้แปลบทความดีๆและมีคุณภาพชิ้นนี้ให้รุ่นหลังได้ศึกษากัน ง่ายขึ้น ...

จุดประสงค์ของบล็อกไตเติ้ลนี้มีอยู่ 2 ประการ

ประการแรก  เพื่อเผยแพร่บทความดีๆต่อผู้สนใจที่จะศึกษา
ประการสอง  เพื่อเป็นการสำรองบทความดีๆ กันเผื่อเกิดอุบัติเหตุ(หายไปเสียดายแย่เลย)

บทความนี้มีเนื้อหาค่อนข้างยาว ก็ไม่จำเป็นต้องอ่านให้จบทีเดียว ค่อยๆอ่านไปเรื่อย อ่านผ่านๆ รู้สึกปวดหัวก็พักไปหาอย่างอื่นทำก่อน นึกขึ้นได้ก็กลับมาอ่านจะค่อยๆเข้าใจไปเอง บทความนี้อาจจะเขียนมานาน แต่หลักๆแล้วสามารถนำมาอ้างอิงหรือเทียบเคียงกับการใช้งานในปัจจุบันได้เป็น อย่างดี ...

พิ้นฐานการคอมไพล์โปรแกรมสำหรับมือใหม่ Linux

เราใช้ภาษาสำหรับโปรแกรมมิ่งในการเขียนโปรแกรมคอมพิวเตอร์ โปรแกรมที่เขียนด้วยภาษาบางอันเรียกที่เรียกว่า ภาษาสคริป จะสามารถทำงานได้ทันที ภาษาดังกล่าวได้แก่ Perl Python และ Tcl/Tk โดยภาษาพวกนี้จะมีตัวแปลที่ทำหน้าที่เป็นล่ามระหว่าง โปรแกรมที่เขียนขึ้นกับระบบ

ในภาษาอื่นๆ อย่างเช่น C หรือ C++นั้น โปรแกรมที่เขียนขึ้นจะต้องผ่านการคอมไพล์ให้เป็น ไบนารี่ ก่อนที่จะสามารถทำงานได้ ภาษาดังกล่าวแต่ละรูปแบบมีข้อดีข้อเสียต่างกัน: ภาษาสคริป (หรือภาษาแปล) ใช้เวลาในการเขียนน้อยกว่า ขณะที่โปรแกรมแบบไบนารี่ไม่จำเป็นต้อง มีตัวแปลดังนั้นจึงทำงานได้เร็วกว่า และโดยทั่วไปจะมีความเหมาะสมสำหรับงานที่ซับซ้อนมากกว่า

การคอมไพล์เป็นการแปลตัวหนังสือที่เราอ่านออกที่เรียกว่า ซอร์ส (Source code) ไปเป็นไฟล์ที่เครื่องอ่านออกที่เรียกว่า ไบนารี่ (Binary) ดังนั้นสิ่งที่จำเป็นต้องมีในการคอมไพล์ก็คือ ตัวคอมไพล์ (Compiler) บน GNU/Linux ตัวคอมไพล์ก็คือ gcc สำหรับโปรแกรม ที่เขียนด้วยภาษา C และ g++หรือ gcc-c++ สำหรับโปรแกรมที่เขียนด้วยภาษา C++

โปรแกรมที่ซับซ้อนสามารถประกอบไปด้วยไฟล์ซอร์ส จำนวนหลายๆ ไฟล์ และเพื่อให้การคอมไพล์ทำได้ง่ายขึ้นขั้นตอนการคอมไพล์จะเขียนอยู่ในไฟล์ที่ ชื่อ Makefile ในการใช้ไฟล์ไฟล์นี้จำเป็นต้องมีโปรแกรมที่เรียกว่า make ซึ่งโปรแกรม make นี่จะอ่านไฟล์ Makefile (การ parse) และ ส่งข้อมูลที่เหมาะสมให้ตัวคอมไพล์ เราสามารถเปลี่ยนข้อมูลเหล่านี้ได้ (อย่างเช่นโฟลเดอร์ที่จะให้ติดตั้งไฟล์ที่คอมไพล์แล้ว) โดยการ แก้ไข Makefile

ในการเขียนโปรแกรม นักเขียนโปรแกรมไม่ได้เขียนโปรแกรมทั้งหมดด้วยตัวเอง เขามักจะใช้ ไลบราลี่ (library) ซึ่ง เก็บชุดฟังก์ชันที่มีการใช้เป็นประจำ คนเขียนก็เพียงแค่ทำลิ้งค์ในไฟล์ซอร์สของเขาอ้างอิงไปยัง library หรือฟังก์ชั่นหนึ่งๆ ใน library นั้น ดังนั้นตัว library นั้นๆ ก็จะจำเป็นสำหรับตัวไบนารี่ในการทำงาน ทีนี้ในการคอมไพล์โปรแกรม ตัวคอมไพล์จะต้องสามารถเข้าถึงไฟล์ซอร์สของแต่ละ library ที่โปรแกรมนั้นใช้ ไฟล์เหล่านี้จะเรียกว่า header files ดังนั้นเราจำเป็นต้องมีไฟล์เหล่านี้ด้วย เนี่องจากเราต้องการ header file เหล่านี้ในการคอมไพล์ จึงมีการแยกตัว RPM-package ออกเป็นสองกลุ่มคือ package ที่มีไฟล์ที่จำเป็นในการทำงานของโปรแกรมกับ package ที่มีไฟล์ที่จำเป็น ในการคอมไพล์โปรแกรม และจริงๆ แล้วก็กลายเป็นเรื่องปรกติสำหรับชุด linux ที่ออกมาที่จะมี package ที่มี library เอง (ตัวที่ทำงาน) กับ packageที่สองที่จะเขียนว่า -devel- (หมายถึง development) ซึ่งจะบรรจุพวก header file ทั้งหลาย ดังนั้นคุณจำเป็นต้องมี package ที่บรรจุพวก header file ของ library ที่โปรแกรมนั้นใช้ด้วยเช่นกัน

คุณอาจจะสงสัยว่าแล้วจะให้รู้ได้อย่างไรว่า library ไหนที่โปรแกรมนั้นต้องการ

วิธีการที่ง่ายที่สุดคือคอมไพล์ไฟล์ซอร์สนั้น ในกระบวนการคอมไพล์จะแสดงให้เราเห็นหากว่าไม่สามารถหา library ที่ต้องการพบ ทางที่เป็นไปได้อีกอย่างคือดูใน Makefile ในส่วนส่วนบนจะมีบรรทัดที่เขียนว่า LIBS = ซึ่งจะแสดงรายชื่อ library ที่ต้องการทั้งหมด สังเกตว่ารายชื่อจะอยู่ในรูปแบบย่อ เช่น -lX11 เป็นตัวอย่างการย่อสำหรับไฟล์ชื่อ libX11.so. ให้สั่งlocate libX11.so เพื่อหาว่าไฟล์นี้ได้ติดตั้งอยู่ในระบบของคุณหรือยัง

วิธีที่สามซึ่งเป็นวิธีค่อนข้างใหม่คือการใช้สคริปคำสั่ง configure ซึ่งคนเขียนโปรแกรมสามารถสร้างขึ้นได้โดยการใช้โปรแกรม autoconf สคริปนี้ เมื่อทำงานจะทำการตรวจสอบระบบว่ามี library และฟังก์ชั่นทึ่จำเป็นอยู่หรือไม่ ถ้าไม่ก็จะบอกว่ามีอะไรผิดปรกติ

การแตกไฟล์ Unpacking Archives
ไฟล์ซอร์สมักจะแจกจ่ายอยู่ในรูปแบบของกลุ่มไฟล์ที่ถูกบีบอัดไว้ (compressed archive) ซึ่งมีความเหมาะสม เพราะมักจะประกอบด้วยไฟล์มากกว่าหนึ่งไฟล์และ การบีบอัดมีประสิทธิภาพดีมากสำหรับไฟล์ตัวหนังสือ

บน UNIX ไฟล์บีบอัดนี้จะสร้างและแตกออกได้ด้วยการใช้สองโปรแกรม อันแรกคือตัวที่รวมไฟล์ทั้งหมดให้อยู่ด้วยกัน (tar) และอีก อันคือตัวบีบอัด (gzip หรือ bzip2) ในภาษาแสลงเราเรียกไฟล์ archive เหล่านี้ว่า tarballs

ในการแตกไฟล์เหล่านี้ออก คุณสามารถใช้ตัวจัดการไฟล์ archive แบบกราฟฟิก เช่น Archiver ของ KDE, guiTAR ของ GNOME หรือ TkZip. บน KDE และ GNOME โปรแกรมจะทำงานเองเมื่อคุณคลิกที่ไฟล์ archive สำหรับการใช้คำสั่ง สามารถใช้:

tar xzf [file].tar.gz สำหรับแตกไฟล์ tar ที่บีบอัดด้วย gzip และ
tar xjf [file].tar.bz2 สำหรับไฟล์ tar ที่บีบอัดด้วย bzip2

option แรก (x) หมายถึง แตกไฟล์ (extract) สำหรับการสร้าง archives คุณสามารถแทนที่ด้วย c ถ้าต้องการแค่ ให้แสดงรายชื่อไฟล์ให้ใช้ t option ที่สองเป็นการบอกชนิดของการบีบอัดและ f จะบอกให้ tar รอรับชื่อไฟล์ option ที่น่าสนใจอีกอันคือ C ซึ่งจะบอกให้ tar ย้ายไปยังโฟล์เดอร์อื่นก่อนการทำการแตกไฟล์:

tar xzfC [file].tar.gz [dir]

เรามักจะไม่พบไฟล์ bzip2 หรือแม้แต่ zip archives อย่างเดียวใน GNU/Linux การแตกไฟล์ดังกล่าวสามารถทำได้ด้วย bunzip2 [archive name] unzip [archive name] (อันหลังนี้สามารถใช้กับไฟล์ self-extracting (.exe) ด้วย)

ไฟล์ที่จำเป็นต้องอ่าน Important Files to Read
ใน archives ส่วนใหญ่จะมีไฟล์ README และ INSTALL บรรจุอยู่ด้วย ไฟล์เหล่านี้จะแสดงข้อมูลความคิดเห็น ของผู้เขียนโปรแกรมต่อโปรแกรมนั้นๆ วิธีการคอมไพล์ สิ่งที่จำเป็นต้องระวัง เช่นเดียวกับไฟล์อื่นๆ ใน archive คุณสามารถ เปิดได้ด้วยทุกโปรแกรมที่สามารถแสดงไฟล์ตัวหน้งสือได้

แพคเกจที่จำเป็น Needed Packages
แพคเกจเหล่านี้ จำเป็นสำหรับการคอมไพล์ ให้ทำการตรวจสอบด้วยคำสั่ง rpm -q [name] ว่ามีการติดตั้งแล้วหรือยัง คุณสามารถหาได้จาก CD หรือ จาก rpmfind.net.

ตัวคอมไพล์
- gcc
- glibc-devel
- gcc-c++
- libstdc++-devel

ระบบ
- make
- kernel-headers

Library ที่ใช้บ่อย
library ที่มักใช้เป็นประจำในโปรแกรม หากคุณมีชุด develope พวกนี้อยู่มักจะทำการคอมไพล์ผ่านโดยไม่ เกิด error เนื่องจากขาด library

- gtk+-devel, glib-devel
- libgr-devel, libungif-devel, libjpeg-devel, libpng-devel, libtiff-devel, xpm-devel (รูปแบบของไฟล์รูปภาพ)
- libtermcap-devel, ncurses-devel (for console applications)
- XFree86-devel (สำหรับแอพพลิเคชันแบบกราฟฟิก)
- zlib-devel (compression library)

ถ้าคุณทำการคอมไพล์โปรแกรมสำหรับ GNOME หรือ KDE คุณจำเป็นต้องมีชุด -devel- ของ library พวกนี้ด้วย สำหรับ KDE คุณต้องมี qt-devel ด้วย

การสั่ง configure
ในปัจจุบันชุดแพ็คเกจซอร์สไฟล์ส่วนใหญ่จะมาพร้อมกับไฟล์คำสั่ง configure ซึ่งจะช่วย ตัวตรวจสอบว่าโปรแกรมสามารถคอมไพล์บนระบบนั้นๆ ได้หรือไม่

คำสั่ง ./configure --help

ตัว configure จะแสดงสรุป option ที่เป็นไปได้สำหรับคำสั่ง configure แต่ไม่ต้องตกใจเพราะว่า โดยทั่วไปค่าที่ตั้งเป็น defualt มักจะใช้งานได้ดีอยู่แล้ว แต่มีอยู่หนึ่ง option ที่คุณควรสนใจมากหน่อยคือ --prefix=[DIR] ซึ่งมักจะมีในส่วนต้นๆ ของรายการเลย อันนี้จะหมายถึงว่าจะกำหนดให้โปรแกรมที่คอมไพล์แล้วและ library ไปอยู่ที่ไหน ค่าตั้งต้นมักจะเป็น [/usr] หรือ [/usr/local] ซึ่งทั้งสองค่าก็ดีแล้วแต่สำหรับผู้เขียนชอบที่จะ เก็บโปรแกรมที่คอมไพล์เองลงใน /usr/local/ มากกว่าเพราะทำให้ง่ายต่อการติดตามในภายหลัง อย่างไรก็ตามโปรแกรมบน KDE บางอันจะคิดว่าคุณมีโฟลเดอร์ /opt/kde และจะใช้โฟลเดอร์นี้เป็นค่าตั้งต้นในการติดตั้งโปรแกรม แต่บน Mandrake จะไม่มีโฟลเดอร์นี้ เนื่องจากไฟล์ของ KDE จะเก็บอยู่ใน /usr แทน ดังนั้นคุณจำเป็นต้องเปลี่ยนค่า ในการสั่ง configure ดังนี้:

./configure --prefix=/usr

คุณอาจจะเริ่มสงสัยแล้วว่าทำไมจึงใช้./configure แทน configure อันนี้เป็นเพราะโฟลเดอร์ของซอร์สไฟล์ที่เพิ่งสร้างขึ้นใหม่นี้ จะไม่ได้เป็นส่วนหนึ่งของ $PATH ในกรณีที่ใช้ security level ที่ไม่ใช่ low ดังนั้นถ้าคุณสั่งเพียง configure ตัว shell จะบอกว่า :

bash: configure: command not found

คุณจำเป็นต้องบอก shell ว่าคุณต้องการจะ execute คำสั่งในโฟล์เดอร์ที่อยู่ตอนนี้ โดยการเพิ่มตัว ./ เข้าไปที่คำสั่งนั้นๆ

โปรดสังเกตว่า ไม่มีความจำเป็น และไม่แนะนำให้สั่ง configure ในขณะเป็น root

ขาดอะไรหรือ ?
เมื่อ configure ทำงานและตรวจสอบระบบของคุณ มันจะแสดงผลที่หน้าจอของ console พร้อมกับเขียนไฟล์ ใหม่ขึ้นมาชื่อ config.log และตัวคำสั่งจะหยุดทำงานเมื่อพบกับข้อผิดพลาดเพื่อป้องกันไม่ให้โปรแกรม ถูกคอมไพล์ และคำสั่งก็จะแสดงข้อความ error และเขียนลง config.log เช่นกัน ตัวอย่างเช่น:

/usr/bin/ld: cannot open -lXt: No such file or directory collect2: ld returned 1 exit status

ดูเหมือนกับขาดอะไรบางอย่าง แต่เจ้า -lXt นี่มันคืออะไร ? ในการเขียนโปรแกรมตัวอักษร l (แอล) จะเป็นตัวย่อของ lib...so นั่นคือสิ่งที่ต้องการคือ libXt.so สิ่งทึ่เป็นไปได้ก็คือมันอยู่ใน ชุด -devel-.rpm ที่คุณไม่ได้ติดตั้ง ถ้าคุณใช้ ML 7 ขึ้นไปให้ใช้ RpmDrake (ใช้ Software Manager หรือ Package manger ก็ได้-- ผู้แปล) หาแพ็กเกจที่มีไฟล์นี้อยู่ หรือใช้คำสั่ง urpmf [file]

คุณจะพบว่าไฟล์นี้เป็นส่วนหนึ่งของ XFree86-devel ก็ให้ติดตั้งโดยใช้ตัวติดตั้ง RPM ที่ชอบ หรือจะใช้ urpmi หรือจะสั่งด้วย

su -c "rpm -i XFree86-devel-[version]mdk.rpm"

กลับไปที่โฟล์เดอร์ซอร์สไฟล์อีกครั้ง ด้วยคำสั่ง cd และให้ลบไฟล์ config.cache และสั่ง configure และทำอย่างนี้จนกระทั่ง configure ทำงานผ่าน ถ้าคุณหา RPM ที่มีไฟล์ที่ต้องการไม่เจอ (ซึ่งมักไม่ค่อยพบ) และเอกสารที่มีมาด้วยก็ไม่ได้บอกอะไรมาก คุณจำเป็นต้องติดต่อกับผู้เขียนซอร์ฟแวร์นั้น ซึ่งจะเป็นผู้ที่รู้ดีที่สุด แต่ต้องแน่ใจว่าคุณเองได้ตรวจสอบทุกอย่าง แล้วอย่างน้อยสองรอบ

การสั่ง make
หากคำสั่ง configure ทำงานผ่านเรียบร้อย ก็ถึงเวลาที่จะคอมไพล์ซอร์สจริงๆ แล้ว ให้สั่ง

make

ซึ่งโดยปรกติจะไม่เกิด error อะไรอีกนอกจากคำสั่ง configure เกิดความผิดปรกติ แม้ว่าตามข้อความ error จาก make มักจะติดตามได้ยากกว่าจาก configure กระบวนการแก้ไขปัญหาก็จะ คล้ายๆกับที่กล่าวมาข้างบน ถ้าผิดพลาดอะไร มักจะเห็น

[file]:[line]: [file]: No such file or directory หรือ [file1]: in file | function [name]: [file2]:[line]: undefined reference to [function] (ฯลฯ)

ในกรณีแรก ให้ติดตั้ง RPM ที่มีไฟล์ที่ขาด ส่วนความผิดพลาดที่มีชื่อ function มักจะหมายถึงว่าโปรแกรมต้องการ library เวอร์ชั่นใหม่หรือเก่ากว่าที่มีอยู่ ก็ให้หา library เวอร์ชั่นใหม่หรือเวอร์ชั่นที่เก่ากว่าแล้วติดตั้ง แนะนำให้สั่ง

make clean

ทุกครั้งก่อนการคอมไพล์ใหม่อีกรอบ สมมติว่าทุกอย่างผ่านไปด้วยดี ก็ถึงเวลาการ install คุณจำเป็นต้องเข้าเป็น root ด้วยคำสั่ง:

su -c "make install"

เรียบร้อยแล้ว คุณอาจะต้องการตรวจสอบว่าโปรแกรมทำงานได้หรือไม่ ตรวจดูให้แน่ใจว่าคุณได้เก็บตัวไบนารี่ไว้ในโฟลเดอร์ที่อยู่ใน $PATH หรือไม่ก็สร้าง symlink ด้วยคำสั่ง ln -s [source] [destination]ไปยัง /usr/bin หรือไม่ก็เพ่ิมโฟลเดอร์เข้าไปใน path

การ Uninstalling
หลายคนไม่เคยรู้เกี่ยวกับอันนี้ แต่โดยทั่วไปเราสามารถ uninstall ไฟล์ต่างๆที่ติดตั้งด้วย make install โดยคุณจำเป็นต้องมี Makefile และเข้าไปในโฟลเดอร์ของ Makefile แล้วสั่ง:

su -c "make uninstall"

วิธีจะสามารถทำได้เมื่อคนเขียนโปรแกรมได้กำหนดการ uninstall ไว้ใน Makefile แล้ว ซึ่งส่วนใหญ่ก็จะทำกัน)

การใช้ Patches
ไฟล์ patch หรือ diff เป็นไฟล์ text แบบพิเศษที่มีคำสั่งสำหรับโปรแกรม patch ที่จะให้แก้ไขอะไรที่ไหนในซอร์สไฟล์ คำสั่ง patch จะเป็นแบบนี้:

patch -p[num] <[patch file]

ส่วนที่น่าสนใจคือหมายเลขหลัง -p option ซึ่งจะเป็นตัวกำหนดว่าจะใช้ไฟล์ patch เข้าไปถึงในระดับไหนของ path: -p0 ให้ใช้ patch ลงไปใน path ทั้งหมดที่กำหนดในไฟล์ , -p1 ให้เอา / อันแรกออก ฯลฯ หาไม่มีการกำหนด -p ให้เอา path ทั้งหมดออกซึ่งใช้ได้หากใช้ patch กับไฟล์ที่อยู่ในโฟล์เดอร์เดียวกัน สิ่งที่มักจะได้ผลคือการเอาไฟล์ patch ไปวางไว้บน parent directory ของโฟลเดอร์ของซอร์สไฟล์ที่ต้องการ patch แล้วสั่ง

patch -p1 <[patch file]

ถ้ามันไม่ทำงานให้ลองหมายเลขอื่นๆ กับ -p option

การคอมไพล์ซอร์สโค้ด (FAQ)

ไฟล์หายและไฟล์สำหรับ build แบบที่ไม่ค่อยพบ

ในไดเร็คทอรี่ของซอร์สไม่มีไฟล์ 'configure' แล้วจะทำอย่างไรดี?

ในกรณีนี้คุณต้องจัดการกับไฟล์ 'Makefile' เอง มีเพียงแค่บรรทัดแรกๆ ที่ขึ้นต้นด้วยอักษรตัวใหญ่เท่านั้นที่ต้องสนใจ และอาจจะต้องแก้ไข ในไฟล์ Makefiles อาจจะไม่ได้มีทุกบรรทัดต่อไปนี้

* CC = compiler บอก 'make' ว่าจะใช้คอมไพเลอร์ตัวไหน โดยทั่วไปจะใช้ GCC โปรแกรมที่เขียนด้วย C++ อาจจะต้องการ G++ แทน
* INCDIR = -I/path/dir1 -I/path/dir2 etc บอก 'make' ว่าไดเร็คทอรี่ไหนที่มี header files ให้ดูว่าค่าที่ติดตั้งตรงกับระบบของคุณหรือไม่
* LIBDIR = -L/path/dir1 -L/path/dir2 etc บอก 'make' ว่ามีไฟล์ไลบรารี่ อยู่ที่ไหนบ้าง
* LIBS = -llib1 -llib2 -llib3 etc บอก 'make' ว่าไลบรารี่ใดที่จำเป็น จำไว้ว่า '-llib' ย่อมาจาก 'liblib.so' ใช้คำสั่ง locate liblib.so เพื่อตรวจว่าไลบราลี่ที่ได้ติดตั้้งไลบราลี่ดังกล่าวหรือยัง ในบางครั้งตัวแปรนี้จะใช้ชื่อว่า LFLAGS.
ถึงตอนนี้ก็แค่สั่ง make

แล้วถ้าในไดเร็คทอรี่ซอร์สมีไฟล์ 'Imakefile', 'GNUmakefile' หรือ 'Makefile.cvs' แทนที่จะเป็น Makefile ตามปรกติล่ะ ?

'Imake' เป็นตัวดั้งเดิมของ 'configure' ให้สั่ง

xmkmf -a

เพื่อสร้าง Makefile จาก Imakefile คำสั่งนี้เป็นส่วนหนึ่งของแพ็คเกจ XFree86-devel ต่อจากนั้นก็ทำตามที่ได้กล่าวมาแล้ว สำหรับไฟล์ GNUmakefiles นั้นไม่ต่างกับ Makefiles เราใช้คำสั่ง 'make' ได้กับทั้งสองไฟล์ ถ้าคุณเจอไฟล์ 'Makefile.cvs' ให้สั่ง

make -f Makefile.cvs

เราจะได้ไฟล์ 'configure'

แล้วถ้าในไดเร็คทอรี่ไม่มีไฟล์สำหรับ build เลยล่ะ ?

ก่อนอื่นให้หาว่าในไดเร็คทอรี่ย่อยต่างๆ มีไฟล์ที่สามารถ execute ได้หรือเปล่า โดยคำสั่ง:

find . -type f -perm -700

จะแสดงรายการไฟล์ที่สามารถ execute ได้ ถ้าคุณไม่เจอไฟล์ดังกล่าวเลย ก็ดูเหมือนว่าคุณจะต้องทำการคอมไพล์ซอร์สไฟล์ตรงๆ และเป็นไปได้มากว่าจะมีแค่ไฟล์ *.c เพียงไฟล์เดียว ให้สั่ง

gcc -o new_name file.c

'-o new_name' จะเป็นการกำหนดชื่อสำหรับไฟล์ไบนาที่ที่ได้ และให้เอาอ็อปชั่น '-o' ออกหากว่าในไดเร็คทอรี่มีไฟล์ *.c (*.C, *.cc, *.cxx) มากกว่าหนึ่งไฟล์ ในกรณีหลังนี้ไฟล์ผลลัพธ์ที่ได้จะชื่อ 'a.out' คุณสามารถ เปลี่ยนชื่อให้เหมาะสมเองได้ภายหลัง
ถ้าคุณจำเป็นต้องระบุ ไฟล์สำหรับ include หรือไดเร็คทอรี่ของไลบราลี่หรือไฟล์ไลบราลี่อื่นๆเป็นพิเศษ คุณสามารถทำได้ด้วยการเพิ่มอ็อพชั่น ให้ gcc โดยตรง เช่น

gcc -o new_name file.c -L/path/dir -llib -I/path/dir

ปัญหาการ build
ทำไม 'configure' บอกว่าขาดไฟล์ library / header ทั้งๆ ที่ติดตั้งไฟล์ดังกล่าวเรียบร้อยแล้ว ?

การเกิดเออเรอร์แบบนี้เกิดได้สามแบบคือ:

1. 'configure' ไม่ได้มองหาในไดเร็คทอรี่ที่มีไลบราลี่นั้น ซึ่งในกรณีนี้คุณต้องเพิ่ม path ของไดเร็คทอรี่นั้นให้ด้วยอ็อปชั่น '--with-extra-libs=[DIR]' เช่นเดียวกับหากเป็นไฟล์ header ก็ใช้ '--with-extra-includes=[DIR]'

2. 'configure' หาไลบรารี่ผิดเวอชั่น ตัวอย่างที่ดีเช่นแอ็พพลิเคชั่นที่คอมไพล์ด้วย Qt2 โดย 'configure' อาจจะบอกข้อความเออเรอร์ที่ไม่ถูกต้องหากคุณติดตั้ง เวอร์ชั่นเก่าของ Qt2 เช่น
   2.1 เมื่อแอ็พพลิเคชั่นต้องการ
   2.2 ในกรณีนี้คุณจำเป็นต้องอํพเกรดไปเป็นเวอร์ชั่นใหม่ อีกปัญหาที่พบบ่อยคือถ้ามีการ
         ติดตั้งทั้ง Qt1 และ Qt2 (และ Qt3 ...) โดยดีฟ้อลท์แล้ว 'configure' จะมองหา
         Qt ใน '/usr/lib/qt' แต่บน ML นั้นในไดเร็คทอรี่ดังกล่าวจะเป็นที่ติดตั้งของ Qt1
         ส่วน Qt2 จะอยู่ใน '/usr/lib/qt2' และ Qt3 อยู่ใน '/usr/lib/qt3' ในกรณีนี้คุณ
         ต้องใส่อ็อปชั่นให้ 'configure' ดังนี้: ./configure -with-qt-dir=/usr/lib/qt2.

3. ความผิดพลาดในการพิมพ์ของสคริป 'configure' ให้คุณดูข้อความในไฟล์ 'config.log' อย่างถี่ถ้วน โดยเฉพาะความผิดพลาดจากตัวอักษรเล็กใหญ่ในชื่อของไลบรารี่และไฟล์ header ถึงแม้ความผิดพลาดแบบนี้จะเกิดน้อยมาก แต่ก็ทำให้ป่วนคุณได้ถ้าคุณคิดว่ามันเป็นไปไม่ได้

ทำไมไบนารี่ที่คอมไพล์ได้ขาดฟีเจอร์ที่ควรจะมี ?

ขึ้นกับคนเขียนโปรแกรมว่าเมื่อมีการขาดไฟล์ไลบรารี่ใดแล้วจึงให้ 'configure' หรือ 'make' หยุดการทำงานและแสดงข้อความเออเรอร์ ดังนั้นการคอมไพล์สำเร็จไม่ได้ประกันว่าไบนารี่ที่ได้มีฟีเจอร์ครบทุกอย่าง การดูรายละเอียดของไฟล์ 'config.log' จะช่วยหาได้ว่ามีไลบรารี่ใดบ้างที่ขาดหายไป ทำการติดตั้ง และทำการคอมไพล์อีกครั้ง

ปัญหาในการ build

ได้ทำการติดตั้งไลบรารี่ที่ขาดแล้ว แต่ทำไม 'configure' หรือ 'make' ยังคงหามันไม่พบ ?

ผลจากการสั่ง 'configure' และ 'make' ถูกเก็บเป็นเคชอยู่ ให้สั่ง

make distclean

เพื่อทำการกำจัดไฟล์ที่เกิดขึ้นในไดเร็คทอรี่ เมื่อทำแล้วคุณสามารถแน่ใจได้ว่าสคริปทั้งสองจะตรวจสอบระบบใหม่ หาก Makefile ไม่รู้จัก 'distclean' ให้สั่ง

make clean && rm config.cache

สาเหตุของปัญหาแบบนี้อีกอันหนึ่งคือหากไลบรารี่ที่ติดตั้งไม่ได้อยู่ในได เร็ค ทอรี่ที่อยู่ในรายการในไฟล์ '/etc/ld.so.conf' โดยไฟล์นี้จะ มีรายการที่ตัว Linux Loader/Linker 'ld' จำทำการมองหาไลบรารี่นอกเหนือไปจากตำแหน่งมาตรฐานคือ '/usr/lib' และ '/lib' ตัวอย่างเช่นเมื่อติดตั้งไลบรารี่ใน '/usr/local/lib' และไม่มีชื่อไดเร็คทอรี่นี้ใน '/etc/ld.so.conf' ไฟล์ไลบรารี่ดังกล่าวก็จะไม่สามารถเข้าถึงได้โดยระบบ การแก้ปัญหานี้คือการเพิ่มไดเร็คทอรี่ดังกล่าวใน '/etc/ld.so.conf' และสั่ง (โดยเป็น 'root')

ldconfig

หลังจากนั้นทำการทำความสะอาดไดเร็คทอรี่ซอร์สไฟล์แล้วทำการคอมไพล์อีกครั้ง

ทำอย่างไรถึงจะแก้ไขปัญหาเวอร์ชั่นของไลบรารี่ไม่ตรงเมื่อได้ติดตั้งทุกไลบรารี่ที่ต้องการแล้ว ?

ในกรณีส่วนใหญ่กระบวนการ build ไม่ได้มองที่เวอร์ชั่นย่อยของไลบรารี่ และจะขึ้นอยู่กับการสร้างลิ้งค์ใน '/usr/lib' ยกตัวอย่างเช่นไลบรารี่ 'libungif.so' ใน '/usr/lib'

lrwxrwxrwx /usr/lib/libungif.so -> libungif.so.4.1.0*
lrwxrwxrwx /usr/lib/libungif.so.3 -> libungif.so.3.1.0*
-rwxr-xr-x /usr/lib/libungif.so.3.1.0*
lrwxrwxrwx /usr/lib/libungif.so.4 -> libungif.so.4.1.0*
-rwxr-xr-x /usr/lib/libungif.so.4.1.0*

จะเห็นว่ามีไลบรารี่สองเวอร์ชั่นติดตั้งอยู่คือ libungif.so.4.1.0 และ libungif.so.3.1.0 (ที่มีเครื่องหมาย *) นอกจากนี่ยังมี 'symlink' (รายการที่ขึ้นด้วยตัวอักษร 'l') คือ: libungif.so, libungif.so.3 และ libungif.so.4.

'Symlinks' นั้นไม่ได้เป็นไฟล์ที่แท้จริง แต่เป็นแค่ตัวชี้ไปยังไฟล์เท่านั้น ก ระบวนการคอมไพล์จากมองหาไฟล์ 'libungif.so.3' ใน '/usr/lib' และได้รับการชี้จาก symlink ไปยังเวอร์ชั่นย่อยของไลบรารี่ในที่นี่คือ 3.1.0

ที่นี่ถ้าเราสมมติว่าคนเขียนโปรแกรมไม่ได้ระบุรายละเอียด (โดยไม่ได้ตั้งใจ) และกระบวนการคอมไพล์จะมองหาแค่ 'libungif.so' ในกรณีนี้มันอาจจะมองไปที่ libungif.so.4.1.0 ซึ่งเป็นไลบรารี่ตัวเดียวกันแต่มีเวอร์ชั่นหลักที่ต่างกัน และโดยทั่วไปแต่ละเวอร์ชั่นหลักมักจะ เข้ากันไม่ได้ ดังนั้นถ้าแอ็พพลิเคชั่นนั้นต้องการเวอร์ชั่น 3 แต่กระบวนการคอมไพล์พบเวอชั่น 4 สคริป 'make' หรือ 'configure' จะหยุดพร้อมกับข้อความเออเรอร์ และมันจะบอกว่า 'missing library' หรือ 'undefined reference' เช่นเดียวกันถ้า symlink ที่มีชื่อตรงกับเวอชั่นหลักนั้นไม่มีอยู่กระบวนการคอมไพล์ก็จะล้มเหลวเช่น กัน

สำหรับในปัญหาแรกนั้น วิธีการแก้ปัญหาอย่างง่ายก็คือทำการสร้าง symlink ใหม่ให้กระบวนการคอมไพล์ด้วยการสั่ง

ln -sf /usr/lib/libungif.so.3.1.0 /usr/lib/libungif.so

ถ้าเจอปัญหาที่สอง ก็ให้ทำการสร้าง symlink ที่จำเป็นด้วยคำสั่ง 'ln' ค่าแรกของอาร์กิวเม้นต์คือไฟล์ที่มีอยู่ ค่าที่สองคือชื่อของ symlink ที่ต้องการ คุณควรระวังในการสร้าง symlink เพราะมันอาจจะไปทำให้โปรแกรมอื่นใช้งานไม่ได้ ถ้าเป็นไปได้ก็ตรวจสอบจากคนเขียนโปรแกรม เพราะเขารู้ดีที่สุด

แปลและเรียบเรียงโดย ETO Legal: All texts on this site are covered by the GNU Free Documentation License. Standard disclaimers of warranty apply. Copyright LSTB (Tom Berger) and Mandrakesoft 1999-2002.

Comments

 

ยาวแบบนี้ ควรทำเป็น Book น่ะครับ
Edit -> TAB Outline -> เลือก Book ว่าจะให้หนังสืออยู่ในหมวดไหน

คุณสมเจตน์ลองดูตัวอย่างที่ bash: แตะ Shell Script

 

ได้ครับอาจารย์จะทำเป็น Book ดู ไตเติ้ลนี้ทำเมื่อคืนตอนดึกๆ มึนๆกับ FCKeditor (พิกล) และต้องตรวจทานข้อความอีก ดูมันแปลกๆกว่าต้นฉบับที่คัดลอกมา ส่วนเรื่อง Book ก็เป็นเรื่องใหม่ของตัวเอง อาจจะดูงุ่มง่ามหรือแปลกๆ ก็เพราะความไม่ประสีประสานะครับ ...

 

Syndicate

Subscribe to Syndicate

Who's online

There are currently 0 users online.