ThaiTux.info - Compiler https://www.thaitux.info/taxonomy/term/280 พื้นฐานการคอมไพล์โปรแกรมบนลินุกส์ https://www.thaitux.info/node/399 <div class="field field-name-body field-type-text-with-summary field-label-hidden"><div class="field-items"><div class="field-item even"><p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://photos1.blogger.com/x/blogger/2060/2983/1600/432751/poster_linux_compiler.jpg"><img width="183" height="133" border="0" style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://photos1.blogger.com/x/blogger/2060/2983/400/969632/poster_linux_compiler.jpg" alt="" /> </a> ตัวเองเริ่มหัดใช้ลินุกส์ใหม่ๆ คงเหมือนหลายท่าน มึนงงในทุกๆเรื่อง ส่วนมากจะเอาประสบการณ์เดิม (DOS/Windows) มาเปรียบเทียบ จะเกิดคำถามในหัวมาก &quot;ทำไม&quot; &quot;เพราะอะไร&quot; &quot;เพื่ออะไร&quot; เยอะแยะตาแป๊ะขายไก่ ภาษาอังกฤษก็แค่ถูๆไถๆ หาหนังสือภาษาไทยมาอ่าน (ซึ่งส่วนมากจะเน้นเรื่อง Server หรือ Admin) อ่านซ้ำแล้วซ้ำอีก ก็ยังง๊งงง พูดตรงๆอ่านไม่ค่อยจะรู้เรื่อง ไม่ค่อยมีที่มาที่ไป ใครว่าลินุกส์เรียนรู้ง่าย ตัวเองเถียงใจขาดดิ้น &quot;ยากจริงๆ&quot; กว่าจะเก็บเกี่ยวประสบการณ์ได้ขนาดนี้ใช้เวลาไม่ต่ำกว่า 3 ปี ซึ่งก็ยังคิดว่าตัวเองไม่รู้เรื่องอะไรเท่าไหร่ จริงๆก็เกือบจะถอดใจไปแล้ว ...</p> <!--break--><p> ถ้าไม่มาเจอคุณหมอมดแดง(DrRider) กับคุณวิทยา(wd) ความรู้ทั้งนั้น เราเองก็รับรู้ ได้บ้าง ไม่ได้บ้าง แต่ทำให้ลินุกส์เป็นเรื่องสนุกสำหรับตัวเองไป สองท่านกล่าวมานี้ตัวเองมักจะขึ้นต้น &quot;อาจารย์&quot; เสมอ โดยให้เกียรติเพราะถือว่าได้ให้ความรู้ด้านลินุกส์กับตัวเองจริงๆ จากที่เคยมีความรู้แบบเทาๆ ก็ชัดเจนขึ้นมาก ทำให้พัฒนาการด้านลินุกส์ช่วงหลังๆไปได้เร็วขึ้น ก็ถือโอกาสขอบคุณมา ณ ที่นี้ด้วย ... </p> <p> ที่มาของบล็อกไตเติ้ลนี้ เนื่องจากไม่สามารถเข้าถึงเว็บ &quot;ไทยลินุกส์คาเฟ่&quot; รอมานานมาก จนอดใจหายว่าจะปิดตัวจริงๆ เสียดายบทความดีๆในเว็บแห่งนี้ ซึ่งตัวเองมักใช้เป็นลิงค์อ้างอิงเสมอๆ บทความแปลชิ้นนี้ตัวเองชอบมาก เพราะทำให้เข้าใจหลักการทำงานลินุกส์ดีขึ้น โชคดีที่ได้คัดลอกเก็บเอาไว้อ่านส่วนตัว พอมาเริ่มเขียนบทความให้เว็บของอาจารย์ wd ก็รู้สึกเกร็งๆการเขียนจริงๆ เพราะมีแต่ผู้รู้ทั้งนั้น (กลัวปล่อยไก่) ในเมื่อยังไม่รู้จะเขียนอะไร ก็ถือโอกาสนี้นำบทความดังกล่าวมาเผยแพร่ (ขัดตาทัพไปก่อน) ...</p> <p> บทความนี้นำมาจากกระทู้ในเว็บบอร์ด &quot;ไทยลินุกส์คาเฟ่&quot; เป็นเรื่องพื้นฐานการคอมไพล์โปรแกรม มีทั้งหมด 3 ตอน แต่ตัวเองนำมายุบรวมกันเป็นเรื่องเดียว ผู้เขียนบทความนี้ก็คือ <span style="font-weight: bold;">คุณ ETO</span> เคยเป็นผู้เชี่ยวชาญเกี่ยวกับลินุกส์ประจำบอร์ดดังกล่าวในรุ่นแรกๆ แล้วอยู่ๆแกก็หายจากวงการนี้ไปสัก 4 ปีให้หลัง ทราบว่าคงมีความจำเป็นบางปราการในเรื่องหน้าที่การงาน แต่ก็ขอขอบคุณที่ได้แปลบทความดีๆและมีคุณภาพชิ้นนี้ให้รุ่นหลังได้ศึกษากัน ง่ายขึ้น ...</p> <p> จุดประสงค์ของบล็อกไตเติ้ลนี้มีอยู่ 2 ประการ </p> <p> ประการแรก&nbsp; เพื่อเผยแพร่บทความดีๆต่อผู้สนใจที่จะศึกษา <br /> ประการสอง&nbsp; เพื่อเป็นการสำรองบทความดีๆ กันเผื่อเกิดอุบัติเหตุ(หายไปเสียดายแย่เลย)</p> <p> บทความนี้มีเนื้อหาค่อนข้างยาว ก็ไม่จำเป็นต้องอ่านให้จบทีเดียว ค่อยๆอ่านไปเรื่อย อ่านผ่านๆ รู้สึกปวดหัวก็พักไปหาอย่างอื่นทำก่อน นึกขึ้นได้ก็กลับมาอ่านจะค่อยๆเข้าใจไปเอง บทความนี้อาจจะเขียนมานาน แต่หลักๆแล้วสามารถนำมาอ้างอิงหรือเทียบเคียงกับการใช้งานในปัจจุบันได้เป็น อย่างดี ... </p> <p> <strong style="color: rgb(255, 0, 255);">พิ้นฐานการคอมไพล์โปรแกรมสำหรับมือใหม่ Linux</strong> </p> <p> เราใช้ภาษาสำหรับโปรแกรมมิ่งในการเขียนโปรแกรมคอมพิวเตอร์ โปรแกรมที่เขียนด้วยภาษาบางอันเรียกที่เรียกว่า ภาษาสคริป จะสามารถทำงานได้ทันที ภาษาดังกล่าวได้แก่ Perl Python และ Tcl/Tk โดยภาษาพวกนี้จะมีตัวแปลที่ทำหน้าที่เป็นล่ามระหว่าง โปรแกรมที่เขียนขึ้นกับระบบ </p> <p> ในภาษาอื่นๆ อย่างเช่น C หรือ C++นั้น โปรแกรมที่เขียนขึ้นจะต้องผ่านการคอมไพล์ให้เป็น ไบนารี่ ก่อนที่จะสามารถทำงานได้ ภาษาดังกล่าวแต่ละรูปแบบมีข้อดีข้อเสียต่างกัน: ภาษาสคริป (หรือภาษาแปล) ใช้เวลาในการเขียนน้อยกว่า ขณะที่โปรแกรมแบบไบนารี่ไม่จำเป็นต้อง มีตัวแปลดังนั้นจึงทำงานได้เร็วกว่า และโดยทั่วไปจะมีความเหมาะสมสำหรับงานที่ซับซ้อนมากกว่า </p> <p> การคอมไพล์เป็นการแปลตัวหนังสือที่เราอ่านออกที่เรียกว่า ซอร์ส (Source code) ไปเป็นไฟล์ที่เครื่องอ่านออกที่เรียกว่า ไบนารี่ (Binary) ดังนั้นสิ่งที่จำเป็นต้องมีในการคอมไพล์ก็คือ ตัวคอมไพล์ (Compiler) บน GNU/Linux ตัวคอมไพล์ก็คือ gcc สำหรับโปรแกรม ที่เขียนด้วยภาษา C และ g++หรือ gcc-c++ สำหรับโปรแกรมที่เขียนด้วยภาษา C++ </p> <p> โปรแกรมที่ซับซ้อนสามารถประกอบไปด้วยไฟล์ซอร์ส จำนวนหลายๆ ไฟล์ และเพื่อให้การคอมไพล์ทำได้ง่ายขึ้นขั้นตอนการคอมไพล์จะเขียนอยู่ในไฟล์ที่ ชื่อ Makefile ในการใช้ไฟล์ไฟล์นี้จำเป็นต้องมีโปรแกรมที่เรียกว่า make ซึ่งโปรแกรม make นี่จะอ่านไฟล์ Makefile (การ parse) และ ส่งข้อมูลที่เหมาะสมให้ตัวคอมไพล์ เราสามารถเปลี่ยนข้อมูลเหล่านี้ได้ (อย่างเช่นโฟลเดอร์ที่จะให้ติดตั้งไฟล์ที่คอมไพล์แล้ว) โดยการ แก้ไข Makefile </p> <p> ในการเขียนโปรแกรม นักเขียนโปรแกรมไม่ได้เขียนโปรแกรมทั้งหมดด้วยตัวเอง เขามักจะใช้ ไลบราลี่ (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 ที่โปรแกรมนั้นใช้ด้วยเช่นกัน <strong style="color: rgb(255, 0, 0);"></p> <p> คุณอาจจะสงสัยว่าแล้วจะให้รู้ได้อย่างไรว่า library ไหนที่โปรแกรมนั้นต้องการ</p> <p> </strong> วิธีการที่ง่ายที่สุดคือคอมไพล์ไฟล์ซอร์สนั้น ในกระบวนการคอมไพล์จะแสดงให้เราเห็นหากว่าไม่สามารถหา library ที่ต้องการพบ ทางที่เป็นไปได้อีกอย่างคือดูใน Makefile ในส่วนส่วนบนจะมีบรรทัดที่เขียนว่า LIBS = ซึ่งจะแสดงรายชื่อ library ที่ต้องการทั้งหมด สังเกตว่ารายชื่อจะอยู่ในรูปแบบย่อ เช่น -lX11 เป็นตัวอย่างการย่อสำหรับไฟล์ชื่อ libX11.so. ให้สั่งlocate libX11.so เพื่อหาว่าไฟล์นี้ได้ติดตั้งอยู่ในระบบของคุณหรือยัง </p> <p> วิธีที่สามซึ่งเป็นวิธีค่อนข้างใหม่คือการใช้สคริปคำสั่ง configure ซึ่งคนเขียนโปรแกรมสามารถสร้างขึ้นได้โดยการใช้โปรแกรม autoconf สคริปนี้ เมื่อทำงานจะทำการตรวจสอบระบบว่ามี library และฟังก์ชั่นทึ่จำเป็นอยู่หรือไม่ ถ้าไม่ก็จะบอกว่ามีอะไรผิดปรกติ <span style="font-weight: bold;"> </p> <p> การแตกไฟล์ Unpacking Archives</span> <br /> ไฟล์ซอร์สมักจะแจกจ่ายอยู่ในรูปแบบของกลุ่มไฟล์ที่ถูกบีบอัดไว้ (compressed archive) ซึ่งมีความเหมาะสม เพราะมักจะประกอบด้วยไฟล์มากกว่าหนึ่งไฟล์และ การบีบอัดมีประสิทธิภาพดีมากสำหรับไฟล์ตัวหนังสือ </p> <p> บน UNIX ไฟล์บีบอัดนี้จะสร้างและแตกออกได้ด้วยการใช้สองโปรแกรม อันแรกคือตัวที่รวมไฟล์ทั้งหมดให้อยู่ด้วยกัน (tar) และอีก อันคือตัวบีบอัด (gzip หรือ bzip2) ในภาษาแสลงเราเรียกไฟล์ archive เหล่านี้ว่า tarballs </p> <p> ในการแตกไฟล์เหล่านี้ออก คุณสามารถใช้ตัวจัดการไฟล์ archive แบบกราฟฟิก เช่น Archiver ของ KDE, guiTAR ของ GNOME หรือ TkZip. บน KDE และ GNOME โปรแกรมจะทำงานเองเมื่อคุณคลิกที่ไฟล์ archive สำหรับการใช้คำสั่ง สามารถใช้: <strong style="color: rgb(0, 0, 255);"></p> <p> tar xzf [file].tar.gz สำหรับแตกไฟล์ tar ที่บีบอัดด้วย gzip และ<br /> tar xjf [file].tar.bz2 สำหรับไฟล์ tar ที่บีบอัดด้วย bzip2</strong> </p> <p> option แรก (x) หมายถึง แตกไฟล์ (extract) สำหรับการสร้าง archives คุณสามารถแทนที่ด้วย c ถ้าต้องการแค่ ให้แสดงรายชื่อไฟล์ให้ใช้ t option ที่สองเป็นการบอกชนิดของการบีบอัดและ f จะบอกให้ tar รอรับชื่อไฟล์ option ที่น่าสนใจอีกอันคือ C ซึ่งจะบอกให้ tar ย้ายไปยังโฟล์เดอร์อื่นก่อนการทำการแตกไฟล์: <br /> <strong style="color: rgb(0, 0, 255);"><br /> tar xzfC [file].tar.gz [dir]</strong> </p> <p> เรามักจะไม่พบไฟล์ bzip2 หรือแม้แต่ zip archives อย่างเดียวใน GNU/Linux การแตกไฟล์ดังกล่าวสามารถทำได้ด้วย bunzip2 [archive name] unzip [archive name] (อันหลังนี้สามารถใช้กับไฟล์ self-extracting (.exe) ด้วย) <span style="font-weight: bold;"></p> <p> ไฟล์ที่จำเป็นต้องอ่าน Important Files to Read</span> <br /> ใน archives ส่วนใหญ่จะมีไฟล์ README และ INSTALL บรรจุอยู่ด้วย ไฟล์เหล่านี้จะแสดงข้อมูลความคิดเห็น ของผู้เขียนโปรแกรมต่อโปรแกรมนั้นๆ วิธีการคอมไพล์ สิ่งที่จำเป็นต้องระวัง เช่นเดียวกับไฟล์อื่นๆ ใน archive คุณสามารถ เปิดได้ด้วยทุกโปรแกรมที่สามารถแสดงไฟล์ตัวหน้งสือได้ </p> <p> <span style="font-weight: bold;">แพคเกจที่จำเป็น Needed Packages</span> <br /> แพคเกจเหล่านี้ จำเป็นสำหรับการคอมไพล์ ให้ทำการตรวจสอบด้วยคำสั่ง rpm -q [name] ว่ามีการติดตั้งแล้วหรือยัง คุณสามารถหาได้จาก CD หรือ จาก rpmfind.net. </p> <p> ตัวคอมไพล์<span style="font-style: italic;"> <br /> - gcc <br /> - glibc-devel <br /> - gcc-c++ <br /> - libstdc++-devel</span> </p> <p> ระบบ <span style="font-style: italic;"> <br /> - make <br /> - kernel-headers</span> </p> <p> <span style="font-weight: bold;">Library ที่ใช้บ่อย</span> <br /> library ที่มักใช้เป็นประจำในโปรแกรม หากคุณมีชุด develope พวกนี้อยู่มักจะทำการคอมไพล์ผ่านโดยไม่ เกิด error เนื่องจากขาด library </p> <p> <span style="font-style: italic;"> - gtk+-devel, glib-devel <br /> - libgr-devel, libungif-devel, libjpeg-devel, libpng-devel, libtiff-devel, xpm-devel (รูปแบบของไฟล์รูปภาพ) <br /> - libtermcap-devel, ncurses-devel (for console applications) <br /> - XFree86-devel (สำหรับแอพพลิเคชันแบบกราฟฟิก) <br /> - zlib-devel (compression library)</span> </p> <p> ถ้าคุณทำการคอมไพล์โปรแกรมสำหรับ GNOME หรือ KDE คุณจำเป็นต้องมีชุด -devel- ของ library พวกนี้ด้วย สำหรับ KDE คุณต้องมี qt-devel ด้วย <span style="font-weight: bold;"> </p> <p> การสั่ง configure</span> <br /> ในปัจจุบันชุดแพ็คเกจซอร์สไฟล์ส่วนใหญ่จะมาพร้อมกับไฟล์คำสั่ง configure ซึ่งจะช่วย ตัวตรวจสอบว่าโปรแกรมสามารถคอมไพล์บนระบบนั้นๆ ได้หรือไม่ </p> <p> <strong style="color: rgb(0, 0, 255);">คำสั่ง ./configure --help</strong> </p> <p> ตัว configure จะแสดงสรุป option ที่เป็นไปได้สำหรับคำสั่ง configure แต่ไม่ต้องตกใจเพราะว่า โดยทั่วไปค่าที่ตั้งเป็น defualt มักจะใช้งานได้ดีอยู่แล้ว แต่มีอยู่หนึ่ง option ที่คุณควรสนใจมากหน่อยคือ --prefix=[DIR] ซึ่งมักจะมีในส่วนต้นๆ ของรายการเลย อันนี้จะหมายถึงว่าจะกำหนดให้โปรแกรมที่คอมไพล์แล้วและ library ไปอยู่ที่ไหน ค่าตั้งต้นมักจะเป็น [/usr] หรือ [/usr/local] ซึ่งทั้งสองค่าก็ดีแล้วแต่สำหรับผู้เขียนชอบที่จะ เก็บโปรแกรมที่คอมไพล์เองลงใน /usr/local/ มากกว่าเพราะทำให้ง่ายต่อการติดตามในภายหลัง อย่างไรก็ตามโปรแกรมบน KDE บางอันจะคิดว่าคุณมีโฟลเดอร์ /opt/kde และจะใช้โฟลเดอร์นี้เป็นค่าตั้งต้นในการติดตั้งโปรแกรม แต่บน Mandrake จะไม่มีโฟลเดอร์นี้ เนื่องจากไฟล์ของ KDE จะเก็บอยู่ใน /usr แทน ดังนั้นคุณจำเป็นต้องเปลี่ยนค่า ในการสั่ง configure ดังนี้: <strong style="color: rgb(0, 0, 255);"></p> <p> ./configure --prefix=/usr</strong> </p> <p> คุณอาจจะเริ่มสงสัยแล้วว่าทำไมจึงใช้./configure แทน configure อันนี้เป็นเพราะโฟลเดอร์ของซอร์สไฟล์ที่เพิ่งสร้างขึ้นใหม่นี้ จะไม่ได้เป็นส่วนหนึ่งของ $PATH ในกรณีที่ใช้ security level ที่ไม่ใช่ low ดังนั้นถ้าคุณสั่งเพียง configure ตัว shell จะบอกว่า : <strong style="color: rgb(0, 0, 255);"></p> <p> bash: configure: command not found</strong> </p> <p> คุณจำเป็นต้องบอก shell ว่าคุณต้องการจะ execute คำสั่งในโฟล์เดอร์ที่อยู่ตอนนี้ โดยการเพิ่มตัว ./ เข้าไปที่คำสั่งนั้นๆ <strong style="color: rgb(255, 0, 0);"></p> <p> โปรดสังเกตว่า ไม่มีความจำเป็น และไม่แนะนำให้สั่ง configure ในขณะเป็น root</strong> <span style="font-weight: bold;"></p> <p> ขาดอะไรหรือ ?</span> <br /> เมื่อ configure ทำงานและตรวจสอบระบบของคุณ มันจะแสดงผลที่หน้าจอของ console พร้อมกับเขียนไฟล์ ใหม่ขึ้นมาชื่อ config.log และตัวคำสั่งจะหยุดทำงานเมื่อพบกับข้อผิดพลาดเพื่อป้องกันไม่ให้โปรแกรม ถูกคอมไพล์ และคำสั่งก็จะแสดงข้อความ error และเขียนลง config.log เช่นกัน ตัวอย่างเช่น: </p> <p> <span style="font-style: italic;">/usr/bin/ld: cannot open -lXt: No such file or directory collect2: ld returned 1 exit status </span> </p> <p> ดูเหมือนกับขาดอะไรบางอย่าง แต่เจ้า -lXt นี่มันคืออะไร ? ในการเขียนโปรแกรมตัวอักษร l (แอล) จะเป็นตัวย่อของ lib...so นั่นคือสิ่งที่ต้องการคือ libXt.so สิ่งทึ่เป็นไปได้ก็คือมันอยู่ใน ชุด -devel-.rpm ที่คุณไม่ได้ติดตั้ง ถ้าคุณใช้ ML 7 ขึ้นไปให้ใช้ RpmDrake (ใช้ Software Manager หรือ Package manger ก็ได้-- ผู้แปล) หาแพ็กเกจที่มีไฟล์นี้อยู่ หรือใช้คำสั่ง urpmf [file] </p> <p> คุณจะพบว่าไฟล์นี้เป็นส่วนหนึ่งของ XFree86-devel ก็ให้ติดตั้งโดยใช้ตัวติดตั้ง RPM ที่ชอบ หรือจะใช้ urpmi หรือจะสั่งด้วย </p> <p> <strong style="color: rgb(0, 0, 255);">su -c &quot;rpm -i XFree86-devel-[version]mdk.rpm&quot;</strong> </p> <p> กลับไปที่โฟล์เดอร์ซอร์สไฟล์อีกครั้ง ด้วยคำสั่ง cd และให้ลบไฟล์ config.cache และสั่ง configure และทำอย่างนี้จนกระทั่ง configure ทำงานผ่าน ถ้าคุณหา RPM ที่มีไฟล์ที่ต้องการไม่เจอ (ซึ่งมักไม่ค่อยพบ) และเอกสารที่มีมาด้วยก็ไม่ได้บอกอะไรมาก คุณจำเป็นต้องติดต่อกับผู้เขียนซอร์ฟแวร์นั้น ซึ่งจะเป็นผู้ที่รู้ดีที่สุด แต่ต้องแน่ใจว่าคุณเองได้ตรวจสอบทุกอย่าง แล้วอย่างน้อยสองรอบ <span style="font-weight: bold;"></p> <p> การสั่ง make</span> <br /> หากคำสั่ง configure ทำงานผ่านเรียบร้อย ก็ถึงเวลาที่จะคอมไพล์ซอร์สจริงๆ แล้ว ให้สั่ง </p> <p> <strong style="color: rgb(0, 0, 255);">make</strong> </p> <p> ซึ่งโดยปรกติจะไม่เกิด error อะไรอีกนอกจากคำสั่ง configure เกิดความผิดปรกติ แม้ว่าตามข้อความ error จาก make มักจะติดตามได้ยากกว่าจาก configure กระบวนการแก้ไขปัญหาก็จะ คล้ายๆกับที่กล่าวมาข้างบน ถ้าผิดพลาดอะไร มักจะเห็น </p> <p> <span style="font-style: italic;">[file]:[line]: [file]: No such file or directory หรือ [file1]: in file | function [name]: [file2]:[line]: undefined reference to [function] (ฯลฯ) </span> </p> <p> ในกรณีแรก ให้ติดตั้ง RPM ที่มีไฟล์ที่ขาด ส่วนความผิดพลาดที่มีชื่อ function มักจะหมายถึงว่าโปรแกรมต้องการ library เวอร์ชั่นใหม่หรือเก่ากว่าที่มีอยู่ ก็ให้หา library เวอร์ชั่นใหม่หรือเวอร์ชั่นที่เก่ากว่าแล้วติดตั้ง แนะนำให้สั่ง </p> <p> <strong style="color: rgb(0, 0, 255);">make clean</strong> </p> <p> ทุกครั้งก่อนการคอมไพล์ใหม่อีกรอบ สมมติว่าทุกอย่างผ่านไปด้วยดี ก็ถึงเวลาการ install คุณจำเป็นต้องเข้าเป็น root ด้วยคำสั่ง: </p> <p> <strong style="color: rgb(0, 0, 255);">su -c &quot;make install&quot;</strong> </p> <p> เรียบร้อยแล้ว คุณอาจะต้องการตรวจสอบว่าโปรแกรมทำงานได้หรือไม่ ตรวจดูให้แน่ใจว่าคุณได้เก็บตัวไบนารี่ไว้ในโฟลเดอร์ที่อยู่ใน $PATH หรือไม่ก็สร้าง symlink ด้วยคำสั่ง ln -s [source] [destination]ไปยัง /usr/bin หรือไม่ก็เพ่ิมโฟลเดอร์เข้าไปใน path <span style="font-weight: bold;"></p> <p> การ Uninstalling</span> <br /> หลายคนไม่เคยรู้เกี่ยวกับอันนี้ แต่โดยทั่วไปเราสามารถ uninstall ไฟล์ต่างๆที่ติดตั้งด้วย make install โดยคุณจำเป็นต้องมี Makefile และเข้าไปในโฟลเดอร์ของ Makefile แล้วสั่ง: </p> <p> <strong style="color: rgb(0, 0, 255);">su -c &quot;make uninstall&quot;</strong> </p> <p> วิธีจะสามารถทำได้เมื่อคนเขียนโปรแกรมได้กำหนดการ uninstall ไว้ใน Makefile แล้ว ซึ่งส่วนใหญ่ก็จะทำกัน) </p> <p> <span style="font-weight: bold;">การใช้ Patches</span> <br /> ไฟล์ patch หรือ diff เป็นไฟล์ text แบบพิเศษที่มีคำสั่งสำหรับโปรแกรม patch ที่จะให้แก้ไขอะไรที่ไหนในซอร์สไฟล์ คำสั่ง patch จะเป็นแบบนี้: <strong style="color: rgb(0, 0, 255);"></p> <p> patch -p[num] &lt;[patch file]</strong> </p> <p> ส่วนที่น่าสนใจคือหมายเลขหลัง -p option ซึ่งจะเป็นตัวกำหนดว่าจะใช้ไฟล์ patch เข้าไปถึงในระดับไหนของ path: -p0 ให้ใช้ patch ลงไปใน path ทั้งหมดที่กำหนดในไฟล์ , -p1 ให้เอา / อันแรกออก ฯลฯ หาไม่มีการกำหนด -p ให้เอา path ทั้งหมดออกซึ่งใช้ได้หากใช้ patch กับไฟล์ที่อยู่ในโฟล์เดอร์เดียวกัน สิ่งที่มักจะได้ผลคือการเอาไฟล์ patch ไปวางไว้บน parent directory ของโฟลเดอร์ของซอร์สไฟล์ที่ต้องการ patch แล้วสั่ง </p> <p> <strong style="color: rgb(0, 0, 255);">patch -p1 &lt;[patch file]</strong> </p> <p> ถ้ามันไม่ทำงานให้ลองหมายเลขอื่นๆ กับ -p option </p> <p> <span style="font-weight: bold;">การคอมไพล์ซอร์สโค้ด (FAQ) </p> <p> ไฟล์หายและไฟล์สำหรับ build แบบที่ไม่ค่อยพบ </p> <p> ในไดเร็คทอรี่ของซอร์สไม่มีไฟล์ 'configure' แล้วจะทำอย่างไรดี? </span> </p> <p> ในกรณีนี้คุณต้องจัดการกับไฟล์ 'Makefile' เอง มีเพียงแค่บรรทัดแรกๆ ที่ขึ้นต้นด้วยอักษรตัวใหญ่เท่านั้นที่ต้องสนใจ และอาจจะต้องแก้ไข ในไฟล์ Makefiles อาจจะไม่ได้มีทุกบรรทัดต่อไปนี้ </p> <p> <span style="font-style: italic;"> * CC = compiler บอก 'make' ว่าจะใช้คอมไพเลอร์ตัวไหน โดยทั่วไปจะใช้ GCC โปรแกรมที่เขียนด้วย C++ อาจจะต้องการ G++ แทน <br /> * INCDIR = -I/path/dir1 -I/path/dir2 etc บอก 'make' ว่าไดเร็คทอรี่ไหนที่มี header files ให้ดูว่าค่าที่ติดตั้งตรงกับระบบของคุณหรือไม่ <br /> * LIBDIR = -L/path/dir1 -L/path/dir2 etc บอก 'make' ว่ามีไฟล์ไลบรารี่ อยู่ที่ไหนบ้าง <br /> * LIBS = -llib1 -llib2 -llib3 etc บอก 'make' ว่าไลบรารี่ใดที่จำเป็น จำไว้ว่า '-llib' ย่อมาจาก 'liblib.so' ใช้คำสั่ง locate liblib.so เพื่อตรวจว่าไลบราลี่ที่ได้ติดตั้้งไลบราลี่ดังกล่าวหรือยัง ในบางครั้งตัวแปรนี้จะใช้ชื่อว่า LFLAGS. </span> ถึงตอนนี้ก็แค่สั่ง make </p> <p> <span style="font-weight: bold;">แล้วถ้าในไดเร็คทอรี่ซอร์สมีไฟล์ 'Imakefile', 'GNUmakefile' หรือ 'Makefile.cvs' แทนที่จะเป็น Makefile ตามปรกติล่ะ ?</span> </p> <p> 'Imake' เป็นตัวดั้งเดิมของ 'configure' ให้สั่ง </p> <p> <strong style="color: rgb(0, 0, 255);">xmkmf -a</strong> </p> <p> เพื่อสร้าง Makefile จาก Imakefile คำสั่งนี้เป็นส่วนหนึ่งของแพ็คเกจ XFree86-devel ต่อจากนั้นก็ทำตามที่ได้กล่าวมาแล้ว สำหรับไฟล์ GNUmakefiles นั้นไม่ต่างกับ Makefiles เราใช้คำสั่ง 'make' ได้กับทั้งสองไฟล์ ถ้าคุณเจอไฟล์ 'Makefile.cvs' ให้สั่ง </p> <p> <strong style="color: rgb(0, 0, 255);">make -f Makefile.cvs</strong> </p> <p> เราจะได้ไฟล์ 'configure' </p> <p> <span style="font-weight: bold;">แล้วถ้าในไดเร็คทอรี่ไม่มีไฟล์สำหรับ build เลยล่ะ ?</span> </p> <p> ก่อนอื่นให้หาว่าในไดเร็คทอรี่ย่อยต่างๆ มีไฟล์ที่สามารถ execute ได้หรือเปล่า โดยคำสั่ง: </p> <p> <strong style="color: rgb(0, 0, 255);">find . -type f -perm -700</strong> </p> <p> จะแสดงรายการไฟล์ที่สามารถ execute ได้ ถ้าคุณไม่เจอไฟล์ดังกล่าวเลย ก็ดูเหมือนว่าคุณจะต้องทำการคอมไพล์ซอร์สไฟล์ตรงๆ และเป็นไปได้มากว่าจะมีแค่ไฟล์ *.c เพียงไฟล์เดียว ให้สั่ง </p> <p> <strong style="color: rgb(0, 0, 255);">gcc -o new_name file.c</strong> <br /> <span style="font-style: italic;"><br /> '-o new_name' จะเป็นการกำหนดชื่อสำหรับไฟล์ไบนาที่ที่ได้ และให้เอาอ็อปชั่น '-o' ออกหากว่าในไดเร็คทอรี่มีไฟล์ *.c (*.C, *.cc, *.cxx) มากกว่าหนึ่งไฟล์ ในกรณีหลังนี้ไฟล์ผลลัพธ์ที่ได้จะชื่อ 'a.out' คุณสามารถ เปลี่ยนชื่อให้เหมาะสมเองได้ภายหลัง </span> ถ้าคุณจำเป็นต้องระบุ ไฟล์สำหรับ include หรือไดเร็คทอรี่ของไลบราลี่หรือไฟล์ไลบราลี่อื่นๆเป็นพิเศษ คุณสามารถทำได้ด้วยการเพิ่มอ็อพชั่น ให้ gcc โดยตรง เช่น </p> <p> <strong style="color: rgb(0, 0, 255);">gcc -o new_name file.c -L/path/dir -llib -I/path/dir</strong> </p> <p> <span style="font-weight: bold;">ปัญหาการ build</span> <br /> ทำไม 'configure' บอกว่าขาดไฟล์ library / header ทั้งๆ ที่ติดตั้งไฟล์ดังกล่าวเรียบร้อยแล้ว ? </p> <p> การเกิดเออเรอร์แบบนี้เกิดได้สามแบบคือ: <span style="font-style: italic;"> </p> <p> 1. 'configure' ไม่ได้มองหาในไดเร็คทอรี่ที่มีไลบราลี่นั้น ซึ่งในกรณีนี้คุณต้องเพิ่ม path ของไดเร็คทอรี่นั้นให้ด้วยอ็อปชั่น '--with-extra-libs=[DIR]' เช่นเดียวกับหากเป็นไฟล์ header ก็ใช้ '--with-extra-includes=[DIR]' </p> <p> 2. 'configure' หาไลบรารี่ผิดเวอชั่น ตัวอย่างที่ดีเช่นแอ็พพลิเคชั่นที่คอมไพล์ด้วย Qt2 โดย 'configure' อาจจะบอกข้อความเออเรอร์ที่ไม่ถูกต้องหากคุณติดตั้ง เวอร์ชั่นเก่าของ Qt2 เช่น <br /> &nbsp;&nbsp; 2.1 เมื่อแอ็พพลิเคชั่นต้องการ <br /> &nbsp;&nbsp; 2.2 ในกรณีนี้คุณจำเป็นต้องอํพเกรดไปเป็นเวอร์ชั่นใหม่ อีกปัญหาที่พบบ่อยคือถ้ามีการ<br /> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ติดตั้งทั้ง Qt1 และ Qt2 (และ Qt3 ...) โดยดีฟ้อลท์แล้ว 'configure' จะมองหา<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Qt ใน '/usr/lib/qt' แต่บน ML นั้นในไดเร็คทอรี่ดังกล่าวจะเป็นที่ติดตั้งของ Qt1<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ส่วน Qt2 จะอยู่ใน '/usr/lib/qt2' และ Qt3 อยู่ใน '/usr/lib/qt3' ในกรณีนี้คุณ<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ต้องใส่อ็อปชั่นให้ 'configure' ดังนี้: ./configure -with-qt-dir=/usr/lib/qt2. </p> <p> 3. ความผิดพลาดในการพิมพ์ของสคริป 'configure' ให้คุณดูข้อความในไฟล์ 'config.log' อย่างถี่ถ้วน โดยเฉพาะความผิดพลาดจากตัวอักษรเล็กใหญ่ในชื่อของไลบรารี่และไฟล์ header ถึงแม้ความผิดพลาดแบบนี้จะเกิดน้อยมาก แต่ก็ทำให้ป่วนคุณได้ถ้าคุณคิดว่ามันเป็นไปไม่ได้</span></p> <p> <span style="font-weight: bold;">ทำไมไบนารี่ที่คอมไพล์ได้ขาดฟีเจอร์ที่ควรจะมี ?</span> </p> <p> ขึ้นกับคนเขียนโปรแกรมว่าเมื่อมีการขาดไฟล์ไลบรารี่ใดแล้วจึงให้ 'configure' หรือ 'make' หยุดการทำงานและแสดงข้อความเออเรอร์ ดังนั้นการคอมไพล์สำเร็จไม่ได้ประกันว่าไบนารี่ที่ได้มีฟีเจอร์ครบทุกอย่าง การดูรายละเอียดของไฟล์ 'config.log' จะช่วยหาได้ว่ามีไลบรารี่ใดบ้างที่ขาดหายไป ทำการติดตั้ง และทำการคอมไพล์อีกครั้ง <span style="font-weight: bold;"></p> <p> ปัญหาในการ build</span> </p> <p> <span style="font-weight: bold;">ได้ทำการติดตั้งไลบรารี่ที่ขาดแล้ว แต่ทำไม 'configure' หรือ 'make' ยังคงหามันไม่พบ ?</p> <p> </span> ผลจากการสั่ง 'configure' และ 'make' ถูกเก็บเป็นเคชอยู่ ให้สั่ง </p> <p> <strong style="color: rgb(0, 0, 255);">make distclean</strong> </p> <p> เพื่อทำการกำจัดไฟล์ที่เกิดขึ้นในไดเร็คทอรี่ เมื่อทำแล้วคุณสามารถแน่ใจได้ว่าสคริปทั้งสองจะตรวจสอบระบบใหม่ หาก Makefile ไม่รู้จัก 'distclean' ให้สั่ง </p> <p> <strong style="color: rgb(0, 0, 255);">make clean &amp;&amp; rm config.cache</strong> </p> <p> สาเหตุของปัญหาแบบนี้อีกอันหนึ่งคือหากไลบรารี่ที่ติดตั้งไม่ได้อยู่ในได เร็ค ทอรี่ที่อยู่ในรายการในไฟล์ '/etc/ld.so.conf' โดยไฟล์นี้จะ มีรายการที่ตัว Linux Loader/Linker 'ld' จำทำการมองหาไลบรารี่นอกเหนือไปจากตำแหน่งมาตรฐานคือ '/usr/lib' และ '/lib' ตัวอย่างเช่นเมื่อติดตั้งไลบรารี่ใน '/usr/local/lib' และไม่มีชื่อไดเร็คทอรี่นี้ใน '/etc/ld.so.conf' ไฟล์ไลบรารี่ดังกล่าวก็จะไม่สามารถเข้าถึงได้โดยระบบ การแก้ปัญหานี้คือการเพิ่มไดเร็คทอรี่ดังกล่าวใน '/etc/ld.so.conf' และสั่ง (โดยเป็น 'root') </p> <p> <strong style="color: rgb(0, 0, 255);">ldconfig</strong> </p> <p> หลังจากนั้นทำการทำความสะอาดไดเร็คทอรี่ซอร์สไฟล์แล้วทำการคอมไพล์อีกครั้ง </p> <p> <span style="font-weight: bold;">ทำอย่างไรถึงจะแก้ไขปัญหาเวอร์ชั่นของไลบรารี่ไม่ตรงเมื่อได้ติดตั้งทุกไลบรารี่ที่ต้องการแล้ว ?</span> </p> <p> ในกรณีส่วนใหญ่กระบวนการ build ไม่ได้มองที่เวอร์ชั่นย่อยของไลบรารี่ และจะขึ้นอยู่กับการสร้างลิ้งค์ใน '/usr/lib' ยกตัวอย่างเช่นไลบรารี่ 'libungif.so' ใน '/usr/lib' </p> <p> <span style="font-style: italic;">lrwxrwxrwx /usr/lib/libungif.so -&gt; libungif.so.4.1.0* <br /> lrwxrwxrwx /usr/lib/libungif.so.3 -&gt; libungif.so.3.1.0* <br /> -rwxr-xr-x /usr/lib/libungif.so.3.1.0* <br /> lrwxrwxrwx /usr/lib/libungif.so.4 -&gt; libungif.so.4.1.0* <br /> -rwxr-xr-x /usr/lib/libungif.so.4.1.0*</span> </p> <p> จะเห็นว่ามีไลบรารี่สองเวอร์ชั่นติดตั้งอยู่คือ libungif.so.4.1.0 และ libungif.so.3.1.0 (ที่มีเครื่องหมาย *) นอกจากนี่ยังมี 'symlink' (รายการที่ขึ้นด้วยตัวอักษร 'l') คือ: libungif.so, libungif.so.3 และ libungif.so.4. </p> <p> 'Symlinks' นั้นไม่ได้เป็นไฟล์ที่แท้จริง แต่เป็นแค่ตัวชี้ไปยังไฟล์เท่านั้น ก ระบวนการคอมไพล์จากมองหาไฟล์ 'libungif.so.3' ใน '/usr/lib' และได้รับการชี้จาก symlink ไปยังเวอร์ชั่นย่อยของไลบรารี่ในที่นี่คือ 3.1.0 </p> <p> ที่นี่ถ้าเราสมมติว่าคนเขียนโปรแกรมไม่ได้ระบุรายละเอียด (โดยไม่ได้ตั้งใจ) และกระบวนการคอมไพล์จะมองหาแค่ 'libungif.so' ในกรณีนี้มันอาจจะมองไปที่ libungif.so.4.1.0 ซึ่งเป็นไลบรารี่ตัวเดียวกันแต่มีเวอร์ชั่นหลักที่ต่างกัน และโดยทั่วไปแต่ละเวอร์ชั่นหลักมักจะ เข้ากันไม่ได้ ดังนั้นถ้าแอ็พพลิเคชั่นนั้นต้องการเวอร์ชั่น 3 แต่กระบวนการคอมไพล์พบเวอชั่น 4 สคริป 'make' หรือ 'configure' จะหยุดพร้อมกับข้อความเออเรอร์ และมันจะบอกว่า 'missing library' หรือ 'undefined reference' เช่นเดียวกันถ้า symlink ที่มีชื่อตรงกับเวอชั่นหลักนั้นไม่มีอยู่กระบวนการคอมไพล์ก็จะล้มเหลวเช่น กัน </p> <p> สำหรับในปัญหาแรกนั้น วิธีการแก้ปัญหาอย่างง่ายก็คือทำการสร้าง symlink ใหม่ให้กระบวนการคอมไพล์ด้วยการสั่ง </p> <p> <strong style="color: rgb(0, 0, 255);">ln -sf /usr/lib/libungif.so.3.1.0 /usr/lib/libungif.so</strong> </p> <p> ถ้าเจอปัญหาที่สอง ก็ให้ทำการสร้าง symlink ที่จำเป็นด้วยคำสั่ง 'ln' ค่าแรกของอาร์กิวเม้นต์คือไฟล์ที่มีอยู่ ค่าที่สองคือชื่อของ symlink ที่ต้องการ คุณควรระวังในการสร้าง symlink เพราะมันอาจจะไปทำให้โปรแกรมอื่นใช้งานไม่ได้ ถ้าเป็นไปได้ก็ตรวจสอบจากคนเขียนโปรแกรม เพราะเขารู้ดีที่สุด </p> <p> <span style="font-weight: bold;">แปลและเรียบเรียงโดย ETO</span><span style="font-style: italic;"> 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.</span></p> </div></div></div><div class="field field-name-taxonomy-vocabulary-1 field-type-taxonomy-term-reference field-label-above"><div class="field-label">Topic:&nbsp;</div><div class="field-items"><div class="field-item even"><a href="/taxonomy/term/1">linux</a></div><div class="field-item odd"><a href="/taxonomy/term/280">Compiler</a></div></div></div> Wed, 12 Dec 2007 14:26:30 +0000 somjate 399 at https://www.thaitux.info https://www.thaitux.info/node/399#comments