ติดตั้งและใช้งาน SFML ด้วย CLion บน Ubuntu

ติดตั้งและใช้งาน SFML ด้วย CLion บน Ubuntu Cover Image

Cover Image : www.jetbrains.com/clion

บทความนี้เป็นบทความที่ผมทำเป็น Note ไว้เมื่อหลายอาทิตย์ก่อน ตอนที่ลองใช้งาน SFML บน Ubuntu แล้วพบปัญหา นั่งแก้ปัญหาอยู่เกือบวัน กว่าจะสามารถแก้ปัญหาเล็กๆน้อยๆได้ เลยทำการจดไว้ ก่อนอื่น ตอนที่ทดลองใช้ SFML ก็เคยเขียน C/C++ มาบ้าง แต่เป็นการเขียนบนสภาพแวดล้อมของ Windows ทั้งหมด ใช้ Visual Studio ส่วน SFML เพิ่งเคยได้จับครั้งแรก ปัญหาที่เกิดวันนี้คือตัว CLion - New C/C++ IDE from JetBrains มองไม่เห็นไฟล์ Library ที่ include เข้าไปในโปรเจ็ค รู้สึกว่าจะต้องใช้ CMake ช่วย ซึ่งผมก็เพิ่งได้รู้จักนี้แหละ เผื่อใครมีปัญหาลักษณะเดียวกัน ก็ลองอ่านดูนะครับ :D

SFML นั้นชื่อเต็มๆคือ Simple and Fast Multimedia Library เป็น Game Engine/Library ตัวหนึ่งที่เขียนด้วย C++ เป็น Multi-Platform สามารถที่จะรันและ compile ได้ทั้ง Windows, Mac OS X, Linux หรือแม้แต่บนมือถือ (iOS และ Android)

ลิงค์ด้านล่างนี้คือแหล่งอ้างอิงของผม

Install SFML on Ubuntu

หากได้อ่านจาก official tutorial จะพบว่า มี 3 วิธีในการติดตั้ง SFML บน Linux ซึ่งผมเลือกใช้วิธีติดตั้งผ่าน Ubuntu Distro ง่ายๆครับ แค่เปิด Terminal แล้วใช้คำสั่งนี้ :

sudo apt-get install libsfml-dev

เมื่อทำการติดตั้งเสร็จ ก็ลองเช็คว่าทุกอย่างติดตั้งสมบูรณ์ครบถ้วนรวมถึงที่อยู่ของ SFML ด้วย ว่าอยู่ที่ไหน ด้วยคำสั่ง :

dpkg -L libsfml-dev

ผลลัพธ์จะแสดงที่อยู่ของ SFML ดังนี้ แสดงว่าติดตั้งเสร็จละ ง่ายๆเลย :)

