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

จาก Theory Wiki
ไปยังการนำทาง ไปยังการค้นหา
แถว 16: แถว 16:
 
เราอาจสามารถสรุปปัญหาที่โปรแกรมเมอร์เจอไว้เป็นข้อๆ ได้ดังต่อไปนี้
 
เราอาจสามารถสรุปปัญหาที่โปรแกรมเมอร์เจอไว้เป็นข้อๆ ได้ดังต่อไปนี้
  
# ไลบรารีภาษา 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)  
 
ซึ่งไม่ปรากฏอยู่ในแพลตฟอร์มอื่นๆ
 
ซึ่งไม่ปรากฏอยู่ในแพลตฟอร์มอื่นๆ
  
# คอมไพเลอร์ที่ใช้เป็นคนละตัวกัน กล่าวคือ โปรแกรมเมอร์ 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 เป๊ะ  
 
และมีข้อแตกต่างยิบย่อยที่ทำให้ซอร์สโค้ดที่เขียนสำหรับแพลตฟอร์มหนึ่งไม่สามารถคอมไพล์บนอีกแพลตฟอร์มหนึ่งได้
 
และมีข้อแตกต่างยิบย่อยที่ทำให้ซอร์สโค้ดที่เขียนสำหรับแพลตฟอร์มหนึ่งไม่สามารถคอมไพล์บนอีกแพลตฟอร์มหนึ่งได้
  
 
# เครื่องมือที่ใช้ในการ build โปรแกรมไม่เหมือนกัน โปรแกรมเมอร์บน Windows จะใช้ Visual Studio
 
# เครื่องมือที่ใช้ในการ build โปรแกรมไม่เหมือนกัน โปรแกรมเมอร์บน Windows จะใช้ Visual Studio
พวกที่ใช้ Linux ก็จะเขียน Makefile แล้วรัน `make` ส่วนขา Mac ก็จะใช้ Xcode
+
พวกที่ใช้ Linux ก็จะเขียน Makefile แล้วรัน make ส่วนขา Mac ก็จะใช้ Xcode
  
 
=== Preprocessor Macro ===
 
=== Preprocessor Macro ===
แถว 34: แถว 34:
 
(current working directory ย่อว่า cwd) แล้ว
 
(current working directory ย่อว่า cwd) แล้ว
  
* ใน Linux และ Mac เราจะต้องใช้คำสั่ง `getcwd` ซึ่งอยู่ใน `unistd.h`
+
* ใน Linux และ Mac เราจะต้องใช้คำสั่ง getcwd ซึ่งอยู่ใน unistd.h
* แต่ใน Windows เราจะต้องใช้คำสั่ง `_getcwd` ซึ่งอยู่ใน `direct.h`
+
* แต่ใน Windows เราจะต้องใช้คำสั่ง _getcwd ซึ่งอยู่ใน direct.h
  
เนื่องจาก `cl` จะนิยามมาโคร `_WIN32` ก่อนคอมไพล์ไฟล์ทุกไฟล์ ดังนั้นเราสามารถเช็คได้ว่า
+
เนื่องจาก cl จะนิยามมาโคร _WIN32 ก่อนคอมไพล์ไฟล์ทุกไฟล์ ดังนั้นเราสามารถเช็คได้ว่า
ตอนนี้โปรแกรมถูกคอมไพล์บน Windows หรือแพลตฟอร์มอื่นได้โดยการเช็คว่า `_WIN32` ถูกนิยามหรือไม่
+
ตอนนี้โปรแกรมถูกคอมไพล์บน Windows หรือแพลตฟอร์มอื่นได้โดยการเช็คว่า _WIN32 ถูกนิยามหรือไม่
 
ฉะนั้นเราสามารถเลือก include ไฟล์ที่ถูกต้องได้ดังนี้
 
ฉะนั้นเราสามารถเลือก include ไฟล์ที่ถูกต้องได้ดังนี้
  
แถว 70: แถว 70:
 
จะเป็นเครื่องมือมาตรฐานสำหรับการสร้างซอฟต์แวร์ภาษา C++ ในแพลตฟอร์มที่สืบเชื้อสายมาจาก
 
จะเป็นเครื่องมือมาตรฐานสำหรับการสร้างซอฟต์แวร์ภาษา C++ ในแพลตฟอร์มที่สืบเชื้อสายมาจาก
 
