Für die Entwicklung und Kompilierung von MEGAchat verwenden wir hauptsächlich CMake als plattformübergreifendes Projektkonfigurationstool. Wir verwenden VCPKG auch, um die erforderlichen Abhängigkeiten zum Erstellen MEGAchat auf den meisten Plattformen zu verwalten: Windows, MacOS und Linux.
Einzelheiten zu den erforderlichen Build-Tools für jedes Betriebssystem finden Sie im Kapitel „Build-Tools“ im MEGA SDK-Repository.
Weitere Informationen zur WebRTC-Android-Kompilierung in WebRTC für Android
Damit MEGAchat funktioniert, sind einige Abhängigkeiten erforderlich. Die meisten davon werden während der Konfigurationsphase automatisch mit VCPKG heruntergeladen und erstellt.
Für Linux werden einige zusätzliche Bibliotheken im System benötigt, damit VCPKG die Abhängigkeiten aufbauen kann. Für Debian-basierte Distributionen können Sie die erforderlichen Bibliotheken mit dem folgenden Befehl installieren:
sudo apt install python3-pkg-resources libglib2.0-dev libgtk-3-dev libasound2-dev libpulse-dev
Die Paketnamen können je nach Linux-Distribution variieren, es sollte jedoch erfolgreich mit Paketen erstellt werden, die dieselben Bibliotheken bereitstellen.
Sie können sich den vollständigen Satz an Abhängigkeiten in der Datei vcpkg.json im Stammverzeichnis des Repositorys ansehen.
MEGAchat benötigt außerdem die MEGA SDK-Bibliothek. Weiter unten in diesem Dokument finden Sie Anweisungen zur Verwendung mit MEGAchat . Das MEGA SDK-Projekt wird automatisch vom MEGAchat CMake geladen, sodass Sie es einfach nur im erwarteten Pfad klonen müssen.
Es gibt nur eine zusätzliche optionale Abhängigkeit, die im System installiert werden sollte: Das Qt Framework. Es ist nur erforderlich, die Qt-Beispiel-App zu erstellen, nicht jedoch für die Tests, das CLI-Beispiel oder die Bibliothek selbst.
Bereiten Sie zunächst ein Verzeichnis Ihrer Wahl für die Arbeit mit MEGAchat vor. Das mega
-Verzeichnis wird in den Beispielen in diesem Dokument als Arbeitsbereichsverzeichnis verwendet.
mkdir mega
cd mega
Klonen Sie nach der Vorbereitung des Verzeichnisses das MEGAchat Repository, um den MEGAchat Quellcode zu erhalten.
git clone https://github.com/meganz/MEGAchat
Da MEGAchat das MEGA SDK benötigt, um zu funktionieren, klonen Sie das MEGA SDK im erwarteten Pfad.
git clone https://github.com/meganz/sdk MEGAchat/third-party/mega
Klonen Sie abschließend das VCPKG-Repository neben dem MEGAchat Ordner. Wenn Sie VCPKG bereits verwenden und über einen lokalen Klon des Repositorys verfügen, können Sie diesen Schritt überspringen und das vorhandene VCPKG auf Ihrem System verwenden.
git clone https://github.com/microsoft/vcpkg
Die folgenden Anweisungen gelten für die Konfiguration des Projekts über die Befehlszeilenschnittstelle (CLI), aber cmake-gui oder jeder mit CMake kompatible Editor oder jede IDE sollte geeignet sein, wenn dieselben CMake-Parameter konfiguriert sind.
MEGAchat wird wie jedes andere reguläre CMake-Projekt konfiguriert. Der einzige Parameter, der immer benötigt wird, ist das VCPKG-Verzeichnis, um die Abhängigkeiten von Drittanbietern zu verwalten. Die MEGA SDK-Abhängigkeit wird als Teil des MEGAchat Builds erstellt.
Um MEGAchat zu konfigurieren, führen Sie im Arbeitsbereich ( mega
-Verzeichnis) CMake aus:
cmake -DVCPKG_ROOT=vcpkg -DCMAKE_BUILD_TYPE=Debug -S MEGAchat -B build_dir
Hinweis 1 : -DCMAKE_BUILD_TYPE=<Debug|Release>
wird für Multiconfig-Generatoren wie Visual Studio möglicherweise nicht benötigt.
Hinweis 2 Wenn das Qt Framework auf Ihrem System installiert ist, CMake es aber nicht erkennt, können Sie -DCMAKE_PREFIX_PATH=</path/to/qt/install/dir>
hinzufügen, damit CMake es finden kann. Wenn Qt nicht installiert ist und Sie es lieber nicht installieren möchten, können Sie die Qt-Beispiel-App deaktivieren, indem Sie -DENABLE_CHATLIB_QTAPP=OFF
festlegen. Die Bibliothek, das CLI-Beispiel und die Tests werden noch erstellt.
Im obigen cmake-Befehl wurden der Einfachheit halber relative Pfade verwendet. Wenn Sie den Speicherort von VCPKG, MEGAchat oder dem Build-Verzeichnis ändern möchten, geben Sie einfach einen gültigen relativen oder absoluten Pfad für einen dieser Pfade an.
Während der Projektkonfiguration erstellt und konfiguriert VCPKG die erforderlichen Bibliotheken für die Plattform. Beim ersten Durchlauf kann es eine Weile dauern, aber sobald die Bibliotheken erstellt sind, ruft VCPKG sie aus dem Binärcache ab.
MEGAchat kann mit verschiedenen Optionen konfiguriert werden, von denen einige in der Datei chatlib_options.cmake zu finden sind. Die Optionen zum Verwalten der Beispiele und Tests befinden sich in CMakeLists.txt.
Sobald MEGAchat konfiguriert ist, erstellen Sie einfach das komplette Projekt:
cmake --build build_dir
Sie können --target=<target>
wie CHATlib
oder megaclc
angeben oder den Befehl einfach unverändert lassen, um alle Tagets zu erstellen. Darüber hinaus kann -j <N>
oder --parallel <N>
hinzugefügt werden, um die Parallelität zu verwalten und den Build zu beschleunigen.
Sobald der Build abgeschlossen ist, stehen Binärdateien im build_dir
zur Verfügung, das im CMake-Konfigurationsbefehl angegeben wurde.
Um die Codekomplexität zu abstrahieren, bietet MEGAchat eine Zwischenschicht, die es ermöglicht, schnell neue Anwendungen zu erstellen.
Die Dokumentation ist unter src/ MEGAchat api.h
verfügbar
Das MEGAchat -Threading-Modell ähnelt dem Javascript-Threading-Modell – alles läuft im Hauptthread (GUI), Blockieren ist niemals erlaubt und externe Ereignisse (Netzwerk, Timer usw., WebRTC-Ereignisse usw.) lösen Rückrufe im Hauptthread aus. Damit dies funktioniert, muss MEGAchat mit der Ereignisschleife der Anwendung interagieren können – im Falle einer GUI-Anwendung ist dies normalerweise die Ereignis-/Nachrichtenschleife des GUI-Frameworks oder im Falle einer Konsolenanwendung eine benutzerdefinierte Nachrichtenschleife. Da diese Nachrichtenschleife sehr plattformspezifisch ist, liegt es in der Verantwortung des Anwendungsentwicklers, die Schnittstelle zwischen ihr und MEGAchat zu implementieren. Das hört sich vielleicht komplizierter an, als es in Wirklichkeit ist – die Schnittstelle besteht aus zwei Teilen. Ein Teil ist die Implementierung der Funktion megaPostMessageToGui(void*)
, die einen undurchsichtigen void*
-Zeiger an die Nachrichtenschleife der Anwendung sendet. Diese Funktion wird normalerweise von anderen Threads als dem Hauptthread aufgerufen, kann aber auch vom GUI-Thread selbst aufgerufen werden. Der andere Teil ist der Code in der Nachrichtenschleife der Anwendung, der diese Art von Nachrichten erkennt und sie an MEGAchat zurückgibt, indem er megaProcessMessage(void*)
mit demselben Zeiger aufruft – dieses Mal im Kontext des Hauptthreads (GUI). All dies ist in /src/base/gcm.h
und /src/base/gcm.hpp
implementiert. Diese Dateien enthalten eine detaillierte Dokumentation. Ein Beispiel für die Implementierung unter Windows ist: megaPostMessageToGui(void*)
würde eine PostMessage()
mit einem Benutzernachrichtentyp und void*
als lParam oder wParam der Nachricht ausführen, und in der switch
-Anweisung für die Ereignisverarbeitung wird dies der Fall sein einen Eintrag für diesen Nachrichtentyp, wobei der void*
-Zeiger durch Umwandlung des lParam oder wParam der Nachricht abgerufen und an megaProcessMessage(void*)
übergeben wird.
MEGAchat verlässt sich auf libuv, das in einem eigenen dedizierten Thread ausgeführt wird, um mehrere Sockets auf unformatierte I/O-Ereignisse zu überwachen und Timer zu implementieren. Es stützt sich auch auf die übergeordneten E/A-Funktionen von libuv wie DNS-Auflösung und SSL-Sockets. Eine dünne Schicht über libuv, genannt „services“ ( /src/base/?services*.*
), wird über libuv und dem GCM implementiert, um einfache, Javascript-ähnliche asynchrone C++11-APIs für Timer zu haben ( src/base/timer.h
), DNS-Auflösung ( /src/base/services-dns.hpp
), http-Client ( /src/base/services-http.hpp
). Diese Schicht war ursprünglich so konzipiert, dass sie über eine Komponente auf niedrigerer Ebene mit einer einfachen C-Schnittstelle ( cservices*.cpp/h
-Dateien) verfügt, sodass die Dienste von mehreren DLLs verwendet werden können, die mit unterschiedlichen Compilern erstellt wurden, und über eine Komponente auf hoher Ebene, die nur aus Headern besteht ++11-Schicht, die das Frontend ist und die öffentliche API enthält – das sind die .hpp-Dateien.
Alle Netzwerkbibliotheken in MEGAchat (libcurl) verwenden libuv für den Netzwerkbetrieb und Timer (C-Bibliotheken verwenden libuv direkt, C++-Code verwendet die C++11-Schicht, d. h. timers.hpp
). Es wird dringend empfohlen, dass auch der SDK-Benutzer dasselbe tut, obwohl es beispielsweise möglich ist, einen dedizierten Arbeitsthread auf einem Socket zu blockieren und Ereignisse über den GCM an den GUI-Thread zu senden.
Das Verwendungsmuster ist wie folgt: Für ein bestimmtes Ereignis (Socket-I/O-Ereignis, Timer usw.) wird ein Rückruf registriert, und dieser Rückruf wird vom libuv-Thread aufgerufen, wenn das Ereignis auftritt. Wenn sich das Ereignis möglicherweise außerhalb der Bibliothek, deren Rückruf aufgerufen wird, und insbesondere zur GUI ausbreitet, muss die Ereignisverarbeitung irgendwann mithilfe des GCM-Mechanismus an den GUI-Thread weitergeleitet werden. Wenn das Ereignis jedoch intern ist und sich niemals außerhalb der Bibliothek verbreitet, kann es direkt im Kontext des libuv-Threads behandelt werden (vorausgesetzt, dass dieser es niemals blockiert). Dies erspart den Leistungsaufwand für das Marshalling an den GUI-Thread und wird empfohlen, wenn das Ereignis mit hoher Häufigkeit auftritt, z. B. ein eingehendes Datenblockereignis, bei dem die Daten nur an einen Puffer angehängt werden müssen. Wenn die Übertragung abgeschlossen ist, kann einmal pro Übertragung ein Abschlussereignis im GUI-Thread gemarshallt werden, wodurch die Vorteile beider Ansätze kombiniert werden.
MEGAchat verfügt über eine erweiterte Protokollierungsfunktion, die Datei- und Konsolenprotokollierung mit Farbe, Protokolldateirotation und mehreren Protokollkanälen mit jeweils individueller Protokollebene unterstützt. Protokollebenen werden zur Laufzeit (beim Start) konfiguriert und nicht zur Kompilierzeit (dh nicht durch Deaktivieren von Protokollmakros). Dadurch kann eine für ein Release erstellte App eine vollständige Debug-Protokollierung für alle Kanäle ermöglichen. Protokollkanäle werden in src/base/loggerChannelConfig.h definiert und standardmäßig konfiguriert. Die Datei enthält eine ausführliche Dokumentation. Der Einfachheit halber werden dedizierte Protokollierungsmakros für jeden Kanal normalerweise in dem Code definiert, der ihn verwendet – Beispiele finden Sie in den XXX_LOG_DEBUG/WARN/ERROR-Makros in karereCommon.h. Dem SDK-Benutzer steht es frei, bei Bedarf zusätzliche Protokollkanäle zu erstellen. Ein GUI-Protokollkanal ist bereits definiert. Die Protokollkanalkonfiguration kann zur Laufzeit durch die Umgebungsvariable KRLOG überschrieben werden. Sein Format ist wie folgt:
KRLOG=<chan name>=<log level>,<chan name2>=<log level2>...
Die Protokollebenen sind „off“, „error“, „warn“, „info“, „verbose“, „debug“, „debugv“.
Es gibt einen speziellen Kanalnamen – „alle“. Durch Festlegen der Protokollebene dieses Kanals werden die Protokollebenen aller Kanäle festgelegt. Dies ermöglicht beispielsweise die einfache Stummschaltung aller Kanäle bis auf einen (oder einige wenige), indem:
KRLOG=all=warn,mychannel=debug,myotherchannel=info
Derselbe Kanal kann mehrfach konfiguriert werden und nur die letzte Einstellung ist wirksam, was den oben genannten Trick ermöglicht.
MEGAchat erfordert, dass die Funktion karere::getAppDir()
von der Anwendung zur Kompilierungszeit definiert wird, um so früh wie möglich zu wissen, wo die Protokolldatei erstellt werden soll, und mit der Protokollierung zu beginnen, bevor main()
eingegeben wird. Wenn MEGAchat als statische Bibliothek erstellt wird, ist dies kein Problem. Im Falle einer dynamischen Bibliothek muss diese Funktion ein schwaches Symbol sein, damit MEGAchat selbst ohne die Funktionsimplementierung und die zu verknüpfende Implementierung kompiliert werden kann, wenn die gemeinsam genutzte MEGAchat Bibliothek beim Start der App geladen wird. Schwache Symbole sind nicht wirklich über Compiler hinweg portierbar, und das kann ein Problem darstellen. Sie werden jedoch sowohl von gcc als auch von clang unterstützt. Wenn keine schwachen Symbole unterstützt werden, muss Karer E als statische Bibliothek erstellt werden.
base/promise.h
und Beispielverwendung beispielsweise in /src/test-promise.cpp
setTimeout()
und setInterval()
in /src/base/timers.hpp
marshallCall()
Marshallt Lambda-Aufrufe von einem Arbeitsthread an den GUI-Thread. Anwendungsbeispiele sind beispielsweise in /src/webrtcAdapter.h
und an vielen verschiedenen Stellen zu sehen. Dieser Mechanismus sollte in High-Level-Code, der im GUI-Thread ausgeführt wird, nicht direkt benötigt werden./src/chatClient.h;.cpp
megaPostMessageToGui()
implementiert wird, wie die „Dienste“ gestartet werden und wie der MEGAchat Client instanziiert wird. Zeigt außerdem, wie die getAppDir()
Methode implementiert wird, ein schwaches Symbol, das von der MEGAchat -Bibliothek benötigt wird, um die Protokolldatei zu erstellen und so früh wie möglich mit der Protokollierung zu beginnen, bevor main()
eingegeben wird.src/rtcModile/IRtcModule.h
und zugehörige HeadermegaPostMessageToGui()
bezeichnet wird, aber einen beliebigen Namen haben kann, vorausgesetzt, die Signatur ist extern "C" void(void*)
. Diese Funktion ist das Herzstück des Nachrichtenübermittlungsmechanismus (Gui Call Marshaller oder GCM genannt), auf den MEGAchat angewiesen ist. Sie müssen einen Zeiger auf diese Funktion an services_init()
übergeben.