/.
/usr
/usr/include
/usr/include/SFML
/usr/include/SFML/System.hpp
/usr/include/SFML/OpenGL.hpp
/usr/include/SFML/Window
/usr/include/SFML/Window/Context.hpp
/usr/include/SFML/Window/Event.hpp
/usr/include/SFML/Window/ContextSettings.hpp
/usr/include/SFML/Window/Export.hpp
/usr/include/SFML/Window/WindowStyle.hpp
/usr/include/SFML/Window/GlResource.hpp
/usr/include/SFML/Window/Mouse.hpp
/usr/include/SFML/Window/Keyboard.hpp
/usr/include/SFML/Window/Joystick.hpp
/usr/include/SFML/Window/Window.hpp
/usr/include/SFML/Window/VideoMode.hpp
/usr/include/SFML/Window/WindowHandle.hpp
/usr/include/SFML/Graphics
/usr/include/SFML/Graphics/Color.hpp
/usr/include/SFML/Graphics/View.hpp
/usr/include/SFML/Graphics/ConvexShape.hpp
/usr/include/SFML/Graphics/RenderStates.hpp
/usr/include/SFML/Graphics/RenderTarget.hpp
/usr/include/SFML/Graphics/Export.hpp
/usr/include/SFML/Graphics/PrimitiveType.hpp
/usr/include/SFML/Graphics/Vertex.hpp
/usr/include/SFML/Graphics/Font.hpp
/usr/include/SFML/Graphics/CircleShape.hpp
/usr/include/SFML/Graphics/Transformable.hpp
/usr/include/SFML/Graphics/Drawable.hpp
/usr/include/SFML/Graphics/RenderWindow.hpp
/usr/include/SFML/Graphics/Image.hpp
/usr/include/SFML/Graphics/Rect.hpp
/usr/include/SFML/Graphics/Glyph.hpp
/usr/include/SFML/Graphics/RectangleShape.hpp
/usr/include/SFML/Graphics/Sprite.hpp
/usr/include/SFML/Graphics/Rect.inl
/usr/include/SFML/Graphics/Shape.hpp
/usr/include/SFML/Graphics/RenderTexture.hpp
/usr/include/SFML/Graphics/Transform.hpp
/usr/include/SFML/Graphics/Texture.hpp
/usr/include/SFML/Graphics/Text.hpp
/usr/include/SFML/Graphics/VertexArray.hpp
/usr/include/SFML/Graphics/Shader.hpp
/usr/include/SFML/Graphics/BlendMode.hpp
/usr/include/SFML/Network.hpp
/usr/include/SFML/Network
/usr/include/SFML/Network/SocketHandle.hpp
/usr/include/SFML/Network/SocketSelector.hpp
/usr/include/SFML/Network/IpAddress.hpp
/usr/include/SFML/Network/Export.hpp
/usr/include/SFML/Network/UdpSocket.hpp
/usr/include/SFML/Network/Http.hpp
/usr/include/SFML/Network/Packet.hpp
/usr/include/SFML/Network/TcpSocket.hpp
/usr/include/SFML/Network/Socket.hpp
/usr/include/SFML/Network/TcpListener.hpp
/usr/include/SFML/Network/Ftp.hpp
/usr/include/SFML/System
/usr/include/SFML/System/Mutex.hpp
/usr/include/SFML/System/Sleep.hpp
/usr/include/SFML/System/Utf.hpp
/usr/include/SFML/System/String.hpp
/usr/include/SFML/System/Clock.hpp
/usr/include/SFML/System/Thread.inl
/usr/include/SFML/System/Export.hpp
/usr/include/SFML/System/Time.hpp
/usr/include/SFML/System/ThreadLocalPtr.inl
/usr/include/SFML/System/Utf.inl
/usr/include/SFML/System/Lock.hpp
/usr/include/SFML/System/ThreadLocalPtr.hpp
/usr/include/SFML/System/ThreadLocal.hpp
/usr/include/SFML/System/InputStream.hpp
/usr/include/SFML/System/Thread.hpp
/usr/include/SFML/System/Err.hpp
/usr/include/SFML/System/Vector2.hpp
/usr/include/SFML/System/NonCopyable.hpp
/usr/include/SFML/System/Vector3.inl
/usr/include/SFML/System/Vector3.hpp
/usr/include/SFML/System/Vector2.inl
/usr/include/SFML/Audio.hpp
/usr/include/SFML/Config.hpp
/usr/include/SFML/Graphics.hpp
/usr/include/SFML/Window.hpp
/usr/include/SFML/Audio
/usr/include/SFML/Audio/Music.hpp
/usr/include/SFML/Audio/Sound.hpp
/usr/include/SFML/Audio/Export.hpp
/usr/include/SFML/Audio/SoundBufferRecorder.hpp
/usr/include/SFML/Audio/SoundSource.hpp
/usr/include/SFML/Audio/SoundRecorder.hpp
/usr/include/SFML/Audio/Listener.hpp
/usr/include/SFML/Audio/SoundStream.hpp
/usr/include/SFML/Audio/SoundBuffer.hpp
/usr/lib
/usr/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu/pkgconfig
/usr/lib/x86_64-linux-gnu/pkgconfig/sfml-graphics.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/sfml-network.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/sfml-audio.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/sfml-all.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/sfml-window.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/sfml-system.pc
/usr/share
/usr/share/doc
/usr/share/doc/libsfml-dev
/usr/share/doc/libsfml-dev/README.Debian
/usr/share/doc/libsfml-dev/copyright
/usr/lib/x86_64-linux-gnu/libsfml-system.so
/usr/lib/x86_64-linux-gnu/libsfml-window.so
/usr/lib/x86_64-linux-gnu/libsfml-graphics.so
/usr/lib/x86_64-linux-gnu/libsfml-audio.so
/usr/lib/x86_64-linux-gnu/libsfml-network.so
/usr/share/doc/libsfml-dev/changelog.Debian.gz

Download CLion

