1.1: การคอมไพล์โปรแกรมบน Linux

AttachmentSize
Image icon c_process.png14.7 KB

การคอมไพล์โปรแกรม ต้องอาศัย compiler ที่ทำหน้าที่แปลงจาก source code ที่โปรแกรมเมอร์เขียนเป็น machine code ที่สามารถทำงานบนเครื่องคอมพิวเตอร์ได้ ซึ่งบนระบบปฏิบัติการ Linux มีชุด compiler ของ GNU ให้เลือกใช้งาน โดยในที่นี่เราจะเลือกใช้งาน gcc หรือ g++ สำหรับ คอมไพล์ภาษา C และ C++ ตามลำดับ

กระบวนการคอมไพล์ Source code ไปเป็น machine code ของภาษา C/C++ เป็นไปตามรูปด้านล่าง คือจาก source code (.c หรือ .cpp) เมื่อผ่านคอมไพเลอร์จะได้ object code (.o) และจาก object code เมื่อนำมาโยงกับ library ต่าง ๆ ที่จำเป็นต่อการใช้งานโดย linker ก็จะได้ machine code โดยปรกติหากเราใช้งานบน Linux จะไม่มีนามสกุล โดยวิธีการใช้คำสั่งคอมไพล์จะกล่าวในลำดับถัดไป

หากเรามี source code โดยให้ชื่อว่า main.cpp และ main.c ดังนี้

//main.cpp
#include <iostream>

int main()
{
  std::cout << "Hello world" << std::endl;
  return 0;
}
//main.c
#include <stdio.h>

int main()
{
  printf("Hello world\n");
  return 0;
}

และคอมไพล์และรันดังต่อไปนี้

สำหรับภาษา C++

$ g++ main.cpp
$ ./a.out
Hello world

สำหรับภาษา C

$ gcc main.c
$ ./a.out
Hello world

โดยปรกติหากเราใช้ gcc/g++ คอมไพล์โปรแกรมโดยไม่ระบุ option เพิ่มเติม g++/gcc จะทำหน้าที่ compile และ link library ให้เลยโดยอัตโนมัติ โดยจะมีชื่อโดยปริยายคือ a.out ดังนั้นเราสามารถที่จะรันโปรแกรมได้เลย นอกจากนี้ gcc/g++ ยังมี option ที่น่าสนใจอีกมาก หากสนใจสามารถใช้คำสั่ง man gcc หรือ info gcc ดูได้ โดยในที่นี่จะนำเสนอ option เฉพาะที่ใช้กันบ่อยๆเท่านั้น

เมื่อเราต้องการ compile โปรแกรมโดยที่มีไฟล์หลายไฟล์สำหรับการเขียนโปรแกรม เช่น main.cpp test.cpp test.h เราสามารถ compile ได้อย่างง่ายๆ โดย ใช้คำสั่งแบบนี้ได้เลย:

$ g++ main.cpp test.cpp
$ ./a.out

แต่ถ้าหาเราจะกำหนดให้ใช้ชื่อโปรแกรมเป็นอย่างอื่นที่ไม่ใช่ a.out ก็สามารถทำได้อย่างง่ายดาย เพียงแต่เพิ่ม option -o ลงไปเช่น

$ g++ main.cpp test.cpp -o myprogram
$ ./myprogram

นอกจากนี้หากเรามีไฟล์โปรแกรม .c หรือ .cpp จำนวนมาก เราก็สามารถใช้ option -c สำหรับ compile ทีละไฟล์ แล้วค่อยมารวมเป็นโปรแกรมทีหลังก็ได้ ซึ่งวิธีการนี้มีข้อดีตรงที่ว่าเมื่อเราแก้ไข source code ไฟล์หนึ่ง เราไม่ต้องไปคอมไพล์ไฟล์ source code อื่น ให้เสียเวลา เราแค่ copile ไฟล์ที่เราแก้ แล้วก็ link โปรแกรมใหม่แค่นี้ก็ใช้งานได้แล้ว โดยการใช้ในกรณีนีหากเราใช้ option -c โดยไม่ใช้ option -o ร่วมด้วย ไฟล์ที่เป็นเอาต์พุตของ g++/gcc โดยปริยายคือ ชื่อไฟล์นั้นมีนามสกุลเป็น .o ซึ่งที่รู้จักกันในนาน object file นั้นเอง ตัวอย่างการใช้งาน

$ g++ -c main.cpp test.cpp
$ ls
main.cpp  main.o  test.cpp  test.o

แต่ไฟล์ .o นี้ยังไม่สามารถใช้งานได้จนกว่าเราจะ link กับ library เสียก่อนโดยใช้ g++/gcc เจ้าเดิม

$ g++ main.o test.o -o myprogram
$ ./myprogram

หากเราพัฒนาโปรแกรมโดยมีการใช้งาน library ที่เพิ่มเข้ามาจากเดิม โดยที่ header file ไม่อยู่ใน /usr/include ซึ่งมักเป็น sub directory ใน /usr/include เช่น /usr/include/opencv เป็นต้น เราสามารถเขียนสามารถ compile โดยใช้ option -I เพิ่มเข้าไปได้ เช่น

// main.cpp
#include <cv.h>
#include <cvaux.h>
#include <highgui.h>
#include <cxcore.h>
:
$ g++ -c -I/usr/include/opencv main.cpp

อย่างนี้ใช้ได้ทุกกรณีไม่ว่าไฟล์ .h จะอยู่ที่ directory อะไร แต่ในกรณีที่มี directory อยู่ใน /usr/include เราสามารถ compile โดยไม่ใช้ option -I ก็ได้แต่เราต้องปรับการเขียน code เป็น

// main.cpp
#include <opencv/cv.h>
#include <opencv/cvaux.h>
#include <opencv/highgui.h>
#include <opencv/cxcore.h>
:
$ g++ -c main.cpp

นอกจากนี้กรณีของ opencv จะใช้ library เพิ่มเติมจาก library มาตรฐานแล้ว ก็คือ library opencv เราต้องเพิ่ม option เพื่อระบุ library เพิ่มเข้าไปอีกด้วย โดยจะมีลักษณะ คือ -l<ชื่อ library.so> เช่น -lcv -lcvaux -lcxcore -lhighgui

$ g++ -lcv -lcvaux -lcxcore -lhighgui main.o -o myprogram

ซึ่งกรณีด้านบนจะใช้ได้ก็ต่อเมื่อ library เหล่านี้อยู่ใน path มาตรฐานด้วยเช่นกัน เช่น /lib หรือ /usr/lib เป็นต้น ถ้าเรามี library ที่ไม่ได้อยู่ในนี้เราสามารถเพิ่ม option -L เข้าไปให้ linker ได้เช่นกัน สมมุติเรา มี library ของ opencv อยู่ใน /usr/local/opencv/lib เราก้สามารถใช้คำสั่งได้ดังนี้

$ g++ -L/usr/local/opencv/lib -lcv -lcvaux -lcxcore -lhighgui main.o -o myprogram 
Taxonomy upgrade extras: 

Comments

s/matchine/machine/ นะครับ :P

ขอบคุณครับที่ช่วย review

thak you

Creative Commons License ลิขสิทธิ์ของบทความเป็นของเจ้าของบทความแต่ละชิ้น
ผลงานนี้ ใช้สัญญาอนุญาตของครีเอทีฟคอมมอนส์แบบ แสดงที่มา-อนุญาตแบบเดียวกัน 3.0 ที่ยังไม่ได้ปรับแก้