ผลต่างระหว่างรุ่นของ "CMake"

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
(หน้าที่ถูกสร้างด้วย 'CMake ([http://www.cmake.org/](http://www.cmake.org/) และ [http://en.wikipedia.org/wiki/Cmake](http://en.wikipedia.org/wiki/Cmake)) …')
 
แถว 1: แถว 1:
CMake ([http://www.cmake.org/](http://www.cmake.org/) และ [http://en.wikipedia.org/wiki/Cmake](http://en.wikipedia.org/wiki/Cmake))  
+
CMake ([http://www.cmake.org/ http://www.cmake.org/] และ [http://en.wikipedia.org/wiki/Cmake http://en.wikipedia.org/wiki/Cmake])  
เป็นซอฟต์แวร์สำหรับสร้าง build script  
+
เป็นซอฟต์แวร์สำหรับสร้าง build script (ไฟล์ที่นิยามวิธีการคอมไพล์และลิงก์โปรแกรมและไลบรารีที่เขียนด้วยภาษา C++) ที่สามารถใช้ร่วมกับเครื่องมือพัฒนาโปรแกรมที่ได้รับความนิยมหลายๆ ตัว
(ไฟล์ที่นิยามวิธีการคอมไพล์และลิงก์โปรแกรมและไลบรารีที่เขียนด้วยภาษา C++)  
 
ที่สามารถใช้ร่วมกับเครื่องมือพัฒนาโปรแกรมที่ได้รับความนิยมหลายๆ ตัว
 
 
อาทิ Microsoft Visual C++, GNU Compiler Collection, Xcode, และ Eclipse CDT เป็นต้น
 
อาทิ Microsoft Visual C++, GNU Compiler Collection, Xcode, และ Eclipse CDT เป็นต้น
  
แถว 11: แถว 9:
 
เป็นการปูพื้นฐานก่อนจะกล่าวถึงการใช้งานที่สลับซับซ้อนขึ้นต่อไป
 
เป็นการปูพื้นฐานก่อนจะกล่าวถึงการใช้งานที่สลับซับซ้อนขึ้นต่อไป
  
ปัญหาของการเขียนโปรแกรมสำหรับหลายแพลตฟอร์ม
+
== ปัญหาของการเขียนโปรแกรมสำหรับหลายแพลตฟอร์ม ==
==========================================
 
  
 
การเขียนโปรแกรมภาษา C++ ให้คอมไพล์และรันบนหลายๆ แพลตฟอร์ม (เขียนครั้งเดียวแต่รันได้ทั้งบน Windows, Unix, Mac, ฯลฯ)
 
การเขียนโปรแกรมภาษา C++ ให้คอมไพล์และรันบนหลายๆ แพลตฟอร์ม (เขียนครั้งเดียวแต่รันได้ทั้งบน Windows, Unix, Mac, ฯลฯ)
แถว 19: แถว 16:
 
เราอาจสามารถสรุปปัญหาที่โปรแกรมเมอร์เจอไว้เป็นข้อๆ ได้ดังต่อไปนี้
 
เราอาจสามารถสรุปปัญหาที่โปรแกรมเมอร์เจอไว้เป็นข้อๆ ได้ดังต่อไปนี้
  
1. ไลบรารีภาษา C/C++ บนแพลตฟอร์มต่างๆ ไม่เหมือนกัน เช่น ใน Linux และ Mac จะมีไฟล์ `unistd.h` แต่ใน Windows
+
# ไลบรารีภาษา C/C++ บนแพลตฟอร์มต่างๆ ไม่เหมือนกัน เช่น ใน Linux และ Mac จะมีไฟล์ `unistd.h` แต่ใน Windows
 
ไม่มี หรือใน Mac มีระบบไลบรารีที่เรียกว่า [bundle และ framework](http://osxbook.com/book/bonus/ancient/whatismacosx//programming.html)  
 
ไม่มี หรือใน Mac มีระบบไลบรารีที่เรียกว่า [bundle และ framework](http://osxbook.com/book/bonus/ancient/whatismacosx//programming.html)  
 
ซึ่งไม่ปรากฏอยู่ในแพลตฟอร์มอื่นๆ
 
ซึ่งไม่ปรากฏอยู่ในแพลตฟอร์มอื่นๆ
  
2. คอมไพเลอร์ที่ใช้เป็นคนละตัวกัน กล่าวคือ โปรแกรมเมอร์ C++ ใน Windows จะใช้ `cl` ของ Microsoft
+
# คอมไพเลอร์ที่ใช้เป็นคนละตัวกัน กล่าวคือ โปรแกรมเมอร์ C++ ใน Windows จะใช้ `cl` ของ Microsoft
 
ส่วนโปรแกรมเมอร์บน Linux และ Mac จะใช้ `gcc` หรือ `g++` ของ GNU Project นี่หมายความว่าภาษา C++  
 
ส่วนโปรแกรมเมอร์บน Linux และ Mac จะใช้ `gcc` หรือ `g++` ของ GNU Project นี่หมายความว่าภาษา C++  
 
ใน Windows จะไม่เหมือนกับภาษา C++ ใน Unix และ Mac เป๊ะ  
 
ใน Windows จะไม่เหมือนกับภาษา C++ ใน Unix และ Mac เป๊ะ  
 
และมีข้อแตกต่างยิบย่อยที่ทำให้ซอร์สโค้ดที่เขียนสำหรับแพลตฟอร์มหนึ่งไม่สามารถคอมไพล์บนอีกแพลตฟอร์มหนึ่งได้
 
และมีข้อแตกต่างยิบย่อยที่ทำให้ซอร์สโค้ดที่เขียนสำหรับแพลตฟอร์มหนึ่งไม่สามารถคอมไพล์บนอีกแพลตฟอร์มหนึ่งได้
  
3. เครื่องมือที่ใช้ในการ build โปรแกรมไม่เหมือนกัน โปรแกรมเมอร์บน Windows จะใช้ Visual Studio
+
# เครื่องมือที่ใช้ในการ build โปรแกรมไม่เหมือนกัน โปรแกรมเมอร์บน Windows จะใช้ Visual Studio
 
พวกที่ใช้ Linux ก็จะเขียน Makefile แล้วรัน `make` ส่วนขา Mac ก็จะใช้ Xcode
 
พวกที่ใช้ Linux ก็จะเขียน Makefile แล้วรัน `make` ส่วนขา Mac ก็จะใช้ Xcode
  
Preprocessor Macro
+
=== Preprocessor Macro ===
------------------
 
  
เราสามารถหลีกเลี่ยงสองปัญหาแรกบางส่วนได้ด้วยการเขียน [preprocessor macro](http://en.wikipedia.org/wiki/Preprocessor_macro)
+
เราสามารถหลีกเลี่ยงสองปัญหาแรกบางส่วนได้ด้วยการเขียน [http://en.wikipedia.org/wiki/Preprocessor_macro preprocessor macro]
 
เพื่อให้คอมไพเลอร์เลือกใช้โค้ดส่วนที่ถูกต้อง ยกตัวอย่าง เช่น หากเราต้องการชื่อของไดเรคทอรีที่โปรแกรมทำงานอยู่ในปัจจุบัน
 
เพื่อให้คอมไพเลอร์เลือกใช้โค้ดส่วนที่ถูกต้อง ยกตัวอย่าง เช่น หากเราต้องการชื่อของไดเรคทอรีที่โปรแกรมทำงานอยู่ในปัจจุบัน
 
(current working directory ย่อว่า cwd) แล้ว
 
(current working directory ย่อว่า cwd) แล้ว
แถว 45: แถว 41:
 
ฉะนั้นเราสามารถเลือก include ไฟล์ที่ถูกต้องได้ดังนี้
 
ฉะนั้นเราสามารถเลือก include ไฟล์ที่ถูกต้องได้ดังนี้
  
{% highlight c %}
+
<geshi lang="c">
#ifdef _WIN32
+
#ifdef _WIN32
#include <direct.h>
+
#include <direct.h>
#else
+
#else
#include <unistd.h>
+
#include <unistd.h>
#endif
+
#endif
 
+
</geshi>
{% endhighlight %}
 
  
 
ส่วนเวลาเรียกใช้คำสั่ง เราสามารถเขียนโค้ดต่อไปนี้ได้
 
ส่วนเวลาเรียกใช้คำสั่ง เราสามารถเขียนโค้ดต่อไปนี้ได้
  
{% highlight c %}
+
<geshi lang="c">
char *buffer;
+
char *buffer;
#ifdef _WIN32
+
#ifdef _WIN32
buffer = _getcwd(NULL, 0);
+
buffer = _getcwd(NULL, 0);
#else
+
#else
buffer = getcwd(NULL, 0);
+
buffer = getcwd(NULL, 0);
#endif
+
#endif
 
+
</geshi>
{% endhighlight %}
 
  
เครื่องมือและสภาพแวดล้อมที่แตกต่าง
+
=== เครื่องมือและสภาพแวดล้อมที่แตกต่าง ===
----------------------------------
 
  
 
อย่างไรก็ดีการเขียน preprocessor macro ก็ยังไม่สามารถแก้ปัญหาได้ทั้งหมด
 
อย่างไรก็ดีการเขียน preprocessor macro ก็ยังไม่สามารถแก้ปัญหาได้ทั้งหมด
แถว 74: แถว 67:
 
ดังนั้นแพลตฟอร์มต่างๆ จึงมีเครื่องมือสำหรับกำหนดกระบวนการนี้เป็นของตัวเอง
 
ดังนั้นแพลตฟอร์มต่างๆ จึงมีเครื่องมือสำหรับกำหนดกระบวนการนี้เป็นของตัวเอง
  
ถึงแม้ว่าในปัจจุบัน [`make`](http://en.wikipedia.org/wiki/Make_%28software%29)
+
ถึงแม้ว่าในปัจจุบัน [http://en.wikipedia.org/wiki/Make_%28software%29 make]
 
จะเป็นเครื่องมือมาตรฐานสำหรับการสร้างซอฟต์แวร์ภาษา C++ ในแพลตฟอร์มที่สืบเชื้อสายมาจาก
 
จะเป็นเครื่องมือมาตรฐานสำหรับการสร้างซอฟต์แวร์ภาษา C++ ในแพลตฟอร์มที่สืบเชื้อสายมาจาก
Unix ทั้งหลาย นอกจากนี้ใน Windows มี [`nmake`](http://msdn.microsoft.com/en-us/library/ms930369.aspx)
+
Unix ทั้งหลาย นอกจากนี้ใน Windows มี [http://msdn.microsoft.com/en-us/library/ms930369.aspx nmake]
 
ให้ใช้ด้วย อย่างไรก็ดีการใช้ `make` ทำให้โปรแกรมเมอร์ต้องสละความสะดวกสบายของ IDE
 
ให้ใช้ด้วย อย่างไรก็ดีการใช้ `make` ทำให้โปรแกรมเมอร์ต้องสละความสะดวกสบายของ IDE
 
ที่ตนถนัด (เนื่องจากผู้เขียนใช้งาน Visual C++ จนติด การต้องไปเขียน Makefile เองจึงเป็นเรื่องที่ทรมานยิ่ง)
 
ที่ตนถนัด (เนื่องจากผู้เขียนใช้งาน Visual C++ จนติด การต้องไปเขียน Makefile เองจึงเป็นเรื่องที่ทรมานยิ่ง)
แถว 85: แถว 78:
 
ส่วนใน Windows นั้นไม่มีที่เก็บที่แน่นอน เป็นเรื่องของโปรแกรมเมอร์ที่จะต้องรู้ที่เก็บไลบรารีเอง
 
ส่วนใน Windows นั้นไม่มีที่เก็บที่แน่นอน เป็นเรื่องของโปรแกรมเมอร์ที่จะต้องรู้ที่เก็บไลบรารีเอง
  
ในแพลตฟอร์ม Unix มีชุดของเครื่องมือที่เรียกว่า [`Autotools`](http://en.wikipedia.org/wiki/Autotools)
+
ในแพลตฟอร์ม Unix มีชุดของเครื่องมือที่เรียกว่า [http://en.wikipedia.org/wiki/Autotools Autotools]
 
ซึ่งสามารถตรวจว่าระบบที่จะทำการคอมไพล์ไฟล์มีไลบรารีที่ต้องการให้ใช้หรือไม่
 
ซึ่งสามารถตรวจว่าระบบที่จะทำการคอมไพล์ไฟล์มีไลบรารีที่ต้องการให้ใช้หรือไม่
 
รวมทั้งสร้างไฟล์ชื่อ `config.h` ซึ่งมี preprocessor macro  
 
รวมทั้งสร้างไฟล์ชื่อ `config.h` ซึ่งมี preprocessor macro  
แถว 96: แถว 89:
 
แต่ในขณะเดียวกันเราก็ยังสามารถพัฒนาซอฟต์แวร์เดียวกันนี้บนแพลตฟอร์มอื่นได้ด้วย
 
แต่ในขณะเดียวกันเราก็ยังสามารถพัฒนาซอฟต์แวร์เดียวกันนี้บนแพลตฟอร์มอื่นได้ด้วย
  
CMake
+
== CMake ==
=====
 
  
 
CMake เป็นเครื่องมือที่ช่วยตอบสนองความต้องการข้างต้นได้ จากมุมมองของผู้ใช้  
 
CMake เป็นเครื่องมือที่ช่วยตอบสนองความต้องการข้างต้นได้ จากมุมมองของผู้ใช้  
 
CMake แล้วกระบวนการคอมไพล์โปรแกรมสามารถแยกออกเป็นสามขั้นตอนดังต่อไปนี้
 
CMake แล้วกระบวนการคอมไพล์โปรแกรมสามารถแยกออกเป็นสามขั้นตอนดังต่อไปนี้
  
1. เขียนไฟล์ชื่อ `CMakeLists.txt` เพื่อกำหนดโปรเจค
+
# เขียนไฟล์ชื่อ `CMakeLists.txt` เพื่อกำหนดโปรเจค
  
2. รัน CMake เพื่อสร้าง build script ที่เฉพาะเจาะจงกับแพลตฟอร์มและเครื่องมือที่เราใชัพัฒนาโปรแกรม
+
# รัน CMake เพื่อสร้าง build script ที่เฉพาะเจาะจงกับแพลตฟอร์มและเครื่องมือที่เราใชัพัฒนาโปรแกรม
  
3. build โปรแกรมด้วยเครื่องมือดังกล่าว
+
# build โปรแกรมด้วยเครื่องมือดังกล่าว
  
 
สังเกตว่าหน้าที่ของ CMake คือการอ่านพิมพ์เขียวของโปรเจคจากไฟล์ `CMakeLists.txt`
 
สังเกตว่าหน้าที่ของ CMake คือการอ่านพิมพ์เขียวของโปรเจคจากไฟล์ `CMakeLists.txt`
แถว 112: แถว 104:
 
นี่เป็นสาเหตุที่ทำให้เราสามารถใช้เครื่องมืออะไรก็ได้ที่ CMake สนับสนุนในการพัฒนาโปรแกรมตามความถนัดของเรา
 
นี่เป็นสาเหตุที่ทำให้เราสามารถใช้เครื่องมืออะไรก็ได้ที่ CMake สนับสนุนในการพัฒนาโปรแกรมตามความถนัดของเรา
  
การติดตั้ง CMake
+
== การติดตั้ง CMake ==
================
 
  
คุณสามารถดาวน์โหลด CMake จาก[หน้าดาวน์โหลดของเวบไซต์อย่างเป็นทางการ](http://www.cmake.org/cmake/resources/software.html)
+
คุณสามารถดาวน์โหลด CMake จาก[http://www.cmake.org/cmake/resources/software.html หน้าดาวน์โหลดของเวบไซต์อย่างเป็นทางการ]
 
โดยเลือก installer ที่เหมาะสมกับแพลตฟอร์มที่คุณใช้
 
โดยเลือก installer ที่เหมาะสมกับแพลตฟอร์มที่คุณใช้
  
 
ผู้ใช้ Debian หรือ Ubuntu สามารถติดตั้ง CMake ผ่าน `apt-get` ได้ด้วยการสั่ง
 
ผู้ใช้ Debian หรือ Ubuntu สามารถติดตั้ง CMake ผ่าน `apt-get` ได้ด้วยการสั่ง
  
> sudo apt-get cmake
+
> sudo apt-get cmake
  
 
ส่วนผู้ใช้ Mac ที่ใช้ [MacPorts](http://www.macports.org/) สามารถติดตั้งได้โดยการสั่ง
 
ส่วนผู้ใช้ Mac ที่ใช้ [MacPorts](http://www.macports.org/) สามารถติดตั้งได้โดยการสั่ง
  
> sudo port install cmake
+
> sudo port install cmake
  
 
หลังจากติดตั้งแล้วเราสามารถทดสอบว่า CMake ถูกติดตั้งเรียบร้อยดีหรือไม่ด้วยการสั่ง
 
หลังจากติดตั้งแล้วเราสามารถทดสอบว่า CMake ถูกติดตั้งเรียบร้อยดีหรือไม่ด้วยการสั่ง
  
> cmake
+
> cmake
  
 
ใน command prompt ซึ่งหลังจากสั่งแล้วคุณควรจะพบว่า CMake พิมพ์วิธีการใช้มันอย่างคร่าวๆ
 
ใน command prompt ซึ่งหลังจากสั่งแล้วคุณควรจะพบว่า CMake พิมพ์วิธีการใช้มันอย่างคร่าวๆ
แถว 207: แถว 198:
 
และ CMake ยังรู้ด้วยว่าในแพลตฟอร์มต่างๆ กันมีเครื่องมือที่แตกต่างกัน
 
และ CMake ยังรู้ด้วยว่าในแพลตฟอร์มต่างๆ กันมีเครื่องมือที่แตกต่างกัน
  
Hello World ด้วย CMake
+
== Hello World ด้วย CMake ==
======================
 
  
 
ในส่วนนี้เราจะทำการสร้างโปรแกรมที่ง่ายที่สุดด้วย CMake ก่อนอื่นให้คุณสร้างไดเรคทอรีชื่อ `helloworld`
 
ในส่วนนี้เราจะทำการสร้างโปรแกรมที่ง่ายที่สุดด้วย CMake ก่อนอื่นให้คุณสร้างไดเรคทอรีชื่อ `helloworld`
แถว 219: แถว 209:
 
โดยที่ `main.cpp` มีเนื้อหาตามธรรมเนียมดังนี้
 
โดยที่ `main.cpp` มีเนื้อหาตามธรรมเนียมดังนี้
  
{% highlight c++ %}
+
<geshi lang="c">
#include <stdio.h>
+
#include <stdio.h>
  
int main()  
+
int main()  
{
+
{
  printf("hello, world\n");
+
  printf("hello, world\n");
  return 0;
+
  return 0;
}
+
}
{% endhighlight %}
+
</geshi>
  
 
ไฟล์ `CMakeLists.txt` เป็นพิมพ์เขียวของโปรเจค ซึ่งในกรณีนี้มันมีเนื้อหาดังต่อไปนี้
 
ไฟล์ `CMakeLists.txt` เป็นพิมพ์เขียวของโปรเจค ซึ่งในกรณีนี้มันมีเนื้อหาดังต่อไปนี้
แถว 256: แถว 246:
 
ที่เราเคยเห็นแล้วจากการสั่ง `cmake` เปล่าๆ ข้างบน
 
ที่เราเคยเห็นแล้วจากการสั่ง `cmake` เปล่าๆ ข้างบน
  
ผลลัพธ์
+
=== ผลลัพธ์ ===
-------
 
  
 
เนื่องจากเราไม่ได้กำหนดว่าจะให้ CMake ใช้ generator ตัวใด  
 
เนื่องจากเราไม่ได้กำหนดว่าจะให้ CMake ใช้ generator ตัวใด  
แถว 303: แถว 292:
 
เพื่อคอมไพล์ `main.cpp` ให้กลายเป็น `helloworld.exe` ได้
 
เพื่อคอมไพล์ `main.cpp` ให้กลายเป็น `helloworld.exe` ได้
  
เลือก Generator เอง
+
=== เลือก Generator เอง ===
-------------------
 
  
 
เราสามารถกำหนดให้ CMake ใช้ generator ตัวอื่นๆ ที่ไม่ใช้ตัวที่มันเลือกให้อัตโนมัติได้
 
เราสามารถกำหนดให้ CMake ใช้ generator ตัวอื่นๆ ที่ไม่ใช้ตัวที่มันเลือกให้อัตโนมัติได้
แถว 331: แถว 319:
 
แล้วจึงสั่ง `cmake -G "Xcode" .` ใหม่อีกรอบ หรือไม่ก็ไปสร้าง build script ในไดเรคทอรีใหม่เลย
 
แล้วจึงสั่ง `cmake -G "Xcode" .` ใหม่อีกรอบ หรือไม่ก็ไปสร้าง build script ในไดเรคทอรีใหม่เลย
  
In-Source Build และ Out-of-Source Build
+
== In-Source Build และ Out-of-Source Build ==
=======================================
 
  
 
สังเกตว่าในการ build โปรเจค `sample` ในส่วนที่แล้วนั้น ได้เรคทอรี `helloworld`
 
สังเกตว่าในการ build โปรเจค `sample` ในส่วนที่แล้วนั้น ได้เรคทอรี `helloworld`
แถว 354: แถว 341:
 
และการพิมพ์ค่ำสั่งเพิ่มอีกเล็กน้อยตอนเรียก CMake เท่านั้น
 
และการพิมพ์ค่ำสั่งเพิ่มอีกเล็กน้อยตอนเรียก CMake เท่านั้น
  
จัดระเบียบไฟล์ใหม่
+
=== จัดระเบียบไฟล์ใหม่ ===
------------------
 
  
 
เราอาจจัดระเบียบไฟล์เพื่อทำ out-of-source build โดยเอาซอร์สโค้ดทั้งหมดไปใส่ไว้ในไดเรคทอรีชื่อ  
 
เราอาจจัดระเบียบไฟล์เพื่อทำ out-of-source build โดยเอาซอร์สโค้ดทั้งหมดไปใส่ไว้ในไดเรคทอรีชื่อ  
แถว 367: แถว 353:
 
        main.cpp
 
        main.cpp
  
เรียก CMake จาก build directory
+
=== เรียก CMake จาก build directory ===
-------------------------------
 
  
 
หลังจากนั้น เวลาเราจะสร้าง build script ก็ให้เปลี่ยนไดเรคทอรีไปยัง `build`:
 
หลังจากนั้น เวลาเราจะสร้าง build script ก็ให้เปลี่ยนไดเรคทอรีไปยัง `build`:
แถว 387: แถว 372:
 
source directory อีกต่อไปเลย ทำให้เกิดความสะดวกขึ้นมาก
 
source directory อีกต่อไปเลย ทำให้เกิดความสะดวกขึ้นมาก
  
สร้าง build script สำหรับเครื่องมือหลายๆ เครื่องมือ
+
=== สร้าง build script สำหรับเครื่องมือหลายๆ เครื่องมือ ===
---------------------------------------------------
 
  
 
เราสามารถมี build directory ได้หลาย build directory ยกตัวอย่างเช่นหากเราต้องการใช้
 
เราสามารถมี build directory ได้หลาย build directory ยกตัวอย่างเช่นหากเราต้องการใช้
 
Xcode ควบคู่ไปกับ Makefile เราอาจสร้างไดเรคทอรี `helloworld/build_xcode` และ
 
Xcode ควบคู่ไปกับ Makefile เราอาจสร้างไดเรคทอรี `helloworld/build_xcode` และ
 
`helloworld/build_make` สำหรับเป็น build directory ของเครื่องมือทั้งสอง ตามลำดับ
 
`helloworld/build_make` สำหรับเป็น build directory ของเครื่องมือทั้งสอง ตามลำดับ

รุ่นแก้ไขเมื่อ 16:44, 8 พฤษภาคม 2553

CMake (http://www.cmake.org/ และ http://en.wikipedia.org/wiki/Cmake) เป็นซอฟต์แวร์สำหรับสร้าง build script (ไฟล์ที่นิยามวิธีการคอมไพล์และลิงก์โปรแกรมและไลบรารีที่เขียนด้วยภาษา C++) ที่สามารถใช้ร่วมกับเครื่องมือพัฒนาโปรแกรมที่ได้รับความนิยมหลายๆ ตัว อาทิ Microsoft Visual C++, GNU Compiler Collection, Xcode, และ Eclipse CDT เป็นต้น

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

ปัญหาของการเขียนโปรแกรมสำหรับหลายแพลตฟอร์ม

การเขียนโปรแกรมภาษา C++ ให้คอมไพล์และรันบนหลายๆ แพลตฟอร์ม (เขียนครั้งเดียวแต่รันได้ทั้งบน Windows, Unix, Mac, ฯลฯ) นั่นเป็นเรื่องที่ทำให้โปรแกรมเมอร์ปวดเศียรเวียนเกล้าอย่างหนักมาหลายคนแล้ว เหตุก็เพราะว่า แพลตฟอร์มต่างๆ กันนั้นมี "สภาพแวดล้อม" สำหรับพัฒนาโปรแกรมภาษา C++ ที่ไม่เหมือนกันเอาเสียเลย เราอาจสามารถสรุปปัญหาที่โปรแกรมเมอร์เจอไว้เป็นข้อๆ ได้ดังต่อไปนี้

  1. ไลบรารีภาษา C/C++ บนแพลตฟอร์มต่างๆ ไม่เหมือนกัน เช่น ใน Linux และ Mac จะมีไฟล์ `unistd.h` แต่ใน Windows

ไม่มี หรือใน Mac มีระบบไลบรารีที่เรียกว่า [bundle และ framework](http://osxbook.com/book/bonus/ancient/whatismacosx//programming.html) ซึ่งไม่ปรากฏอยู่ในแพลตฟอร์มอื่นๆ

  1. คอมไพเลอร์ที่ใช้เป็นคนละตัวกัน กล่าวคือ โปรแกรมเมอร์ C++ ใน Windows จะใช้ `cl` ของ Microsoft

ส่วนโปรแกรมเมอร์บน Linux และ Mac จะใช้ `gcc` หรือ `g++` ของ GNU Project นี่หมายความว่าภาษา C++ ใน Windows จะไม่เหมือนกับภาษา C++ ใน Unix และ Mac เป๊ะ และมีข้อแตกต่างยิบย่อยที่ทำให้ซอร์สโค้ดที่เขียนสำหรับแพลตฟอร์มหนึ่งไม่สามารถคอมไพล์บนอีกแพลตฟอร์มหนึ่งได้

  1. เครื่องมือที่ใช้ในการ build โปรแกรมไม่เหมือนกัน โปรแกรมเมอร์บน Windows จะใช้ Visual Studio

พวกที่ใช้ Linux ก็จะเขียน Makefile แล้วรัน `make` ส่วนขา Mac ก็จะใช้ Xcode

Preprocessor Macro

เราสามารถหลีกเลี่ยงสองปัญหาแรกบางส่วนได้ด้วยการเขียน preprocessor macro เพื่อให้คอมไพเลอร์เลือกใช้โค้ดส่วนที่ถูกต้อง ยกตัวอย่าง เช่น หากเราต้องการชื่อของไดเรคทอรีที่โปรแกรมทำงานอยู่ในปัจจุบัน (current working directory ย่อว่า cwd) แล้ว

  • ใน Linux และ Mac เราจะต้องใช้คำสั่ง `getcwd` ซึ่งอยู่ใน `unistd.h`
  • แต่ใน Windows เราจะต้องใช้คำสั่ง `_getcwd` ซึ่งอยู่ใน `direct.h`

เนื่องจาก `cl` จะนิยามมาโคร `_WIN32` ก่อนคอมไพล์ไฟล์ทุกไฟล์ ดังนั้นเราสามารถเช็คได้ว่า ตอนนี้โปรแกรมถูกคอมไพล์บน Windows หรือแพลตฟอร์มอื่นได้โดยการเช็คว่า `_WIN32` ถูกนิยามหรือไม่ ฉะนั้นเราสามารถเลือก include ไฟล์ที่ถูกต้องได้ดังนี้

<geshi lang="c">

  1. ifdef _WIN32
  2. include <direct.h>
  3. else
  4. include <unistd.h>
  5. endif

</geshi>

ส่วนเวลาเรียกใช้คำสั่ง เราสามารถเขียนโค้ดต่อไปนี้ได้

<geshi lang="c"> char *buffer;

  1. ifdef _WIN32

buffer = _getcwd(NULL, 0);

  1. else

buffer = getcwd(NULL, 0);

  1. endif

</geshi>

เครื่องมือและสภาพแวดล้อมที่แตกต่าง

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

ถึงแม้ว่าในปัจจุบัน make จะเป็นเครื่องมือมาตรฐานสำหรับการสร้างซอฟต์แวร์ภาษา C++ ในแพลตฟอร์มที่สืบเชื้อสายมาจาก Unix ทั้งหลาย นอกจากนี้ใน Windows มี nmake ให้ใช้ด้วย อย่างไรก็ดีการใช้ `make` ทำให้โปรแกรมเมอร์ต้องสละความสะดวกสบายของ IDE ที่ตนถนัด (เนื่องจากผู้เขียนใช้งาน Visual C++ จนติด การต้องไปเขียน Makefile เองจึงเป็นเรื่องที่ทรมานยิ่ง)

แต่ปัญหาที่ใหญ่ที่สุดเกิดขึ้นเมื่อซอฟต์แวร์ที่เราสร้างใช้ไลบรารีภายนอกที่เราไม่ได้เขียนเอง เนื่องจากแพลตฟอร์มต่างๆ มีที่เก็บไลบรารีที่แตกต่างกัน เช่น ใน Mac จะเก็บอยู่ในไดเรคทอรี `/Library` ส่วนใน Unix อาจเก็บอยู่ที่ `/usr` หรือ `/usr/local` ส่วนใน Windows นั้นไม่มีที่เก็บที่แน่นอน เป็นเรื่องของโปรแกรมเมอร์ที่จะต้องรู้ที่เก็บไลบรารีเอง

ในแพลตฟอร์ม Unix มีชุดของเครื่องมือที่เรียกว่า Autotools ซึ่งสามารถตรวจว่าระบบที่จะทำการคอมไพล์ไฟล์มีไลบรารีที่ต้องการให้ใช้หรือไม่ รวมทั้งสร้างไฟล์ชื่อ `config.h` ซึ่งมี preprocessor macro ซึ่งช่วยให้เรา include ไฟล์และเลือกใช้คำสั่งที่ถูกต้องได้ดังที่กล่าวไว้ข้างบน แต่การใช้ Autotools บังคับให้เราต้องใช้ `make` ไปโดยปริยาย

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

CMake

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

  1. เขียนไฟล์ชื่อ `CMakeLists.txt` เพื่อกำหนดโปรเจค
  1. รัน CMake เพื่อสร้าง build script ที่เฉพาะเจาะจงกับแพลตฟอร์มและเครื่องมือที่เราใชัพัฒนาโปรแกรม
  1. build โปรแกรมด้วยเครื่องมือดังกล่าว

สังเกตว่าหน้าที่ของ CMake คือการอ่านพิมพ์เขียวของโปรเจคจากไฟล์ `CMakeLists.txt` แล้วสร้าง build script แต่มันไม่ได้ทำการ build โปรแกรมด้วยตัวเองเหมือนกับเครื่องมือลักษณะคล้ายๆ กันตัวอื่น นี่เป็นสาเหตุที่ทำให้เราสามารถใช้เครื่องมืออะไรก็ได้ที่ CMake สนับสนุนในการพัฒนาโปรแกรมตามความถนัดของเรา

การติดตั้ง CMake

คุณสามารถดาวน์โหลด CMake จากหน้าดาวน์โหลดของเวบไซต์อย่างเป็นทางการ โดยเลือก installer ที่เหมาะสมกับแพลตฟอร์มที่คุณใช้

ผู้ใช้ Debian หรือ Ubuntu สามารถติดตั้ง CMake ผ่าน `apt-get` ได้ด้วยการสั่ง

> sudo apt-get cmake

ส่วนผู้ใช้ Mac ที่ใช้ [MacPorts](http://www.macports.org/) สามารถติดตั้งได้โดยการสั่ง

> sudo port install cmake

หลังจากติดตั้งแล้วเราสามารถทดสอบว่า CMake ถูกติดตั้งเรียบร้อยดีหรือไม่ด้วยการสั่ง

> cmake

ใน command prompt ซึ่งหลังจากสั่งแล้วคุณควรจะพบว่า CMake พิมพ์วิธีการใช้มันอย่างคร่าวๆ รวมทั้งออปชันต่างๆ ที่คุณสามารถกำหนดได้ออกมาทางหน้าจอ โดยตอนท้ายของข้อความที่ CMake พิมพ์ออกมาจะมีส่วนที่กล่าวถึง "Generators" ซึ่งบอกว่าขณะนี้ CMake สามารถสร้าง build script ที่ใช้กับเครื่องมือใดได้บ้าง

เมื่อผู้เขียนรันคำสั่ง `cmake` บนภายใต้ระบบปฏิบัติการ Mac OSX แล้วได้ผลลัพธ์ดังต่อไปนี้

cmake version 2.6-patch 4 Usage

cmake [options] <path-to-source> cmake [options] <path-to-existing-build>

Options <<< ข้อความแสดงออปชันต่างๆ ที่ผู้ใช้สามารถกำหนดได้ >>>

Generators

The following generators are available on this platform: Unix Makefiles = Generates standard UNIX makefiles. Xcode = Generate XCode project files. CodeBlocks - Unix Makefiles = Generates CodeBlocks project files. Eclipse CDT4 - Unix Makefiles = Generates Eclipse CDT 4.0 project files. KDevelop3 = Generates KDevelop 3 project files. KDevelop3 - Unix Makefiles = Generates KDevelop 3 project files.

แต่ถ้ารันมันภายใต้ Windows XP แล้วจะได้ผลลัพธ์ดังต่อไปนี้

cmake version 2.8.1 Usage

cmake [options] <path-to-source> cmake [options] <path-to-existing-build>

Options <<< ข้อความแสดงออปชันต่างๆ ที่ผู้ใช้สามารถกำหนดได้ >>>

Generators

The following generators are available on this platform: Borland Makefiles = Generates Borland makefiles. MSYS Makefiles = Generates MSYS makefiles. MinGW Makefiles = Generates a make file for use with mingw32-make. NMake Makefiles = Generates NMake makefiles. NMake Makefiles JOM = Generates JOM makefiles. Unix Makefiles = Generates standard UNIX makefiles. Visual Studio 10 = Generates Visual Studio 10 project files. Visual Studio 10 Win64 = Generates Visual Studio 10 Win64 project files. Visual Studio 6 = Generates Visual Studio 6 project files. Visual Studio 7 = Generates Visual Studio .NET 2002 project files. Visual Studio 7 .NET 2003 = Generates Visual Studio .NET 2003 project files. Visual Studio 8 2005 = Generates Visual Studio .NET 2005 project files. Visual Studio 8 2005 Win64 = Generates Visual Studio .NET 2005 Win64 project files. Visual Studio 9 2008 = Generates Visual Studio 9 2008 project files. Visual Studio 9 2008 Win64 = Generates Visual Studio 9 2008 Win64 project files. Watcom WMake = Generates Watcom WMake makefiles. CodeBlocks - MinGW Makefiles= Generates CodeBlocks project files. CodeBlocks - NMake Makefiles= Generates CodeBlocks project files. CodeBlocks - Unix Makefiles = Generates CodeBlocks project files. Eclipse CDT4 - MinGW Makefiles = Generates Eclipse CDT 4.0 project files. Eclipse CDT4 - NMake Makefiles = Generates Eclipse CDT 4.0 project files. Eclipse CDT4 - Unix Makefiles = Generates Eclipse CDT 4.0 project files.

ผลลัพธ์ทั้งสองแสดงให้เห็นว่าเราสามารถสร้าง build script สำหรับเครื่องมือที่แตกต่างกันได้หลายชนิด และ CMake ยังรู้ด้วยว่าในแพลตฟอร์มต่างๆ กันมีเครื่องมือที่แตกต่างกัน

Hello World ด้วย CMake

ในส่วนนี้เราจะทำการสร้างโปรแกรมที่ง่ายที่สุดด้วย CMake ก่อนอื่นให้คุณสร้างไดเรคทอรีชื่อ `helloworld` ซึ่งมีโครงสร้างดังต่อไปนี้

helloworld/ CMakeLists.txt main.cpp

โดยที่ `main.cpp` มีเนื้อหาตามธรรมเนียมดังนี้

<geshi lang="c">

  1. include <stdio.h>

int main() {

 printf("hello, world\n");
 return 0;

} </geshi>

ไฟล์ `CMakeLists.txt` เป็นพิมพ์เขียวของโปรเจค ซึ่งในกรณีนี้มันมีเนื้อหาดังต่อไปนี้

PROJECT(sample) CMAKE_MINIMUM_REQUIRED(VERSION 2.6)

ADD_EXECUTABLE(helloworld main.cpp)

บรรทัดแรกของไฟล์บอกว่าโปรเจคของเรามีชื่อว่า sample ส่วนบรรทัดที่สองเป็นการเช็คว่า CMake ที่เราใช้นั้นใหม่กว่าเวอร์ชัน 2.6 บรรทัดที่สามเป็นบรรทัดบอกว่าเราจะทำการสร้างไฟล์ executable เพียงไฟล์เดียวชื่อ `helloworld` ด้วยการคอมไพล์ `main.cpp`

ตอนนี้เราพร้อมที่จะสร้าง build script ด้วย CMake แล้ว อันดับแรกให้ทำการเปลี่ยนไดเรคทอรีไปยังไดเรคทอรี `helloworld` ที่เราเพิ่งจะสร้างขึ้น

> cd helloworld

แล้วจึงสั่ง

> cmake .

เพื่อบอกให้ CMake สร้าง build script โดยอ่าน `CMakeLists.txt` จากไดเรคทอรีปัจจุบัน การสั่งแบบนี้สอดคล้องกับการใช้ CMake โดยสั่ง

cmake [options] <path-to-source>

ที่เราเคยเห็นแล้วจากการสั่ง `cmake` เปล่าๆ ข้างบน

ผลลัพธ์

เนื่องจากเราไม่ได้กำหนดว่าจะให้ CMake ใช้ generator ตัวใด CMake จึงเลือกใช้ generator ตัวที่ถูกเลือกเป็นตัวเลือกอัตโนมัติสำหรับแพลตฟอร์มที่เรารันมัน

เวลาที่ผู้เขียนใช้ Mac ผู้เขียนพบว่า CMake จะสร้าง "Unix Makefiles" ดังนั้นหากเราดูไฟล์ในไดเรคทอรี helloworld หล้งรัน CMake จะมีไฟล์ดังต่อไปนี้

> ls CMakeCache.txt Makefile main.cpp CMakeFiles cmake_install.cmake CMakeLists.txt

โดยไฟล์ที่เป็นผลลัพธ์ที่สำคัญที่สุดคือ `Makefile` ซึ่งทำให้เราสามารถสั่ง

> make

แล้วจะได้ไฟล์ executable ชื่อ `helloworld` ตามที่เราต้องการ

ในทางกลับกัน ถ้าผู้เขียนใช้ Windows แล้ว CMake จะใช้ generator ชื่อ "Visual Studio 9 2008" เพื่อสร้างไฟล์โปรเจคสำหรับ Visual C++ 2008 เมื่อผู้เขียนสำรวจดูไดเรคทอรี `helloworld` ก็พบว่ามีไฟล์ดังต่อไปนี้

C:\***\helloworld>dir Volume in drive C is ******** Volume Serial Number is ****-****

Directory of C:\***\helloworld

05/08/2010 08:00 PM <DIR> . 05/08/2010 08:00 PM <DIR> .. 05/08/2010 08:00 PM 23,520 ALL_BUILD.vcproj 05/08/2010 08:00 PM 12,587 CMakeCache.txt 05/08/2010 08:00 PM <DIR> CMakeFiles 05/08/2010 07:57 PM 91 CMakeLists.txt 05/08/2010 08:00 PM 1,473 cmake_install.cmake 05/08/2010 08:00 PM 26,038 helloworld.vcproj 05/08/2010 07:56 PM 92 main.cpp 05/08/2010 08:00 PM 3,151 sample.sln 05/08/2010 08:00 PM 20,415 ZERO_CHECK.vcproj 8 File(s) 87,367 bytes 3 Dir(s) 5,633,990,656 bytes free

ซึ่งผู้เขียนสามารถใช้ Microsoft Visual Studio 2009 เปิดไฟล์ `sample.sln` เพื่อคอมไพล์ `main.cpp` ให้กลายเป็น `helloworld.exe` ได้

เลือก Generator เอง

เราสามารถกำหนดให้ CMake ใช้ generator ตัวอื่นๆ ที่ไม่ใช้ตัวที่มันเลือกให้อัตโนมัติได้ ด้วยการใช้ออปชัน `-G "ชื่อ generator"` ยกตัวอย่างเช่น หากเราต้องการใช้ Xcode ในการพัฒนาซอฟต์แวร์บนเครื่อง Mac แทนที่จะใช้ Unix Makefiles เราสามารถสั่ง

> cmake -G "Xcode" .

แทนการสั่ง `cmake .` ที่กล่าวไปในส่วนที่แล้ว ในกรณีของโปรเจค `sample` ข้างบน เราได้จะได้ไดเรคทอรีชื่อ `sample.xcodeproj` ซึ่งสามารถใช้ Xcode เปิดได้

คุณสามารถชื่อของ generator ที่ใช้ได้ในแต่ละแพลตฟอร์มได้จากส่วน "Generators" ของข้อความที่ CMake พิมพ์ออกมาเมื่อเราสั่ง `cmake` เฉยๆ ใน command prompt

อย่างไรก็ดี หากคุณใช้สั่ง `cmake .` สร้าง build script ลงในไดเรคทอรี `helloworld` เสร็จแล้วพยายามจะเปลี่ยน generator ที่ใช้ด้วยการสั่ง `cmake -G "Xcode" .` แล้ว CMake จะบ่นว่า

CMake Error: Error: generator : Xcode Does not match the generator used previously: Unix Makefiles Either remove the CMakeCache.txt file or choose a different binary directory

ปัญหานี้เกิดขึ้นจากข้อจำกัดของ CMake ที่ว่า ในไดเรคทอรีหนึ่งๆ มันสามารถสร้าง build script ของเครื่องมือได้เพียงเครื่องมือเดียวเท่านั้น หากเราต้องการเปลี่ยนเครื่องมือใหม่ เราจะต้องทำให้ CMake "ลืม" build script ของเครื่องมือเดิมด้วยการลบไฟล์ `CMakeCache.txt` แล้วจึงสั่ง `cmake -G "Xcode" .` ใหม่อีกรอบ หรือไม่ก็ไปสร้าง build script ในไดเรคทอรีใหม่เลย

In-Source Build และ Out-of-Source Build

สังเกตว่าในการ build โปรเจค `sample` ในส่วนที่แล้วนั้น ได้เรคทอรี `helloworld` บรรจุดทั้งซอร์สโค้ด (มีสองไฟล์คือ `main.cpp` และ `CMakeLists.txt`) และไฟล์อื่นๆ ที่ CMake สร้างขึ้นไว้ทั้งคู่ การทำเช่นนี้เรียกว่าการทำ *in-source build* และมันมีข้อเสียดังต่อไปนี้

1. ไดเรคทอรีที่เก็บซอร์สโค้ดสามารถเก็บ build script ของเครื่องมือได้เครื่องมือเดียวเท่านั้น จึงเกิดความไม่สะดวกอย่างยิ่งเวลาต้องการสร้าง build script สำหรับเครื่องมือหลายๆ เครื่องมือ

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

ในทางกลับกัน *out-of-source build* คือการแยกไดเรคทอรีที่เก็บซอร์สโค้ด (CMake เรียกไดเรคทอรีนี้ว่า *source directory*) และไดเรคทอรีที่เก็บ build script และข้อมูลอื่นๆ (CMake เรียกไดเรคทอรีนี้ว่า *binary directory*) ให้เป็นคนละไดเรคทอรีกัน การทำ out-of-source build ช่วยให้เราหลีกเลี่ยงปัญหาข้างต้นทั้งสองข้อได้โดยสิ้นเชิง โดยแลกมากับการจัดระเบียบวิธีการเก็บไฟล์ใหม่ และการพิมพ์ค่ำสั่งเพิ่มอีกเล็กน้อยตอนเรียก CMake เท่านั้น

จัดระเบียบไฟล์ใหม่

เราอาจจัดระเบียบไฟล์เพื่อทำ out-of-source build โดยเอาซอร์สโค้ดทั้งหมดไปใส่ไว้ในไดเรคทอรีชื่อ `src` ซึ่งทำหน้าที่เป็น source directory และสร้างไดเรคทอรีว่างชื่อ `build` เพื่อทำหน้าที่เป็น build directory ดังนั้นสำหรับโปรเจค `sample` เราอาจจัดระเบียบไฟล์ใหม่ดังต่อไปนี้

helloworld/ build/ src/ CMakeLists.txt main.cpp

เรียก CMake จาก build directory

หลังจากนั้น เวลาเราจะสร้าง build script ก็ให้เปลี่ยนไดเรคทอรีไปยัง `build`:

> cd helloworld/build

แล้วจึงสั่ง `cmake` แล้วให้ source directory เป็น argument:

> cmake ../src

เมื่อสั่งแล้วไฟล์ build script ทุกอย่างจะถูกบรรจุอยุ่ใน `build` และเมื่อเราเรียก `make` (สมมติว่าเราเขียนโปรแกรมอยู่บนเครื่อง Mac) แล้วเราจะได้ไฟล์ `helloworld` อยู่ในไดเรคทอรี `build` ด้วย

หลังจากที่เราสั่ง `cmake` โดยให้ source directory เป็น argument ไปเป็นครั้งแรกแล้ว หากเราเข้าไปใน build directory อีกครั้งแล้วสั่ง `cmake .` อีกครั้ง CMake จะ update ไฟล์ใน build directory ใหม่โดยใช้ generator ตัวเดิม ทำให้เราไม่ต้องพิมพ์ตำแหน่งของ source directory อีกต่อไปเลย ทำให้เกิดความสะดวกขึ้นมาก

สร้าง build script สำหรับเครื่องมือหลายๆ เครื่องมือ

เราสามารถมี build directory ได้หลาย build directory ยกตัวอย่างเช่นหากเราต้องการใช้ Xcode ควบคู่ไปกับ Makefile เราอาจสร้างไดเรคทอรี `helloworld/build_xcode` และ `helloworld/build_make` สำหรับเป็น build directory ของเครื่องมือทั้งสอง ตามลำดับ