對於MEGAchat的開發和編譯,我們主要使用CMake作為跨平台的專案設定工具。我們也使用 VCPKG 來管理在大多數平台(Windows、MacOS 和 Linux)中建置MEGAchat所需的依賴項。
有關每個作業系統所需建置工具的詳細信息,請查看 MEGA SDK 儲存庫中的「建置工具」一章。
WebRTC for 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
最後,克隆MEGAchat資料夾旁邊的 VCPKG 儲存庫。如果您已經在使用 VCPKG 並且擁有儲存庫的本機克隆,則可以跳過此步驟並使用系統上現有的 VCPKG。
git clone https://github.com/microsoft/vcpkg
以下說明用於從命令列介面 (CLI) 配置項目,但如果配置了相同的 CMake 參數,則 cmake-gui 或任何與 CMake 相容的編輯器或 IDE 都應該適合。
MEGAchat的配置與其他常規 CMake 專案一樣。唯一始終需要的參數是 VCPKG 目錄,用於管理第三方相依性。 MEGA SDK 依賴項是作為MEGAchat建構的一部分建構的。
若要設定MEGAchat ,請從工作區( mega
目錄)執行 CMake:
cmake -DVCPKG_ROOT=vcpkg -DCMAKE_BUILD_TYPE=Debug -S MEGAchat -B build_dir
註 1 :多重配置產生器(例如 Visual Studio)可能不需要-DCMAKE_BUILD_TYPE=<Debug|Release>
。
註2如果您的系統上安裝了Qt Framework,但CMake無法偵測到它,您可以新增-DCMAKE_PREFIX_PATH=</path/to/qt/install/dir>
以便CMake可以找到它。如果未安裝 Qt 並且您不想安裝它,可以透過設定-DENABLE_CHATLIB_QTAPP=OFF
來停用 Qt 範例應用程式。庫、CLI 範例和測試仍將建置。
在上面的 cmake 指令中,為了簡單起見,使用了相對路徑。如果您想更改 VCPKG、 MEGAchat或建置目錄的位置,只需為其中任何一個提供有效的相對或絕對路徑即可。
在專案配置過程中,VCPKG 將為平台建置和配置必要的程式庫。第一次運行可能需要一段時間,但是一旦建置了庫,VCPKG 就會從二進位快取中檢索它們。
MEGAchat可以配置不同的選項,其中一些可以在 chatlib_options.cmake 檔案中找到。管理範例和測試的選項位於 CMakeLists.txt 中。
配置MEGAchat後,只需建置完整的專案:
cmake --build build_dir
您可以像CHATlib
或megaclc
一樣指定--target=<target>
,或只保留命令以建置所有目標。此外,可以添加-j <N>
或--parallel <N>
來管理並發並加快建置速度。
建置完成後,二進位檔案將在 CMake 設定命令中指定的build_dir
中可用。
為了抽象程式碼複雜性, MEGAchat提供了一個中間層,可以快速建立新應用程式。
該文檔位於src/ MEGAchat api.h
MEGAchat執行緒模型類似於 javascript 執行緒模型 - 一切都在主 (GUI) 執行緒中運行,絕不允許阻塞,外部事件(網路、計時器等、webrtc 事件等)會在主執行緒上觸發回呼。為此, MEGAchat必須能夠與應用程式的事件循環互動 - 對於 GUI 應用程式來說,這通常是 GUI 框架的事件/訊息循環,對於控制台應用程式來說,這通常是自訂訊息循環。由於此訊息循環是特定於平台的,因此應用程式開發人員有責任實現它與MEGAchat之間的介面。這聽起來可能比實際情況更複雜 - 介面由兩部分組成。其中一部分是megaPostMessageToGui(void*)
函數的實現,它將一個不透明的void*
指標傳送到應用程式的訊息循環。該函數通常由主執行緒以外的執行緒調用,但也可以由 GUI 執行緒本身調用。另一部分是應用程式訊息循環中的程式碼,它識別這種類型的消息,並透過使用相同指標呼叫megaProcessMessage(void*)
將它們傳遞回MEGAchat - 這次是在主 (GUI) 執行緒的上下文中。所有這些都在/src/base/gcm.h
和/src/base/gcm.hpp
中實作。這些文件包含詳細的文件。在 Windows 上實現此功能的一個範例是: megaPostMessageToGui(void*)
將使用使用者訊息類型執行PostMessage()
,並將void*
作為訊息的 lParam 或 wParam,並且在事件處理switch
語句中,將有該訊息類型的條目,透過轉換訊息的lParam 或wParam 來取得void*
指針,並將其傳遞給megaProcessMessage(void*)
。
MEGAchat依賴 libuv,在自己的專用執行緒中運行,以監視多個套接字的原始 I/O 事件,並實作計時器。它還依賴 libuv 的高階 I/O 功能,例如 DNS 解析和 SSL 套接字。 libuv 之上的一個薄層,稱為「服務」( /src/base/?services*.*
) 是在libuv 和GCM 之上實現的,以便為計時器提供簡單的、類似javascript 的非同步C ++11 API ( 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 使用者也這樣做,儘管可以在套接字上阻塞專用工作線程,並透過 GCM 將事件發佈到 GUI 線程。
使用模式如下:為某個事件(套接字 I/O 事件、計時器等)註冊回調,並在事件發生時由libuv 執行緒呼叫該回調。如果事件可能在呼叫回呼的庫之外傳播,尤其是傳播到 GUI,那麼在某些時候,必須使用 GCM 機制將事件處理編組到 GUI 執行緒。但是,如果事件是內部的並且從不傳播到庫外部,則可以直接在 libuv 線程的上下文中處理它(前提是它永遠不會阻止它)。這節省了將其編組到 GUI 執行緒的效能成本,如果事件發生頻率很高(例如僅需要將資料附加到緩衝區的傳入資料區塊事件),則建議這樣做。當傳輸完成時,每次傳輸都可以在 GUI 執行緒上編組一次完成事件,從而結合了兩種方法的優點。
MEGAchat擁有先進的日誌記錄工具,支援帶有顏色的檔案和控制台日誌記錄、日誌檔案輪替、多個日誌通道,每個通道都有單獨的日誌等級。日誌等級是在執行時間(啟動時)配置的,而不是在編譯時配置的(即不是透過停用日誌巨集)。這允許發佈建置的應用程式為任何通道啟用完整的偵錯日誌記錄。日誌通道在 src/base/loggerChannelConfig.h 中定義和預設配置。該文件包含詳細的文件。為了方便起見,每個通道的專用日誌記錄巨集通常在使用它的程式碼中定義 - 有關範例,請參閱 karereCommon.h 中的 XXX_LOG_DEBUG/WARN/ERROR 巨集。如果需要,SDK 使用者可以自由建立額外的日誌通道。 GUI 日誌通道已定義。日誌通道配置可以在運行時由 KRLOG 環境變數覆蓋。其格式如下:
KRLOG=<chan name>=<log level>,<chan name2>=<log level2>...
日誌等級為「關閉」、「錯誤」、「警告」、「資訊」、「詳細」、「調試」、「調試」。
有一個特殊的頻道名稱—「全部」。設定該通道的日誌等級將設定所有通道的日誌等級。例如,這可以輕鬆地使除一個(或幾個)之外的所有通道靜音,方法是:
KRLOG=all=warn,mychannel=debug,myotherchannel=info
同一個通道可以多次配置,只有最後一次設定才有效,這使得上述技巧成為可能。
MEGAchat要求應用程式在編譯時定義函數karere::getAppDir()
,以便在進入main()
之前知道在哪裡建立日誌檔案並儘早開始記錄。如果MEGAchat建構為靜態庫,則這不是問題。在動態函式庫的情況下,函數必須是弱符號,以便MEGAchat本身可以在沒有函數實作的情況下進行編譯,並且在應用程式啟動時載入MEGAchat共享庫時要連結的實作。弱符號實際上不能跨編譯器移植,這可能是一個問題。然而,它們受到 gcc 和 clang 的支持。如果不支援弱符號,則 karer e 必須建構成靜態函式庫。
base/promise.h
中的 Promise 函式庫和/src/test-promise.cpp
中的範例用法/src/base/timers.hpp
中的setTimeout()
和setInterval()
定時器函數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*)
。此函數是MEGAchat所依賴的訊息傳遞機制(稱為 Gui Call Marshaller,或 GCM)的核心。您必須將此函數的指標傳遞給services_init()
。