ต่อมา ดาวน์โหลด IDE ซึ่งจะใช้ CLion ใครยังไม่รู้จักก็ลองอ่านจากลิงค์ได้เลย Download CLion ทำการ Extract Folder ออกมา จะไว้ที่ไหนก็ตามสะดวกเลยครับ ่่ส่วนไฟล์ Execute ของมันจะอยู่ภายในโฟลเดอร์ /bin ทำการเปิด CLion ด้วยคำสั่งนี้

cd path/to/clion/bin
./clion.sh

เมื่อ CLion ถูกเปิด ก็เลือก Theme, Config อะไรให้เรียบร้อย ดังภาพเลย

Choose Theme

Config CMAKE

Plugin

Plugin Featured

Then create new Project, then try to create simple SFML จากนั้น ลองสร้าง New Project ด้วย SFML (รายละเอียดและวิธีการสร้างผมไม่พูดถึงนะครับ บทความนี้จริงๆโฟกัสไปที่ปัญหา CLion มองไม่เห็นไฟล์ library ที่ include มากกว่า)

// in file main.cpp
#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
    sf::CircleShape shape(100.f);
    shape.setFillColor(sf::Color::Green);

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear();
        window.draw(shape);
        window.display();
    }

    return 0;
}

หากว่าปกติ เวลาเราสั่งรันโปรแกรมด้วยการคลิ๊กปุ่ม Run จะพบว่ามี Error undefined reference ของ SFML ต่างๆ เพียบเลย แต่ถ้าใช้วิธีสั่งรันผ่าน Command Line ด้วยวิธีข้างล่างนี้จะไม่มีปัญหาอะไร

g++ main.o -o sfml-app -lsfml-graphics -lsfml-window -lsfml-system
./sfml-app

ผลลัพธ์ปกติดี

Demo

แต่ปัญหาของผมคือ ทำไมต้องสั่งผ่าน Command Line ด้วยละ ในเมื่อคลิก Run ทีเดียว ก็ให้มันรันไม่ได้หรอ ก็เลยไปหาวิธี ว่าทำไม CLion มองไม่เห็น Library ของ SFML นะ จนได้คำตอบ

Build SFML with CMAKE

ต้องใช้ CMAKE ครับ ถึงแม้ว่าจะรันได้ปกติผ่าน Terminal แต่มันก็ลำบากกว่าการกดปุ่มนะ หาคำตอบจนได้ไปเจออันนี้เข้า Build your SFML Project with CMAKE get เลย

  1. ทำการสร้างโฟลเดอร์ cmake_modules และก็ดาวน์โหลดไฟล์จากที่นี่ FindSFML.cmake มาใส่
  2. แก้ไขไฟล์ CMakeLists.txt โดยการเพิ่มโค๊ดข้างล่างนี้ลงไป
# Define sources and executable
set(EXECUTABLE_NAME "SFML")
add_executable(${EXECUTABLE_NAME} main.cpp)

# Detect and add SFML
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules" ${CMAKE_MODULE_PATH})
find_package(SFML 2 REQUIRED system window graphics network audio)
if(SFML_FOUND)
    include_directories(${SFML_INCLUDE_DIR})
    target_link_libraries(${EXECUTABLE_NAME} ${SFML_LIBRARIES})
endif()

สุดท้ายไฟล์ CMakeLists.txt ก็จะมีหน้าตาแบบนี้

cmake_minimum_required(VERSION 2.8.4)
project(SimpleSFML)

set(SOURCE_FILES main.cpp)
add_executable(SimpleSFML ${SOURCE_FILES})

# Define sources and executable
set(EXECUTABLE_NAME "SFML")
add_executable(${EXECUTABLE_NAME} main.cpp)

# Detect and add SFML
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules" ${CMAKE_MODULE_PATH})
find_package(SFML 2 REQUIRED system window graphics network audio)
if(SFML_FOUND)
    include_directories(${SFML_INCLUDE_DIR})
    target_link_libraries(${EXECUTABLE_NAME} ${SFML_LIBRARIES})
endif()

และ File Structure จะได้แบบนี้

├── CMakeLists.txt
├── cmake_modules
│   └── FindSFML.cmake
└── main.cpp

กดปุ่ม Reload Change และก็เลือก Executeable Name ชื่อ SFML และก็ Run ได้ปกติ

Selecte Executable

Fin! :D

Chai Chai Phonbopit : Software Engineer @Nextzy • ผู้ชายธรรมดาๆ ที่ชื่นชอบ Android, JavaScript (Node.js) และ Open Source มีงานอดิเรกเป็น Acoustic Guitar และ Football

บทความล่าสุด