Unix ทั้งหลาย นอกจากนี้ใน Windows มี [http://msdn.microsoft.com/en-us/library/ms930369.aspx nmake]
 
Unix ทั้งหลาย นอกจากนี้ใน Windows มี [http://msdn.microsoft.com/en-us/library/ms930369.aspx nmake]
ให้ใช้ด้วย อย่างไรก็ดีการใช้ `make` ทำให้โปรแกรมเมอร์ต้องสละความสะดวกสบายของ IDE
+
ให้ใช้ด้วย อย่างไรก็ดีการใช้ make ทำให้โปรแกรมเมอร์ต้องสละความสะดวกสบายของ IDE
 
ที่ตนถนัด (เนื่องจากผู้เขียนใช้งาน Visual C++ จนติด การต้องไปเขียน Makefile เองจึงเป็นเรื่องที่ทรมานยิ่ง)
 
ที่ตนถนัด (เนื่องจากผู้เขียนใช้งาน Visual C++ จนติด การต้องไปเขียน Makefile เองจึงเป็นเรื่องที่ทรมานยิ่ง)
  
 
แต่ปัญหาที่ใหญ่ที่สุดเกิดขึ้นเมื่อซอฟต์แวร์ที่เราสร้างใช้ไลบรารีภายนอกที่เราไม่ได้เขียนเอง
 
แต่ปัญหาที่ใหญ่ที่สุดเกิดขึ้นเมื่อซอฟต์แวร์ที่เราสร้างใช้ไลบรารีภายนอกที่เราไม่ได้เขียนเอง
 
เนื่องจากแพลตฟอร์มต่างๆ มีที่เก็บไลบรารีที่แตกต่างกัน เช่น ใน Mac จะเก็บอยู่ในไดเรคทอรี
 
เนื่องจากแพลตฟอร์มต่างๆ มีที่เก็บไลบรารีที่แตกต่างกัน เช่น ใน Mac จะเก็บอยู่ในไดเรคทอรี
`/Library` ส่วนใน Unix อาจเก็บอยู่ที่ `/usr` หรือ `/usr/local`
+
/Library ส่วนใน Unix อาจเก็บอยู่ที่ /usr หรือ /usr/local
 
ส่วนใน Windows นั้นไม่มีที่เก็บที่แน่นอน เป็นเรื่องของโปรแกรมเมอร์ที่จะต้องรู้ที่เก็บไลบรารีเอง
 
ส่วนใน Windows นั้นไม่มีที่เก็บที่แน่นอน เป็นเรื่องของโปรแกรมเมอร์ที่จะต้องรู้ที่เก็บไลบรารีเอง
  
 
ในแพลตฟอร์ม Unix มีชุดของเครื่องมือที่เรียกว่า [http://en.wikipedia.org/wiki/Autotools Autotools]
 
ในแพลตฟอร์ม Unix มีชุดของเครื่องมือที่เรียกว่า [http://en.wikipedia.org/wiki/Autotools Autotools]
 
ซึ่งสามารถตรวจว่าระบบที่จะทำการคอมไพล์ไฟล์มีไลบรารีที่ต้องการให้ใช้หรือไม่
 
ซึ่งสามารถตรวจว่าระบบที่จะทำการคอมไพล์ไฟล์มีไลบรารีที่ต้องการให้ใช้หรือไม่
รวมทั้งสร้างไฟล์ชื่อ `config.h` ซึ่งมี preprocessor macro  
+
รวมทั้งสร้างไฟล์ชื่อ config.h ซึ่งมี preprocessor macro  
 
ซึ่งช่วยให้เรา include ไฟล์และเลือกใช้คำสั่งที่ถูกต้องได้ดังที่กล่าวไว้ข้างบน
 
ซึ่งช่วยให้เรา include ไฟล์และเลือกใช้คำสั่งที่ถูกต้องได้ดังที่กล่าวไว้ข้างบน
แต่การใช้ Autotools บังคับให้เราต้องใช้ `make` ไปโดยปริยาย
+
แต่การใช้ Autotools บังคับให้เราต้องใช้ make ไปโดยปริยาย
  
 
ดังนั้นจึงการดีอย่างยิ่งหากเรามีเครื่องมือที่ช่วยให้เรากำหนดซอฟต์แวร์ที่เราต้องการสร้างเพียงครั้งเดียว
 
ดังนั้นจึงการดีอย่างยิ่งหากเรามีเครื่องมือที่ช่วยให้เรากำหนดซอฟต์แวร์ที่เราต้องการสร้างเพียงครั้งเดียว
แถว 94: แถว 94:
 
CMake แล้วกระบวนการคอมไพล์โปรแกรมสามารถแยกออกเป็นสามขั้นตอนดังต่อไปนี้
 
CMake แล้วกระบวนการคอมไพล์โปรแกรมสามารถแยกออกเป็นสามขั้นตอนดังต่อไปนี้
  
# เขียนไฟล์ชื่อ `CMakeLists.txt` เพื่อกำหนดโปรเจค
+
# เขียนไฟล์ชื่อ CMakeLists.txt เพื่อกำหนดโปรเจค
  
 
# รัน CMake เพื่อสร้าง build script ที่เฉพาะเจาะจงกับแพลตฟอร์มและเครื่องมือที่เราใชัพัฒนาโปรแกรม
 
# รัน CMake เพื่อสร้าง build script ที่เฉพาะเจาะจงกับแพลตฟอร์มและเครื่องมือที่เราใชัพัฒนาโปรแกรม
แถว 100: แถว 100:
 
# build โปรแกรมด้วยเครื่องมือดังกล่าว
 
# build โปรแกรมด้วยเครื่องมือดังกล่าว
  
สังเกตว่าหน้าที่ของ CMake คือการอ่านพิมพ์เขียวของโปรเจคจากไฟล์ `CMakeLists.txt`
+
สังเกตว่าหน้าที่ของ CMake คือการอ่านพิมพ์เขียวของโปรเจคจากไฟล์ CMakeLists.txt
 
แล้วสร้าง build script แต่มันไม่ได้ทำการ build โปรแกรมด้วยตัวเองเหมือนกับเครื่องมือลักษณะคล้ายๆ กันตัวอื่น
 
แล้วสร้าง build script แต่มันไม่ได้ทำการ build โปรแกรมด้วยตัวเองเหมือนกับเครื่องมือลักษณะคล้ายๆ กันตัวอื่น
 
นี่เป็นสาเหตุที่ทำให้เราสามารถใช้เครื่องมืออะไรก็ได้ที่ CMake สนับสนุนในการพัฒนาโปรแกรมตามความถนัดของเรา
 
นี่เป็นสาเหตุที่ทำให้เราสามารถใช้เครื่องมืออะไรก็ได้ที่ CMake สนับสนุนในการพัฒนาโปรแกรมตามความถนัดของเรา
แถว 109: แถว 109:
 
โดยเลือก installer ที่เหมาะสมกับแพลตฟอร์มที่คุณใช้
 
โดยเลือก installer ที่เหมาะสมกับแพลตฟอร์มที่คุณใช้
  
ผู้ใช้ Debian หรือ Ubuntu สามารถติดตั้ง CMake ผ่าน `apt-get` ได้ด้วยการสั่ง
+
ผู้ใช้ Debian หรือ Ubuntu สามารถติดตั้ง CMake ผ่าน apt-get ได้ด้วยการสั่ง
  
 
  > sudo apt-get cmake
 
  > sudo apt-get cmake
แถว 126: แถว 126:
 
ซึ่งบอกว่าขณะนี้ CMake สามารถสร้าง build script ที่ใช้กับเครื่องมือใดได้บ้าง
 
ซึ่งบอกว่าขณะนี้ CMake สามารถสร้าง build script ที่ใช้กับเครื่องมือใดได้บ้าง
  
เมื่อผู้เขียนรันคำสั่ง `cmake` บนภายใต้ระบบปฏิบัติการ Mac OSX แล้วได้ผลลัพธ์ดังต่อไปนี้
+
เมื่อผู้เขียนรันคำสั่ง cmake บนภายใต้ระบบปฏิบัติการ Mac OSX แล้วได้ผลลัพธ์ดังต่อไปนี้
  
cmake version 2.6-patch 4
+
  cmake version 2.6-patch 4
Usage
+
  Usage
  
  cmake [options] <path-to-source>
+
    cmake [options] <path-to-source>
  cmake [options] <path-to-existing-build>
+
    cmake [options] <path-to-existing-build>
  
Options
+
  Options
  <<< ข้อความแสดงออปชันต่างๆ ที่ผู้ใช้สามารถกำหนดได้ >>>
+
    <<< ข้อความแสดงออปชันต่างๆ ที่ผู้ใช้สามารถกำหนดได้ >>>
  
Generators
+
  Generators
  
The following generators are available on this platform:
+
  The following generators are available on this platform:
  Unix Makefiles              = Generates standard UNIX makefiles.
+
    Unix Makefiles              = Generates standard UNIX makefiles.
  Xcode                      = Generate XCode project files.
+
    Xcode                      = Generate XCode project files.
  CodeBlocks - Unix Makefiles = Generates CodeBlocks project files.
+
    CodeBlocks - Unix Makefiles = Generates CodeBlocks project files.
  Eclipse CDT4 - Unix Makefiles
+
    Eclipse CDT4 - Unix Makefiles
                              = Generates Eclipse CDT 4.0 project files.
+
                                = Generates Eclipse CDT 4.0 project files.
  KDevelop3                  = Generates KDevelop 3 project files.
+
    KDevelop3                  = Generates KDevelop 3 project files.
  KDevelop3 - Unix Makefiles  = Generates KDevelop 3 project files.
+
    KDevelop3 - Unix Makefiles  = Generates KDevelop 3 project files.
  
 
แต่ถ้ารันมันภายใต้ Windows XP แล้วจะได้ผลลัพธ์ดังต่อไปนี้
 
แต่ถ้ารันมันภายใต้ Windows XP แล้วจะได้ผลลัพธ์ดังต่อไปนี้
  
cmake version 2.8.1
+
  cmake version 2.8.1
Usage
+
  Usage
  
  cmake [options] <path-to-source>
+
    cmake [options] <path-to-source>
  cmake [options] <path-to-existing-build>
+
    cmake [options] <path-to-existing-build>
  
Options
+
  Options
  <<< ข้อความแสดงออปชันต่างๆ ที่ผู้ใช้สามารถกำหนดได้ >>>
+
    <<< ข้อความแสดงออปชันต่างๆ ที่ผู้ใช้สามารถกำหนดได้ >>>
  
Generators
+
  Generators
  
The following generators are available on this platform:
+
  The following generators are available on this platform:
  Borland Makefiles          = Generates Borland makefiles.
+
    Borland Makefiles          = Generates Borland makefiles.
  MSYS Makefiles              = Generates MSYS makefiles.
+
    MSYS Makefiles              = Generates MSYS makefiles.
  MinGW Makefiles            = Generates a make file for use with
+
    MinGW Makefiles            = Generates a make file for use with
                                mingw32-make.
+
                                  mingw32-make.
  NMake Makefiles            = Generates NMake makefiles.
+
    NMake Makefiles            = Generates NMake makefiles.
  NMake Makefiles JOM        = Generates JOM makefiles.
+
    NMake Makefiles JOM        = Generates JOM makefiles.
  Unix Makefiles              = Generates standard UNIX makefiles.
+
    Unix Makefiles              = Generates standard UNIX makefiles.
  Visual Studio 10            = Generates Visual Studio 10 project files.
+
    Visual Studio 10            = Generates Visual Studio 10 project files.
  Visual Studio 10 Win64      = Generates Visual Studio 10 Win64 project
+
    Visual Studio 10 Win64      = Generates Visual Studio 10 Win64 project
                                files.
+
                                  files.
  Visual Studio 6            = Generates Visual Studio 6 project files.
+
    Visual Studio 6            = Generates Visual Studio 6 project files.
  Visual Studio 7            = Generates Visual Studio .NET 2002 project
+
    Visual Studio 7            = Generates Visual Studio .NET 2002 project
                                files.
+
                                  files.
  Visual Studio 7 .NET 2003  = Generates Visual Studio .NET 2003 project
+
    Visual Studio 7 .NET 2003  = Generates Visual Studio .NET 2003 project
                                files.
+
                                  files.
  Visual Studio 8 2005        = Generates Visual Studio .NET 2005 project
+
    Visual Studio 8 2005        = Generates Visual Studio .NET 2005 project
                                files.
+
                                  files.
  Visual Studio 8 2005 Win64  = Generates Visual Studio .NET 2005 Win64
+
    Visual Studio 8 2005 Win64  = Generates Visual Studio .NET 2005 Win64
                                project files.
+
                                  project files.
  Visual Studio 9 2008        = Generates Visual Studio 9 2008 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
+
    Visual Studio 9 2008 Win64  = Generates Visual Studio 9 2008 Win64 project
                                files.
+
                                  files.
  Watcom WMake                = Generates Watcom WMake makefiles.
+
    Watcom WMake                = Generates Watcom WMake makefiles.
  CodeBlocks - MinGW Makefiles= Generates CodeBlocks project files.
+
    CodeBlocks - MinGW Makefiles= Generates CodeBlocks project files.
  CodeBlocks - NMake Makefiles= Generates CodeBlocks project files.
+
    CodeBlocks - NMake Makefiles= Generates CodeBlocks project files.
  CodeBlocks - Unix Makefiles = Generates CodeBlocks project files.
+
    CodeBlocks - Unix Makefiles = Generates CodeBlocks project files.
  Eclipse CDT4 - MinGW Makefiles
+
    Eclipse CDT4 - MinGW Makefiles
                              = Generates Eclipse CDT 4.0 project files.
+
                                = Generates Eclipse CDT 4.0 project files.
  Eclipse CDT4 - NMake Makefiles
+
    Eclipse CDT4 - NMake Makefiles
                              = Generates Eclipse CDT 4.0 project files.
+
                                = Generates Eclipse CDT 4.0 project files.
  Eclipse CDT4 - Unix Makefiles
+
    Eclipse CDT4 - Unix Makefiles
                              = Generates Eclipse CDT 4.0 project files.
+
                                = Generates Eclipse CDT 4.0 project files.
  
 
ผลลัพธ์ทั้งสองแสดงให้เห็นว่าเราสามารถสร้าง build script สำหรับเครื่องมือที่แตกต่างกันได้หลายชนิด
 
ผลลัพธ์ทั้งสองแสดงให้เห็นว่าเราสามารถสร้าง build script สำหรับเครื่องมือที่แตกต่างกันได้หลายชนิด
แถว 200: แถว 200:
 
== Hello World ด้วย CMake ==
 
== Hello World ด้วย CMake ==
  
ในส่วนนี้เราจะทำการสร้างโปรแกรมที่ง่ายที่สุดด้วย CMake ก่อนอื่นให้คุณสร้างไดเรคทอรีชื่อ `helloworld`
+
ในส่วนนี้เราจะทำการสร้างโปรแกรมที่ง่ายที่สุดด้วย CMake ก่อนอื่นให้คุณสร้างไดเรคทอรีชื่อ helloworld
 
ซึ่งมีโครงสร้างดังต่อไปนี้
 
ซึ่งมีโครงสร้างดังต่อไปนี้
  
helloworld/
+
  helloworld/
    CMakeLists.txt
+
      CMakeLists.txt
    main.cpp
+
      main.cpp
  
โดยที่ `main.cpp` มีเนื้อหาตามธรรมเนียมดังนี้
+
โดยที่ main.cpp มีเนื้อหาตามธรรมเนียมดังนี้
  
 
<geshi lang="c">
 
<geshi lang="c">
แถว 219: แถว 219:
 
</geshi>
 
</geshi>
  
ไฟล์ `CMakeLists.txt` เป็นพิมพ์เขียวของโปรเจค ซึ่งในกรณีนี้มันมีเนื้อหาดังต่อไปนี้
+
ไฟล์ CMakeLists.txt เป็นพิมพ์เขียวของโปรเจค ซึ่งในกรณีนี้มันมีเนื้อหาดังต่อไปนี้
  
PROJECT(sample)
+
  PROJECT(sample)
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
  CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
 
ADD_EXECUTABLE(helloworld main.cpp)
+
  ADD_EXECUTABLE(helloworld main.cpp)
  
 
บรรทัดแรกของไฟล์บอกว่าโปรเจคของเรามีชื่อว่า sample ส่วนบรรทัดที่สองเป็นการเช็คว่า CMake  
 
บรรทัดแรกของไฟล์บอกว่าโปรเจคของเรามีชื่อว่า sample ส่วนบรรทัดที่สองเป็นการเช็คว่า CMake  
 
ที่เราใช้นั้นใหม่กว่าเวอร์ชัน 2.6 บรรทัดที่สามเป็นบรรทัดบอกว่าเราจะทำการสร้างไฟล์ executable
 
ที่เราใช้นั้นใหม่กว่าเวอร์ชัน 2.6 บรรทัดที่สามเป็นบรรทัดบอกว่าเราจะทำการสร้างไฟล์ executable
เพียงไฟล์เดียวชื่อ `helloworld` ด้วยการคอมไพล์ `main.cpp`
+
เพียงไฟล์เดียวชื่อ helloworld ด้วยการคอมไพล์ main.cpp
  
 
ตอนนี้เราพร้อมที่จะสร้าง build script ด้วย CMake แล้ว  
 
ตอนนี้เราพร้อมที่จะสร้าง build script ด้วย CMake แล้ว  
อันดับแรกให้ทำการเปลี่ยนไดเรคทอรีไปยังไดเรคทอรี `helloworld` ที่เราเพิ่งจะสร้างขึ้น
+
อันดับแรกให้ทำการเปลี่ยนไดเรคทอรีไปยังไดเรคทอรี helloworld ที่เราเพิ่งจะสร้างขึ้น
  
> cd helloworld
+
  > cd helloworld
  
 
แล้วจึงสั่ง
 
แล้วจึงสั่ง
  
> cmake .
+
  > cmake .
  
เพื่อบอกให้ CMake สร้าง build script โดยอ่าน `CMakeLists.txt` จากไดเรคทอรีปัจจุบัน
+
เพื่อบอกให้ CMake สร้าง build script โดยอ่าน CMakeLists.txt จากไดเรคทอรีปัจจุบัน
 
การสั่งแบบนี้สอดคล้องกับการใช้ CMake โดยสั่ง
 
การสั่งแบบนี้สอดคล้องกับการใช้ CMake โดยสั่ง
  
cmake [options] <path-to-source>
+
  cmake [options] <path-to-source>
  
ที่เราเคยเห็นแล้วจากการสั่ง `cmake` เปล่าๆ ข้างบน
+
ที่เราเคยเห็นแล้วจากการสั่ง cmake เปล่าๆ ข้างบน
  
 
=== ผลลัพธ์ ===
 
=== ผลลัพธ์ ===
แถว 254: แถว 254:
 
ดังนั้นหากเราดูไฟล์ในไดเรคทอรี helloworld หล้งรัน CMake จะมีไฟล์ดังต่อไปนี้
 
ดังนั้นหากเราดูไฟล์ในไดเรคทอรี helloworld หล้งรัน CMake จะมีไฟล์ดังต่อไปนี้
  
> ls
+
  > ls
CMakeCache.txt    Makefile                main.cpp
+
  CMakeCache.txt    Makefile                main.cpp
CMakeFiles        cmake_install.cmake
+
  CMakeFiles        cmake_install.cmake
CMakeLists.txt
+
  CMakeLists.txt
  
โดยไฟล์ที่เป็นผลลัพธ์ที่สำคัญที่สุดคือ `Makefile` ซึ่งทำให้เราสามารถสั่ง
+
โดยไฟล์ที่เป็นผลลัพธ์ที่สำคัญที่สุดคือ Makefile ซึ่งทำให้เราสามารถสั่ง
  
> make
+
  > make
  
แล้วจะได้ไฟล์ executable ชื่อ `helloworld` ตามที่เราต้องการ
+
แล้วจะได้ไฟล์ executable ชื่อ helloworld ตามที่เราต้องการ
  
 
ในทางกลับกัน ถ้าผู้เขียนใช้ Windows แล้ว CMake จะใช้ generator ชื่อ "Visual Studio 9 2008"
 
ในทางกลับกัน ถ้าผู้เขียนใช้ Windows แล้ว CMake จะใช้ generator ชื่อ "Visual Studio 9 2008"
เพื่อสร้างไฟล์โปรเจคสำหรับ Visual C++ 2008 เมื่อผู้เขียนสำรวจดูไดเรคทอรี `helloworld`
+
เพื่อสร้างไฟล์โปรเจคสำหรับ Visual C++ 2008 เมื่อผู้เขียนสำรวจดูไดเรคทอรี helloworld
 
ก็พบว่ามีไฟล์ดังต่อไปนี้
 
ก็พบว่ามีไฟล์ดังต่อไปนี้
  
C:\***\helloworld>dir
+
  C:\***\helloworld>dir
Volume in drive C is ********
+
  Volume in drive C is ********
Volume Serial Number is ****-****
+
  Volume Serial Number is ****-****
  
Directory of C:\***\helloworld
+
  Directory of C:\***\helloworld
  
05/08/2010  08:00 PM    <DIR>          .
+
  05/08/2010  08:00 PM    <DIR>          .
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            23,520 ALL_BUILD.vcproj
05/08/2010  08:00 PM            12,587 CMakeCache.txt
+
  05/08/2010  08:00 PM            12,587 CMakeCache.txt
05/08/2010  08:00 PM    <DIR>          CMakeFiles
+
  05/08/2010  08:00 PM    <DIR>          CMakeFiles
05/08/2010  07:57 PM                91 CMakeLists.txt
+
  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            1,473 cmake_install.cmake
05/08/2010  08:00 PM            26,038 helloworld.vcproj
+
  05/08/2010  08:00 PM            26,038 helloworld.vcproj
05/08/2010  07:56 PM                92 main.cpp
+
  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            3,151 sample.sln
05/08/2010  08:00 PM            20,415 ZERO_CHECK.vcproj
+
  05/08/2010  08:00 PM            20,415 ZERO_CHECK.vcproj
              8 File(s)        87,367 bytes
+
                8 File(s)        87,367 bytes
              3 Dir(s)  5,633,990,656 bytes free
+
                3 Dir(s)  5,633,990,656 bytes free
  
ซึ่งผู้เขียนสามารถใช้ Microsoft Visual Studio 2009 เปิดไฟล์ `sample.sln`
+
ซึ่งผู้เขียนสามารถใช้ Microsoft Visual Studio 2009 เปิดไฟล์ sample.sln
เพื่อคอมไพล์ `main.cpp` ให้กลายเป็น `helloworld.exe` ได้
+
เพื่อคอมไพล์ main.cpp ให้กลายเป็น helloworld.exe ได้
  
 
=== เลือก Generator เอง ===
 
=== เลือก Generator เอง ===
  
 
เราสามารถกำหนดให้ CMake ใช้ generator ตัวอื่นๆ ที่ไม่ใช้ตัวที่มันเลือกให้อัตโนมัติได้
 
เราสามารถกำหนดให้ CMake ใช้ generator ตัวอื่นๆ ที่ไม่ใช้ตัวที่มันเลือกให้อัตโนมัติได้
ด้วยการใช้ออปชัน `-G "ชื่อ generator"` ยกตัวอย่างเช่น หากเราต้องการใช้ Xcode
+
ด้วยการใช้ออปชัน -G "ชื่อ generator" ยกตัวอย่างเช่น หากเราต้องการใช้ Xcode
 
ในการพัฒนาซอฟต์แวร์บนเครื่อง Mac แทนที่จะใช้ Unix Makefiles เราสามารถสั่ง
 
ในการพัฒนาซอฟต์แวร์บนเครื่อง Mac แทนที่จะใช้ Unix Makefiles เราสามารถสั่ง
  
> cmake -G "Xcode" .
+
  > cmake -G "Xcode" .
  
แทนการสั่ง `cmake .` ที่กล่าวไปในส่วนที่แล้ว ในกรณีของโปรเจค `sample` ข้างบน  
+
แทนการสั่ง cmake . ที่กล่าวไปในส่วนที่แล้ว ในกรณีของโปรเจค sample ข้างบน  
เราได้จะได้ไดเรคทอรีชื่อ `sample.xcodeproj` ซึ่งสามารถใช้ Xcode เปิดได้
+
เราได้จะได้ไดเรคทอรีชื่อ sample.xcodeproj ซึ่งสามารถใช้ Xcode เปิดได้
  
 
คุณสามารถชื่อของ generator ที่ใช้ได้ในแต่ละแพลตฟอร์มได้จากส่วน "Generators"
 
คุณสามารถชื่อของ generator ที่ใช้ได้ในแต่ละแพลตฟอร์มได้จากส่วน "Generators"
ของข้อความที่ CMake พิมพ์ออกมาเมื่อเราสั่ง `cmake` เฉยๆ ใน command prompt
+
ของข้อความที่ CMake พิมพ์ออกมาเมื่อเราสั่ง cmake เฉยๆ ใน command prompt
  
อย่างไรก็ดี หากคุณใช้สั่ง `cmake .` สร้าง build script ลงในไดเรคทอรี `helloworld`
+
อย่างไรก็ดี หากคุณใช้สั่ง cmake . สร้าง build script ลงในไดเรคทอรี helloworld
เสร็จแล้วพยายามจะเปลี่ยน generator ที่ใช้ด้วยการสั่ง `cmake -G "Xcode" .` แล้ว
+
เสร็จแล้วพยายามจะเปลี่ยน generator ที่ใช้ด้วยการสั่ง cmake -G "Xcode" . แล้ว
 
CMake จะบ่นว่า
 
CMake จะบ่นว่า
  
CMake Error: Error: generator : Xcode
+
  CMake Error: Error: generator : Xcode
Does not match the generator used previously: Unix Makefiles
+
  Does not match the generator used previously: Unix Makefiles
Either remove the CMakeCache.txt file or choose a different binary directory
+
  Either remove the CMakeCache.txt file or choose a different binary directory
  
 
ปัญหานี้เกิดขึ้นจากข้อจำกัดของ CMake ที่ว่า ในไดเรคทอรีหนึ่งๆ มันสามารถสร้าง  
 
ปัญหานี้เกิดขึ้นจากข้อจำกัดของ CMake ที่ว่า ในไดเรคทอรีหนึ่งๆ มันสามารถสร้าง  
 
build script ของเครื่องมือได้เพียงเครื่องมือเดียวเท่านั้น หากเราต้องการเปลี่ยนเครื่องมือใหม่
 
build script ของเครื่องมือได้เพียงเครื่องมือเดียวเท่านั้น หากเราต้องการเปลี่ยนเครื่องมือใหม่
เราจะต้องทำให้ CMake "ลืม" build script ของเครื่องมือเดิมด้วยการลบไฟล์ `CMakeCache.txt`
+
เราจะต้องทำให้ CMake "ลืม" build script ของเครื่องมือเดิมด้วยการลบไฟล์ CMakeCache.txt
แล้วจึงสั่ง `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
บรรจุดทั้งซอร์สโค้ด (มีสองไฟล์คือ `main.cpp` และ `CMakeLists.txt`) และไฟล์อื่นๆ
+
บรรจุดทั้งซอร์สโค้ด (มีสองไฟล์คือ main.cpp และ CMakeLists.txt) และไฟล์อื่นๆ
 
ที่ CMake สร้างขึ้นไว้ทั้งคู่ การทำเช่นนี้เรียกว่าการทำ *in-source build*
 
ที่ CMake สร้างขึ้นไว้ทั้งคู่ การทำเช่นนี้เรียกว่าการทำ *in-source build*
 
และมันมีข้อเสียดังต่อไปนี้
 
และมันมีข้อเสียดังต่อไปนี้
แถว 344: แถว 344:
  
 
เราอาจจัดระเบียบไฟล์เพื่อทำ out-of-source build โดยเอาซอร์สโค้ดทั้งหมดไปใส่ไว้ในไดเรคทอรีชื่อ  
 
เราอาจจัดระเบียบไฟล์เพื่อทำ out-of-source build โดยเอาซอร์สโค้ดทั้งหมดไปใส่ไว้ในไดเรคทอรีชื่อ  
`src` ซึ่งทำหน้าที่เป็น source directory และสร้างไดเรคทอรีว่างชื่อ `build` เพื่อทำหน้าที่เป็น
+
src ซึ่งทำหน้าที่เป็น source directory และสร้างไดเรคทอรีว่างชื่อ build เพื่อทำหน้าที่เป็น
build directory ดังนั้นสำหรับโปรเจค `sample` เราอาจจัดระเบียบไฟล์ใหม่ดังต่อไปนี้
+
build directory ดังนั้นสำหรับโปรเจค sample เราอาจจัดระเบียบไฟล์ใหม่ดังต่อไปนี้
  
helloworld/
+
  helloworld/
    build/
+
      build/
    src/
+
      src/
        CMakeLists.txt
+
          CMakeLists.txt
        main.cpp
+
          main.cpp
  
 
=== เรียก CMake จาก build directory ===
 
=== เรียก CMake จาก build directory ===
  
หลังจากนั้น เวลาเราจะสร้าง build script ก็ให้เปลี่ยนไดเรคทอรีไปยัง `build`:
+
หลังจากนั้น เวลาเราจะสร้าง build script ก็ให้เปลี่ยนไดเรคทอรีไปยัง build:
  
> cd helloworld/build
+
  > cd helloworld/build
  
แล้วจึงสั่ง `cmake` แล้วให้ source directory เป็น argument:
+
แล้วจึงสั่ง cmake แล้วให้ source directory เป็น argument:
  
> cmake ../src
+
  > cmake ../src
  
เมื่อสั่งแล้วไฟล์ build script ทุกอย่างจะถูกบรรจุอยุ่ใน `build` และเมื่อเราเรียก
+
เมื่อสั่งแล้วไฟล์ build script ทุกอย่างจะถูกบรรจุอยุ่ใน build และเมื่อเราเรียก
`make` (สมมติว่าเราเขียนโปรแกรมอยู่บนเครื่อง Mac) แล้วเราจะได้ไฟล์ `helloworld`
+
make (สมมติว่าเราเขียนโปรแกรมอยู่บนเครื่อง Mac) แล้วเราจะได้ไฟล์ helloworld
อยู่ในไดเรคทอรี `build` ด้วย
+
อยู่ในไดเรคทอรี build ด้วย
  
หลังจากที่เราสั่ง `cmake` โดยให้ source directory เป็น argument ไปเป็นครั้งแรกแล้ว
+
หลังจากที่เราสั่ง cmake โดยให้ source directory เป็น argument ไปเป็นครั้งแรกแล้ว
หากเราเข้าไปใน build directory อีกครั้งแล้วสั่ง `cmake .` อีกครั้ง CMake จะ update
+
หากเราเข้าไปใน build directory อีกครั้งแล้วสั่ง cmake . อีกครั้ง CMake จะ update
 
ไฟล์ใน build directory ใหม่โดยใช้ generator ตัวเดิม ทำให้เราไม่ต้องพิมพ์ตำแหน่งของ
 
ไฟล์ใน build directory ใหม่โดยใช้ generator ตัวเดิม ทำให้เราไม่ต้องพิมพ์ตำแหน่งของ
 
source directory อีกต่อไปเลย ทำให้เกิดความสะดวกขึ้นมาก
 
source directory อีกต่อไปเลย ทำให้เกิดความสะดวกขึ้นมาก
แถว 375: แถว 375:
  
 
เราสามารถมี 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:50, 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 ของเครื่องมือทั้งสอง ตามลำดับ