สำหรับการพัฒนาและการรวบรวม MEGAchat เราใช้ CMake เป็นเครื่องมือกำหนดค่าโปรเจ็กต์ข้ามแพลตฟอร์มเป็นหลัก นอกจากนี้เรายังใช้ VCPKG เพื่อจัดการการพึ่งพาที่จำเป็นเพื่อสร้าง MEGAchat ในแพลตฟอร์มส่วนใหญ่: Windows, MacOS และ Linux
สำหรับรายละเอียดเกี่ยวกับเครื่องมือสร้างที่จำเป็นสำหรับระบบปฏิบัติการแต่ละระบบ โปรดดูบทเครื่องมือก่อสร้างในพื้นที่เก็บข้อมูล MEGA SDK
ข้อมูลเพิ่มเติมสำหรับการคอมไพล์ WebRTC Android ใน WebRTC สำหรับ Android
MEGAchat ต้องการการพึ่งพาบางอย่างในการทำงาน ส่วนใหญ่จะถูกดาวน์โหลดและสร้างโดยอัตโนมัติโดยใช้ VCPKG ในระหว่างขั้นตอนการกำหนดค่า
สำหรับ Linux จำเป็นต้องมีไลบรารีเพิ่มเติมในระบบเพื่อให้ VCPKG สามารถสร้างการพึ่งพาได้ สำหรับการแจกแจงแบบ Debian คุณสามารถติดตั้งไลบรารีที่จำเป็นได้โดยใช้คำสั่งต่อไปนี้:
sudo apt install python3-pkg-resources libglib2.0-dev libgtk-3-dev libasound2-dev libpulse-dev
ชื่อแพ็คเกจอาจแตกต่างกันไปตามการแจกแจง Linux ที่แตกต่างกัน แต่ควรสร้างได้สำเร็จด้วยแพ็คเกจที่มีไลบรารีเดียวกัน
คุณสามารถดูชุดการขึ้นต่อกันทั้งหมดในไฟล์ vcpkg.json ที่รากของที่เก็บ
MEGAchat ต้องการไลบรารี MEGA SDK ด้วย มีคำแนะนำในส่วนท้ายของเอกสารนี้เกี่ยวกับวิธีการใช้งานร่วมกับ MEGAchat โปรเจ็กต์ MEGA SDK ได้รับการโหลดโดยอัตโนมัติโดย MEGAchat CMake ดังนั้นคุณเพียงแค่โคลนมันในเส้นทางที่คาดไว้เท่านั้น
มีการพึ่งพาเพิ่มเติมเพียงทางเลือกเดียวเท่านั้นที่ควรติดตั้งในระบบ: Qt Framework จำเป็นต้องสร้างแอปตัวอย่าง Qt เท่านั้น แต่ไม่จำเป็นสำหรับการทดสอบ ตัวอย่าง CLI หรือไลบรารี
ก่อนอื่น เตรียมไดเร็กทอรีที่คุณเลือกเพื่อทำงานกับ MEGAchat mega
ไดเร็กทอรีจะถูกใช้เป็นไดเร็กทอรีพื้นที่ทำงานตามตัวอย่างในเอกสารนี้
mkdir mega
cd mega
หลังจากเตรียมไดเร็กทอรีแล้ว ให้โคลนพื้นที่เก็บข้อมูล MEGAchat เพื่อรับซอร์สโค้ด MEGAchat
git clone https://github.com/meganz/MEGAchat
เนื่องจาก MEGAchat ต้องการให้ MEGA SDK ทำงาน ให้โคลน MEGA SDK ในเส้นทางที่คาดไว้
git clone https://github.com/meganz/sdk MEGAchat/third-party/mega
สุดท้าย โคลนพื้นที่เก็บข้อมูล VCPKG ถัดจากโฟลเดอร์ MEGAchat หากคุณใช้ VCPKG อยู่แล้วและคุณมีโคลนของที่เก็บในเครื่อง คุณสามารถข้ามขั้นตอนนี้และใช้ VCPKG ที่มีอยู่ในระบบของคุณได้
git clone https://github.com/microsoft/vcpkg
คำแนะนำต่อไปนี้ใช้สำหรับการกำหนดค่าโปรเจ็กต์จากอินเทอร์เฟซบรรทัดคำสั่ง (CLI) แต่ cmake-gui หรือตัวแก้ไขหรือ IDE ใด ๆ ที่เข้ากันได้กับ CMake ควรเหมาะสมหากมีการกำหนดค่าพารามิเตอร์ CMake เดียวกัน
MEGAchat ได้รับการกำหนดค่าเหมือนกับโปรเจ็กต์ CMake ทั่วไปอื่นๆ พารามิเตอร์เดียวที่จำเป็นเสมอคือไดเร็กทอรี VCPKG เพื่อจัดการการขึ้นต่อกันของบุคคลที่สาม การพึ่งพา MEGA SDK ถูกสร้างขึ้นโดยเป็นส่วนหนึ่งของการสร้าง MEGAchat
หากต้องการกำหนดค่า MEGAchat จากพื้นที่ทำงาน ( mega
ไดเร็กทอรี) ให้รัน CMake:
cmake -DVCPKG_ROOT=vcpkg -DCMAKE_BUILD_TYPE=Debug -S MEGAchat -B build_dir
หมายเหตุ 1 : -DCMAKE_BUILD_TYPE=<Debug|Release>
อาจไม่จำเป็นสำหรับตัวสร้างหลายการกำหนดค่า เช่น Visual Studio
หมายเหตุ 2 หากมีการติดตั้ง Qt Framework บนระบบของคุณ แต่ CMake ไม่สามารถตรวจพบได้ คุณสามารถเพิ่ม -DCMAKE_PREFIX_PATH=</path/to/qt/install/dir>
เพื่อให้ CMake สามารถระบุตำแหน่งได้ หากไม่ได้ติดตั้ง Qt และคุณไม่ต้องการติดตั้ง คุณสามารถปิดการใช้งาน Qt Example App ได้โดยการตั้งค่า -DENABLE_CHATLIB_QTAPP=OFF
ไลบรารี ตัวอย่าง CLI และการทดสอบจะยังคงถูกสร้างขึ้น
ในคำสั่ง cmake ด้านบน เส้นทางสัมพัทธ์ถูกนำมาใช้เพื่อความเรียบง่าย หากคุณต้องการเปลี่ยนตำแหน่งของ VCPKG, MEGAchat หรือไดเร็กทอรี build เพียงแค่ระบุพาธแบบสัมพัทธ์หรือแบบสัมบูรณ์ที่ถูกต้องสำหรับรายการใดรายการหนึ่ง
ในระหว่างการกำหนดค่าโปรเจ็กต์ VCPKG จะสร้างและกำหนดค่าไลบรารีที่จำเป็นสำหรับแพลตฟอร์ม อาจใช้เวลาสักครู่ในการรันครั้งแรก แต่เมื่อสร้างไลบรารีแล้ว VCPKG จะดึงไลบรารีเหล่านั้นจากแคชไบนารี
MEGAchat สามารถกำหนดค่าได้ด้วยตัวเลือกต่างๆ ซึ่งบางส่วนสามารถพบได้ในไฟล์ chatlib_options.cmake ตัวเลือกในการจัดการตัวอย่างและการทดสอบอยู่ใน CMakeLists.txt
เมื่อกำหนดค่า MEGAchat แล้ว เพียงสร้างโปรเจ็กต์ให้เสร็จสมบูรณ์:
cmake --build build_dir
คุณสามารถระบุ --target=<target>
เช่น CHATlib
หรือ megaclc
หรือเพียงปล่อยคำสั่งไว้เหมือนเดิมเพื่อสร้าง tagets ทั้งหมด นอกจากนี้ คุณสามารถเพิ่ม -j <N>
หรือ --parallel <N>
เพื่อจัดการการทำงานพร้อมกันและเพิ่มความเร็วในการสร้าง
เมื่อการบิลด์เสร็จสิ้น ไบนารีจะพร้อมใช้งานใน build_dir
ซึ่งระบุไว้ในคำสั่งการกำหนดค่า CMake
เพื่อสรุปความซับซ้อนของโค้ด MEGAchat จัดเตรียมเลเยอร์ระดับกลางที่ช่วยให้สามารถสร้างแอปพลิเคชันใหม่ได้อย่างรวดเร็ว
เอกสารมีอยู่ที่ src/ MEGAchat api.h
โมเดลเธรด MEGAchat นั้นคล้ายคลึงกับโมเดลเธรดจาวาสคริปต์ - ทุกอย่างทำงานในเธรดหลัก (GUI) ไม่อนุญาตให้บล็อก และเหตุการณ์ภายนอก (เครือข่าย ตัวจับเวลา ฯลฯ กิจกรรม webrtc ฯลฯ ) จะทริกเกอร์การโทรกลับบนเธรดหลัก เพื่อให้สิ่งนี้ทำงานได้ MEGAchat จะต้องสามารถโต้ตอบกับลูปเหตุการณ์ของแอปพลิเคชันได้ ซึ่งโดยปกติจะเป็นลูปเหตุการณ์/ข้อความของเฟรมเวิร์ก GUI ในกรณีของแอปพลิเคชัน GUI หรือลูปข้อความแบบกำหนดเองในกรณีของแอปพลิเคชันคอนโซล เนื่องจากการวนซ้ำข้อความนี้มีความเฉพาะเจาะจงกับแพลตฟอร์มมาก จึงเป็นความรับผิดชอบของผู้พัฒนาแอปพลิเคชันในการใช้อินเทอร์เฟซระหว่างข้อความกับ MEGAchat สิ่งนี้อาจฟังดูซับซ้อนกว่าความเป็นจริง - อินเทอร์เฟซประกอบด้วยสองส่วน ส่วนหนึ่งคือการใช้งานฟังก์ชัน megaPostMessageToGui(void*)
ซึ่งโพสต์ตัวชี้ void*
แบบทึบไปยังลูปข้อความของแอปพลิเคชัน โดยปกติแล้วฟังก์ชันนี้จะถูกเรียกโดยเธรดอื่นที่ไม่ใช่เธรดหลัก แต่ก็สามารถเรียกโดยเธรด GUI ได้เช่นกัน อีกส่วนคือรหัสในลูปข้อความของแอปพลิเคชันที่จดจำข้อความประเภทนี้และส่งกลับไปยัง MEGAchat โดยการเรียก megaProcessMessage(void*)
ด้วยตัวชี้เดียวกัน - คราวนี้ในบริบทของเธรดหลัก (GUI) ทั้งหมดนี้ถูกนำไปใช้ใน /src/base/gcm.h
และ /src/base/gcm.hpp
ไฟล์เหล่านี้มีเอกสารประกอบโดยละเอียด ตัวอย่างของการดำเนินการนี้บน Windows คือ: megaPostMessageToGui(void*)
จะทำ PostMessage()
ด้วยประเภทข้อความของผู้ใช้ และ void*
เป็น lParam หรือ wParam ของข้อความ และในคำสั่ง switch
การประมวลผลเหตุการณ์ จะมี รายการสำหรับประเภทข้อความนั้น รับตัวชี้ void*
โดยการส่ง lParam หรือ wParam ของข้อความ แล้วส่งต่อไปยัง megaProcessMessage(void*)
MEGAchat อาศัย libuv ซึ่งทำงานในเธรดเฉพาะของตัวเอง เพื่อตรวจสอบซ็อกเก็ตหลายช่องสำหรับเหตุการณ์ Raw I/O และเพื่อใช้ตัวจับเวลา นอกจากนี้ยังอาศัยฟังก์ชัน I/O ระดับสูงกว่าของ libuv เช่น ความละเอียด DNS และซ็อกเก็ต SSL เลเยอร์บาง ๆ ที่ด้านบนของ libuv เรียกว่า 'services' ( /src/base/?services*.*
) ถูกนำไปใช้บน libuv และ GCM เพื่อให้มี async C++11 APIs ที่เรียบง่ายคล้ายจาวาสคริปต์สำหรับตัวจับเวลา ( src/base/timer.h
), ความละเอียด DNS ( /src/base/services-dns.hpp
), ไคลเอ็นต์ http ( /src/base/services-http.hpp
) เดิมทีเลเยอร์นี้ได้รับการออกแบบให้มีส่วนประกอบระดับล่างพร้อมอินเทอร์เฟซ C ธรรมดา (ไฟล์ cservices*.cpp/h
) เพื่อให้สามารถใช้บริการโดย DLL หลายตัวที่สร้างด้วยคอมไพเลอร์ที่แตกต่างกัน และ C ส่วนหัวระดับสูงเท่านั้น ++11 เลเยอร์ที่เป็นส่วนหน้าและมี API สาธารณะ - นี่คือไฟล์ .hpp
ไลบรารีเครือข่ายทั้งหมดใน MEGAchat (libcurl) ใช้ libuv สำหรับการทำงานของเครือข่ายและตัวจับเวลา (ไลบรารี C ใช้ libuv โดยตรง รหัส C++ ใช้เลเยอร์ C++11 เช่น timers.hpp
) ขอแนะนำอย่างยิ่งให้ผู้ใช้ SDK ทำเช่นเดียวกัน แม้ว่าจะเป็นไปได้ เช่น ให้เธรดของผู้ปฏิบัติงานเฉพาะบล็อกบนซ็อกเก็ต และการโพสต์เหตุการณ์ไปยังเธรด GUI ผ่านทาง GCM
รูปแบบการใช้งานมีดังนี้: มีการลงทะเบียนการโทรกลับสำหรับเหตุการณ์บางอย่าง (เหตุการณ์ซ็อกเก็ต I/O ตัวจับเวลา ฯลฯ) และการเรียกกลับนั้นจะถูกเรียกโดย เธรด libuv เมื่อเหตุการณ์เกิดขึ้น หากเหตุการณ์อาจเผยแพร่นอกไลบรารีที่มีการเรียกกลับ และโดยเฉพาะอย่างยิ่งไปยัง GUI ดังนั้น ในบางจุด การประมวลผลเหตุการณ์จะต้องถูกจัดเรียงไว้ที่เธรด GUI โดยใช้กลไก GCM อย่างไรก็ตาม หากเหตุการณ์นั้นเป็นเหตุการณ์ภายในและไม่เคยเผยแพร่ภายนอกไลบรารี ก็สามารถจัดการได้โดยตรงในบริบทของเธรด libuv (โดยมีเงื่อนไขว่าจะไม่บล็อกเหตุการณ์นั้น) ซึ่งจะช่วยประหยัดต้นทุนด้านประสิทธิภาพในการจัดรวมเข้ากับเธรด GUI และขอแนะนำหากเหตุการณ์เกิดขึ้นที่ความถี่สูง เช่น เหตุการณ์ก้อนข้อมูลขาเข้าที่ต้องการเพียงข้อมูลที่ต่อท้ายบัฟเฟอร์เท่านั้น เมื่อการถ่ายโอนเสร็จสมบูรณ์ เหตุการณ์ที่เสร็จสมบูรณ์สามารถจัดเรียงบนเธรด GUI ได้หนึ่งครั้งต่อการถ่ายโอน ซึ่งเป็นการรวมข้อดีของทั้งสองวิธีเข้าด้วยกัน
MEGAchat มีสิ่งอำนวยความสะดวกการบันทึกขั้นสูงที่รองรับไฟล์และคอนโซลการบันทึกด้วยสี การหมุนเวียนไฟล์บันทึก ช่องบันทึกหลายช่อง โดยแต่ละช่องมีระดับการบันทึกแยกกัน ระดับบันทึกได้รับการกำหนดค่าที่รันไทม์ (เมื่อเริ่มต้น) และไม่ใช่ในเวลาคอมไพล์ (เช่น ไม่ใช่โดยการปิดใช้งานมาโครบันทึก) ซึ่งช่วยให้แอปที่สร้างขึ้นเพื่อเปิดใช้งานการบันทึกการแก้ไขจุดบกพร่องเต็มรูปแบบสำหรับช่องใดๆ ก็ตาม ช่องบันทึกถูกกำหนดและกำหนดค่าเริ่มต้นใน src/base/loggerChannelConfig.h ไฟล์ประกอบด้วยเอกสารโดยละเอียด เพื่อความสะดวก โดยปกติแล้วมาโครการบันทึกเฉพาะสำหรับแต่ละช่องจะถูกกำหนดไว้ในโค้ดที่ใช้ - ดูตัวอย่างมาโคร XXX_LOG_DEBUG/WARN/ERROR ใน karereCommon.h ผู้ใช้ SDK มีอิสระในการสร้างช่องบันทึกเพิ่มเติมหากจำเป็น ช่องทางบันทึก GUI ถูกกำหนดไว้แล้ว การกำหนดค่าช่องบันทึกสามารถแทนที่ได้ในขณะรันไทม์โดยตัวแปรสภาพแวดล้อม KRLOG รูปแบบของมันมีดังนี้:
KRLOG=<chan name>=<log level>,<chan name2>=<log level2>...
ระดับการบันทึกคือ 'ปิด', 'ข้อผิดพลาด', 'เตือน', 'ข้อมูล', 'verbose', 'debug', 'debugv'
มีชื่อช่องพิเศษหนึ่งชื่อ - 'ทั้งหมด' การตั้งค่าระดับบันทึกของช่องนี้จะกำหนดระดับบันทึกของทุกช่อง วิธีนี้ทำให้สามารถปิดเสียงทุกช่องได้อย่างง่ายดาย ยกเว้นช่องเดียว (หรือไม่กี่ช่อง) โดย:
KRLOG=all=warn,mychannel=debug,myotherchannel=info
ช่องเดียวกันสามารถกำหนดค่าได้หลายครั้ง และเฉพาะการตั้งค่าสุดท้ายเท่านั้นที่จะมีผล ซึ่งทำให้เคล็ดลับข้างต้นเป็นไปได้
MEGAchat ต้องการให้แอปพลิเคชันกำหนดฟังก์ชัน karere::getAppDir()
ในขณะคอมไพล์ เพื่อให้ทราบว่าจะสร้างไฟล์บันทึกได้ที่ไหน และเริ่มบันทึกโดยเร็วที่สุดก่อนที่จะป้อน main()
หาก MEGAchat ถูกสร้างขึ้นเป็น lib แบบคงที่ ก็ไม่เป็นปัญหา ในกรณีของ Dynamic lib ฟังก์ชันนี้จะต้องเป็นสัญลักษณ์ที่อ่อนแอ เพื่อให้ MEGAchat เองสามารถคอมไพล์ได้โดยไม่ต้องใช้ฟังก์ชัน และการใช้งานที่จะเชื่อมโยงเมื่อมีการโหลด lib ที่ใช้ร่วมกัน MEGAchat เมื่อเริ่มต้นแอป สัญลักษณ์ที่อ่อนแอไม่สามารถพกพาข้ามคอมไพเลอร์ได้ และอาจเป็นปัญหาได้ อย่างไรก็ตาม พวกเขาได้รับการสนับสนุนจากทั้ง gcc และ clang หากไม่มีการสนับสนุนสัญลักษณ์ที่อ่อนแอ จะต้องสร้าง karer เป็น lib แบบคงที่
base/promise.h
และตัวอย่างการใช้งาน เช่น ใน /src/test-promise.cpp
setTimeout()
และ setInterval()
ใน /src/base/timers.hpp
marshallCall()
เรียก lambda จากเธรดผู้ปฏิบัติงานไปยังเธรด GUI สามารถดูตัวอย่างการใช้งานได้ใน /src/webrtcAdapter.h
และในที่ต่างๆ มากมาย กลไกนี้ไม่ควรจำเป็นโดยตรงในโค้ดระดับสูงที่ทำงานในเธรด GUI/src/chatClient.h;.cpp
megaPostMessageToGui()
วิธีเริ่ม 'บริการ' และวิธีการสร้างอินสแตนซ์ไคลเอ็นต์ MEGAchat ยังแสดงวิธีการใช้เมธอด getAppDir()
ซึ่งเป็นสัญลักษณ์อ่อนที่จำเป็นสำหรับไลบรารี MEGAchat เพื่อสร้างไฟล์บันทึกและเริ่มการบันทึกโดยเร็วที่สุดก่อนที่จะป้อน main()
src/rtcModile/IRtcModule.h
และส่วนหัวที่เกี่ยวข้องmegaPostMessageToGui()
แต่สามารถมีชื่อใดก็ได้ โดยมีเงื่อนไขว่าลายเซ็นจะอยู่ extern "C" void(void*)
. ฟังก์ชั่นนี้เป็นหัวใจสำคัญของกลไกการส่งข้อความ (เรียกว่า Gui Call Marshaller หรือ GCM) ที่ MEGAchat พึ่งพา คุณต้องส่งพอยน์เตอร์ไปยังฟังก์ชันนี้ไปที่ services_init()